From 45c12216aa28bffd2072615024bb9b0f170fa735 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Mon, 29 May 2017 22:09:20 +0200 Subject: Use npm run testrpc on circlecCI --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index 448524aa1..4919516f2 100644 --- a/circle.yml +++ b/circle.yml @@ -4,7 +4,7 @@ machine: test: override: - - node node_modules/ethereumjs-testrpc/bin/testrpc -m "concert load couple harbor equip island argue ramp clarify fence smart topic": + - npm run testrpc: background: true - git clone git@github.com:0xProject/contracts.git ../contracts - cd ../contracts; git checkout 38c2b4c; npm install && npm run migrate -- cgit From 34de5986421cca90d37b30a1b64678a8a5149b57 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Mon, 29 May 2017 22:09:43 +0200 Subject: Add tests to linter targets --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 310ca4a8e..4c196f3bb 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "scripts": { "prebuild": "npm run clean", "build": "run-p build:*:prod", - "lint": "tslint src/**/*.ts", + "lint": "tslint src/**/*.ts test/**/*.ts", "test": "run-s clean test:commonjs", "test:umd": "run-s substitute_umd_bundle run_mocha; npm run clean", "test:coverage": "nyc npm run test --all", -- cgit From 7dddf2010e16167260f7ffbb7c7d2fd83609d8a0 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Mon, 29 May 2017 22:14:18 +0200 Subject: Add getExchangeInstanceOrThrowAsync && getSenderAddressOrThrowAsync --- src/contract_wrappers/exchange_wrapper.ts | 13 +++++++------ src/web3_wrapper.ts | 7 +++++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index f0f153c2b..e18b6d35e 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -16,11 +16,8 @@ export class ExchangeWrapper extends ContractWrapper { assert.doesConformToSchema('ecSignature', ecSignature, ecSignatureSchema); assert.isETHAddressHex('signerAddressHex', signerAddressHex); - const senderAddressIfExists = await this.web3Wrapper.getSenderAddressIfExistsAsync(); - assert.assert(!_.isUndefined(senderAddressIfExists), ZeroExError.USER_HAS_NO_ASSOCIATED_ADDRESSES); - - const contractInstance = await this.instantiateContractIfExistsAsync((ExchangeArtifacts as any)); - const exchangeInstance = contractInstance as ExchangeContract; + const senderAddress = await this.web3Wrapper.getSenderAddressOrThrowAsync(); + const exchangeInstance = await this.getExchangeInstanceOrThrowAsync(); const isValidSignature = await exchangeInstance.isValidSignature.call( signerAddressHex, @@ -29,9 +26,13 @@ export class ExchangeWrapper extends ContractWrapper { ecSignature.r, ecSignature.s, { - from: senderAddressIfExists, + from: senderAddress, }, ); return isValidSignature; } + private async getExchangeInstanceOrThrowAsync(): Promise { + const contractInstance = await this.instantiateContractIfExistsAsync((ExchangeArtifacts as any)); + return contractInstance as ExchangeContract; + } } diff --git a/src/web3_wrapper.ts b/src/web3_wrapper.ts index 3b460e4da..72daabe6f 100644 --- a/src/web3_wrapper.ts +++ b/src/web3_wrapper.ts @@ -2,6 +2,8 @@ import * as _ from 'lodash'; import * as Web3 from 'web3'; import * as BigNumber from 'bignumber.js'; import promisify = require('es6-promisify'); +import {ZeroExError} from "./types"; +import {assert} from "./utils/assert"; export class Web3Wrapper { private web3: Web3; @@ -20,6 +22,11 @@ export class Web3Wrapper { const firstAccount = await this.getFirstAddressIfExistsAsync(); return firstAccount; } + public async getSenderAddressOrThrowAsync(): Promise { + const senderAddressIfExists = await this.getSenderAddressIfExistsAsync(); + assert.assert(!_.isUndefined(senderAddressIfExists), ZeroExError.USER_HAS_NO_ASSOCIATED_ADDRESSES); + return senderAddressIfExists as string; + } public async getFirstAddressIfExistsAsync(): Promise { const addresses = await promisify(this.web3.eth.getAccounts)(); if (_.isEmpty(addresses)) { -- cgit From 96092de5cb97430af35a1c03f22fdc34d7100107 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Mon, 29 May 2017 22:30:18 +0200 Subject: Add initial implementation of fillOrderAsync --- src/contract_wrappers/exchange_wrapper.ts | 64 ++++++++++++++++++++++++++++++- src/types.ts | 33 ++++++++++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index e18b6d35e..dfa639954 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -1,10 +1,18 @@ import * as _ from 'lodash'; import {Web3Wrapper} from '../web3_wrapper'; -import {ECSignature, ZeroExError, ExchangeContract} from '../types'; +import { + ECSignature, + ExchangeContract, + ExchangeContractErrs, + OrderValues, + OrderAddresses, +} from '../types'; import {assert} from '../utils/assert'; import {ContractWrapper} from './contract_wrapper'; import * as ExchangeArtifacts from '../artifacts/Exchange.json'; import {ecSignatureSchema} from '../schemas/ec_signature_schema'; +import {ContractResponse} from '../types'; +import {constants} from '../utils/constants'; export class ExchangeWrapper extends ContractWrapper { constructor(web3Wrapper: Web3Wrapper) { @@ -31,6 +39,60 @@ export class ExchangeWrapper extends ContractWrapper { ); return isValidSignature; } + public async fillOrderAsync(maker: string, taker: string, makerTokenAddress: string, + takerTokenAddress: string, makerTokenAmount: BigNumber.BigNumber, + takerTokenAmount: BigNumber.BigNumber, makerFee: BigNumber.BigNumber, + takerFee: BigNumber.BigNumber, expirationUnixTimestampSec: BigNumber.BigNumber, + feeRecipient: string, fillAmount: BigNumber.BigNumber, + signatureData: ECSignature, salt: BigNumber.BigNumber) { + const senderAddress = await this.web3Wrapper.getSenderAddressOrThrowAsync(); + const exchangeInstance = await this.getExchangeInstanceOrThrowAsync(); + + taker = taker === '' ? constants.NULL_ADDRESS : taker; + const shouldCheckTransfer = true; + const orderAddresses: OrderAddresses = [ + maker, + taker, + makerTokenAddress, + takerTokenAddress, + feeRecipient, + ]; + const orderValues: OrderValues = [ + makerTokenAmount, + takerTokenAmount, + makerFee, + takerFee, + expirationUnixTimestampSec, + salt, + ]; + const response: ContractResponse = await exchangeInstance.fill( + orderAddresses, + orderValues, + fillAmount, + shouldCheckTransfer, + signatureData.v, + signatureData.r, + signatureData.s, + { + from: senderAddress, + }, + ); + const errEvent = _.find(response.logs, {event: 'LogError'}); + if (!_.isUndefined(errEvent)) { + const errCode = errEvent.args.errorId.toNumber(); + const humanReadableErrMessage = this.exchangeContractErrToMsg[errCode]; + throw new Error(humanReadableErrMessage); + } + return response; + } + private exchangeContractErrToMsg = { + [ExchangeContractErrs.ERROR_FILL_EXPIRED]: 'The order you attempted to fill is expired', + [ExchangeContractErrs.ERROR_CANCEL_EXPIRED]: 'The order you attempted to cancel is expired', + [ExchangeContractErrs.ERROR_FILL_NO_VALUE]: 'This order has already been filled or cancelled', + [ExchangeContractErrs.ERROR_CANCEL_NO_VALUE]: 'This order has already been filled or cancelled', + [ExchangeContractErrs.ERROR_FILL_TRUNCATION]: 'The rounding error was too large when filling this order', + [ExchangeContractErrs.ERROR_FILL_BALANCE_ALLOWANCE]: 'Maker or taker has insufficient balance or allowance', + }; private async getExchangeInstanceOrThrowAsync(): Promise { const contractInstance = await this.instantiateContractIfExistsAsync((ExchangeArtifacts as any)); return contractInstance as ExchangeContract; diff --git a/src/types.ts b/src/types.ts index 3bed01547..0c661915e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -26,8 +26,23 @@ export interface ECSignature { s: string; } +export type OrderAddresses = [string, string, string, string, string]; + +export type OrderValues = [ + BigNumber.BigNumber, BigNumber.BigNumber, BigNumber.BigNumber, + BigNumber.BigNumber, BigNumber.BigNumber, BigNumber.BigNumber +]; + +export interface TxData { + from: string; +} + export interface ExchangeContract { isValidSignature: any; + fill: ( + orderAddresses: OrderAddresses, orderValues: OrderValues, fillAmount: BigNumber.BigNumber, + shouldCheckTransfer: boolean, v: number, r: string, s: string, txData: TxData, + ) => ContractResponse; } export const SolidityTypes = strEnum([ @@ -35,3 +50,21 @@ export const SolidityTypes = strEnum([ 'uint256', ]); export type SolidityTypes = keyof typeof SolidityTypes; + +export enum ExchangeContractErrs { + ERROR_FILL_EXPIRED, // Order has already expired + ERROR_FILL_NO_VALUE, // Order has already been fully filled or cancelled + ERROR_FILL_TRUNCATION, // Rounding error too large + ERROR_FILL_BALANCE_ALLOWANCE, // Insufficient balance or allowance for token transfer + ERROR_CANCEL_EXPIRED, // Order has already expired + ERROR_CANCEL_NO_VALUE, // Order has already been fully filled or cancelled +}; + +export interface ContractResponse { + logs: ContractEvent[]; +} + +export interface ContractEvent { + event: string; + args: any; +} -- cgit From b46ad44856fd3744d90562426356283c90db4fc1 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Mon, 29 May 2017 22:34:06 +0200 Subject: Move field declaration to the begining of the class --- src/contract_wrappers/exchange_wrapper.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index dfa639954..ce5a7b8f2 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -15,6 +15,14 @@ import {ContractResponse} from '../types'; import {constants} from '../utils/constants'; export class ExchangeWrapper extends ContractWrapper { + private exchangeContractErrToMsg = { + [ExchangeContractErrs.ERROR_FILL_EXPIRED]: 'The order you attempted to fill is expired', + [ExchangeContractErrs.ERROR_CANCEL_EXPIRED]: 'The order you attempted to cancel is expired', + [ExchangeContractErrs.ERROR_FILL_NO_VALUE]: 'This order has already been filled or cancelled', + [ExchangeContractErrs.ERROR_CANCEL_NO_VALUE]: 'This order has already been filled or cancelled', + [ExchangeContractErrs.ERROR_FILL_TRUNCATION]: 'The rounding error was too large when filling this order', + [ExchangeContractErrs.ERROR_FILL_BALANCE_ALLOWANCE]: 'Maker or taker has insufficient balance or allowance', + }; constructor(web3Wrapper: Web3Wrapper) { super(web3Wrapper); } @@ -85,14 +93,6 @@ export class ExchangeWrapper extends ContractWrapper { } return response; } - private exchangeContractErrToMsg = { - [ExchangeContractErrs.ERROR_FILL_EXPIRED]: 'The order you attempted to fill is expired', - [ExchangeContractErrs.ERROR_CANCEL_EXPIRED]: 'The order you attempted to cancel is expired', - [ExchangeContractErrs.ERROR_FILL_NO_VALUE]: 'This order has already been filled or cancelled', - [ExchangeContractErrs.ERROR_CANCEL_NO_VALUE]: 'This order has already been filled or cancelled', - [ExchangeContractErrs.ERROR_FILL_TRUNCATION]: 'The rounding error was too large when filling this order', - [ExchangeContractErrs.ERROR_FILL_BALANCE_ALLOWANCE]: 'Maker or taker has insufficient balance or allowance', - }; private async getExchangeInstanceOrThrowAsync(): Promise { const contractInstance = await this.instantiateContractIfExistsAsync((ExchangeArtifacts as any)); return contractInstance as ExchangeContract; -- cgit From 7fea7119272a1dd7033719504433357e219847c2 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Mon, 29 May 2017 22:42:32 +0200 Subject: Add assertions for parameters --- src/contract_wrappers/exchange_wrapper.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index ce5a7b8f2..691d465cc 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -52,7 +52,21 @@ export class ExchangeWrapper extends ContractWrapper { takerTokenAmount: BigNumber.BigNumber, makerFee: BigNumber.BigNumber, takerFee: BigNumber.BigNumber, expirationUnixTimestampSec: BigNumber.BigNumber, feeRecipient: string, fillAmount: BigNumber.BigNumber, - signatureData: ECSignature, salt: BigNumber.BigNumber) { + ecSignature: ECSignature, salt: BigNumber.BigNumber) { + assert.isBigNumber('salt', salt); + assert.isBigNumber('makerFee', makerFee); + assert.isBigNumber('takerFee', takerFee); + assert.isBigNumber('fillAmount', fillAmount); + assert.isBigNumber('makerTokenAmount', makerTokenAmount); + assert.isBigNumber('takerTokenAmount', takerTokenAmount); + assert.isBigNumber('expirationUnixTimestampSec', expirationUnixTimestampSec); + assert.isETHAddressHex('maker', maker); + assert.isETHAddressHex('taker', taker); + assert.isETHAddressHex('feeRecipient', feeRecipient); + assert.isETHAddressHex('makerTokenAddress', makerTokenAddress); + assert.isETHAddressHex('takerTokenAddress', takerTokenAddress); + assert.doesConformToSchema('ecSignature', ecSignature, ecSignatureSchema); + const senderAddress = await this.web3Wrapper.getSenderAddressOrThrowAsync(); const exchangeInstance = await this.getExchangeInstanceOrThrowAsync(); -- cgit From 9bb738bb2f2b26b61049315ca26a96511460062e Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Mon, 29 May 2017 22:45:05 +0200 Subject: Finish ecSignature renaming --- src/contract_wrappers/exchange_wrapper.ts | 6 +++--- test/utils/blockchain_lifecycle.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 691d465cc..c129eb367 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -92,9 +92,9 @@ export class ExchangeWrapper extends ContractWrapper { orderValues, fillAmount, shouldCheckTransfer, - signatureData.v, - signatureData.r, - signatureData.s, + ecSignature.v, + ecSignature.r, + ecSignature.s, { from: senderAddress, }, diff --git a/test/utils/blockchain_lifecycle.ts b/test/utils/blockchain_lifecycle.ts index 68e169ac0..50eb57b95 100644 --- a/test/utils/blockchain_lifecycle.ts +++ b/test/utils/blockchain_lifecycle.ts @@ -17,4 +17,4 @@ export class BlockchainLifecycle { throw new Error(`Snapshot with id #${this.snapshotId} failed to revert`); } } -}; +} -- cgit From 603a88872d07cb7a380be4eee3111b024bfed886 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 11:56:23 +0200 Subject: Add Order and SignedOrder types --- src/types.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/types.ts b/src/types.ts index 0c661915e..a14115ef5 100644 --- a/src/types.ts +++ b/src/types.ts @@ -68,3 +68,26 @@ export interface ContractEvent { event: string; args: any; } + +export interface Order { + maker: string; + taker?: string; + + makerFee: BigNumber.BigNumber; + takerFee: BigNumber.BigNumber; + + makerTokenAmount: BigNumber.BigNumber; + takerTokenAmount: BigNumber.BigNumber; + + makerTokenAddress: string; + takerTokenAddress: string; + + salt: BigNumber.BigNumber; + fillAmount: BigNumber.BigNumber; + feeRecipient: string; + expirationUnixTimestampSec: BigNumber.BigNumber; +} + +export interface SignedOrder extends Order { + ecSignature: ECSignature; +} -- cgit From 699e588d1fda7f7e8190a4b3347905964cef2d95 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 12:00:23 +0200 Subject: Add signedOrderSchema and all subschemas --- src/schemas/signed_order_schema.ts | 50 ++++++++++++++++++++++++++++++++++++++ src/utils/schema_validator.ts | 7 +++++- 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/schemas/signed_order_schema.ts diff --git a/src/schemas/signed_order_schema.ts b/src/schemas/signed_order_schema.ts new file mode 100644 index 000000000..b9321cad1 --- /dev/null +++ b/src/schemas/signed_order_schema.ts @@ -0,0 +1,50 @@ +export const addressSchema = { + id: '/addressSchema', + type: 'string', + pattern: '^0[xX][0-9A-Fa-f]{40}$', +}; + +export const bigNumberSchema = { + id: '/bigNumberSchema', + type: 'string', + pattern: '^\d*$', +}; + +export const orderSchema = { + id: '/orderSchema', + properties: { + maker: {$ref: '/addressSchema'}, + taker: {$ref: '/addressSchema'}, + + makerFee: {$ref: '/bigNumberSchema'}, + takerFee: {$ref: '/bigNumberSchema'}, + + makerTokenAmount: {$ref: '/bigNumberSchema'}, + takerTokenAmount: {$ref: '/bigNumberSchema'}, + + makerTokenAddress: {$ref: '/addressSchema'}, + takerTokenAddress: {$ref: '/addressSchema'}, + + salt: {$ref: '/bigNumberSchema'}, + fillAmount: {$ref: '/bigNumberSchema'}, + feeRecipient: {$ref: '/addressSchema'}, + expirationUnixTimestampSec: {$ref: '/bigNumberSchema'}, + }, + required: [ + 'maker', /*'taker',*/ 'makerFee', 'takerFee', 'makerTokenAmount', 'takerTokenAmount', + 'salt', 'fillAmount', 'feeRecipient', 'expirationUnixTimestampSec', + ], + type: 'object', +}; + +export const signedOrderSchema = { + allOf: [ + { $ref: '/orderSchema' }, + { + properties: { + ecSignature: {$ref: '/addressSchema'}, + }, + required: ['ecSignature'], + }, + ], +}; diff --git a/src/utils/schema_validator.ts b/src/utils/schema_validator.ts index 61f4c09c8..0159b6b0b 100644 --- a/src/utils/schema_validator.ts +++ b/src/utils/schema_validator.ts @@ -1,12 +1,17 @@ import {Validator, ValidatorResult} from 'jsonschema'; import {ecSignatureSchema, ecSignatureParameter} from '../schemas/ec_signature_schema'; +import {addressSchema, bigNumberSchema, orderSchema, signedOrderSchema} from '../schemas/signed_order_schema'; export class SchemaValidator { private validator: Validator; constructor() { this.validator = new Validator(); - this.validator.addSchema(ecSignatureParameter, ecSignatureParameter.id); + this.validator.addSchema(orderSchema, orderSchema.id); + this.validator.addSchema(addressSchema, addressSchema.id); + this.validator.addSchema(bigNumberSchema, bigNumberSchema.id); this.validator.addSchema(ecSignatureSchema, ecSignatureSchema.id); + this.validator.addSchema(signedOrderSchema, signedOrderSchema.id); + this.validator.addSchema(ecSignatureParameter, ecSignatureParameter.id); } public validate(instance: object, schema: Schema): ValidatorResult { return this.validator.validate(instance, schema); -- cgit From 95b78d877a1b231d5df2e75447c97b643da4fdaa Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 12:00:51 +0200 Subject: Add isBoolean assertion --- src/utils/assert.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/utils/assert.ts b/src/utils/assert.ts index 1baf572d1..aeed1c6dc 100644 --- a/src/utils/assert.ts +++ b/src/utils/assert.ts @@ -27,6 +27,9 @@ export const assert = { isNumber(variableName: string, value: number): void { this.assert(_.isFinite(value), this.typeAssertionMessage(variableName, 'number', value)); }, + isBoolean(variableName: string, value: boolean): void { + this.assert(_.isBoolean(value), this.typeAssertionMessage(variableName, 'boolean', value)); + }, doesConformToSchema(variableName: string, value: object, schema: Schema): void { const schemaValidator = new SchemaValidator(); const validationResult = schemaValidator.validate(value, schema); -- cgit From 72e3b0e2904551db6866bcf4d13cdc9b44722175 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 12:01:32 +0200 Subject: Add first order fixture --- test/fixtures/orders/5_MKR_for_42_MLN.json | 35 ++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 test/fixtures/orders/5_MKR_for_42_MLN.json diff --git a/test/fixtures/orders/5_MKR_for_42_MLN.json b/test/fixtures/orders/5_MKR_for_42_MLN.json new file mode 100644 index 000000000..2c2a3d73e --- /dev/null +++ b/test/fixtures/orders/5_MKR_for_42_MLN.json @@ -0,0 +1,35 @@ +{ + "maker": { + "address": "0xffa119a5761eb93eacfe5d2b0e8944648c3d7164", + "token": { + "name": "MakerDAO", + "symbol": "MKR", + "decimals": 18, + "address": "0x1dad4783cf3fe3085c1426157ab175a6119a04ba" + }, + "amount": "5000000000000000000", + "feeAmount": "0" + }, + "taker": { + "address": "", + "token": { + "name": "Melon Token", + "symbol": "MLN", + "decimals": 18, + "address": "0x323b5d4c32345ced77393b3530b1eed0f346429d" + }, + "amount": "42000000000000000000", + "feeAmount": "0" + }, + "expiration": "1496181600", + "feeRecipient": "0x0000000000000000000000000000000000000000", + "salt": "28894038927316056783595066163529969528517282468995826064292810658599101267743", + "signature": { + "v": 28, + "r": "0x1e84173b09bc51e4e3f923718d747bd91c3584cfa3556d79294891ddd740e819", + "s": "0x36c0f453a01487f49e16157703cacb6cee08d337549f805c25d3f78221823eed", + "hash": "0x3f64711f39393f7f60a0980e3effba087c15bb9b1cbf678ede63a69798e5dc14" + }, + "exchangeContract": "0x9ce1a5e2311f9b8b8e6b40ed20b5b090de4a4c4d", + "networkId": 42 +} \ No newline at end of file -- cgit From 4b8ff4bf5f18bfb96c50df5928beee3463aca616 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 12:02:50 +0200 Subject: Add id to signedOrderSchema --- src/schemas/signed_order_schema.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/schemas/signed_order_schema.ts b/src/schemas/signed_order_schema.ts index b9321cad1..fc72476d9 100644 --- a/src/schemas/signed_order_schema.ts +++ b/src/schemas/signed_order_schema.ts @@ -38,6 +38,7 @@ export const orderSchema = { }; export const signedOrderSchema = { + id: '/signedOrderSchema', allOf: [ { $ref: '/orderSchema' }, { -- cgit From 170dd91bfd2896e45a804240938dd8ca8219569e Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 12:13:30 +0200 Subject: Change BigNumber schema to Number schema --- src/schemas/signed_order_schema.ts | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/schemas/signed_order_schema.ts b/src/schemas/signed_order_schema.ts index fc72476d9..69f33b7bd 100644 --- a/src/schemas/signed_order_schema.ts +++ b/src/schemas/signed_order_schema.ts @@ -4,10 +4,9 @@ export const addressSchema = { pattern: '^0[xX][0-9A-Fa-f]{40}$', }; -export const bigNumberSchema = { - id: '/bigNumberSchema', - type: 'string', - pattern: '^\d*$', +export const numberSchema = { + id: '/numberSchema', + type: 'number', }; export const orderSchema = { @@ -16,19 +15,19 @@ export const orderSchema = { maker: {$ref: '/addressSchema'}, taker: {$ref: '/addressSchema'}, - makerFee: {$ref: '/bigNumberSchema'}, - takerFee: {$ref: '/bigNumberSchema'}, + makerFee: {$ref: '/numberSchema'}, + takerFee: {$ref: '/numberSchema'}, - makerTokenAmount: {$ref: '/bigNumberSchema'}, - takerTokenAmount: {$ref: '/bigNumberSchema'}, + makerTokenAmount: {$ref: '/numberSchema'}, + takerTokenAmount: {$ref: '/numberSchema'}, makerTokenAddress: {$ref: '/addressSchema'}, takerTokenAddress: {$ref: '/addressSchema'}, - salt: {$ref: '/bigNumberSchema'}, - fillAmount: {$ref: '/bigNumberSchema'}, + salt: {$ref: '/numberSchema'}, + fillAmount: {$ref: '/numberSchema'}, feeRecipient: {$ref: '/addressSchema'}, - expirationUnixTimestampSec: {$ref: '/bigNumberSchema'}, + expirationUnixTimestampSec: {$ref: '/numberSchema'}, }, required: [ 'maker', /*'taker',*/ 'makerFee', 'takerFee', 'makerTokenAmount', 'takerTokenAmount', -- cgit From cf63e1d1a6606c1b3ab82d5fec56df8ac4128eea Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 12:16:33 +0200 Subject: Change BigNumber schema to Number schema --- src/utils/schema_validator.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/schema_validator.ts b/src/utils/schema_validator.ts index 0159b6b0b..5b2c4aaa5 100644 --- a/src/utils/schema_validator.ts +++ b/src/utils/schema_validator.ts @@ -1,14 +1,14 @@ import {Validator, ValidatorResult} from 'jsonschema'; import {ecSignatureSchema, ecSignatureParameter} from '../schemas/ec_signature_schema'; -import {addressSchema, bigNumberSchema, orderSchema, signedOrderSchema} from '../schemas/signed_order_schema'; +import {addressSchema, numberSchema, orderSchema, signedOrderSchema} from '../schemas/signed_order_schema'; export class SchemaValidator { private validator: Validator; constructor() { this.validator = new Validator(); this.validator.addSchema(orderSchema, orderSchema.id); + this.validator.addSchema(numberSchema, numberSchema.id); this.validator.addSchema(addressSchema, addressSchema.id); - this.validator.addSchema(bigNumberSchema, bigNumberSchema.id); this.validator.addSchema(ecSignatureSchema, ecSignatureSchema.id); this.validator.addSchema(signedOrderSchema, signedOrderSchema.id); this.validator.addSchema(ecSignatureParameter, ecSignatureParameter.id); -- cgit From 380c1e1ca521ffad6f4e3832d896bd737f67eab2 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 12:17:43 +0200 Subject: Make fillOrderAsync accept signedOrder instead of a shit-ton of params --- src/contract_wrappers/exchange_wrapper.ts | 56 ++++++++++++------------------- 1 file changed, 21 insertions(+), 35 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index c129eb367..a4db63b66 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -6,11 +6,13 @@ import { ExchangeContractErrs, OrderValues, OrderAddresses, + SignedOrder, } from '../types'; import {assert} from '../utils/assert'; import {ContractWrapper} from './contract_wrapper'; import * as ExchangeArtifacts from '../artifacts/Exchange.json'; import {ecSignatureSchema} from '../schemas/ec_signature_schema'; +import {signedOrderSchema} from '../schemas/signed_order_schema'; import {ContractResponse} from '../types'; import {constants} from '../utils/constants'; @@ -47,54 +49,38 @@ export class ExchangeWrapper extends ContractWrapper { ); return isValidSignature; } - public async fillOrderAsync(maker: string, taker: string, makerTokenAddress: string, - takerTokenAddress: string, makerTokenAmount: BigNumber.BigNumber, - takerTokenAmount: BigNumber.BigNumber, makerFee: BigNumber.BigNumber, - takerFee: BigNumber.BigNumber, expirationUnixTimestampSec: BigNumber.BigNumber, - feeRecipient: string, fillAmount: BigNumber.BigNumber, - ecSignature: ECSignature, salt: BigNumber.BigNumber) { - assert.isBigNumber('salt', salt); - assert.isBigNumber('makerFee', makerFee); - assert.isBigNumber('takerFee', takerFee); - assert.isBigNumber('fillAmount', fillAmount); - assert.isBigNumber('makerTokenAmount', makerTokenAmount); - assert.isBigNumber('takerTokenAmount', takerTokenAmount); - assert.isBigNumber('expirationUnixTimestampSec', expirationUnixTimestampSec); - assert.isETHAddressHex('maker', maker); - assert.isETHAddressHex('taker', taker); - assert.isETHAddressHex('feeRecipient', feeRecipient); - assert.isETHAddressHex('makerTokenAddress', makerTokenAddress); - assert.isETHAddressHex('takerTokenAddress', takerTokenAddress); - assert.doesConformToSchema('ecSignature', ecSignature, ecSignatureSchema); + public async fillOrderAsync(signedOrder: SignedOrder, shouldCheckTransfer: boolean = true) { + assert.doesConformToSchema('signedOrder', JSON.parse(JSON.stringify(signedOrder)), signedOrderSchema); + assert.isBoolean('shouldCheckTransfer', shouldCheckTransfer); const senderAddress = await this.web3Wrapper.getSenderAddressOrThrowAsync(); const exchangeInstance = await this.getExchangeInstanceOrThrowAsync(); - taker = taker === '' ? constants.NULL_ADDRESS : taker; - const shouldCheckTransfer = true; + const taker = _.isUndefined(signedOrder.taker) ? constants.NULL_ADDRESS : signedOrder.taker; + const orderAddresses: OrderAddresses = [ - maker, + signedOrder.maker, taker, - makerTokenAddress, - takerTokenAddress, - feeRecipient, + signedOrder.makerTokenAddress, + signedOrder.takerTokenAddress, + signedOrder.feeRecipient, ]; const orderValues: OrderValues = [ - makerTokenAmount, - takerTokenAmount, - makerFee, - takerFee, - expirationUnixTimestampSec, - salt, + signedOrder.makerTokenAmount, + signedOrder.takerTokenAmount, + signedOrder.makerFee, + signedOrder.takerFee, + signedOrder.expirationUnixTimestampSec, + signedOrder.salt, ]; const response: ContractResponse = await exchangeInstance.fill( orderAddresses, orderValues, - fillAmount, + signedOrder.fillAmount, shouldCheckTransfer, - ecSignature.v, - ecSignature.r, - ecSignature.s, + signedOrder.ecSignature.v, + signedOrder.ecSignature.r, + signedOrder.ecSignature.s, { from: senderAddress, }, -- cgit From 968df3424ccab04ca15bbe4138e35ff90d1c00a4 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 12:55:00 +0200 Subject: Add copy_fixtures command --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 59e33a7dd..c232e2828 100644 --- a/package.json +++ b/package.json @@ -27,11 +27,12 @@ "build:umd:dev": "webpack", "build:umd:prod": "webpack -p", "build:commonjs:dev": "tsc; copyfiles -u 2 ./src/artifacts/*.json ../0x.js/lib/src/artifacts;", - "test:commonjs": "run-s build:commonjs:dev run_mocha", + "test:commonjs": "run-s build:commonjs:dev copy_fixtures run_mocha", "pretest:umd": "run-s clean build:*:dev", "substitute_umd_bundle": "npm run remove_src_files_not_used_by_tests; shx mv _bundles/* lib/src", "remove_src_files_not_used_by_tests": "find ./lib/src \\( -path ./lib/src/utils -o -path ./lib/src/schemas -o -path \"./lib/src/types.*\" \\) -prune -o -type f -print | xargs rm", - "run_mocha": "mocha lib/test/**/*_test.js" + "run_mocha": "mocha lib/test/**/*_test.js", + "copy_fixtures": "shx cp -r ./test/fixtures ./lib/test/fixtures" }, "config": { "artifacts": "Proxy Exchange TokenRegistry Token Mintable EtherToken", -- cgit From 766d46041ec3958ebd625eb5adbc5b46b329b6d8 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 12:55:42 +0200 Subject: Add fillAmount parameter --- src/contract_wrappers/exchange_wrapper.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index a4db63b66..141e9502a 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -49,7 +49,8 @@ export class ExchangeWrapper extends ContractWrapper { ); return isValidSignature; } - public async fillOrderAsync(signedOrder: SignedOrder, shouldCheckTransfer: boolean = true) { + public async fillOrderAsync(signedOrder: SignedOrder, fillAmount: BigNumber.BigNumber, + shouldCheckTransfer: boolean = true): Promise { assert.doesConformToSchema('signedOrder', JSON.parse(JSON.stringify(signedOrder)), signedOrderSchema); assert.isBoolean('shouldCheckTransfer', shouldCheckTransfer); @@ -76,7 +77,7 @@ export class ExchangeWrapper extends ContractWrapper { const response: ContractResponse = await exchangeInstance.fill( orderAddresses, orderValues, - signedOrder.fillAmount, + fillAmount, shouldCheckTransfer, signedOrder.ecSignature.v, signedOrder.ecSignature.r, -- cgit From 0b81cd9d78584958d5f33a1a9826a071ed450fc3 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 12:56:11 +0200 Subject: Fix orderSchema --- src/schemas/signed_order_schema.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/schemas/signed_order_schema.ts b/src/schemas/signed_order_schema.ts index 69f33b7bd..dc7e51e40 100644 --- a/src/schemas/signed_order_schema.ts +++ b/src/schemas/signed_order_schema.ts @@ -6,7 +6,8 @@ export const addressSchema = { export const numberSchema = { id: '/numberSchema', - type: 'number', + type: 'string', + format: '\d+(\.\d+)?', }; export const orderSchema = { @@ -25,13 +26,12 @@ export const orderSchema = { takerTokenAddress: {$ref: '/addressSchema'}, salt: {$ref: '/numberSchema'}, - fillAmount: {$ref: '/numberSchema'}, feeRecipient: {$ref: '/addressSchema'}, expirationUnixTimestampSec: {$ref: '/numberSchema'}, }, required: [ 'maker', /*'taker',*/ 'makerFee', 'takerFee', 'makerTokenAmount', 'takerTokenAmount', - 'salt', 'fillAmount', 'feeRecipient', 'expirationUnixTimestampSec', + 'salt', 'feeRecipient', 'expirationUnixTimestampSec', ], type: 'object', }; @@ -42,7 +42,7 @@ export const signedOrderSchema = { { $ref: '/orderSchema' }, { properties: { - ecSignature: {$ref: '/addressSchema'}, + ecSignature: {$ref: '/ECSignature'}, }, required: ['ecSignature'], }, -- cgit From 76ddd12b4a0fc520b90d9f57f8f6534523d3691e Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 12:56:28 +0200 Subject: Fix order type --- src/types.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/types.ts b/src/types.ts index a14115ef5..327293cc6 100644 --- a/src/types.ts +++ b/src/types.ts @@ -83,7 +83,6 @@ export interface Order { takerTokenAddress: string; salt: BigNumber.BigNumber; - fillAmount: BigNumber.BigNumber; feeRecipient: string; expirationUnixTimestampSec: BigNumber.BigNumber; } -- cgit From acd5fba1336659053be470e4041b803150588cc5 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 12:56:51 +0200 Subject: Add order utils --- test/utils/order.ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 test/utils/order.ts diff --git a/test/utils/order.ts b/test/utils/order.ts new file mode 100644 index 000000000..dc0be670c --- /dev/null +++ b/test/utils/order.ts @@ -0,0 +1,21 @@ +import {SignedOrder} from '../../lib/src/types'; +import * as BigNumber from 'bignumber.js'; +import * as _ from 'lodash'; + +export function signedOrderFromJSON(signedOrderJSON: any): SignedOrder { + const signedOrder = { + maker: signedOrderJSON.maker.address, + taker: _.isEmpty(signedOrderJSON.taker.address) ? undefined : signedOrderJSON.taker.address, + makerTokenAddress: signedOrderJSON.maker.token.address, + takerTokenAddress: signedOrderJSON.taker.token.address, + makerTokenAmount: new BigNumber(signedOrderJSON.maker.amount), + takerTokenAmount: new BigNumber(signedOrderJSON.taker.amount), + makerFee: new BigNumber(signedOrderJSON.maker.feeAmount), + takerFee: new BigNumber(signedOrderJSON.taker.feeAmount), + expirationUnixTimestampSec: new BigNumber(signedOrderJSON.expiration), + feeRecipient: signedOrderJSON.feeRecipient, + ecSignature: signedOrderJSON.signature, + salt: new BigNumber(signedOrderJSON.salt), + }; + return signedOrder; +} -- cgit From 18d65f5f55bcdbbb1e1058ac9e8fe193804b1a06 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 14:36:14 +0200 Subject: Append _test to exchange_wrapper --- test/exchange_wrapper.ts | 95 -------------------------------------- test/exchange_wrapper_test.ts | 105 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 95 deletions(-) delete mode 100644 test/exchange_wrapper.ts create mode 100644 test/exchange_wrapper_test.ts diff --git a/test/exchange_wrapper.ts b/test/exchange_wrapper.ts deleted file mode 100644 index 4bfc49374..000000000 --- a/test/exchange_wrapper.ts +++ /dev/null @@ -1,95 +0,0 @@ -import 'mocha'; -import * as chai from 'chai'; -import chaiAsPromised = require('chai-as-promised'); -import * as Web3 from 'web3'; -import {web3Factory} from './utils/web3_factory'; -import {ZeroEx} from '../src/0x.js'; -import {BlockchainLifecycle} from './utils/blockchain_lifecycle'; - -const expect = chai.expect; -chai.use(chaiAsPromised); -const blockchainLifecycle = new BlockchainLifecycle(); - -describe('ExchangeWrapper', () => { - let zeroEx: ZeroEx; - before(async () => { - const web3 = web3Factory.create(); - zeroEx = new ZeroEx(web3); - }); - beforeEach(async () => { - await blockchainLifecycle.startAsync(); - }); - afterEach(async () => { - await blockchainLifecycle.revertAsync(); - }); - describe('#isValidSignatureAsync', () => { - // The Exchange smart contract `isValidSignature` method only validates orderHashes and assumes - // the length of the data is exactly 32 bytes. Thus for these tests, we use data of this size. - const dataHex = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0'; - const signature = { - v: 27, - r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33', - s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254', - }; - const address = '0x5409ed021d9299bf6814279a6a1411a7e866a631'; - describe('should throw if passed a malformed signature', () => { - it('malformed v', async () => { - const malformedSignature = { - v: 34, - r: signature.r, - s: signature.s, - }; - expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address)) - .to.be.rejected; - }); - it('r lacks 0x prefix', () => { - const malformedR = signature.r.replace('0x', ''); - const malformedSignature = { - v: signature.v, - r: malformedR, - s: signature.s, - }; - expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address)) - .to.be.rejected; - }); - it('r is too short', () => { - const malformedR = signature.r.substr(10); - const malformedSignature = { - v: signature.v, - r: malformedR, - s: signature.s.replace('0', 'z'), - }; - expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address)) - .to.be.rejected; - }); - it('s is not hex', () => { - const malformedS = signature.s.replace('0', 'z'); - const malformedSignature = { - v: signature.v, - r: signature.r, - s: malformedS, - }; - expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address)) - .to.be.rejected; - }); - }); - it('should return false if the data doesn\'t pertain to the signature & address', async () => { - const isValid = await zeroEx.exchange.isValidSignatureAsync('0x0', signature, address); - expect(isValid).to.be.false; - }); - it('should return false if the address doesn\'t pertain to the signature & dataHex', async () => { - const validUnrelatedAddress = '0x8b0292B11a196601eD2ce54B665CaFEca0347D42'; - const isValid = await zeroEx.exchange.isValidSignatureAsync(dataHex, signature, validUnrelatedAddress); - expect(isValid).to.be.false; - }); - it('should return false if the signature doesn\'t pertain to the dataHex & address', async () => { - const wrongSignature = Object.assign({}, signature, {v: 28}); - const isValid = await zeroEx.exchange.isValidSignatureAsync(dataHex, wrongSignature, address); - expect(isValid).to.be.false; - }); - it('should return true if the signature does pertain to the dataHex & address', async () => { - const isValid = await zeroEx.exchange.isValidSignatureAsync(dataHex, signature, address); - expect(isValid).to.be.true; - }); - }); -}); diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts new file mode 100644 index 000000000..bb09a0344 --- /dev/null +++ b/test/exchange_wrapper_test.ts @@ -0,0 +1,105 @@ +import 'mocha'; +import * as chai from 'chai'; +import chaiAsPromised = require('chai-as-promised'); +import {web3Factory} from './utils/web3_factory'; +import {ZeroEx} from '../src/0x.js'; +import {BlockchainLifecycle} from './utils/blockchain_lifecycle'; +import * as OrderJSON from './fixtures/orders/5_MKR_for_42_MLN.json'; +import * as BigNumber from 'bignumber.js'; +import {signedOrderFromJSON} from './utils/order'; + +const expect = chai.expect; +chai.use(chaiAsPromised); +const blockchainLifecycle = new BlockchainLifecycle(); + +describe('ExchangeWrapper', () => { + let zeroEx: ZeroEx; + before(async () => { + const web3 = web3Factory.create(); + zeroEx = new ZeroEx(web3); + }); + beforeEach(async () => { + await blockchainLifecycle.startAsync(); + }); + afterEach(async () => { + await blockchainLifecycle.revertAsync(); + }); + describe('#isValidSignatureAsync', () => { + // The Exchange smart contract `isValidSignature` method only validates orderHashes and assumes + // the length of the data is exactly 32 bytes. Thus for these tests, we use data of this size. + const dataHex = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0'; + const signature = { + v: 27, + r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33', + s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254', + }; + const address = '0x5409ed021d9299bf6814279a6a1411a7e866a631'; + describe('should throw if passed a malformed signature', () => { + it('malformed v', async () => { + const malformedSignature = { + v: 34, + r: signature.r, + s: signature.s, + }; + expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address)) + .to.be.rejected; + }); + it('r lacks 0x prefix', () => { + const malformedR = signature.r.replace('0x', ''); + const malformedSignature = { + v: signature.v, + r: malformedR, + s: signature.s, + }; + expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address)) + .to.be.rejected; + }); + it('r is too short', () => { + const malformedR = signature.r.substr(10); + const malformedSignature = { + v: signature.v, + r: malformedR, + s: signature.s.replace('0', 'z'), + }; + expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address)) + .to.be.rejected; + }); + it('s is not hex', () => { + const malformedS = signature.s.replace('0', 'z'); + const malformedSignature = { + v: signature.v, + r: signature.r, + s: malformedS, + }; + expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address)) + .to.be.rejected; + }); + }); + it('should return false if the data doesn\'t pertain to the signature & address', async () => { + const isValid = await zeroEx.exchange.isValidSignatureAsync('0x0', signature, address); + expect(isValid).to.be.false; + }); + it('should return false if the address doesn\'t pertain to the signature & dataHex', async () => { + const validUnrelatedAddress = '0x8b0292B11a196601eD2ce54B665CaFEca0347D42'; + const isValid = await zeroEx.exchange.isValidSignatureAsync(dataHex, signature, validUnrelatedAddress); + expect(isValid).to.be.false; + }); + it('should return false if the signature doesn\'t pertain to the dataHex & address', async () => { + const wrongSignature = Object.assign({}, signature, {v: 28}); + const isValid = await zeroEx.exchange.isValidSignatureAsync(dataHex, wrongSignature, address); + expect(isValid).to.be.false; + }); + it('should return true if the signature does pertain to the dataHex & address', async () => { + const isValid = await zeroEx.exchange.isValidSignatureAsync(dataHex, signature, address); + expect(isValid).to.be.true; + }); + }); + describe('#fillOrderAsync', () => { + const fillAmount = new BigNumber(1); + const signedOrder = signedOrderFromJSON(OrderJSON); + it('fillsOrder', async () => { + const orderFillResponse = await zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount); + console.log(orderFillResponse); + }); + }); +}); -- cgit From 8c0d783ccc40d5430a5fdc8253968aa457f717bd Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 14:48:45 +0200 Subject: Add throwErrorLogsAsErrors --- src/contract_wrappers/exchange_wrapper.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 141e9502a..7a80c5800 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -7,6 +7,7 @@ import { OrderValues, OrderAddresses, SignedOrder, + ContractEvent, } from '../types'; import {assert} from '../utils/assert'; import {ContractWrapper} from './contract_wrapper'; @@ -86,16 +87,19 @@ export class ExchangeWrapper extends ContractWrapper { from: senderAddress, }, ); - const errEvent = _.find(response.logs, {event: 'LogError'}); - if (!_.isUndefined(errEvent)) { - const errCode = errEvent.args.errorId.toNumber(); - const humanReadableErrMessage = this.exchangeContractErrToMsg[errCode]; - throw new Error(humanReadableErrMessage); - } + this.throwErrorLogsAsErrors(response.logs); return response; } private async getExchangeInstanceOrThrowAsync(): Promise { const contractInstance = await this.instantiateContractIfExistsAsync((ExchangeArtifacts as any)); return contractInstance as ExchangeContract; } + private throwErrorLogsAsErrors(logs: ContractEvent[]): void { + const errEvent = _.find(logs, {event: 'LogError'}); + if (!_.isUndefined(errEvent)) { + const errCode = errEvent.args.errorId.toNumber(); + const humanReadableErrMessage = this.exchangeContractErrToMsg[errCode]; + throw new Error(humanReadableErrMessage); + } + } } -- cgit From dfcf49464b1a93b6e5df39289e9d14b2e60e62d2 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 14:49:04 +0200 Subject: Temporarily remove test --- test/exchange_wrapper_test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index bb09a0344..b97a62100 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -98,8 +98,7 @@ describe('ExchangeWrapper', () => { const fillAmount = new BigNumber(1); const signedOrder = signedOrderFromJSON(OrderJSON); it('fillsOrder', async () => { - const orderFillResponse = await zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount); - console.log(orderFillResponse); + // const orderFillResponse = await zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount); }); }); }); -- cgit From be4248f3459e120cc2a67d2d8a7238445571056c Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 14:59:24 +0200 Subject: Fix import --- test/utils/order.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/utils/order.ts b/test/utils/order.ts index dc0be670c..690f50ef5 100644 --- a/test/utils/order.ts +++ b/test/utils/order.ts @@ -1,4 +1,4 @@ -import {SignedOrder} from '../../lib/src/types'; +import {SignedOrder} from '../../src/types'; import * as BigNumber from 'bignumber.js'; import * as _ from 'lodash'; -- cgit From 18d6b3b86fbbf9fa85238279bd40fa6a0bd01d25 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 15:57:22 +0200 Subject: replace test fixture with the one from testrpc --- test/fixtures/orders/5_MKR_for_42_MLN.json | 35 ------------------------------ test/fixtures/orders/5_MLN_for_42_GLM.json | 35 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 35 deletions(-) delete mode 100644 test/fixtures/orders/5_MKR_for_42_MLN.json create mode 100644 test/fixtures/orders/5_MLN_for_42_GLM.json diff --git a/test/fixtures/orders/5_MKR_for_42_MLN.json b/test/fixtures/orders/5_MKR_for_42_MLN.json deleted file mode 100644 index 2c2a3d73e..000000000 --- a/test/fixtures/orders/5_MKR_for_42_MLN.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "maker": { - "address": "0xffa119a5761eb93eacfe5d2b0e8944648c3d7164", - "token": { - "name": "MakerDAO", - "symbol": "MKR", - "decimals": 18, - "address": "0x1dad4783cf3fe3085c1426157ab175a6119a04ba" - }, - "amount": "5000000000000000000", - "feeAmount": "0" - }, - "taker": { - "address": "", - "token": { - "name": "Melon Token", - "symbol": "MLN", - "decimals": 18, - "address": "0x323b5d4c32345ced77393b3530b1eed0f346429d" - }, - "amount": "42000000000000000000", - "feeAmount": "0" - }, - "expiration": "1496181600", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "salt": "28894038927316056783595066163529969528517282468995826064292810658599101267743", - "signature": { - "v": 28, - "r": "0x1e84173b09bc51e4e3f923718d747bd91c3584cfa3556d79294891ddd740e819", - "s": "0x36c0f453a01487f49e16157703cacb6cee08d337549f805c25d3f78221823eed", - "hash": "0x3f64711f39393f7f60a0980e3effba087c15bb9b1cbf678ede63a69798e5dc14" - }, - "exchangeContract": "0x9ce1a5e2311f9b8b8e6b40ed20b5b090de4a4c4d", - "networkId": 42 -} \ No newline at end of file diff --git a/test/fixtures/orders/5_MLN_for_42_GLM.json b/test/fixtures/orders/5_MLN_for_42_GLM.json new file mode 100644 index 000000000..36b20a9b3 --- /dev/null +++ b/test/fixtures/orders/5_MLN_for_42_GLM.json @@ -0,0 +1,35 @@ +{ + "maker": { + "address": "0x5409ed021d9299bf6814279a6a1411a7e866a631", + "token": { + "name": "Melon Token", + "symbol": "MLN", + "decimals": 18, + "address": "0x07f96aa816c1f244cbc6ef114bb2b023ba54a2eb" + }, + "amount": "5000000000000000000", + "feeAmount": "0" + }, + "taker": { + "address": "", + "token": { + "name": "Golem Network Token", + "symbol": "GNT", + "decimals": 18, + "address": "0x1e2f9e10d02a6b8f8f69fcbf515e75039d2ea30d" + }, + "amount": "42000000000000000000", + "feeAmount": "0" + }, + "expiration": "2524604400", + "feeRecipient": "0x0000000000000000000000000000000000000000", + "salt": "80413416917564919552159131224076944404960040388740544082559161373345429797193", + "signature": { + "v": 27, + "r": "0xd2b64004d731e04864e28d49d15c42abd2801272219ee61f71e5b7e4e79a7b40", + "s": "0x22fc752de2a2489af154fcb285cb10e373faaf72f7b00aabf481872ca450fb8f", + "hash": "0xc066ae8f00083071f7e53b2737e1462ec5e11f5305b081f06e35a591e49121ee" + }, + "exchangeContract": "0xb69e673309512a9d726f87304c6984054f87a93b", + "networkId": 50 +} \ No newline at end of file -- cgit From a4e5ec6c08596d3d59f07aa237887bf27b198e67 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 15:58:51 +0200 Subject: Add isBigNumber argument assertion --- src/contract_wrappers/exchange_wrapper.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 66e53a7d4..0749a7e80 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -57,6 +57,7 @@ export class ExchangeWrapper extends ContractWrapper { public async fillOrderAsync(signedOrder: SignedOrder, fillAmount: BigNumber.BigNumber, shouldCheckTransfer: boolean = true): Promise { assert.doesConformToSchema('signedOrder', JSON.parse(JSON.stringify(signedOrder)), signedOrderSchema); + assert.isBigNumber('fillAmount', fillAmount); assert.isBoolean('shouldCheckTransfer', shouldCheckTransfer); const senderAddress = await this.web3Wrapper.getSenderAddressOrThrowAsync(); -- cgit From 90caa189ccdf4f17f3c60d0872bb6efd9ab646f1 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 16:19:35 +0200 Subject: Add first passing test --- test/exchange_wrapper_test.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index b97a62100..e00edefbe 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -4,7 +4,7 @@ import chaiAsPromised = require('chai-as-promised'); import {web3Factory} from './utils/web3_factory'; import {ZeroEx} from '../src/0x.js'; import {BlockchainLifecycle} from './utils/blockchain_lifecycle'; -import * as OrderJSON from './fixtures/orders/5_MKR_for_42_MLN.json'; +import * as OrderJSON from './fixtures/orders/5_MLN_for_42_GLM.json'; import * as BigNumber from 'bignumber.js'; import {signedOrderFromJSON} from './utils/order'; @@ -95,10 +95,11 @@ describe('ExchangeWrapper', () => { }); }); describe('#fillOrderAsync', () => { - const fillAmount = new BigNumber(1); const signedOrder = signedOrderFromJSON(OrderJSON); - it('fillsOrder', async () => { - // const orderFillResponse = await zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount); + it('should throw when the fill amount is zero', async () => { + const fillAmount = new BigNumber(0); + expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount)) + .to.be.rejectedWith('This order has already been filled or cancelled'); }); }); }); -- cgit From 68f39765aaac456f89c636e2dff0fc576ac0eb1e Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 17:05:29 +0200 Subject: Remove fixture --- test/fixtures/orders/5_MLN_for_42_GLM.json | 35 ------------------------------ 1 file changed, 35 deletions(-) delete mode 100644 test/fixtures/orders/5_MLN_for_42_GLM.json diff --git a/test/fixtures/orders/5_MLN_for_42_GLM.json b/test/fixtures/orders/5_MLN_for_42_GLM.json deleted file mode 100644 index 36b20a9b3..000000000 --- a/test/fixtures/orders/5_MLN_for_42_GLM.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "maker": { - "address": "0x5409ed021d9299bf6814279a6a1411a7e866a631", - "token": { - "name": "Melon Token", - "symbol": "MLN", - "decimals": 18, - "address": "0x07f96aa816c1f244cbc6ef114bb2b023ba54a2eb" - }, - "amount": "5000000000000000000", - "feeAmount": "0" - }, - "taker": { - "address": "", - "token": { - "name": "Golem Network Token", - "symbol": "GNT", - "decimals": 18, - "address": "0x1e2f9e10d02a6b8f8f69fcbf515e75039d2ea30d" - }, - "amount": "42000000000000000000", - "feeAmount": "0" - }, - "expiration": "2524604400", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "salt": "80413416917564919552159131224076944404960040388740544082559161373345429797193", - "signature": { - "v": 27, - "r": "0xd2b64004d731e04864e28d49d15c42abd2801272219ee61f71e5b7e4e79a7b40", - "s": "0x22fc752de2a2489af154fcb285cb10e373faaf72f7b00aabf481872ca450fb8f", - "hash": "0xc066ae8f00083071f7e53b2737e1462ec5e11f5305b081f06e35a591e49121ee" - }, - "exchangeContract": "0xb69e673309512a9d726f87304c6984054f87a93b", - "networkId": 50 -} \ No newline at end of file -- cgit From 843ec2d4cf4bbc9061ba6dc5a09fc6d694c3083a Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 17:06:38 +0200 Subject: Remove spaces in types --- src/types.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/types.ts b/src/types.ts index 2ada20e3c..dc2a4d848 100644 --- a/src/types.ts +++ b/src/types.ts @@ -81,16 +81,12 @@ export interface ContractEvent { export interface Order { maker: string; taker?: string; - makerFee: BigNumber.BigNumber; takerFee: BigNumber.BigNumber; - makerTokenAmount: BigNumber.BigNumber; takerTokenAmount: BigNumber.BigNumber; - makerTokenAddress: string; takerTokenAddress: string; - salt: BigNumber.BigNumber; feeRecipient: string; expirationUnixTimestampSec: BigNumber.BigNumber; -- cgit From be13cf127c00c762d03c5eaf17a11c2775701530 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 30 May 2017 17:35:17 +0200 Subject: Refactor getOrderHash to accept order as an object --- package.json | 5 ++--- src/0x.js.ts | 45 +++++++++++++++-------------------------- test/0x.js_test.ts | 47 +++++++++++++++++-------------------------- test/exchange_wrapper_test.ts | 7 +++---- test/utils/order.ts | 35 +++++++++++++++++++------------- 5 files changed, 61 insertions(+), 78 deletions(-) diff --git a/package.json b/package.json index c232e2828..59e33a7dd 100644 --- a/package.json +++ b/package.json @@ -27,12 +27,11 @@ "build:umd:dev": "webpack", "build:umd:prod": "webpack -p", "build:commonjs:dev": "tsc; copyfiles -u 2 ./src/artifacts/*.json ../0x.js/lib/src/artifacts;", - "test:commonjs": "run-s build:commonjs:dev copy_fixtures run_mocha", + "test:commonjs": "run-s build:commonjs:dev run_mocha", "pretest:umd": "run-s clean build:*:dev", "substitute_umd_bundle": "npm run remove_src_files_not_used_by_tests; shx mv _bundles/* lib/src", "remove_src_files_not_used_by_tests": "find ./lib/src \\( -path ./lib/src/utils -o -path ./lib/src/schemas -o -path \"./lib/src/types.*\" \\) -prune -o -type f -print | xargs rm", - "run_mocha": "mocha lib/test/**/*_test.js", - "copy_fixtures": "shx cp -r ./test/fixtures ./lib/test/fixtures" + "run_mocha": "mocha lib/test/**/*_test.js" }, "config": { "artifacts": "Proxy Exchange TokenRegistry Token Mintable EtherToken", diff --git a/src/0x.js.ts b/src/0x.js.ts index 69c0cc567..47b6679eb 100644 --- a/src/0x.js.ts +++ b/src/0x.js.ts @@ -14,6 +14,8 @@ import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper'; import {TokenRegistryWrapper} from './contract_wrappers/token_registry_wrapper'; import {ecSignatureSchema} from './schemas/ec_signature_schema'; import {SolidityTypes, ECSignature, ZeroExError} from './types'; +import {Order} from './types'; +import {orderSchema} from "./schemas/signed_order_schema"; const MAX_DIGITS_IN_UNSIGNED_256_INT = 78; @@ -24,38 +26,23 @@ export class ZeroEx { /** * Computes the orderHash given the order parameters and returns it as a hex encoded string. */ - public static getOrderHashHex(exchangeContractAddr: string, makerAddr: string, takerAddr: string, - tokenMAddress: string, tokenTAddress: string, feeRecipient: string, - valueM: BigNumber.BigNumber, valueT: BigNumber.BigNumber, - makerFee: BigNumber.BigNumber, takerFee: BigNumber.BigNumber, - expiration: BigNumber.BigNumber, salt: BigNumber.BigNumber): string { - takerAddr = _.isEmpty(takerAddr) ? constants.NULL_ADDRESS : takerAddr ; - assert.isETHAddressHex('exchangeContractAddr', exchangeContractAddr); - assert.isETHAddressHex('makerAddr', makerAddr); - assert.isETHAddressHex('takerAddr', takerAddr); - assert.isETHAddressHex('tokenMAddress', tokenMAddress); - assert.isETHAddressHex('tokenTAddress', tokenTAddress); - assert.isETHAddressHex('feeRecipient', feeRecipient); - assert.isBigNumber('valueM', valueM); - assert.isBigNumber('valueT', valueT); - assert.isBigNumber('makerFee', makerFee); - assert.isBigNumber('takerFee', takerFee); - assert.isBigNumber('expiration', expiration); - assert.isBigNumber('salt', salt); + public static getOrderHashHex(exchangeContractAddr: string, order: Order): string { + assert.doesConformToSchema('order', JSON.parse(JSON.stringify(order)), orderSchema); + const taker = _.isEmpty(order.taker) ? constants.NULL_ADDRESS : order.taker ; const orderParts = [ {value: exchangeContractAddr, type: SolidityTypes.address}, - {value: makerAddr, type: SolidityTypes.address}, - {value: takerAddr, type: SolidityTypes.address}, - {value: tokenMAddress, type: SolidityTypes.address}, - {value: tokenTAddress, type: SolidityTypes.address}, - {value: feeRecipient, type: SolidityTypes.address}, - {value: utils.bigNumberToBN(valueM), type: SolidityTypes.uint256}, - {value: utils.bigNumberToBN(valueT), type: SolidityTypes.uint256}, - {value: utils.bigNumberToBN(makerFee), type: SolidityTypes.uint256}, - {value: utils.bigNumberToBN(takerFee), type: SolidityTypes.uint256}, - {value: utils.bigNumberToBN(expiration), type: SolidityTypes.uint256}, - {value: utils.bigNumberToBN(salt), type: SolidityTypes.uint256}, + {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); diff --git a/test/0x.js_test.ts b/test/0x.js_test.ts index 5d23d7094..a84785f4b 100644 --- a/test/0x.js_test.ts +++ b/test/0x.js_test.ts @@ -7,6 +7,7 @@ import * as Sinon from 'sinon'; import {ZeroEx} from '../src/0x.js'; import {constants} from './utils/constants'; import {web3Factory} from './utils/web3_factory'; +import {Order} from '../src/types'; // Use BigNumber chai add-on chai.use(ChaiBigNumber()); @@ -43,38 +44,28 @@ describe('ZeroEx library', () => { }); describe('#getOrderHash', () => { const expectedOrderHash = '0x103a5e97dab5dbeb8f385636f86a7d1e458a7ccbe1bd194727f0b2f85ab116c7'; + const order: Order = { + maker: constants.NULL_ADDRESS, + feeRecipient: constants.NULL_ADDRESS, + makerTokenAddress: constants.NULL_ADDRESS, + takerTokenAddress: constants.NULL_ADDRESS, + salt: new BigNumber(0), + makerFee: new BigNumber(0), + takerFee: new BigNumber(0), + makerTokenAmount: new BigNumber(0), + takerTokenAmount: new BigNumber(0), + expirationUnixTimestampSec: new BigNumber(0), + }; + const exchangeAddress = constants.NULL_ADDRESS; it('defaults takerAddress to NULL address', () => { - const orderHash = ZeroEx.getOrderHashHex( - constants.NULL_ADDRESS, - constants.NULL_ADDRESS, - '', - constants.NULL_ADDRESS, - constants.NULL_ADDRESS, - constants.NULL_ADDRESS, - new BigNumber(0), - new BigNumber(0), - new BigNumber(0), - new BigNumber(0), - new BigNumber(0), - new BigNumber(0), - ); + const orderHash = ZeroEx.getOrderHashHex(exchangeAddress, order); expect(orderHash).to.be.equal(expectedOrderHash); }); it('calculates the order hash', () => { - const orderHash = ZeroEx.getOrderHashHex( - constants.NULL_ADDRESS, - constants.NULL_ADDRESS, - constants.NULL_ADDRESS, - constants.NULL_ADDRESS, - constants.NULL_ADDRESS, - constants.NULL_ADDRESS, - new BigNumber(0), - new BigNumber(0), - new BigNumber(0), - new BigNumber(0), - new BigNumber(0), - new BigNumber(0), - ); + const orderWithZeroTaker = _.assign(order, { + taker: constants.NULL_ADDRESS, + }); + const orderHash = ZeroEx.getOrderHashHex(exchangeAddress, orderWithZeroTaker); expect(orderHash).to.be.equal(expectedOrderHash); }); }); diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index e00edefbe..355a5d01b 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -4,9 +4,8 @@ import chaiAsPromised = require('chai-as-promised'); import {web3Factory} from './utils/web3_factory'; import {ZeroEx} from '../src/0x.js'; import {BlockchainLifecycle} from './utils/blockchain_lifecycle'; -import * as OrderJSON from './fixtures/orders/5_MLN_for_42_GLM.json'; import * as BigNumber from 'bignumber.js'; -import {signedOrderFromJSON} from './utils/order'; +import {createSignedOrder} from './utils/order'; const expect = chai.expect; chai.use(chaiAsPromised); @@ -94,8 +93,8 @@ describe('ExchangeWrapper', () => { expect(isValid).to.be.true; }); }); - describe('#fillOrderAsync', () => { - const signedOrder = signedOrderFromJSON(OrderJSON); + describe('#fillOrderAsync', async () => { + const signedOrder = await createSignedOrder(zeroEx); it('should throw when the fill amount is zero', async () => { const fillAmount = new BigNumber(0); expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount)) diff --git a/test/utils/order.ts b/test/utils/order.ts index 690f50ef5..a69c1b62f 100644 --- a/test/utils/order.ts +++ b/test/utils/order.ts @@ -1,21 +1,28 @@ import {SignedOrder} from '../../src/types'; import * as BigNumber from 'bignumber.js'; import * as _ from 'lodash'; +import {ZeroEx} from '../../src/0x.js'; +import {constants} from './constants'; -export function signedOrderFromJSON(signedOrderJSON: any): SignedOrder { - const signedOrder = { - maker: signedOrderJSON.maker.address, - taker: _.isEmpty(signedOrderJSON.taker.address) ? undefined : signedOrderJSON.taker.address, - makerTokenAddress: signedOrderJSON.maker.token.address, - takerTokenAddress: signedOrderJSON.taker.token.address, - makerTokenAmount: new BigNumber(signedOrderJSON.maker.amount), - takerTokenAmount: new BigNumber(signedOrderJSON.taker.amount), - makerFee: new BigNumber(signedOrderJSON.maker.feeAmount), - takerFee: new BigNumber(signedOrderJSON.taker.feeAmount), - expirationUnixTimestampSec: new BigNumber(signedOrderJSON.expiration), - feeRecipient: signedOrderJSON.feeRecipient, - ecSignature: signedOrderJSON.signature, - salt: new BigNumber(signedOrderJSON.salt), +export async function createSignedOrder(zeroEx: ZeroEx): Promise { + // TODO: fetch properly + const EXCHANGE_ADDRESS = '0xb69e673309512a9d726f87304c6984054f87a93b'; + const INF_TIMESTAMP = 2524604400; + const order = { + maker: '0x5409ed021d9299bf6814279a6a1411a7e866a631', + taker: undefined, + makerFee: new BigNumber(0), + takerFee: new BigNumber(0), + makerTokenAmount: new BigNumber(5000000000000000000), + takerTokenAmount: new BigNumber(42000000000000000000), + makerTokenAddress: '0x07f96aa816c1f244cbc6ef114bb2b023ba54a2eb', + takerTokenAddress: '0x1e2f9e10d02a6b8f8f69fcbf515e75039d2ea30d', + salt: ZeroEx.generatePseudoRandomSalt(), + feeRecipient: constants.NULL_ADDRESS, + expirationUnixTimestampSec: new BigNumber(INF_TIMESTAMP), }; + const orderHash = ZeroEx.getOrderHashHex(EXCHANGE_ADDRESS, order); + const ecSignature = await zeroEx.signOrderHashAsync(orderHash); + const signedOrder: SignedOrder = _.assign(order, {ecSignature}); return signedOrder; } -- cgit From 72ca9a57de76b4514de2a07a675eadfa4e251b2c Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 31 May 2017 14:12:14 +0200 Subject: Fix linter command --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 59e33a7dd..541dc44e6 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "scripts": { "prebuild": "npm run clean", "build": "run-p build:*:prod", - "lint": "tslint src/**/*.ts test/**/*.ts", + "lint": "tslint src/*.ts test/*.ts", "test": "run-s clean test:commonjs", "test:umd": "run-s substitute_umd_bundle run_mocha; npm run clean", "test:coverage": "nyc npm run test --all", -- cgit From 76a1319387028c3389f10fdb7079aca1d19190ad Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 31 May 2017 14:12:36 +0200 Subject: Set bignumber config --- src/0x.js.ts | 2 ++ src/bignumber_config.ts | 9 +++++++++ 2 files changed, 11 insertions(+) create mode 100644 src/bignumber_config.ts diff --git a/src/0x.js.ts b/src/0x.js.ts index 97eb4d126..63a540ad4 100644 --- a/src/0x.js.ts +++ b/src/0x.js.ts @@ -1,5 +1,7 @@ import * as _ from 'lodash'; import * as BigNumber from 'bignumber.js'; +import {setBigNumberConfig} from './bignumber_config'; +setBigNumberConfig(); import * as ethUtil from 'ethereumjs-util'; import contract = require('truffle-contract'); import * as Web3 from 'web3'; diff --git a/src/bignumber_config.ts b/src/bignumber_config.ts new file mode 100644 index 000000000..9641159d0 --- /dev/null +++ b/src/bignumber_config.ts @@ -0,0 +1,9 @@ +import * as BigNumber from 'bignumber.js'; + +export function setBigNumberConfig() { + // By default BigNumber's `toString` method converts to exponential notation if the value has + // more then 20 digits. We want to avoid this behavior, so we set EXPONENTIAL_AT to a high number + BigNumber.config({ + EXPONENTIAL_AT: 1000, + }); +} -- cgit From 722a6ad5dce484ef5875132fd57970390c69e85d Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 31 May 2017 15:56:52 +0200 Subject: Don't return contract response --- src/contract_wrappers/exchange_wrapper.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 0749a7e80..3f6210894 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -55,7 +55,7 @@ export class ExchangeWrapper extends ContractWrapper { return isValidSignature; } public async fillOrderAsync(signedOrder: SignedOrder, fillAmount: BigNumber.BigNumber, - shouldCheckTransfer: boolean = true): Promise { + shouldCheckTransfer: boolean = true): Promise { assert.doesConformToSchema('signedOrder', JSON.parse(JSON.stringify(signedOrder)), signedOrderSchema); assert.isBigNumber('fillAmount', fillAmount); assert.isBoolean('shouldCheckTransfer', shouldCheckTransfer); @@ -93,7 +93,6 @@ export class ExchangeWrapper extends ContractWrapper { }, ); this.throwErrorLogsAsErrors(response.logs); - return response; } private async getExchangeInstanceOrThrowAsync(): Promise { const contractInstance = await this.instantiateContractIfExistsAsync((ExchangeArtifacts as any)); -- cgit From 7f269cd791e4f0ed1515e90478de6b35683ce2bf Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 31 May 2017 16:03:06 +0200 Subject: Add createSignedOrder function --- test/utils/order.ts | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/test/utils/order.ts b/test/utils/order.ts index a69c1b62f..2de87bac1 100644 --- a/test/utils/order.ts +++ b/test/utils/order.ts @@ -1,28 +1,45 @@ -import {SignedOrder} from '../../src/types'; +import {SignedOrder, Token} from '../../src/types'; import * as BigNumber from 'bignumber.js'; import * as _ from 'lodash'; import {ZeroEx} from '../../src/0x.js'; import {constants} from './constants'; -export async function createSignedOrder(zeroEx: ZeroEx): Promise { +export async function createSignedOrder( + zeroEx: ZeroEx, + tokens: Token[], + makerTokenAmount: BigNumber.BigNumber|number, + makerTokenSymbol: string, + takerTokenAmount: BigNumber.BigNumber|number, + takerTokenSymbol: string): Promise { // TODO: fetch properly const EXCHANGE_ADDRESS = '0xb69e673309512a9d726f87304c6984054f87a93b'; const INF_TIMESTAMP = 2524604400; + const makerToken = _.find(tokens, {symbol: makerTokenSymbol}); + const takerToken = _.find(tokens, {symbol: takerTokenSymbol}); + if (_.isUndefined(makerToken)) { + throw new Error(`Token ${makerTokenSymbol} not found`); + } + if (_.isUndefined(takerToken)) { + throw new Error(`Token ${takerTokenSymbol} not found`); + } const order = { maker: '0x5409ed021d9299bf6814279a6a1411a7e866a631', taker: undefined, makerFee: new BigNumber(0), takerFee: new BigNumber(0), - makerTokenAmount: new BigNumber(5000000000000000000), - takerTokenAmount: new BigNumber(42000000000000000000), - makerTokenAddress: '0x07f96aa816c1f244cbc6ef114bb2b023ba54a2eb', - takerTokenAddress: '0x1e2f9e10d02a6b8f8f69fcbf515e75039d2ea30d', + makerTokenAmount: _.isNumber(makerTokenAmount) ? new BigNumber(makerTokenAmount) : makerTokenAmount, + takerTokenAmount: _.isNumber(takerTokenAmount) ? new BigNumber(takerTokenAmount) : takerTokenAmount, + makerTokenAddress: makerToken.address, + takerTokenAddress: takerToken.address, salt: ZeroEx.generatePseudoRandomSalt(), feeRecipient: constants.NULL_ADDRESS, expirationUnixTimestampSec: new BigNumber(INF_TIMESTAMP), }; + console.log(order.makerTokenAmount.toString()); + console.log(order.takerTokenAmount.toString()); const orderHash = ZeroEx.getOrderHashHex(EXCHANGE_ADDRESS, order); const ecSignature = await zeroEx.signOrderHashAsync(orderHash); const signedOrder: SignedOrder = _.assign(order, {ecSignature}); + console.log(signedOrder); return signedOrder; } -- cgit From 84c652d205af0fd289149762661536895eaaafef Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 31 May 2017 16:03:16 +0200 Subject: Revert tests --- test/exchange_wrapper_test.ts | 50 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index ede4198d8..ad82e6e82 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -2,18 +2,25 @@ import 'mocha'; import * as chai from 'chai'; import {web3Factory} from './utils/web3_factory'; import {ZeroEx} from '../src/0x.js'; +import promisify = require('es6-promisify'); +import * as _ from 'lodash'; import {BlockchainLifecycle} from './utils/blockchain_lifecycle'; import * as BigNumber from 'bignumber.js'; import {createSignedOrder} from './utils/order'; +import {Token} from '../src/types'; +import * as Web3 from 'web3'; const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(); describe('ExchangeWrapper', () => { let zeroEx: ZeroEx; + let userAddresses: string[]; + let web3: Web3; before(async () => { - const web3 = web3Factory.create(); + web3 = web3Factory.create(); zeroEx = new ZeroEx(web3); + userAddresses = await promisify(web3.eth.getAccounts)(); }); beforeEach(async () => { await blockchainLifecycle.startAsync(); @@ -91,12 +98,41 @@ describe('ExchangeWrapper', () => { expect(isValid).to.be.true; }); }); - describe('#fillOrderAsync', async () => { - const signedOrder = await createSignedOrder(zeroEx); - it('should throw when the fill amount is zero', async () => { - const fillAmount = new BigNumber(0); - expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount)) - .to.be.rejectedWith('This order has already been filled or cancelled'); + describe('#fillOrderAsync', () => { + let tokens: Token[]; + const giveMeTokens = async (toAddress: string, + amountInBaseUnits: BigNumber.BigNumber|number, + symbol: string) => { + const amount = _.isNumber(amountInBaseUnits) ? new BigNumber(amountInBaseUnits) : amountInBaseUnits; + const token = _.find(tokens, {symbol}); + if (_.isUndefined(token)) { + throw new Error(`Token ${symbol} not found`); + } else { + await zeroEx.token.transferAsync(token.address, userAddresses[0], toAddress, amount); + } + }; + before('fetch tokens', async () => { + tokens = await zeroEx.tokenRegistry.getTokensAsync(); + }); + describe('failed fills', () => { + it('should throw when the fill amount is zero', async () => { + const signedOrder = await createSignedOrder(zeroEx, tokens, 5, 'MLN', 5, 'GNT'); + const fillAmount = new BigNumber(0); + expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount)) + .to.be.rejectedWith('This order has already been filled or cancelled'); + }); + }); + describe('successful fills', () => { + afterEach('reset default account', () => { + web3.eth.defaultAccount = userAddresses[0]; + }); + it('should fill the valid order', async () => { + const signedOrder = await createSignedOrder(zeroEx, tokens, 5, 'MLN', 5, 'GNT'); + await giveMeTokens(userAddresses[0], 5, 'GNT'); + const fillAmount = new BigNumber(0); + web3.eth.defaultAccount = userAddresses[1]; + expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount)).to.become(undefined); + }); }); }); }); -- cgit From 7d29fb217445497d81ef62d0feb821c8e16ca88a Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 31 May 2017 16:06:14 +0200 Subject: Remove debug output --- test/utils/order.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/utils/order.ts b/test/utils/order.ts index 2de87bac1..d775dc616 100644 --- a/test/utils/order.ts +++ b/test/utils/order.ts @@ -35,11 +35,8 @@ export async function createSignedOrder( feeRecipient: constants.NULL_ADDRESS, expirationUnixTimestampSec: new BigNumber(INF_TIMESTAMP), }; - console.log(order.makerTokenAmount.toString()); - console.log(order.takerTokenAmount.toString()); const orderHash = ZeroEx.getOrderHashHex(EXCHANGE_ADDRESS, order); const ecSignature = await zeroEx.signOrderHashAsync(orderHash); const signedOrder: SignedOrder = _.assign(order, {ecSignature}); - console.log(signedOrder); return signedOrder; } -- cgit From 1955e90bbbfeb7d2aeebfd84132f684d20e17400 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 31 May 2017 16:15:16 +0200 Subject: Fix linter errors --- src/0x.js.ts | 2 +- src/types.ts | 2 +- src/web3_wrapper.ts | 4 ++-- test/exchange_wrapper_test.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/0x.js.ts b/src/0x.js.ts index 63a540ad4..25b4af777 100644 --- a/src/0x.js.ts +++ b/src/0x.js.ts @@ -18,7 +18,7 @@ import {ecSignatureSchema} from './schemas/ec_signature_schema'; import {TokenWrapper} from './contract_wrappers/token_wrapper'; import {SolidityTypes, ECSignature, ZeroExError} from './types'; import {Order} from './types'; -import {orderSchema} from "./schemas/signed_order_schema"; +import {orderSchema} from './schemas/signed_order_schema'; const MAX_DIGITS_IN_UNSIGNED_256_INT = 78; diff --git a/src/types.ts b/src/types.ts index 861df3187..b70afe298 100644 --- a/src/types.ts +++ b/src/types.ts @@ -83,7 +83,7 @@ export enum ExchangeContractErrs { ERROR_FILL_BALANCE_ALLOWANCE, // Insufficient balance or allowance for token transfer ERROR_CANCEL_EXPIRED, // Order has already expired ERROR_CANCEL_NO_VALUE, // Order has already been fully filled or cancelled -}; +} export interface ContractResponse { logs: ContractEvent[]; diff --git a/src/web3_wrapper.ts b/src/web3_wrapper.ts index 361f28476..79fd166ec 100644 --- a/src/web3_wrapper.ts +++ b/src/web3_wrapper.ts @@ -2,8 +2,8 @@ import * as _ from 'lodash'; import * as Web3 from 'web3'; import * as BigNumber from 'bignumber.js'; import promisify = require('es6-promisify'); -import {ZeroExError} from "./types"; -import {assert} from "./utils/assert"; +import {ZeroExError} from './types'; +import {assert} from './utils/assert'; export class Web3Wrapper { private web3: Web3; diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index ad82e6e82..24383906f 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -89,7 +89,7 @@ describe('ExchangeWrapper', () => { expect(isValid).to.be.false; }); it('should return false if the signature doesn\'t pertain to the dataHex & address', async () => { - const wrongSignature = Object.assign({}, signature, {v: 28}); + const wrongSignature = {...signature, v: 28}; const isValid = await zeroEx.exchange.isValidSignatureAsync(dataHex, wrongSignature, address); expect(isValid).to.be.false; }); -- cgit From 82a46b4938902009896bef1d296b887f66b284fd Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 31 May 2017 17:45:15 +0200 Subject: Add setAllowance function --- test/exchange_wrapper_test.ts | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 24383906f..5138e140f 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -21,6 +21,7 @@ describe('ExchangeWrapper', () => { web3 = web3Factory.create(); zeroEx = new ZeroEx(web3); userAddresses = await promisify(web3.eth.getAccounts)(); + web3.eth.defaultAccount = userAddresses[0]; }); beforeEach(async () => { await blockchainLifecycle.startAsync(); @@ -100,7 +101,7 @@ describe('ExchangeWrapper', () => { }); describe('#fillOrderAsync', () => { let tokens: Token[]; - const giveMeTokens = async (toAddress: string, + const setBalance = async (toAddress: string, amountInBaseUnits: BigNumber.BigNumber|number, symbol: string) => { const amount = _.isNumber(amountInBaseUnits) ? new BigNumber(amountInBaseUnits) : amountInBaseUnits; @@ -111,6 +112,17 @@ describe('ExchangeWrapper', () => { await zeroEx.token.transferAsync(token.address, userAddresses[0], toAddress, amount); } }; + const setAllowance = async (ownerAddress: string, + amountInBaseUnits: BigNumber.BigNumber|number, + symbol: string) => { + const amount = _.isNumber(amountInBaseUnits) ? new BigNumber(amountInBaseUnits) : amountInBaseUnits; + const token = _.find(tokens, {symbol}); + if (_.isUndefined(token)) { + throw new Error(`Token ${symbol} not found`); + } else { + await zeroEx.token.setProxyAllowanceAsync(token.address, ownerAddress, amount); + } + }; before('fetch tokens', async () => { tokens = await zeroEx.tokenRegistry.getTokensAsync(); }); @@ -127,11 +139,13 @@ describe('ExchangeWrapper', () => { web3.eth.defaultAccount = userAddresses[0]; }); it('should fill the valid order', async () => { + await setAllowance(userAddresses[0], 5, 'MLN'); + await setBalance(userAddresses[1], 5, 'GNT'); + await setAllowance(userAddresses[1], 5, 'GNT'); const signedOrder = await createSignedOrder(zeroEx, tokens, 5, 'MLN', 5, 'GNT'); - await giveMeTokens(userAddresses[0], 5, 'GNT'); - const fillAmount = new BigNumber(0); + const fillAmount = new BigNumber(5); web3.eth.defaultAccount = userAddresses[1]; - expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount)).to.become(undefined); + await zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount); }); }); }); -- cgit From 28dee77db84549db24b95d9aaaca949a2fdec29c Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 31 May 2017 21:15:15 +0200 Subject: Temp push --- test/exchange_wrapper_test.ts | 49 +++++++++++++++++++-------------- test/utils/order.ts | 64 ++++++++++++++++++++----------------------- 2 files changed, 58 insertions(+), 55 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 5138e140f..a5a327dc4 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -6,7 +6,7 @@ import promisify = require('es6-promisify'); import * as _ from 'lodash'; import {BlockchainLifecycle} from './utils/blockchain_lifecycle'; import * as BigNumber from 'bignumber.js'; -import {createSignedOrder} from './utils/order'; +import {orderFactory} from './utils/order'; import {Token} from '../src/types'; import * as Web3 from 'web3'; @@ -101,34 +101,31 @@ describe('ExchangeWrapper', () => { }); describe('#fillOrderAsync', () => { let tokens: Token[]; + let addressBySymbol: {[symbol: string]: string} = {}; + let networkId: number; const setBalance = async (toAddress: string, amountInBaseUnits: BigNumber.BigNumber|number, - symbol: string) => { + tokenAddress: string) => { const amount = _.isNumber(amountInBaseUnits) ? new BigNumber(amountInBaseUnits) : amountInBaseUnits; - const token = _.find(tokens, {symbol}); - if (_.isUndefined(token)) { - throw new Error(`Token ${symbol} not found`); - } else { - await zeroEx.token.transferAsync(token.address, userAddresses[0], toAddress, amount); - } + await zeroEx.token.transferAsync(tokenAddress, userAddresses[0], toAddress, amount); }; const setAllowance = async (ownerAddress: string, amountInBaseUnits: BigNumber.BigNumber|number, - symbol: string) => { + tokenAddress: string) => { const amount = _.isNumber(amountInBaseUnits) ? new BigNumber(amountInBaseUnits) : amountInBaseUnits; - const token = _.find(tokens, {symbol}); - if (_.isUndefined(token)) { - throw new Error(`Token ${symbol} not found`); - } else { - await zeroEx.token.setProxyAllowanceAsync(token.address, ownerAddress, amount); - } + await zeroEx.token.setProxyAllowanceAsync(tokenAddress, ownerAddress, amount); }; before('fetch tokens', async () => { tokens = await zeroEx.tokenRegistry.getTokensAsync(); + _.forEach(tokens, token => { + addressBySymbol[token.symbol] = token.address; + }); + networkId = await promisify(web3.version.getNetwork)(); }); describe('failed fills', () => { it('should throw when the fill amount is zero', async () => { - const signedOrder = await createSignedOrder(zeroEx, tokens, 5, 'MLN', 5, 'GNT'); + const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, userAddresses[0], + 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); const fillAmount = new BigNumber(0); expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount)) .to.be.rejectedWith('This order has already been filled or cancelled'); @@ -139,13 +136,23 @@ describe('ExchangeWrapper', () => { web3.eth.defaultAccount = userAddresses[0]; }); it('should fill the valid order', async () => { - await setAllowance(userAddresses[0], 5, 'MLN'); - await setBalance(userAddresses[1], 5, 'GNT'); - await setAllowance(userAddresses[1], 5, 'GNT'); - const signedOrder = await createSignedOrder(zeroEx, tokens, 5, 'MLN', 5, 'GNT'); + const maker = userAddresses[0]; + const taker = userAddresses[1]; + await setAllowance(maker, 5, addressBySymbol.MLN); + await setBalance(taker, 5, addressBySymbol.GNT); + await setAllowance(taker, 5, addressBySymbol.GNT); + const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, + 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); const fillAmount = new BigNumber(5); - web3.eth.defaultAccount = userAddresses[1]; + web3.eth.defaultAccount = taker; + expect(await zeroEx.token.getBalanceAsync(addressBySymbol.MLN, maker)).to.be.bignumber.greaterThan(5); + expect(await zeroEx.token.getBalanceAsync(addressBySymbol.MLN, taker)).to.be.bignumber.equal(0); + expect(await zeroEx.token.getBalanceAsync(addressBySymbol.GNT, taker)).to.be.bignumber.equal(5); + expect(await zeroEx.token.getProxyAllowanceAsync(addressBySymbol.MLN, maker)).to.be.bignumber.equal(5); + expect(await zeroEx.token.getProxyAllowanceAsync(addressBySymbol.GNT, taker)).to.be.bignumber.equal(5); await zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount); + expect(await zeroEx.token.getBalanceAsync(addressBySymbol.MLN, taker)).to.be.bignumber.equal(5); + expect(await zeroEx.token.getBalanceAsync(addressBySymbol.GNT, taker)).to.be.bignumber.equal(0); }); }); }); diff --git a/test/utils/order.ts b/test/utils/order.ts index d775dc616..8a7d8430e 100644 --- a/test/utils/order.ts +++ b/test/utils/order.ts @@ -3,40 +3,36 @@ import * as BigNumber from 'bignumber.js'; import * as _ from 'lodash'; import {ZeroEx} from '../../src/0x.js'; import {constants} from './constants'; +import * as ExchangeArtifacts from '../../src/artifacts/Exchange.json'; -export async function createSignedOrder( - zeroEx: ZeroEx, - tokens: Token[], - makerTokenAmount: BigNumber.BigNumber|number, - makerTokenSymbol: string, - takerTokenAmount: BigNumber.BigNumber|number, - takerTokenSymbol: string): Promise { - // TODO: fetch properly - const EXCHANGE_ADDRESS = '0xb69e673309512a9d726f87304c6984054f87a93b'; - const INF_TIMESTAMP = 2524604400; - const makerToken = _.find(tokens, {symbol: makerTokenSymbol}); - const takerToken = _.find(tokens, {symbol: takerTokenSymbol}); - if (_.isUndefined(makerToken)) { - throw new Error(`Token ${makerTokenSymbol} not found`); +export const orderFactory = { + async createSignedOrderAsync( + zeroEx: ZeroEx, + networkId: number, + maker: string, + makerTokenAmount: BigNumber.BigNumber|number, + makerTokenAddress: string, + takerTokenAmount: BigNumber.BigNumber|number, + takerTokenAddress: string): Promise { + // TODO refactor and check + const exchangeAddress: string = (ExchangeArtifacts as any).networks[networkId].address; + const INF_TIMESTAMP = 2524604400; + const order = { + maker, + taker: undefined, + makerFee: new BigNumber(0), + takerFee: new BigNumber(0), + makerTokenAmount: _.isNumber(makerTokenAmount) ? new BigNumber(makerTokenAmount) : makerTokenAmount, + takerTokenAmount: _.isNumber(takerTokenAmount) ? new BigNumber(takerTokenAmount) : takerTokenAmount, + makerTokenAddress, + takerTokenAddress, + salt: ZeroEx.generatePseudoRandomSalt(), + feeRecipient: constants.NULL_ADDRESS, + expirationUnixTimestampSec: new BigNumber(INF_TIMESTAMP), + }; + const orderHash = ZeroEx.getOrderHashHex(exchangeAddress, order); + const ecSignature = await zeroEx.signOrderHashAsync(orderHash); + const signedOrder: SignedOrder = _.assign(order, {ecSignature}); + return signedOrder; } - if (_.isUndefined(takerToken)) { - throw new Error(`Token ${takerTokenSymbol} not found`); - } - const order = { - maker: '0x5409ed021d9299bf6814279a6a1411a7e866a631', - taker: undefined, - makerFee: new BigNumber(0), - takerFee: new BigNumber(0), - makerTokenAmount: _.isNumber(makerTokenAmount) ? new BigNumber(makerTokenAmount) : makerTokenAmount, - takerTokenAmount: _.isNumber(takerTokenAmount) ? new BigNumber(takerTokenAmount) : takerTokenAmount, - makerTokenAddress: makerToken.address, - takerTokenAddress: takerToken.address, - salt: ZeroEx.generatePseudoRandomSalt(), - feeRecipient: constants.NULL_ADDRESS, - expirationUnixTimestampSec: new BigNumber(INF_TIMESTAMP), - }; - const orderHash = ZeroEx.getOrderHashHex(EXCHANGE_ADDRESS, order); - const ecSignature = await zeroEx.signOrderHashAsync(orderHash); - const signedOrder: SignedOrder = _.assign(order, {ecSignature}); - return signedOrder; } -- cgit From f450f538a0af0b4c85eefdd81c4983f40d230a33 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 11:07:36 +0200 Subject: Add setDefaultAccount --- src/0x.js.ts | 7 +++++++ src/web3_wrapper.ts | 3 +++ test/exchange_wrapper_test.ts | 4 ++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/0x.js.ts b/src/0x.js.ts index 25b4af777..5a0d3033c 100644 --- a/src/0x.js.ts +++ b/src/0x.js.ts @@ -137,6 +137,13 @@ export class ZeroEx { this.tokenRegistry.invalidateContractInstance(); this.token.invalidateContractInstances(); } + + /** + * Sets default account for sending transactions. + */ + public setDefaultAccount(account: string): void { + this.web3Wrapper.setDefaultAccount(account); + } /** * Signs an orderHash and returns it's elliptic curve signature * This method currently supports TestRPC, Geth and Parity above and below V1.6.6 diff --git a/src/web3_wrapper.ts b/src/web3_wrapper.ts index 79fd166ec..70e77dbe3 100644 --- a/src/web3_wrapper.ts +++ b/src/web3_wrapper.ts @@ -17,6 +17,9 @@ export class Web3Wrapper { public isAddress(address: string): boolean { return this.web3.isAddress(address); } + public setDefaultAccount(address: string): void { + this.web3.eth.defaultAccount = address; + } public async getSenderAddressIfExistsAsync(): Promise { const defaultAccount = this.web3.eth.defaultAccount; if (!_.isUndefined(defaultAccount)) { diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index a5a327dc4..ea541ca8e 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -133,7 +133,7 @@ describe('ExchangeWrapper', () => { }); describe('successful fills', () => { afterEach('reset default account', () => { - web3.eth.defaultAccount = userAddresses[0]; + zeroEx.setDefaultAccount(userAddresses[0]); }); it('should fill the valid order', async () => { const maker = userAddresses[0]; @@ -144,12 +144,12 @@ describe('ExchangeWrapper', () => { const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); const fillAmount = new BigNumber(5); - web3.eth.defaultAccount = taker; expect(await zeroEx.token.getBalanceAsync(addressBySymbol.MLN, maker)).to.be.bignumber.greaterThan(5); expect(await zeroEx.token.getBalanceAsync(addressBySymbol.MLN, taker)).to.be.bignumber.equal(0); expect(await zeroEx.token.getBalanceAsync(addressBySymbol.GNT, taker)).to.be.bignumber.equal(5); expect(await zeroEx.token.getProxyAllowanceAsync(addressBySymbol.MLN, maker)).to.be.bignumber.equal(5); expect(await zeroEx.token.getProxyAllowanceAsync(addressBySymbol.GNT, taker)).to.be.bignumber.equal(5); + zeroEx.setDefaultAccount(taker); await zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount); expect(await zeroEx.token.getBalanceAsync(addressBySymbol.MLN, taker)).to.be.bignumber.equal(5); expect(await zeroEx.token.getBalanceAsync(addressBySymbol.GNT, taker)).to.be.bignumber.equal(0); -- cgit From cc7592e9315f9cd9eba0a4049c4382545e8154e1 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 11:07:58 +0200 Subject: Use const --- test/exchange_wrapper_test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index ea541ca8e..36ad34fab 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -101,7 +101,7 @@ describe('ExchangeWrapper', () => { }); describe('#fillOrderAsync', () => { let tokens: Token[]; - let addressBySymbol: {[symbol: string]: string} = {}; + const addressBySymbol: {[symbol: string]: string} = {}; let networkId: number; const setBalance = async (toAddress: string, amountInBaseUnits: BigNumber.BigNumber|number, -- cgit From b05e96699f781398c2aac97082c565a531b6e4eb Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 11:08:14 +0200 Subject: Temporarily fix gas extimation --- src/contract_wrappers/exchange_wrapper.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 3f6210894..754210778 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -80,6 +80,18 @@ export class ExchangeWrapper extends ContractWrapper { signedOrder.expirationUnixTimestampSec, signedOrder.salt, ]; + const gas = await exchangeInstance.fill.estimateGas( + orderAddresses, + orderValues, + fillAmount, + shouldCheckTransfer, + signedOrder.ecSignature.v, + signedOrder.ecSignature.r, + signedOrder.ecSignature.s, + { + from: senderAddress, + }, + ); const response: ContractResponse = await exchangeInstance.fill( orderAddresses, orderValues, @@ -90,6 +102,7 @@ export class ExchangeWrapper extends ContractWrapper { signedOrder.ecSignature.s, { from: senderAddress, + gas, }, ); this.throwErrorLogsAsErrors(response.logs); -- cgit From 81f0414c27bcf64fdc10035951e36bf27f689431 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 11:15:33 +0200 Subject: Remove TxData --- src/types.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/types.ts b/src/types.ts index 8c378816f..cf1376754 100644 --- a/src/types.ts +++ b/src/types.ts @@ -34,15 +34,11 @@ export type OrderValues = [ BigNumber.BigNumber, BigNumber.BigNumber, BigNumber.BigNumber ]; -export interface TxData { - from: string; -} - export interface ExchangeContract { isValidSignature: any; fill: ( orderAddresses: OrderAddresses, orderValues: OrderValues, fillAmount: BigNumber.BigNumber, - shouldCheckTransfer: boolean, v: number, r: string, s: string, txData: TxData, + shouldCheckTransfer: boolean, v: number, r: string, s: string, txData: TxOpts, ) => ContractResponse; } -- cgit From 0a68a69d0ca75b45c4ebf46ff35f513f1c4344ec Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 11:15:52 +0200 Subject: Allign parameters --- test/exchange_wrapper_test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 36ad34fab..0c8182c73 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -104,8 +104,8 @@ describe('ExchangeWrapper', () => { const addressBySymbol: {[symbol: string]: string} = {}; let networkId: number; const setBalance = async (toAddress: string, - amountInBaseUnits: BigNumber.BigNumber|number, - tokenAddress: string) => { + amountInBaseUnits: BigNumber.BigNumber|number, + tokenAddress: string) => { const amount = _.isNumber(amountInBaseUnits) ? new BigNumber(amountInBaseUnits) : amountInBaseUnits; await zeroEx.token.transferAsync(tokenAddress, userAddresses[0], toAddress, amount); }; -- cgit From cc4b322a93d659820c4d2a621ebcbf15d32e8929 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 11:34:32 +0200 Subject: Type estimateGas --- src/types.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/types.ts b/src/types.ts index cf1376754..c3cabd4c7 100644 --- a/src/types.ts +++ b/src/types.ts @@ -36,10 +36,12 @@ export type OrderValues = [ export interface ExchangeContract { isValidSignature: any; - fill: ( - orderAddresses: OrderAddresses, orderValues: OrderValues, fillAmount: BigNumber.BigNumber, - shouldCheckTransfer: boolean, v: number, r: string, s: string, txData: TxOpts, - ) => ContractResponse; + fill: { + (orderAddresses: OrderAddresses, orderValues: OrderValues, fillAmount: BigNumber.BigNumber, + shouldCheckTransfer: boolean, v: number, r: string, s: string, txData: TxOpts): ContractResponse; + estimateGas: (orderAddresses: OrderAddresses, orderValues: OrderValues, fillAmount: BigNumber.BigNumber, + shouldCheckTransfer: boolean, v: number, r: string, s: string, txData: TxOpts) => number; + }; } export interface TokenContract { -- cgit From de3a2ff6726351b9d8400a6757a9ce2a18c3c3f6 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 11:40:08 +0200 Subject: Add dirty-chai --- package.json | 1 + src/globals.d.ts | 1 + test/exchange_wrapper_test.ts | 4 ++++ yarn.lock | 36 ++++++++++-------------------------- 4 files changed, 16 insertions(+), 26 deletions(-) diff --git a/package.json b/package.json index 7df7679c1..c3eeb171d 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "chai-as-promised": "^6.0.0", "chai-bignumber": "^2.0.0", "copyfiles": "^1.2.0", + "dirty-chai": "^1.2.2", "ethereumjs-testrpc": "3.0.5", "json-loader": "^0.5.4", "mocha": "^3.4.1", diff --git a/src/globals.d.ts b/src/globals.d.ts index 0f2fe0f2f..d86f54dfc 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -1,4 +1,5 @@ declare module 'chai-bignumber'; +declare module 'dirty-chai'; declare module 'bn.js'; declare module 'request-promise-native'; declare module 'web3-provider-engine'; diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 0c8182c73..c0d5b292b 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -9,7 +9,11 @@ import * as BigNumber from 'bignumber.js'; import {orderFactory} from './utils/order'; import {Token} from '../src/types'; import * as Web3 from 'web3'; +import * as dirtyChai from 'dirty-chai'; +import ChaiBigNumber = require('chai-bignumber'); +chai.use(dirtyChai); +chai.use(ChaiBigNumber()); const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(); diff --git a/yarn.lock b/yarn.lock index 144095202..fa21b0c66 100644 --- a/yarn.lock +++ b/yarn.lock @@ -235,7 +235,7 @@ async@^1.4.0, async@^1.4.2, async@^1.5.2, async@~1.5.0: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" -async@^2.0.1, async@^2.1.2, async@^2.4.0: +async@^2.1.2, async@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/async/-/async-2.4.1.tgz#62a56b279c98a11d0987096a01cc3eeb8eb7bbd7" dependencies: @@ -412,9 +412,9 @@ bignumber.js@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-4.0.2.tgz#2d1dc37ee5968867ecea90b6da4d16e68608d21d" -"bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", "bignumber.js@git+https://github.com/debris/bignumber.js.git#master": +"bignumber.js@git+https://github.com/debris/bignumber.js#master", "bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2": version "2.0.7" - resolved "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" + resolved "git+https://github.com/debris/bignumber.js#94d7146671b9719e00a09c29b01a691bc85048c2" bignumber.js@~2.1.4: version "2.1.4" @@ -964,6 +964,10 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" +dirty-chai@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/dirty-chai/-/dirty-chai-1.2.2.tgz#78495e619635f7fe44219aa4c837849bf183142e" + dom-walk@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" @@ -1124,17 +1128,7 @@ ethereumjs-account@^2.0.3, ethereumjs-account@~2.0.4: ethereumjs-util "^4.0.1" rlp "^2.0.0" -ethereumjs-block@^1.2.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.5.0.tgz#b0b9018e9cd73146c601dc7db2f6b2a4561e468c" - dependencies: - async "^2.0.1" - ethereum-common "0.0.18" - ethereumjs-tx "^1.2.2" - ethereumjs-util "^5.0.0" - merkle-patricia-tree "^2.1.2" - -ethereumjs-block@~1.2.2: +ethereumjs-block@^1.2.2, ethereumjs-block@~1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.2.2.tgz#2ec7534a59021b8ec9b83c30e49690c6ebaedda1" dependencies: @@ -1167,7 +1161,7 @@ ethereumjs-testrpc@3.0.5: web3-provider-engine "~8.1.0" yargs "~3.29.0" -ethereumjs-tx@^1.0.0, ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.0: +ethereumjs-tx@^1.0.0, ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.3.0: version "1.3.1" resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.1.tgz#d6909abcfb37da6404fc18124d351eda20047dac" dependencies: @@ -3199,7 +3193,7 @@ sntp@1.x.x: dependencies: hoek "2.x.x" -solc@0.4.6: +solc@0.4.6, solc@^0.4.2: version "0.4.6" resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.6.tgz#afa929a1ceafc0252cfbb4217c8e2b1dab139db7" dependencies: @@ -3208,16 +3202,6 @@ solc@0.4.6: require-from-string "^1.1.0" yargs "^4.7.1" -solc@^0.4.2: - version "0.4.11" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.11.tgz#2522eb43e7c0419bac2060b96e20a2593bfb5e8b" - dependencies: - fs-extra "^0.30.0" - memorystream "^0.3.1" - require-from-string "^1.1.0" - semver "^5.3.0" - yargs "^4.7.1" - source-list-map@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-1.1.2.tgz#9889019d1024cce55cdc069498337ef6186a11a1" -- cgit From dbb30aa1dd5db685cf9fea0e23029a77a66290da Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 11:46:57 +0200 Subject: Fix linter errors --- src/globals.d.ts | 4 ++++ test/0x.js_test.ts | 30 ++++++++++++++++-------------- test/exchange_wrapper_test.ts | 16 ++++++++-------- 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/globals.d.ts b/src/globals.d.ts index d86f54dfc..901377bd2 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -18,6 +18,10 @@ declare namespace Chai { bignumber: Assertion; // HACK: In order to comply with chai-as-promised we make eventually a `PromisedAssertion` not an `Assertion` eventually: PromisedAssertion; + true: () => void; + false: () => void; + rejected: () => void; + undefined: () => void; } } /* tslint:enable */ diff --git a/test/0x.js_test.ts b/test/0x.js_test.ts index a84785f4b..32040bd33 100644 --- a/test/0x.js_test.ts +++ b/test/0x.js_test.ts @@ -3,6 +3,7 @@ import * as chai from 'chai'; import 'mocha'; import * as BigNumber from 'bignumber.js'; import ChaiBigNumber = require('chai-bignumber'); +import * as dirtyChai from 'dirty-chai'; import * as Sinon from 'sinon'; import {ZeroEx} from '../src/0x.js'; import {constants} from './utils/constants'; @@ -11,6 +12,7 @@ import {Order} from '../src/types'; // Use BigNumber chai add-on chai.use(ChaiBigNumber()); +chai.use(dirtyChai); const expect = chai.expect; describe('ZeroEx library', () => { @@ -21,8 +23,8 @@ describe('ZeroEx library', () => { // Instantiate the contract instances with the current provider await (zeroEx.exchange as any).getExchangeContractAsync(); await (zeroEx.tokenRegistry as any).getTokenRegistryContractAsync(); - expect((zeroEx.exchange as any).exchangeContractIfExists).to.not.be.undefined; - expect((zeroEx.tokenRegistry as any).tokenRegistryContractIfExists).to.not.be.undefined; + expect((zeroEx.exchange as any).exchangeContractIfExists).to.not.be.undefined(); + expect((zeroEx.tokenRegistry as any).tokenRegistryContractIfExists).to.not.be.undefined(); const newProvider = web3Factory.getRpcProvider(); // Add property to newProvider so that we can differentiate it from old provider @@ -30,8 +32,8 @@ describe('ZeroEx library', () => { zeroEx.setProvider(newProvider); // Check that contractInstances with old provider are removed after provider update - expect((zeroEx.exchange as any).exchangeContractIfExists).to.be.undefined; - expect((zeroEx.tokenRegistry as any).tokenRegistryContractIfExists).to.be.undefined; + expect((zeroEx.exchange as any).exchangeContractIfExists).to.be.undefined(); + expect((zeroEx.tokenRegistry as any).tokenRegistryContractIfExists).to.be.undefined(); // Check that all nested web3 instances return the updated provider const nestedWeb3WrapperProvider = (zeroEx as any).web3Wrapper.getCurrentProvider(); @@ -118,47 +120,47 @@ describe('ZeroEx library', () => { }); it('should return false if the data doesn\'t pertain to the signature & address', () => { const isValid = ZeroEx.isValidSignature('0x0', signature, address); - expect(isValid).to.be.false; + expect(isValid).to.be.false(); }); it('should return false if the address doesn\'t pertain to the signature & data', () => { const validUnrelatedAddress = '0x8b0292B11a196601eD2ce54B665CaFEca0347D42'; const isValid = ZeroEx.isValidSignature(data, signature, validUnrelatedAddress); - expect(isValid).to.be.false; + expect(isValid).to.be.false(); }); it('should return false if the signature doesn\'t pertain to the data & address', () => { const wrongSignature = _.assign({}, signature, {v: 28}); const isValid = ZeroEx.isValidSignature(data, wrongSignature, address); - expect(isValid).to.be.false; + expect(isValid).to.be.false(); }); it('should return true if the signature does pertain to the data & address', () => { const isValid = ZeroEx.isValidSignature(data, signature, address); - expect(isValid).to.be.true; + expect(isValid).to.be.true(); }); }); describe('#generateSalt', () => { it('generates different salts', () => { const equal = ZeroEx.generatePseudoRandomSalt().eq(ZeroEx.generatePseudoRandomSalt()); - expect(equal).to.be.false; + expect(equal).to.be.false(); }); it('generates salt in range [0..2^256)', () => { const salt = ZeroEx.generatePseudoRandomSalt(); - expect(salt.greaterThanOrEqualTo(0)).to.be.true; + expect(salt.greaterThanOrEqualTo(0)).to.be.true(); const twoPow256 = new BigNumber(2).pow(256); - expect(salt.lessThan(twoPow256)).to.be.true; + expect(salt.lessThan(twoPow256)).to.be.true(); }); }); describe('#isValidOrderHash', () => { it('returns false if the value is not a hex string', () => { const isValid = ZeroEx.isValidOrderHash('not a hex'); - expect(isValid).to.be.false; + expect(isValid).to.be.false(); }); it('returns false if the length is wrong', () => { const isValid = ZeroEx.isValidOrderHash('0xdeadbeef'); - expect(isValid).to.be.false; + expect(isValid).to.be.false(); }); it('returns true if order hash is correct', () => { const isValid = ZeroEx.isValidOrderHash('0x' + Array(65).join('0')); - expect(isValid).to.be.true; + expect(isValid).to.be.true(); }); }); describe('#toUnitAmount', () => { diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index c0d5b292b..ca040ab28 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -51,7 +51,7 @@ describe('ExchangeWrapper', () => { s: signature.s, }; expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address)) - .to.be.rejected; + .to.be.rejected(); }); it('r lacks 0x prefix', () => { const malformedR = signature.r.replace('0x', ''); @@ -61,7 +61,7 @@ describe('ExchangeWrapper', () => { s: signature.s, }; expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address)) - .to.be.rejected; + .to.be.rejected(); }); it('r is too short', () => { const malformedR = signature.r.substr(10); @@ -71,7 +71,7 @@ describe('ExchangeWrapper', () => { s: signature.s.replace('0', 'z'), }; expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address)) - .to.be.rejected; + .to.be.rejected(); }); it('s is not hex', () => { const malformedS = signature.s.replace('0', 'z'); @@ -81,26 +81,26 @@ describe('ExchangeWrapper', () => { s: malformedS, }; expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address)) - .to.be.rejected; + .to.be.rejected(); }); }); it('should return false if the data doesn\'t pertain to the signature & address', async () => { const isValid = await zeroEx.exchange.isValidSignatureAsync('0x0', signature, address); - expect(isValid).to.be.false; + expect(isValid).to.be.false(); }); it('should return false if the address doesn\'t pertain to the signature & dataHex', async () => { const validUnrelatedAddress = '0x8b0292B11a196601eD2ce54B665CaFEca0347D42'; const isValid = await zeroEx.exchange.isValidSignatureAsync(dataHex, signature, validUnrelatedAddress); - expect(isValid).to.be.false; + expect(isValid).to.be.false(); }); it('should return false if the signature doesn\'t pertain to the dataHex & address', async () => { const wrongSignature = {...signature, v: 28}; const isValid = await zeroEx.exchange.isValidSignatureAsync(dataHex, wrongSignature, address); - expect(isValid).to.be.false; + expect(isValid).to.be.false(); }); it('should return true if the signature does pertain to the dataHex & address', async () => { const isValid = await zeroEx.exchange.isValidSignatureAsync(dataHex, signature, address); - expect(isValid).to.be.true; + expect(isValid).to.be.true(); }); }); describe('#fillOrderAsync', () => { -- cgit From 1fe1675726c965b70b118a0f04ad1ddd661ee32e Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 14:11:25 +0200 Subject: make bigNumberConfig a module --- src/0x.js.ts | 6 ++++-- src/bignumber_config.ts | 16 +++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/0x.js.ts b/src/0x.js.ts index 5a0d3033c..f2093b745 100644 --- a/src/0x.js.ts +++ b/src/0x.js.ts @@ -1,7 +1,6 @@ import * as _ from 'lodash'; import * as BigNumber from 'bignumber.js'; -import {setBigNumberConfig} from './bignumber_config'; -setBigNumberConfig(); +import {bigNumberConfigs} from './bignumber_config'; import * as ethUtil from 'ethereumjs-util'; import contract = require('truffle-contract'); import * as Web3 from 'web3'; @@ -20,6 +19,9 @@ import {SolidityTypes, ECSignature, ZeroExError} from './types'; import {Order} from './types'; import {orderSchema} from './schemas/signed_order_schema'; +// Customize our BigNumber instances +bigNumberConfigs.configure(); + const MAX_DIGITS_IN_UNSIGNED_256_INT = 78; export class ZeroEx { diff --git a/src/bignumber_config.ts b/src/bignumber_config.ts index 9641159d0..9c1715f86 100644 --- a/src/bignumber_config.ts +++ b/src/bignumber_config.ts @@ -1,9 +1,11 @@ import * as BigNumber from 'bignumber.js'; -export function setBigNumberConfig() { - // By default BigNumber's `toString` method converts to exponential notation if the value has - // more then 20 digits. We want to avoid this behavior, so we set EXPONENTIAL_AT to a high number - BigNumber.config({ - EXPONENTIAL_AT: 1000, - }); -} +export const bigNumberConfigs = { + configure() { + // By default BigNumber's `toString` method converts to exponential notation if the value has + // more then 20 digits. We want to avoid this behavior, so we set EXPONENTIAL_AT to a high number + BigNumber.config({ + EXPONENTIAL_AT: 1000, + }); + }, +}; -- cgit From 0991191a9b6c00fac80cd9f5ffa8e76c62f82eb5 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 14:43:14 +0200 Subject: move external imports to top --- src/0x.js.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/0x.js.ts b/src/0x.js.ts index f2093b745..e5eb6b520 100644 --- a/src/0x.js.ts +++ b/src/0x.js.ts @@ -5,12 +5,12 @@ 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 findVersions = require('find-versions'); -import compareVersions = require('compare-versions'); import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper'; import {TokenRegistryWrapper} from './contract_wrappers/token_registry_wrapper'; import {ecSignatureSchema} from './schemas/ec_signature_schema'; -- cgit From c74b16eda9465104e1969b1635ac826835d203eb Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 14:46:09 +0200 Subject: Add convertToJSONSchemaCompatibleObject method --- src/0x.js.ts | 5 ++++- src/contract_wrappers/exchange_wrapper.ts | 5 ++++- src/utils/schema_validator.ts | 7 +++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/0x.js.ts b/src/0x.js.ts index e5eb6b520..92a5d2c54 100644 --- a/src/0x.js.ts +++ b/src/0x.js.ts @@ -11,6 +11,7 @@ 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'; @@ -33,7 +34,9 @@ export class ZeroEx { * Computes the orderHash given the order parameters and returns it as a hex encoded string. */ public static getOrderHashHex(exchangeContractAddr: string, order: Order): string { - assert.doesConformToSchema('order', JSON.parse(JSON.stringify(order)), orderSchema); + assert.doesConformToSchema('order', + SchemaValidator.convertToJSONSchemaCompatibleObject(order as object), + orderSchema); const taker = _.isEmpty(order.taker) ? constants.NULL_ADDRESS : order.taker ; const orderParts = [ diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 754210778..59e6c755e 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -14,6 +14,7 @@ import {ContractWrapper} from './contract_wrapper'; import * as ExchangeArtifacts from '../artifacts/Exchange.json'; import {ecSignatureSchema} from '../schemas/ec_signature_schema'; import {signedOrderSchema} from '../schemas/signed_order_schema'; +import {SchemaValidator} from '../utils/schema_validator'; import {ContractResponse} from '../types'; import {constants} from '../utils/constants'; @@ -56,7 +57,9 @@ export class ExchangeWrapper extends ContractWrapper { } public async fillOrderAsync(signedOrder: SignedOrder, fillAmount: BigNumber.BigNumber, shouldCheckTransfer: boolean = true): Promise { - assert.doesConformToSchema('signedOrder', JSON.parse(JSON.stringify(signedOrder)), signedOrderSchema); + assert.doesConformToSchema('signedOrder', + SchemaValidator.convertToJSONSchemaCompatibleObject(signedOrder as object), + signedOrderSchema); assert.isBigNumber('fillAmount', fillAmount); assert.isBoolean('shouldCheckTransfer', shouldCheckTransfer); diff --git a/src/utils/schema_validator.ts b/src/utils/schema_validator.ts index cf45d0343..9ff7259d9 100644 --- a/src/utils/schema_validator.ts +++ b/src/utils/schema_validator.ts @@ -5,6 +5,13 @@ import {tokenSchema} from '../schemas/token_schema'; export class SchemaValidator { private validator: Validator; + // In order to validate a complex JS object using jsonschema, we must replace any complex + // sub-types (e.g BigNumber) with a simpler string represenation. Since BigNumber and other + // complex types implement the `toString` method, we can stringify the object and + // then parse it. The resultant object can then be checked using jsonschema. + public static convertToJSONSchemaCompatibleObject(obj: object): object { + return JSON.parse(JSON.stringify(obj)); + } constructor() { this.validator = new Validator(); this.validator.addSchema(tokenSchema, tokenSchema.id); -- cgit From 84f8570e78ef7637bbeb39d861342af9dda45943 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 14:46:24 +0200 Subject: Fix types hell with, chai and chai-as-promised --- package.json | 4 +- src/globals.d.ts | 4 - tsconfig.json | 4 +- yarn.lock | 399 +++++++++++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 365 insertions(+), 46 deletions(-) diff --git a/package.json b/package.json index c3eeb171d..8cef48c95 100644 --- a/package.json +++ b/package.json @@ -46,8 +46,6 @@ }, "devDependencies": { "@types/bignumber.js": "^4.0.2", - "@types/chai": "^3.5.2", - "@types/chai-as-promised": "0.0.30", "@types/jsonschema": "^1.1.1", "@types/lodash": "^4.14.64", "@types/mocha": "^2.2.41", @@ -57,7 +55,9 @@ "bignumber.js": "^4.0.2", "chai": "^3.5.0", "chai-as-promised": "^6.0.0", + "chai-as-promised-typescript-typings": "0.0.2", "chai-bignumber": "^2.0.0", + "chai-typescript-typings": "^0.0.0", "copyfiles": "^1.2.0", "dirty-chai": "^1.2.2", "ethereumjs-testrpc": "3.0.5", diff --git a/src/globals.d.ts b/src/globals.d.ts index 901377bd2..d86f54dfc 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -18,10 +18,6 @@ declare namespace Chai { bignumber: Assertion; // HACK: In order to comply with chai-as-promised we make eventually a `PromisedAssertion` not an `Assertion` eventually: PromisedAssertion; - true: () => void; - false: () => void; - rejected: () => void; - undefined: () => void; } } /* tslint:enable */ diff --git a/tsconfig.json b/tsconfig.json index b86d0ec6e..6e49168b7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,6 +12,8 @@ "include": [ "./src/**/*", "./test/**/*", - "./node_modules/web3-typescript-typings/index.d.ts" + "./node_modules/web3-typescript-typings/index.d.ts", + "./node_modules/chai-typescript-typings/index.d.ts", + "./node_modules/chai-as-promised-typescript-typings/index.d.ts" ] } diff --git a/yarn.lock b/yarn.lock index fa21b0c66..38ec3cb25 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6,16 +6,6 @@ version "4.0.2" resolved "https://registry.yarnpkg.com/@types/bignumber.js/-/bignumber.js-4.0.2.tgz#22a16946c9faa9f2c9c0ad4c7c3734a3033320ae" -"@types/chai-as-promised@0.0.30": - version "0.0.30" - resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-0.0.30.tgz#2341321cc796c6c3544a949a063e7609a222f303" - dependencies: - "@types/chai" "*" - -"@types/chai@*", "@types/chai@^3.5.2": - version "3.5.2" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-3.5.2.tgz#c11cd2817d3a401b7ba0f5a420f35c56139b1c1e" - "@types/fs-extra@^3.0.0": version "3.0.2" resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-3.0.2.tgz#00cbf48563f377f9ce5cf24237b21b3d9779e055" @@ -53,8 +43,8 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.41.tgz#e27cf0817153eb9f2713b2d3f6c68f1e1c3ca608" "@types/node@*", "@types/node@^7.0.22": - version "7.0.22" - resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.22.tgz#4593f4d828bdd612929478ea40c67b4f403ca255" + version "7.0.23" + resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.23.tgz#ededfd92e61046c32fcad56ea7e1101733fad4a4" "@types/shelljs@^0.7.0": version "0.7.1" @@ -310,6 +300,74 @@ babel-generator@^6.18.0, babel-generator@^6.24.1: source-map "^0.5.0" trim-right "^1.0.1" +babel-helper-call-delegate@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-define-map@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.24.1.tgz#7a9747f258d8947d32d515f6aa1c7bd02204a080" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + lodash "^4.2.0" + +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + dependencies: + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-regex@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.24.1.tgz#d36e22fab1008d79d88648e32116868128456ce8" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + lodash "^4.2.0" + +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + dependencies: + babel-helper-optimise-call-expression "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + babel-helpers@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" @@ -323,6 +381,222 @@ babel-messages@^6.23.0: dependencies: babel-runtime "^6.22.0" +babel-plugin-check-es2015-constants@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-arrow-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoping@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.24.1.tgz#76c295dc3a4741b1665adfd3167215dcff32a576" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + lodash "^4.2.0" + +babel-plugin-transform-es2015-classes@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + dependencies: + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-computed-properties@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-destructuring@^6.22.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-for-of@^6.22.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-modules-amd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-commonjs@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.1.tgz#d3e310b40ef664a36622200097c6d440298f2bfe" + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-modules-systemjs@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-umd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-object-super@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" + dependencies: + babel-helper-replace-supers "^6.24.1" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-parameters@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" + dependencies: + babel-helper-call-delegate "^6.24.1" + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-shorthand-properties@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-spread@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-sticky-regex@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-template-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.22.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-unicode-regex@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-regenerator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.24.1.tgz#b8da305ad43c3c99b4848e4fe4037b770d23c418" + dependencies: + regenerator-transform "0.9.11" + +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-preset-es2015@^6.24.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939" + dependencies: + babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.24.1" + babel-plugin-transform-es2015-classes "^6.24.1" + babel-plugin-transform-es2015-computed-properties "^6.24.1" + babel-plugin-transform-es2015-destructuring "^6.22.0" + babel-plugin-transform-es2015-duplicate-keys "^6.24.1" + babel-plugin-transform-es2015-for-of "^6.22.0" + babel-plugin-transform-es2015-function-name "^6.24.1" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-plugin-transform-es2015-modules-systemjs "^6.24.1" + babel-plugin-transform-es2015-modules-umd "^6.24.1" + babel-plugin-transform-es2015-object-super "^6.24.1" + babel-plugin-transform-es2015-parameters "^6.24.1" + babel-plugin-transform-es2015-shorthand-properties "^6.24.1" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.24.1" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.22.0" + babel-plugin-transform-es2015-unicode-regex "^6.24.1" + babel-plugin-transform-regenerator "^6.24.1" + babel-register@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.24.1.tgz#7e10e13a2f71065bdfad5a1787ba45bca6ded75f" @@ -335,7 +609,7 @@ babel-register@^6.24.1: mkdirp "^0.5.1" source-map-support "^0.4.2" -babel-runtime@^6.22.0: +babel-runtime@^6.18.0, babel-runtime@^6.22.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b" dependencies: @@ -366,7 +640,7 @@ babel-traverse@^6.18.0, babel-traverse@^6.24.1: invariant "^2.2.0" lodash "^4.2.0" -babel-types@^6.18.0, babel-types@^6.24.1: +babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.24.1.tgz#a136879dc15b3606bda0d90c1fc74304c2ff0975" dependencies: @@ -383,8 +657,8 @@ babelify@^7.3.0: object-assign "^4.0.0" babylon@^6.11.0, babylon@^6.13.0, babylon@^6.15.0: - version "6.17.1" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.1.tgz#17f14fddf361b695981fe679385e4f1c01ebd86f" + version "6.17.2" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.2.tgz#201d25ef5f892c41bae49488b08db0dd476e9f5c" balanced-match@^0.4.1: version "0.4.2" @@ -624,6 +898,12 @@ center-align@^0.1.1: align-text "^0.1.3" lazy-cache "^1.0.3" +chai-as-promised-typescript-typings@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/chai-as-promised-typescript-typings/-/chai-as-promised-typescript-typings-0.0.2.tgz#5df99c418917a78eb314e5f83f306cb95ae846cb" + dependencies: + chai-typescript-typings "^0.0.0" + chai-as-promised@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-6.0.0.tgz#1a02a433a6f24dafac63b9c96fa1684db1aa8da6" @@ -634,6 +914,10 @@ chai-bignumber@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/chai-bignumber/-/chai-bignumber-2.0.0.tgz#0cbf9b81790801c3f24fb77f59fa1e17a9c6e3f2" +chai-typescript-typings@^0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/chai-typescript-typings/-/chai-typescript-typings-0.0.0.tgz#52e076d72cf29129c94ab1dba6e33ce3828a0724" + chai@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247" @@ -732,7 +1016,7 @@ combined-stream@^1.0.5, combined-stream@~1.0.5: dependencies: delayed-stream "~1.0.0" -commander@2.9.0: +commander@2.9.0, commander@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" dependencies: @@ -1179,9 +1463,11 @@ ethereumjs-util@^4.0.0, ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0, ethereum secp256k1 "^3.0.1" ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.1.1.tgz#122fb38dea747dc62b3aebfc365d1bd48be4b73e" + version "5.1.2" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.1.2.tgz#25ba0215cbb4c2f0b108a6f96af2a2e62e45921f" dependencies: + babel-preset-es2015 "^6.24.0" + babelify "^7.3.0" bn.js "^4.8.0" create-hash "^1.1.2" ethjs-util "^0.1.3" @@ -1604,8 +1890,8 @@ heap@~0.2.6: resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac" highlight.js@^9.0.0: - version "9.11.0" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.11.0.tgz#47f98c7399918700db2caf230ded12cec41a84ae" + version "9.12.0" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e" hmac-drbg@^1.0.0: version "1.0.1" @@ -1915,6 +2201,10 @@ jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + json-loader@^0.5.4: version "0.5.4" resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.4.tgz#8baa1365a632f58a3c46d20175fc6002c96e37de" @@ -2366,8 +2656,8 @@ native-promise-only@^0.8.1: resolved "https://registry.yarnpkg.com/native-promise-only/-/native-promise-only-0.8.1.tgz#20a318c30cb45f71fe7adfbf7b21c99c1472ef11" node-abi@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.0.2.tgz#00f3e0a58100eb480133b48c99a32cc1f9e6c93e" + version "2.0.3" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.0.3.tgz#0ca67e5e667b8e1343549ca17153a815d0bbfdaa" node-fetch@^1.0.1, node-fetch@~1.6.0: version "1.6.3" @@ -2405,8 +2695,8 @@ node-libs-browser@^2.0.0: vm-browserify "0.0.4" node-pre-gyp@^0.6.29: - version "0.6.34" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.34.tgz#94ad1c798a11d7fc67381b50d47f8cc18d9799f7" + version "0.6.36" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz#db604112cb74e0d477554e9b505b17abddfab786" dependencies: mkdirp "^0.5.1" nopt "^4.0.1" @@ -2565,7 +2855,7 @@ opn@^4.0.0: object-assign "^4.0.1" pinkie-promise "^2.0.0" -optimist@^0.6.1, optimist@~0.6.0: +optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" dependencies: @@ -2902,10 +3192,22 @@ redent@^1.0.0: indent-string "^2.1.0" strip-indent "^1.0.1" +regenerate@^1.2.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260" + regenerator-runtime@^0.10.0: version "0.10.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" +regenerator-transform@0.9.11: + version "0.9.11" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.9.11.tgz#3a7d067520cb7b7176769eb5ff868691befe1283" + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + regex-cache@^0.4.2: version "0.4.3" resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145" @@ -2913,6 +3215,24 @@ regex-cache@^0.4.2: is-equal-shallow "^0.1.3" is-primitive "^2.0.0" +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + dependencies: + jsesc "~0.5.0" + remove-trailing-separator@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.0.1.tgz#615ebb96af559552d4bf4057c8436d486ab63cc4" @@ -3525,7 +3845,7 @@ truffle-contract@^2.0.0: truffle-contract-schema "0.0.5" web3 "^0.18.0" -tslib@^1.6.0: +tslib@^1.7.1: version "1.7.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.7.1.tgz#bc8004164691923a79fe8378bbeb3da2017538ec" @@ -3540,22 +3860,22 @@ tslint-react@^3.0.0: resolved "https://registry.yarnpkg.com/tslint-react/-/tslint-react-3.0.0.tgz#00c48ab7f22e91533b62bdef2c162b49447af00a" tslint@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.3.2.tgz#e56459fb095a7307f103b84052174f5e3bbef6ed" + version "5.4.0" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.4.0.tgz#e5e26524ca39fe950a51416456c2f296ccb69348" dependencies: babel-code-frame "^6.22.0" colors "^1.1.2" + commander "^2.9.0" diff "^3.2.0" glob "^7.1.1" - optimist "~0.6.0" resolve "^1.3.2" semver "^5.3.0" - tslib "^1.6.0" - tsutils "^2.0.0" + tslib "^1.7.1" + tsutils "^2.3.0" -tsutils@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.2.0.tgz#218614657f21c677e4536b4ba75daf8ebce1b367" +tsutils@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.3.0.tgz#96e661d7c2363f31adc8992ac67bbe7b7fc175e5" tty-browserify@0.0.0: version "0.0.0" @@ -3618,8 +3938,8 @@ typescript@2.3.2: resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.3.2.tgz#f0f045e196f69a72f06b25fd3bd39d01c3ce9984" typescript@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.3.3.tgz#9639f3c3b40148e8ca97fe08a51dd1891bb6be22" + version "2.3.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.3.4.tgz#3d38321828231e434f287514959c37a82b629f42" uglify-js@^2.6, uglify-js@^2.8.27: version "2.8.27" @@ -3707,8 +4027,8 @@ watchpack@^1.3.1: graceful-fs "^4.1.2" web3-provider-engine@^12.1.0: - version "12.1.0" - resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-12.1.0.tgz#92319bb22388aa9ef93254767ea06565867f3a9f" + version "12.2.1" + resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-12.2.1.tgz#848c2ee187f9701b0a382e2207c9b10f174a8d72" dependencies: async "^2.1.2" clone "^2.0.0" @@ -3720,6 +4040,7 @@ web3-provider-engine@^12.1.0: ethereumjs-vm "^2.0.2" fetch-ponyfill "^4.0.0" json-rpc-error "^2.0.0" + json-stable-stringify "^1.0.1" promise-to-callback "^1.0.0" readable-stream "^2.2.9" request "^2.67.0" -- cgit From 448be396cba7265d6ea0d69c9388e32db25773e8 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 14:52:25 +0200 Subject: Remove unnecessary checks --- test/exchange_wrapper_test.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index ca040ab28..548ef0c36 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -148,11 +148,6 @@ describe('ExchangeWrapper', () => { const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); const fillAmount = new BigNumber(5); - expect(await zeroEx.token.getBalanceAsync(addressBySymbol.MLN, maker)).to.be.bignumber.greaterThan(5); - expect(await zeroEx.token.getBalanceAsync(addressBySymbol.MLN, taker)).to.be.bignumber.equal(0); - expect(await zeroEx.token.getBalanceAsync(addressBySymbol.GNT, taker)).to.be.bignumber.equal(5); - expect(await zeroEx.token.getProxyAllowanceAsync(addressBySymbol.MLN, maker)).to.be.bignumber.equal(5); - expect(await zeroEx.token.getProxyAllowanceAsync(addressBySymbol.GNT, taker)).to.be.bignumber.equal(5); zeroEx.setDefaultAccount(taker); await zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount); expect(await zeroEx.token.getBalanceAsync(addressBySymbol.MLN, taker)).to.be.bignumber.equal(5); -- cgit From ef7ac6ac2df34cc45bce461bbbf0e83be5187aed Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 14:53:26 +0200 Subject: Rename order to order_factory --- test/exchange_wrapper_test.ts | 2 +- test/utils/order.ts | 38 -------------------------------------- test/utils/order_factory.ts | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 39 deletions(-) delete mode 100644 test/utils/order.ts create mode 100644 test/utils/order_factory.ts diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 548ef0c36..352eb9e05 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -6,7 +6,7 @@ import promisify = require('es6-promisify'); import * as _ from 'lodash'; import {BlockchainLifecycle} from './utils/blockchain_lifecycle'; import * as BigNumber from 'bignumber.js'; -import {orderFactory} from './utils/order'; +import {orderFactory} from './utils/order_factory'; import {Token} from '../src/types'; import * as Web3 from 'web3'; import * as dirtyChai from 'dirty-chai'; diff --git a/test/utils/order.ts b/test/utils/order.ts deleted file mode 100644 index 8a7d8430e..000000000 --- a/test/utils/order.ts +++ /dev/null @@ -1,38 +0,0 @@ -import {SignedOrder, Token} from '../../src/types'; -import * as BigNumber from 'bignumber.js'; -import * as _ from 'lodash'; -import {ZeroEx} from '../../src/0x.js'; -import {constants} from './constants'; -import * as ExchangeArtifacts from '../../src/artifacts/Exchange.json'; - -export const orderFactory = { - async createSignedOrderAsync( - zeroEx: ZeroEx, - networkId: number, - maker: string, - makerTokenAmount: BigNumber.BigNumber|number, - makerTokenAddress: string, - takerTokenAmount: BigNumber.BigNumber|number, - takerTokenAddress: string): Promise { - // TODO refactor and check - const exchangeAddress: string = (ExchangeArtifacts as any).networks[networkId].address; - const INF_TIMESTAMP = 2524604400; - const order = { - maker, - taker: undefined, - makerFee: new BigNumber(0), - takerFee: new BigNumber(0), - makerTokenAmount: _.isNumber(makerTokenAmount) ? new BigNumber(makerTokenAmount) : makerTokenAmount, - takerTokenAmount: _.isNumber(takerTokenAmount) ? new BigNumber(takerTokenAmount) : takerTokenAmount, - makerTokenAddress, - takerTokenAddress, - salt: ZeroEx.generatePseudoRandomSalt(), - feeRecipient: constants.NULL_ADDRESS, - expirationUnixTimestampSec: new BigNumber(INF_TIMESTAMP), - }; - const orderHash = ZeroEx.getOrderHashHex(exchangeAddress, order); - const ecSignature = await zeroEx.signOrderHashAsync(orderHash); - const signedOrder: SignedOrder = _.assign(order, {ecSignature}); - return signedOrder; - } -} diff --git a/test/utils/order_factory.ts b/test/utils/order_factory.ts new file mode 100644 index 000000000..8a7d8430e --- /dev/null +++ b/test/utils/order_factory.ts @@ -0,0 +1,38 @@ +import {SignedOrder, Token} from '../../src/types'; +import * as BigNumber from 'bignumber.js'; +import * as _ from 'lodash'; +import {ZeroEx} from '../../src/0x.js'; +import {constants} from './constants'; +import * as ExchangeArtifacts from '../../src/artifacts/Exchange.json'; + +export const orderFactory = { + async createSignedOrderAsync( + zeroEx: ZeroEx, + networkId: number, + maker: string, + makerTokenAmount: BigNumber.BigNumber|number, + makerTokenAddress: string, + takerTokenAmount: BigNumber.BigNumber|number, + takerTokenAddress: string): Promise { + // TODO refactor and check + const exchangeAddress: string = (ExchangeArtifacts as any).networks[networkId].address; + const INF_TIMESTAMP = 2524604400; + const order = { + maker, + taker: undefined, + makerFee: new BigNumber(0), + takerFee: new BigNumber(0), + makerTokenAmount: _.isNumber(makerTokenAmount) ? new BigNumber(makerTokenAmount) : makerTokenAmount, + takerTokenAmount: _.isNumber(takerTokenAmount) ? new BigNumber(takerTokenAmount) : takerTokenAmount, + makerTokenAddress, + takerTokenAddress, + salt: ZeroEx.generatePseudoRandomSalt(), + feeRecipient: constants.NULL_ADDRESS, + expirationUnixTimestampSec: new BigNumber(INF_TIMESTAMP), + }; + const orderHash = ZeroEx.getOrderHashHex(exchangeAddress, order); + const ecSignature = await zeroEx.signOrderHashAsync(orderHash); + const signedOrder: SignedOrder = _.assign(order, {ecSignature}); + return signedOrder; + } +} -- cgit From 75d0b69db294a58b8fdca330d4724ecf758d65f2 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 14:57:34 +0200 Subject: Add taker parameter to createSignedOrder --- test/exchange_wrapper_test.ts | 6 ++++-- test/utils/order_factory.ts | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 352eb9e05..b2fb1894b 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -128,7 +128,9 @@ describe('ExchangeWrapper', () => { }); describe('failed fills', () => { it('should throw when the fill amount is zero', async () => { - const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, userAddresses[0], + const maker = userAddresses[0]; + const taker = userAddresses[1]; + const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); const fillAmount = new BigNumber(0); expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount)) @@ -145,7 +147,7 @@ describe('ExchangeWrapper', () => { await setAllowance(maker, 5, addressBySymbol.MLN); await setBalance(taker, 5, addressBySymbol.GNT); await setAllowance(taker, 5, addressBySymbol.GNT); - const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, + const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); const fillAmount = new BigNumber(5); zeroEx.setDefaultAccount(taker); diff --git a/test/utils/order_factory.ts b/test/utils/order_factory.ts index 8a7d8430e..e41e973ee 100644 --- a/test/utils/order_factory.ts +++ b/test/utils/order_factory.ts @@ -10,6 +10,7 @@ export const orderFactory = { zeroEx: ZeroEx, networkId: number, maker: string, + taker: string, makerTokenAmount: BigNumber.BigNumber|number, makerTokenAddress: string, takerTokenAmount: BigNumber.BigNumber|number, @@ -19,7 +20,7 @@ export const orderFactory = { const INF_TIMESTAMP = 2524604400; const order = { maker, - taker: undefined, + taker, makerFee: new BigNumber(0), takerFee: new BigNumber(0), makerTokenAmount: _.isNumber(makerTokenAmount) ? new BigNumber(makerTokenAmount) : makerTokenAmount, -- cgit From 1668a085049d3b065c47709ef0018a66f637b992 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 14:59:03 +0200 Subject: rename signed_order_schema to order_schemas --- src/0x.js.ts | 2 +- src/contract_wrappers/exchange_wrapper.ts | 2 +- src/schemas/order_schemas.ts | 50 +++++++++++++++++++++++++++++++ src/schemas/signed_order_schema.ts | 50 ------------------------------- src/utils/schema_validator.ts | 2 +- 5 files changed, 53 insertions(+), 53 deletions(-) create mode 100644 src/schemas/order_schemas.ts delete mode 100644 src/schemas/signed_order_schema.ts diff --git a/src/0x.js.ts b/src/0x.js.ts index 92a5d2c54..bf56d5f8d 100644 --- a/src/0x.js.ts +++ b/src/0x.js.ts @@ -18,7 +18,7 @@ import {ecSignatureSchema} from './schemas/ec_signature_schema'; import {TokenWrapper} from './contract_wrappers/token_wrapper'; import {SolidityTypes, ECSignature, ZeroExError} from './types'; import {Order} from './types'; -import {orderSchema} from './schemas/signed_order_schema'; +import {orderSchema} from './schemas/order_schemas'; // Customize our BigNumber instances bigNumberConfigs.configure(); diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 59e6c755e..ad2573c6b 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -13,7 +13,7 @@ import {assert} from '../utils/assert'; import {ContractWrapper} from './contract_wrapper'; import * as ExchangeArtifacts from '../artifacts/Exchange.json'; import {ecSignatureSchema} from '../schemas/ec_signature_schema'; -import {signedOrderSchema} from '../schemas/signed_order_schema'; +import {signedOrderSchema} from '../schemas/order_schemas'; import {SchemaValidator} from '../utils/schema_validator'; import {ContractResponse} from '../types'; import {constants} from '../utils/constants'; diff --git a/src/schemas/order_schemas.ts b/src/schemas/order_schemas.ts new file mode 100644 index 000000000..dc7e51e40 --- /dev/null +++ b/src/schemas/order_schemas.ts @@ -0,0 +1,50 @@ +export const addressSchema = { + id: '/addressSchema', + type: 'string', + pattern: '^0[xX][0-9A-Fa-f]{40}$', +}; + +export const numberSchema = { + id: '/numberSchema', + type: 'string', + format: '\d+(\.\d+)?', +}; + +export const orderSchema = { + id: '/orderSchema', + properties: { + maker: {$ref: '/addressSchema'}, + taker: {$ref: '/addressSchema'}, + + makerFee: {$ref: '/numberSchema'}, + takerFee: {$ref: '/numberSchema'}, + + makerTokenAmount: {$ref: '/numberSchema'}, + takerTokenAmount: {$ref: '/numberSchema'}, + + makerTokenAddress: {$ref: '/addressSchema'}, + takerTokenAddress: {$ref: '/addressSchema'}, + + salt: {$ref: '/numberSchema'}, + feeRecipient: {$ref: '/addressSchema'}, + expirationUnixTimestampSec: {$ref: '/numberSchema'}, + }, + required: [ + 'maker', /*'taker',*/ 'makerFee', 'takerFee', 'makerTokenAmount', 'takerTokenAmount', + 'salt', 'feeRecipient', 'expirationUnixTimestampSec', + ], + type: 'object', +}; + +export const signedOrderSchema = { + id: '/signedOrderSchema', + allOf: [ + { $ref: '/orderSchema' }, + { + properties: { + ecSignature: {$ref: '/ECSignature'}, + }, + required: ['ecSignature'], + }, + ], +}; diff --git a/src/schemas/signed_order_schema.ts b/src/schemas/signed_order_schema.ts deleted file mode 100644 index dc7e51e40..000000000 --- a/src/schemas/signed_order_schema.ts +++ /dev/null @@ -1,50 +0,0 @@ -export const addressSchema = { - id: '/addressSchema', - type: 'string', - pattern: '^0[xX][0-9A-Fa-f]{40}$', -}; - -export const numberSchema = { - id: '/numberSchema', - type: 'string', - format: '\d+(\.\d+)?', -}; - -export const orderSchema = { - id: '/orderSchema', - properties: { - maker: {$ref: '/addressSchema'}, - taker: {$ref: '/addressSchema'}, - - makerFee: {$ref: '/numberSchema'}, - takerFee: {$ref: '/numberSchema'}, - - makerTokenAmount: {$ref: '/numberSchema'}, - takerTokenAmount: {$ref: '/numberSchema'}, - - makerTokenAddress: {$ref: '/addressSchema'}, - takerTokenAddress: {$ref: '/addressSchema'}, - - salt: {$ref: '/numberSchema'}, - feeRecipient: {$ref: '/addressSchema'}, - expirationUnixTimestampSec: {$ref: '/numberSchema'}, - }, - required: [ - 'maker', /*'taker',*/ 'makerFee', 'takerFee', 'makerTokenAmount', 'takerTokenAmount', - 'salt', 'feeRecipient', 'expirationUnixTimestampSec', - ], - type: 'object', -}; - -export const signedOrderSchema = { - id: '/signedOrderSchema', - allOf: [ - { $ref: '/orderSchema' }, - { - properties: { - ecSignature: {$ref: '/ECSignature'}, - }, - required: ['ecSignature'], - }, - ], -}; diff --git a/src/utils/schema_validator.ts b/src/utils/schema_validator.ts index 9ff7259d9..db8a960ba 100644 --- a/src/utils/schema_validator.ts +++ b/src/utils/schema_validator.ts @@ -1,6 +1,6 @@ import {Validator, ValidatorResult} from 'jsonschema'; import {ecSignatureSchema, ecSignatureParameter} from '../schemas/ec_signature_schema'; -import {addressSchema, numberSchema, orderSchema, signedOrderSchema} from '../schemas/signed_order_schema'; +import {addressSchema, numberSchema, orderSchema, signedOrderSchema} from '../schemas/order_schemas'; import {tokenSchema} from '../schemas/token_schema'; export class SchemaValidator { -- cgit From 88316455b74d2ecde1da55bf2bb36b6c9b46bcb1 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 15:10:22 +0200 Subject: Make taker required on Order object and expect NULL_ADDRESS from 0x.js --- src/0x.js.ts | 3 ++- src/contract_wrappers/exchange_wrapper.ts | 4 +--- src/schemas/order_schemas.ts | 2 +- src/types.ts | 4 ++-- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/0x.js.ts b/src/0x.js.ts index bf56d5f8d..1a46fe9a5 100644 --- a/src/0x.js.ts +++ b/src/0x.js.ts @@ -26,6 +26,8 @@ bigNumberConfigs.configure(); const MAX_DIGITS_IN_UNSIGNED_256_INT = 78; export class ZeroEx { + public static NULL_ADDRESS = constants.NULL_ADDRESS; + public exchange: ExchangeWrapper; public tokenRegistry: TokenRegistryWrapper; public token: TokenWrapper; @@ -37,7 +39,6 @@ export class ZeroEx { assert.doesConformToSchema('order', SchemaValidator.convertToJSONSchemaCompatibleObject(order as object), orderSchema); - const taker = _.isEmpty(order.taker) ? constants.NULL_ADDRESS : order.taker ; const orderParts = [ {value: exchangeContractAddr, type: SolidityTypes.address}, diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index ad2573c6b..d1763e307 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -66,11 +66,9 @@ export class ExchangeWrapper extends ContractWrapper { const senderAddress = await this.web3Wrapper.getSenderAddressOrThrowAsync(); const exchangeInstance = await this.getExchangeInstanceOrThrowAsync(); - const taker = _.isUndefined(signedOrder.taker) ? constants.NULL_ADDRESS : signedOrder.taker; - const orderAddresses: OrderAddresses = [ signedOrder.maker, - taker, + signedOrder.taker, signedOrder.makerTokenAddress, signedOrder.takerTokenAddress, signedOrder.feeRecipient, diff --git a/src/schemas/order_schemas.ts b/src/schemas/order_schemas.ts index dc7e51e40..72012dc26 100644 --- a/src/schemas/order_schemas.ts +++ b/src/schemas/order_schemas.ts @@ -30,7 +30,7 @@ export const orderSchema = { expirationUnixTimestampSec: {$ref: '/numberSchema'}, }, required: [ - 'maker', /*'taker',*/ 'makerFee', 'takerFee', 'makerTokenAmount', 'takerTokenAmount', + 'maker', 'taker', 'makerFee', 'takerFee', 'makerTokenAmount', 'takerTokenAmount', 'salt', 'feeRecipient', 'expirationUnixTimestampSec', ], type: 'object', diff --git a/src/types.ts b/src/types.ts index c3cabd4c7..7d668e78a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -31,7 +31,7 @@ export type OrderAddresses = [string, string, string, string, string]; export type OrderValues = [ BigNumber.BigNumber, BigNumber.BigNumber, BigNumber.BigNumber, - BigNumber.BigNumber, BigNumber.BigNumber, BigNumber.BigNumber + BigNumber.BigNumber, BigNumber.BigNumber, BigNumber.BigNumber, ]; export interface ExchangeContract { @@ -90,7 +90,7 @@ export interface ContractEvent { export interface Order { maker: string; - taker?: string; + taker: string; makerFee: BigNumber.BigNumber; takerFee: BigNumber.BigNumber; makerTokenAmount: BigNumber.BigNumber; -- cgit From 07cdfa655be81862f7ff40fe5ac6fdb38d780370 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 15:12:27 +0200 Subject: Add FILL_AMOUNT_IS_ZERO check --- src/contract_wrappers/exchange_wrapper.ts | 9 +++++++++ src/types.ts | 5 +++++ test/exchange_wrapper_test.ts | 4 ++-- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index d1763e307..7a5b6ac8c 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -4,6 +4,7 @@ import { ECSignature, ExchangeContract, ExchangeContractErrs, + FillOrderValidationErrs, OrderValues, OrderAddresses, SignedOrder, @@ -66,6 +67,8 @@ export class ExchangeWrapper extends ContractWrapper { const senderAddress = await this.web3Wrapper.getSenderAddressOrThrowAsync(); const exchangeInstance = await this.getExchangeInstanceOrThrowAsync(); + this.validateFillOrder(signedOrder, fillAmount, senderAddress, shouldCheckTransfer); + const orderAddresses: OrderAddresses = [ signedOrder.maker, signedOrder.taker, @@ -108,6 +111,12 @@ export class ExchangeWrapper extends ContractWrapper { ); this.throwErrorLogsAsErrors(response.logs); } + private validateFillOrder(signedOrder: SignedOrder, fillAmount: BigNumber.BigNumber, senderAddress: string, + shouldCheckTransfer: boolean = true) { + if (fillAmount.eq(0)) { + throw new Error(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); + } + } private async getExchangeInstanceOrThrowAsync(): Promise { const contractInstance = await this.instantiateContractIfExistsAsync((ExchangeArtifacts as any)); return contractInstance as ExchangeContract; diff --git a/src/types.ts b/src/types.ts index 7d668e78a..d9ed0b6bf 100644 --- a/src/types.ts +++ b/src/types.ts @@ -79,6 +79,11 @@ export enum ExchangeContractErrs { ERROR_CANCEL_NO_VALUE, // Order has already been fully filled or cancelled } +export const FillOrderValidationErrs = strEnum([ + 'FILL_AMOUNT_IS_ZERO', +]); +export type FillOrderValidationErrs = keyof typeof FillOrderValidationErrs; + export interface ContractResponse { logs: ContractEvent[]; } diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index b2fb1894b..4867427ae 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -7,7 +7,7 @@ import * as _ from 'lodash'; import {BlockchainLifecycle} from './utils/blockchain_lifecycle'; import * as BigNumber from 'bignumber.js'; import {orderFactory} from './utils/order_factory'; -import {Token} from '../src/types'; +import {FillOrderValidationErrs, Token} from '../src/types'; import * as Web3 from 'web3'; import * as dirtyChai from 'dirty-chai'; import ChaiBigNumber = require('chai-bignumber'); @@ -134,7 +134,7 @@ describe('ExchangeWrapper', () => { 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); const fillAmount = new BigNumber(0); expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount)) - .to.be.rejectedWith('This order has already been filled or cancelled'); + .to.be.rejectedWith(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); }); }); describe('successful fills', () => { -- cgit From d5d20db439a4a6fe913462bd216a776cc4300450 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 15:18:13 +0200 Subject: Add NOT_A_TAKER check --- src/contract_wrappers/exchange_wrapper.ts | 3 +++ src/types.ts | 1 + test/exchange_wrapper_test.ts | 11 ++++++++++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 7a5b6ac8c..e53754e07 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -116,6 +116,9 @@ export class ExchangeWrapper extends ContractWrapper { if (fillAmount.eq(0)) { throw new Error(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); } + if (signedOrder.taker !== constants.NULL_ADDRESS && signedOrder.taker !== senderAddress) { + throw new Error(FillOrderValidationErrs.NOT_A_TAKER); + } } private async getExchangeInstanceOrThrowAsync(): Promise { const contractInstance = await this.instantiateContractIfExistsAsync((ExchangeArtifacts as any)); diff --git a/src/types.ts b/src/types.ts index d9ed0b6bf..d6970bc0b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -81,6 +81,7 @@ export enum ExchangeContractErrs { export const FillOrderValidationErrs = strEnum([ 'FILL_AMOUNT_IS_ZERO', + 'NOT_A_TAKER', ]); export type FillOrderValidationErrs = keyof typeof FillOrderValidationErrs; diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 4867427ae..c5cbc58be 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -129,13 +129,22 @@ describe('ExchangeWrapper', () => { describe('failed fills', () => { it('should throw when the fill amount is zero', async () => { const maker = userAddresses[0]; - const taker = userAddresses[1]; + const taker = userAddresses[0]; const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); const fillAmount = new BigNumber(0); expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount)) .to.be.rejectedWith(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); }); + it('should throw when sender is not a taker', async () => { + const maker = userAddresses[0]; + const taker = userAddresses[1]; + const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, + 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); + const fillAmount = new BigNumber(5); + expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount)) + .to.be.rejectedWith(FillOrderValidationErrs.NOT_A_TAKER); + }); }); describe('successful fills', () => { afterEach('reset default account', () => { -- cgit From 21d00f04d46a8067801ff539fb21cbbed416c8b3 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 15:21:24 +0200 Subject: Fix tests --- test/0x.js_test.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/test/0x.js_test.ts b/test/0x.js_test.ts index 32040bd33..a548d8268 100644 --- a/test/0x.js_test.ts +++ b/test/0x.js_test.ts @@ -48,6 +48,7 @@ describe('ZeroEx library', () => { const expectedOrderHash = '0x103a5e97dab5dbeb8f385636f86a7d1e458a7ccbe1bd194727f0b2f85ab116c7'; const order: Order = { maker: constants.NULL_ADDRESS, + taker: constants.NULL_ADDRESS, feeRecipient: constants.NULL_ADDRESS, makerTokenAddress: constants.NULL_ADDRESS, takerTokenAddress: constants.NULL_ADDRESS, @@ -59,15 +60,8 @@ describe('ZeroEx library', () => { expirationUnixTimestampSec: new BigNumber(0), }; const exchangeAddress = constants.NULL_ADDRESS; - it('defaults takerAddress to NULL address', () => { - const orderHash = ZeroEx.getOrderHashHex(exchangeAddress, order); - expect(orderHash).to.be.equal(expectedOrderHash); - }); it('calculates the order hash', () => { - const orderWithZeroTaker = _.assign(order, { - taker: constants.NULL_ADDRESS, - }); - const orderHash = ZeroEx.getOrderHashHex(exchangeAddress, orderWithZeroTaker); + const orderHash = ZeroEx.getOrderHashHex(exchangeAddress, order); expect(orderHash).to.be.equal(expectedOrderHash); }); }); -- cgit From d8e35c364ea94b606810b340fb02d8706e257c3c Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 15:46:27 +0200 Subject: Add EXPIRED test --- package.json | 2 +- src/contract_wrappers/exchange_wrapper.ts | 3 +++ src/types.ts | 3 ++- test/exchange_wrapper_test.ts | 38 ++++++++++++++++++------------- test/utils/order_factory.ts | 10 +++++--- 5 files changed, 35 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index 8cef48c95..8b472f2a9 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "pretest:umd": "run-s clean build:*:dev", "substitute_umd_bundle": "npm run remove_src_files_not_used_by_tests; shx mv _bundles/* lib/src", "remove_src_files_not_used_by_tests": "find ./lib/src \\( -path ./lib/src/utils -o -path ./lib/src/schemas -o -path \"./lib/src/types.*\" \\) -prune -o -type f -print | xargs rm", - "run_mocha": "mocha lib/test/**/*_test.js" + "run_mocha": "mocha lib/test/**/*_test.js --timeout 3000" }, "config": { "artifacts": "Proxy Exchange TokenRegistry Token Mintable EtherToken", diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index e53754e07..88b0fa913 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -119,6 +119,9 @@ export class ExchangeWrapper extends ContractWrapper { if (signedOrder.taker !== constants.NULL_ADDRESS && signedOrder.taker !== senderAddress) { throw new Error(FillOrderValidationErrs.NOT_A_TAKER); } + if (signedOrder.expirationUnixTimestampSec.lessThan(Date.now() / 1000)) { + throw new Error(FillOrderValidationErrs.EXPIRED); + } } private async getExchangeInstanceOrThrowAsync(): Promise { const contractInstance = await this.instantiateContractIfExistsAsync((ExchangeArtifacts as any)); diff --git a/src/types.ts b/src/types.ts index d6970bc0b..6d4166013 100644 --- a/src/types.ts +++ b/src/types.ts @@ -31,7 +31,7 @@ export type OrderAddresses = [string, string, string, string, string]; export type OrderValues = [ BigNumber.BigNumber, BigNumber.BigNumber, BigNumber.BigNumber, - BigNumber.BigNumber, BigNumber.BigNumber, BigNumber.BigNumber, + BigNumber.BigNumber, BigNumber.BigNumber, BigNumber.BigNumber ]; export interface ExchangeContract { @@ -82,6 +82,7 @@ export enum ExchangeContractErrs { export const FillOrderValidationErrs = strEnum([ 'FILL_AMOUNT_IS_ZERO', 'NOT_A_TAKER', + 'EXPIRED', ]); export type FillOrderValidationErrs = keyof typeof FillOrderValidationErrs; diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index c5cbc58be..f929df149 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -107,6 +107,9 @@ describe('ExchangeWrapper', () => { let tokens: Token[]; const addressBySymbol: {[symbol: string]: string} = {}; let networkId: number; + let maker: string; + let taker: string; + const fillAmount = new BigNumber(5); const setBalance = async (toAddress: string, amountInBaseUnits: BigNumber.BigNumber|number, tokenAddress: string) => { @@ -126,40 +129,43 @@ describe('ExchangeWrapper', () => { }); networkId = await promisify(web3.version.getNetwork)(); }); + beforeEach('get ready for fill', async () => { + [maker, taker] = userAddresses; + zeroEx.setDefaultAccount(taker); + await setAllowance(maker, 5, addressBySymbol.MLN); + await setBalance(taker, 5, addressBySymbol.GNT); + await setAllowance(taker, 5, addressBySymbol.GNT); + }); + afterEach('reset sender', () => { + zeroEx.setDefaultAccount(userAddresses[0]); + }); describe('failed fills', () => { it('should throw when the fill amount is zero', async () => { - const maker = userAddresses[0]; - const taker = userAddresses[0]; const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); - const fillAmount = new BigNumber(0); expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount)) .to.be.rejectedWith(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); }); it('should throw when sender is not a taker', async () => { - const maker = userAddresses[0]; - const taker = userAddresses[1]; const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); - const fillAmount = new BigNumber(5); + const notTaker = userAddresses[2]; + zeroEx.setDefaultAccount(notTaker); expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount)) .to.be.rejectedWith(FillOrderValidationErrs.NOT_A_TAKER); }); + it('should throw when order is expired', async () => { + const OLD_TIMESTAMP = new BigNumber(42); + const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, + 5, addressBySymbol.MLN, 5, addressBySymbol.GNT, OLD_TIMESTAMP); + expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount)) + .to.be.rejectedWith(FillOrderValidationErrs.EXPIRED); + }); }); describe('successful fills', () => { - afterEach('reset default account', () => { - zeroEx.setDefaultAccount(userAddresses[0]); - }); it('should fill the valid order', async () => { - const maker = userAddresses[0]; - const taker = userAddresses[1]; - await setAllowance(maker, 5, addressBySymbol.MLN); - await setBalance(taker, 5, addressBySymbol.GNT); - await setAllowance(taker, 5, addressBySymbol.GNT); const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); - const fillAmount = new BigNumber(5); - zeroEx.setDefaultAccount(taker); await zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount); expect(await zeroEx.token.getBalanceAsync(addressBySymbol.MLN, taker)).to.be.bignumber.equal(5); expect(await zeroEx.token.getBalanceAsync(addressBySymbol.GNT, taker)).to.be.bignumber.equal(0); diff --git a/test/utils/order_factory.ts b/test/utils/order_factory.ts index e41e973ee..c6c6ed927 100644 --- a/test/utils/order_factory.ts +++ b/test/utils/order_factory.ts @@ -14,10 +14,14 @@ export const orderFactory = { makerTokenAmount: BigNumber.BigNumber|number, makerTokenAddress: string, takerTokenAmount: BigNumber.BigNumber|number, - takerTokenAddress: string): Promise { + takerTokenAddress: string, + expirationUnixTimestampSec?: BigNumber.BigNumber): Promise { // TODO refactor and check const exchangeAddress: string = (ExchangeArtifacts as any).networks[networkId].address; - const INF_TIMESTAMP = 2524604400; + const INF_TIMESTAMP = new BigNumber(2524604400); + expirationUnixTimestampSec = _.isUndefined(expirationUnixTimestampSec) ? + INF_TIMESTAMP : + expirationUnixTimestampSec; const order = { maker, taker, @@ -29,7 +33,7 @@ export const orderFactory = { takerTokenAddress, salt: ZeroEx.generatePseudoRandomSalt(), feeRecipient: constants.NULL_ADDRESS, - expirationUnixTimestampSec: new BigNumber(INF_TIMESTAMP), + expirationUnixTimestampSec, }; const orderHash = ZeroEx.getOrderHashHex(exchangeAddress, order); const ecSignature = await zeroEx.signOrderHashAsync(orderHash); -- cgit From 6a57c42e253a52a449cae8a5c6565276cb01a86c Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 15:51:45 +0200 Subject: Rename ExchangeContractErrs to ExchangeContractErrCodes --- src/contract_wrappers/exchange_wrapper.ts | 18 +++++++++--------- src/types.ts | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index d1763e307..1311730a0 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -3,7 +3,7 @@ import {Web3Wrapper} from '../web3_wrapper'; import { ECSignature, ExchangeContract, - ExchangeContractErrs, + ExchangeContractErrCodes, OrderValues, OrderAddresses, SignedOrder, @@ -19,13 +19,13 @@ import {ContractResponse} from '../types'; import {constants} from '../utils/constants'; export class ExchangeWrapper extends ContractWrapper { - private exchangeContractErrToMsg = { - [ExchangeContractErrs.ERROR_FILL_EXPIRED]: 'The order you attempted to fill is expired', - [ExchangeContractErrs.ERROR_CANCEL_EXPIRED]: 'The order you attempted to cancel is expired', - [ExchangeContractErrs.ERROR_FILL_NO_VALUE]: 'This order has already been filled or cancelled', - [ExchangeContractErrs.ERROR_CANCEL_NO_VALUE]: 'This order has already been filled or cancelled', - [ExchangeContractErrs.ERROR_FILL_TRUNCATION]: 'The rounding error was too large when filling this order', - [ExchangeContractErrs.ERROR_FILL_BALANCE_ALLOWANCE]: 'Maker or taker has insufficient balance or allowance', + private exchangeContractErrCodesToMsg = { + [ExchangeContractErrCodes.ERROR_FILL_EXPIRED]: 'The order you attempted to fill is expired', + [ExchangeContractErrCodes.ERROR_CANCEL_EXPIRED]: 'The order you attempted to cancel is expired', + [ExchangeContractErrCodes.ERROR_FILL_NO_VALUE]: 'This order has already been filled or cancelled', + [ExchangeContractErrCodes.ERROR_CANCEL_NO_VALUE]: 'This order has already been filled or cancelled', + [ExchangeContractErrCodes.ERROR_FILL_TRUNCATION]: 'The rounding error was too large when filling this order', + [ExchangeContractErrCodes.ERROR_FILL_BALANCE_ALLOWANCE]: 'Maker or taker has insufficient balance or allowance', }; private exchangeContractIfExists?: ExchangeContract; constructor(web3Wrapper: Web3Wrapper) { @@ -116,7 +116,7 @@ export class ExchangeWrapper extends ContractWrapper { const errEvent = _.find(logs, {event: 'LogError'}); if (!_.isUndefined(errEvent)) { const errCode = errEvent.args.errorId.toNumber(); - const humanReadableErrMessage = this.exchangeContractErrToMsg[errCode]; + const humanReadableErrMessage = this.exchangeContractErrCodesToMsg[errCode]; throw new Error(humanReadableErrMessage); } } diff --git a/src/types.ts b/src/types.ts index 7d668e78a..18de4d27e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -70,7 +70,7 @@ export const SolidityTypes = strEnum([ ]); export type SolidityTypes = keyof typeof SolidityTypes; -export enum ExchangeContractErrs { +export enum ExchangeContractErrCodes { ERROR_FILL_EXPIRED, // Order has already expired ERROR_FILL_NO_VALUE, // Order has already been fully filled or cancelled ERROR_FILL_TRUNCATION, // Rounding error too large -- cgit From a685d7604fcd0854ad49df762c4ed5a51cc86065 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 16:02:44 +0200 Subject: fix formatting --- src/types.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/types.ts b/src/types.ts index 992bb4b00..c3a19d3b6 100644 --- a/src/types.ts +++ b/src/types.ts @@ -29,10 +29,8 @@ export interface ECSignature { export type OrderAddresses = [string, string, string, string, string]; -export type OrderValues = [ - BigNumber.BigNumber, BigNumber.BigNumber, BigNumber.BigNumber, - BigNumber.BigNumber, BigNumber.BigNumber, BigNumber.BigNumber -]; +export type OrderValues = [BigNumber.BigNumber, BigNumber.BigNumber, BigNumber.BigNumber, + BigNumber.BigNumber, BigNumber.BigNumber, BigNumber.BigNumber]; export interface ExchangeContract { isValidSignature: any; -- cgit From 88a70afa70f84efc866ff53121d05a6d8d77bff8 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 16:03:09 +0200 Subject: Add ExchangeContractErrs string enum --- src/contract_wrappers/exchange_wrapper.ts | 17 +++++++++-------- src/types.ts | 8 ++++++++ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index bf3f10e28..1232b969b 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -4,6 +4,7 @@ import { ECSignature, ExchangeContract, ExchangeContractErrCodes, + ExchangeContractErrs, FillOrderValidationErrs, OrderValues, OrderAddresses, @@ -21,12 +22,12 @@ import {constants} from '../utils/constants'; export class ExchangeWrapper extends ContractWrapper { private exchangeContractErrCodesToMsg = { - [ExchangeContractErrCodes.ERROR_FILL_EXPIRED]: 'The order you attempted to fill is expired', - [ExchangeContractErrCodes.ERROR_CANCEL_EXPIRED]: 'The order you attempted to cancel is expired', - [ExchangeContractErrCodes.ERROR_FILL_NO_VALUE]: 'This order has already been filled or cancelled', - [ExchangeContractErrCodes.ERROR_CANCEL_NO_VALUE]: 'This order has already been filled or cancelled', - [ExchangeContractErrCodes.ERROR_FILL_TRUNCATION]: 'The rounding error was too large when filling this order', - [ExchangeContractErrCodes.ERROR_FILL_BALANCE_ALLOWANCE]: 'Maker or taker has insufficient balance or allowance', + [ExchangeContractErrCodes.ERROR_FILL_EXPIRED]: ExchangeContractErrs.ORDER_EXPIRED, + [ExchangeContractErrCodes.ERROR_CANCEL_EXPIRED]: ExchangeContractErrs.ORDER_EXPIRED, + [ExchangeContractErrCodes.ERROR_FILL_NO_VALUE]: ExchangeContractErrs.ORDER_REMAINING_FILL_AMOUNT_ZERO, + [ExchangeContractErrCodes.ERROR_CANCEL_NO_VALUE]: ExchangeContractErrs.ORDER_REMAINING_FILL_AMOUNT_ZERO, + [ExchangeContractErrCodes.ERROR_FILL_TRUNCATION]: ExchangeContractErrs.ORDER_ROUNDING_ERROR, + [ExchangeContractErrCodes.ERROR_FILL_BALANCE_ALLOWANCE]: ExchangeContractErrs.ORDER_BALANCE_ALLOWANCE_ERROR, }; private exchangeContractIfExists?: ExchangeContract; constructor(web3Wrapper: Web3Wrapper) { @@ -131,8 +132,8 @@ export class ExchangeWrapper extends ContractWrapper { const errEvent = _.find(logs, {event: 'LogError'}); if (!_.isUndefined(errEvent)) { const errCode = errEvent.args.errorId.toNumber(); - const humanReadableErrMessage = this.exchangeContractErrCodesToMsg[errCode]; - throw new Error(humanReadableErrMessage); + const errMessage = this.exchangeContractErrCodesToMsg[errCode]; + throw new Error(errMessage); } } private async getExchangeContractAsync(): Promise { diff --git a/src/types.ts b/src/types.ts index c3a19d3b6..7c5e1825d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -77,6 +77,14 @@ export enum ExchangeContractErrCodes { ERROR_CANCEL_NO_VALUE, // Order has already been fully filled or cancelled } +export const ExchangeContractErrs = strEnum([ + 'ORDER_EXPIRED', + 'ORDER_REMAINING_FILL_AMOUNT_ZERO', + 'ORDER_ROUNDING_ERROR', + 'ORDER_BALANCE_ALLOWANCE_ERROR', +]); +export type ExchangeContractErrs = keyof typeof ExchangeContractErrs; + export const FillOrderValidationErrs = strEnum([ 'FILL_AMOUNT_IS_ZERO', 'NOT_A_TAKER', -- cgit From a1041348d5695ee3b84433e9874176e85543a4e0 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 16:07:43 +0200 Subject: Get getSenderAddressOrThrowAsync everywhere where we throw if the senderAddress doesn't exist --- src/0x.js.ts | 11 ++++------- src/web3_wrapper.ts | 16 ++++++++-------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/0x.js.ts b/src/0x.js.ts index 1a46fe9a5..a29c25e0c 100644 --- a/src/0x.js.ts +++ b/src/0x.js.ts @@ -157,6 +157,8 @@ export class ZeroEx { public async signOrderHashAsync(orderHashHex: string): Promise { assert.isHexString('orderHashHex', orderHashHex); + const makerAddress = await this.web3Wrapper.getSenderAddressOrThrowAsync(); + let msgHashHex; const nodeVersion = await this.web3Wrapper.getNodeVersionAsync(); const isParityNode = utils.isParityNode(nodeVersion); @@ -169,12 +171,7 @@ export class ZeroEx { msgHashHex = ethUtil.bufferToHex(msgHashBuff); } - const makerAddressIfExists = await this.web3Wrapper.getSenderAddressIfExistsAsync(); - if (_.isUndefined(makerAddressIfExists)) { - throw new Error(ZeroExError.USER_HAS_NO_ASSOCIATED_ADDRESSES); - } - - const signature = await this.web3Wrapper.signTransactionAsync(makerAddressIfExists, msgHashHex); + const signature = await this.web3Wrapper.signTransactionAsync(makerAddress, msgHashHex); let signatureData; const [nodeVersionNumber] = findVersions(nodeVersion); @@ -204,7 +201,7 @@ export class ZeroEx { r: ethUtil.bufferToHex(r), s: ethUtil.bufferToHex(s), }; - const isValidSignature = ZeroEx.isValidSignature(orderHashHex, ecSignature, makerAddressIfExists); + const isValidSignature = ZeroEx.isValidSignature(orderHashHex, ecSignature, makerAddress); if (!isValidSignature) { throw new Error(ZeroExError.INVALID_SIGNATURE); } diff --git a/src/web3_wrapper.ts b/src/web3_wrapper.ts index 70e77dbe3..c1263222a 100644 --- a/src/web3_wrapper.ts +++ b/src/web3_wrapper.ts @@ -20,14 +20,6 @@ export class Web3Wrapper { public setDefaultAccount(address: string): void { this.web3.eth.defaultAccount = address; } - public async getSenderAddressIfExistsAsync(): Promise { - const defaultAccount = this.web3.eth.defaultAccount; - if (!_.isUndefined(defaultAccount)) { - return defaultAccount; - } - const firstAccount = await this.getFirstAddressIfExistsAsync(); - return firstAccount; - } public async getSenderAddressOrThrowAsync(): Promise { const senderAddressIfExists = await this.getSenderAddressIfExistsAsync(); assert.assert(!_.isUndefined(senderAddressIfExists), ZeroExError.USER_HAS_NO_ASSOCIATED_ADDRESSES); @@ -74,6 +66,14 @@ export class Web3Wrapper { const {timestamp} = await promisify(this.web3.eth.getBlock)(blockHash); return timestamp; } + private async getSenderAddressIfExistsAsync(): Promise { + const defaultAccount = this.web3.eth.defaultAccount; + if (!_.isUndefined(defaultAccount)) { + return defaultAccount; + } + const firstAccount = await this.getFirstAddressIfExistsAsync(); + return firstAccount; + } private async getNetworkAsync(): Promise { const networkId = await promisify(this.web3.version.getNetwork)(); return networkId; -- cgit From 771c88ec791cb6bedf2ddd3418e89dec1581e326 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 16:11:25 +0200 Subject: Revert "Add EXPIRED test" This reverts commit d8e35c364ea94b606810b340fb02d8706e257c3c. --- package.json | 2 +- src/contract_wrappers/exchange_wrapper.ts | 3 --- src/types.ts | 1 - test/exchange_wrapper_test.ts | 38 +++++++++++++------------------ test/utils/order_factory.ts | 10 +++----- 5 files changed, 20 insertions(+), 34 deletions(-) diff --git a/package.json b/package.json index 8b472f2a9..8cef48c95 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "pretest:umd": "run-s clean build:*:dev", "substitute_umd_bundle": "npm run remove_src_files_not_used_by_tests; shx mv _bundles/* lib/src", "remove_src_files_not_used_by_tests": "find ./lib/src \\( -path ./lib/src/utils -o -path ./lib/src/schemas -o -path \"./lib/src/types.*\" \\) -prune -o -type f -print | xargs rm", - "run_mocha": "mocha lib/test/**/*_test.js --timeout 3000" + "run_mocha": "mocha lib/test/**/*_test.js" }, "config": { "artifacts": "Proxy Exchange TokenRegistry Token Mintable EtherToken", diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 1232b969b..dbb427d2c 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -120,9 +120,6 @@ export class ExchangeWrapper extends ContractWrapper { if (signedOrder.taker !== constants.NULL_ADDRESS && signedOrder.taker !== senderAddress) { throw new Error(FillOrderValidationErrs.NOT_A_TAKER); } - if (signedOrder.expirationUnixTimestampSec.lessThan(Date.now() / 1000)) { - throw new Error(FillOrderValidationErrs.EXPIRED); - } } private async getExchangeInstanceOrThrowAsync(): Promise { const contractInstance = await this.instantiateContractIfExistsAsync((ExchangeArtifacts as any)); diff --git a/src/types.ts b/src/types.ts index 7c5e1825d..216026b3d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -88,7 +88,6 @@ export type ExchangeContractErrs = keyof typeof ExchangeContractErrs; export const FillOrderValidationErrs = strEnum([ 'FILL_AMOUNT_IS_ZERO', 'NOT_A_TAKER', - 'EXPIRED', ]); export type FillOrderValidationErrs = keyof typeof FillOrderValidationErrs; diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index f929df149..c5cbc58be 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -107,9 +107,6 @@ describe('ExchangeWrapper', () => { let tokens: Token[]; const addressBySymbol: {[symbol: string]: string} = {}; let networkId: number; - let maker: string; - let taker: string; - const fillAmount = new BigNumber(5); const setBalance = async (toAddress: string, amountInBaseUnits: BigNumber.BigNumber|number, tokenAddress: string) => { @@ -129,43 +126,40 @@ describe('ExchangeWrapper', () => { }); networkId = await promisify(web3.version.getNetwork)(); }); - beforeEach('get ready for fill', async () => { - [maker, taker] = userAddresses; - zeroEx.setDefaultAccount(taker); - await setAllowance(maker, 5, addressBySymbol.MLN); - await setBalance(taker, 5, addressBySymbol.GNT); - await setAllowance(taker, 5, addressBySymbol.GNT); - }); - afterEach('reset sender', () => { - zeroEx.setDefaultAccount(userAddresses[0]); - }); describe('failed fills', () => { it('should throw when the fill amount is zero', async () => { + const maker = userAddresses[0]; + const taker = userAddresses[0]; const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); + const fillAmount = new BigNumber(0); expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount)) .to.be.rejectedWith(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); }); it('should throw when sender is not a taker', async () => { + const maker = userAddresses[0]; + const taker = userAddresses[1]; const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); - const notTaker = userAddresses[2]; - zeroEx.setDefaultAccount(notTaker); + const fillAmount = new BigNumber(5); expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount)) .to.be.rejectedWith(FillOrderValidationErrs.NOT_A_TAKER); }); - it('should throw when order is expired', async () => { - const OLD_TIMESTAMP = new BigNumber(42); - const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, - 5, addressBySymbol.MLN, 5, addressBySymbol.GNT, OLD_TIMESTAMP); - expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount)) - .to.be.rejectedWith(FillOrderValidationErrs.EXPIRED); - }); }); describe('successful fills', () => { + afterEach('reset default account', () => { + zeroEx.setDefaultAccount(userAddresses[0]); + }); it('should fill the valid order', async () => { + const maker = userAddresses[0]; + const taker = userAddresses[1]; + await setAllowance(maker, 5, addressBySymbol.MLN); + await setBalance(taker, 5, addressBySymbol.GNT); + await setAllowance(taker, 5, addressBySymbol.GNT); const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); + const fillAmount = new BigNumber(5); + zeroEx.setDefaultAccount(taker); await zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount); expect(await zeroEx.token.getBalanceAsync(addressBySymbol.MLN, taker)).to.be.bignumber.equal(5); expect(await zeroEx.token.getBalanceAsync(addressBySymbol.GNT, taker)).to.be.bignumber.equal(0); diff --git a/test/utils/order_factory.ts b/test/utils/order_factory.ts index c6c6ed927..e41e973ee 100644 --- a/test/utils/order_factory.ts +++ b/test/utils/order_factory.ts @@ -14,14 +14,10 @@ export const orderFactory = { makerTokenAmount: BigNumber.BigNumber|number, makerTokenAddress: string, takerTokenAmount: BigNumber.BigNumber|number, - takerTokenAddress: string, - expirationUnixTimestampSec?: BigNumber.BigNumber): Promise { + takerTokenAddress: string): Promise { // TODO refactor and check const exchangeAddress: string = (ExchangeArtifacts as any).networks[networkId].address; - const INF_TIMESTAMP = new BigNumber(2524604400); - expirationUnixTimestampSec = _.isUndefined(expirationUnixTimestampSec) ? - INF_TIMESTAMP : - expirationUnixTimestampSec; + const INF_TIMESTAMP = 2524604400; const order = { maker, taker, @@ -33,7 +29,7 @@ export const orderFactory = { takerTokenAddress, salt: ZeroEx.generatePseudoRandomSalt(), feeRecipient: constants.NULL_ADDRESS, - expirationUnixTimestampSec, + expirationUnixTimestampSec: new BigNumber(INF_TIMESTAMP), }; const orderHash = ZeroEx.getOrderHashHex(exchangeAddress, order); const ecSignature = await zeroEx.signOrderHashAsync(orderHash); -- cgit From 7fb18e512e2afaf37c6605ceb1d7b9f674052b29 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 16:14:32 +0200 Subject: Increase mocha timeout --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8cef48c95..8b472f2a9 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "pretest:umd": "run-s clean build:*:dev", "substitute_umd_bundle": "npm run remove_src_files_not_used_by_tests; shx mv _bundles/* lib/src", "remove_src_files_not_used_by_tests": "find ./lib/src \\( -path ./lib/src/utils -o -path ./lib/src/schemas -o -path \"./lib/src/types.*\" \\) -prune -o -type f -print | xargs rm", - "run_mocha": "mocha lib/test/**/*_test.js" + "run_mocha": "mocha lib/test/**/*_test.js --timeout 3000" }, "config": { "artifacts": "Proxy Exchange TokenRegistry Token Mintable EtherToken", -- cgit From 7d64ce1220c21c6a4c9f06df39132aceb72c4461 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 16:15:30 +0200 Subject: Add EXPIRED error type --- src/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/types.ts b/src/types.ts index 216026b3d..7c5e1825d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -88,6 +88,7 @@ export type ExchangeContractErrs = keyof typeof ExchangeContractErrs; export const FillOrderValidationErrs = strEnum([ 'FILL_AMOUNT_IS_ZERO', 'NOT_A_TAKER', + 'EXPIRED', ]); export type FillOrderValidationErrs = keyof typeof FillOrderValidationErrs; -- cgit From 78259dc2af07a7c56b89669cd0b6a1c7b997092b Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 16:15:58 +0200 Subject: Add expired check --- src/contract_wrappers/exchange_wrapper.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index dbb427d2c..1232b969b 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -120,6 +120,9 @@ export class ExchangeWrapper extends ContractWrapper { if (signedOrder.taker !== constants.NULL_ADDRESS && signedOrder.taker !== senderAddress) { throw new Error(FillOrderValidationErrs.NOT_A_TAKER); } + if (signedOrder.expirationUnixTimestampSec.lessThan(Date.now() / 1000)) { + throw new Error(FillOrderValidationErrs.EXPIRED); + } } private async getExchangeInstanceOrThrowAsync(): Promise { const contractInstance = await this.instantiateContractIfExistsAsync((ExchangeArtifacts as any)); -- cgit From 52bdc0d3432ef917cca15522cea78255d03d82f6 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 16:17:15 +0200 Subject: Add timestamp parameter to order factory --- test/utils/order_factory.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/test/utils/order_factory.ts b/test/utils/order_factory.ts index e41e973ee..c6c6ed927 100644 --- a/test/utils/order_factory.ts +++ b/test/utils/order_factory.ts @@ -14,10 +14,14 @@ export const orderFactory = { makerTokenAmount: BigNumber.BigNumber|number, makerTokenAddress: string, takerTokenAmount: BigNumber.BigNumber|number, - takerTokenAddress: string): Promise { + takerTokenAddress: string, + expirationUnixTimestampSec?: BigNumber.BigNumber): Promise { // TODO refactor and check const exchangeAddress: string = (ExchangeArtifacts as any).networks[networkId].address; - const INF_TIMESTAMP = 2524604400; + const INF_TIMESTAMP = new BigNumber(2524604400); + expirationUnixTimestampSec = _.isUndefined(expirationUnixTimestampSec) ? + INF_TIMESTAMP : + expirationUnixTimestampSec; const order = { maker, taker, @@ -29,7 +33,7 @@ export const orderFactory = { takerTokenAddress, salt: ZeroEx.generatePseudoRandomSalt(), feeRecipient: constants.NULL_ADDRESS, - expirationUnixTimestampSec: new BigNumber(INF_TIMESTAMP), + expirationUnixTimestampSec, }; const orderHash = ZeroEx.getOrderHashHex(exchangeAddress, order); const ecSignature = await zeroEx.signOrderHashAsync(orderHash); -- cgit From 44f11442424c88d1130ee398d0714636c5ade045 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 16:21:01 +0200 Subject: Add comment for fillOrderAsync method, rename fillAmount to fillTakerAmountInBaseUnits and remove default value for shouldCheckTransfer --- src/contract_wrappers/exchange_wrapper.ts | 17 +++++++++++------ test/exchange_wrapper_test.ts | 7 ++++--- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index dbb427d2c..40f22bd28 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -57,18 +57,23 @@ export class ExchangeWrapper extends ContractWrapper { ); return isValidSignature; } - public async fillOrderAsync(signedOrder: SignedOrder, fillAmount: BigNumber.BigNumber, - shouldCheckTransfer: boolean = true): Promise { + /** + * Fills a signed order with a specified amount in baseUnits of the taker token. The caller can + * decide whether they want the call to throw if the balance/allowance checks fail by setting + * shouldCheckTransfer to false. If true, the call will fail without throwing, preserving gas costs. + */ + public async fillOrderAsync(signedOrder: SignedOrder, fillTakerAmountInBaseUnits: BigNumber.BigNumber, + shouldCheckTransfer: boolean): Promise { assert.doesConformToSchema('signedOrder', SchemaValidator.convertToJSONSchemaCompatibleObject(signedOrder as object), signedOrderSchema); - assert.isBigNumber('fillAmount', fillAmount); + assert.isBigNumber('fillTakerAmountInBaseUnits', fillTakerAmountInBaseUnits); assert.isBoolean('shouldCheckTransfer', shouldCheckTransfer); const senderAddress = await this.web3Wrapper.getSenderAddressOrThrowAsync(); const exchangeInstance = await this.getExchangeInstanceOrThrowAsync(); - this.validateFillOrder(signedOrder, fillAmount, senderAddress, shouldCheckTransfer); + this.validateFillOrder(signedOrder, fillTakerAmountInBaseUnits, senderAddress, shouldCheckTransfer); const orderAddresses: OrderAddresses = [ signedOrder.maker, @@ -88,7 +93,7 @@ export class ExchangeWrapper extends ContractWrapper { const gas = await exchangeInstance.fill.estimateGas( orderAddresses, orderValues, - fillAmount, + fillTakerAmountInBaseUnits, shouldCheckTransfer, signedOrder.ecSignature.v, signedOrder.ecSignature.r, @@ -100,7 +105,7 @@ export class ExchangeWrapper extends ContractWrapper { const response: ContractResponse = await exchangeInstance.fill( orderAddresses, orderValues, - fillAmount, + fillTakerAmountInBaseUnits, shouldCheckTransfer, signedOrder.ecSignature.v, signedOrder.ecSignature.r, diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index c5cbc58be..f324c5492 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -107,6 +107,7 @@ describe('ExchangeWrapper', () => { let tokens: Token[]; const addressBySymbol: {[symbol: string]: string} = {}; let networkId: number; + const shouldCheckTransfer = false; const setBalance = async (toAddress: string, amountInBaseUnits: BigNumber.BigNumber|number, tokenAddress: string) => { @@ -133,7 +134,7 @@ describe('ExchangeWrapper', () => { const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); const fillAmount = new BigNumber(0); - expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount)) + expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); }); it('should throw when sender is not a taker', async () => { @@ -142,7 +143,7 @@ describe('ExchangeWrapper', () => { const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); const fillAmount = new BigNumber(5); - expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount)) + expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.NOT_A_TAKER); }); }); @@ -160,7 +161,7 @@ describe('ExchangeWrapper', () => { 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); const fillAmount = new BigNumber(5); zeroEx.setDefaultAccount(taker); - await zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount); + await zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount, shouldCheckTransfer); expect(await zeroEx.token.getBalanceAsync(addressBySymbol.MLN, taker)).to.be.bignumber.equal(5); expect(await zeroEx.token.getBalanceAsync(addressBySymbol.GNT, taker)).to.be.bignumber.equal(0); }); -- cgit From 6c590354c7536ae3ed941fb757be9d0240739e14 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 16:25:28 +0200 Subject: improve comment --- src/contract_wrappers/exchange_wrapper.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index ded0d3519..96bb4c0a0 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -58,9 +58,9 @@ export class ExchangeWrapper extends ContractWrapper { return isValidSignature; } /** - * Fills a signed order with a specified amount in baseUnits of the taker token. The caller can + * Fills a signed order with a fillAmount denominated in baseUnits of the taker token. The caller can * decide whether they want the call to throw if the balance/allowance checks fail by setting - * shouldCheckTransfer to false. If true, the call will fail without throwing, preserving gas costs. + * shouldCheckTransfer to false. If set to true, the call will fail without throwing, preserving gas costs. */ public async fillOrderAsync(signedOrder: SignedOrder, fillTakerAmountInBaseUnits: BigNumber.BigNumber, shouldCheckTransfer: boolean): Promise { -- cgit From f756e1d24e4a27b4e0ce8078884408a321fe2d28 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 16:25:37 +0200 Subject: remove unneeded method --- src/contract_wrappers/exchange_wrapper.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 96bb4c0a0..39b6d27b4 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -71,7 +71,7 @@ export class ExchangeWrapper extends ContractWrapper { assert.isBoolean('shouldCheckTransfer', shouldCheckTransfer); const senderAddress = await this.web3Wrapper.getSenderAddressOrThrowAsync(); - const exchangeInstance = await this.getExchangeInstanceOrThrowAsync(); + const exchangeInstance = await this.getExchangeContractAsync(); this.validateFillOrder(signedOrder, fillTakerAmountInBaseUnits, senderAddress, shouldCheckTransfer); @@ -129,10 +129,6 @@ export class ExchangeWrapper extends ContractWrapper { throw new Error(FillOrderValidationErrs.EXPIRED); } } - private async getExchangeInstanceOrThrowAsync(): Promise { - const contractInstance = await this.instantiateContractIfExistsAsync((ExchangeArtifacts as any)); - return contractInstance as ExchangeContract; - } private throwErrorLogsAsErrors(logs: ContractEvent[]): void { const errEvent = _.find(logs, {event: 'LogError'}); if (!_.isUndefined(errEvent)) { -- cgit From fe025506c97da7d1d32fae0973624d49470340b9 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 16:30:06 +0200 Subject: remove unused arg --- src/contract_wrappers/exchange_wrapper.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 39b6d27b4..0712dd34a 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -117,8 +117,7 @@ export class ExchangeWrapper extends ContractWrapper { ); this.throwErrorLogsAsErrors(response.logs); } - private validateFillOrder(signedOrder: SignedOrder, fillAmount: BigNumber.BigNumber, senderAddress: string, - shouldCheckTransfer: boolean = true) { + private validateFillOrder(signedOrder: SignedOrder, fillAmount: BigNumber.BigNumber, senderAddress: string) { if (fillAmount.eq(0)) { throw new Error(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); } -- cgit From ea42715b9ade871f54d01741ce45f36bce2a6ca2 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 16:54:20 +0200 Subject: remove superfluous param --- src/contract_wrappers/exchange_wrapper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 0712dd34a..b2d201516 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -73,7 +73,7 @@ export class ExchangeWrapper extends ContractWrapper { const senderAddress = await this.web3Wrapper.getSenderAddressOrThrowAsync(); const exchangeInstance = await this.getExchangeContractAsync(); - this.validateFillOrder(signedOrder, fillTakerAmountInBaseUnits, senderAddress, shouldCheckTransfer); + this.validateFillOrder(signedOrder, fillTakerAmountInBaseUnits, senderAddress); const orderAddresses: OrderAddresses = [ signedOrder.maker, -- cgit From 8193d0f5b28043cbcb005b58790abf32ffee38e1 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 16:55:34 +0200 Subject: rename txData to txOpts --- src/types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/types.ts b/src/types.ts index 7c5e1825d..872422af6 100644 --- a/src/types.ts +++ b/src/types.ts @@ -36,9 +36,9 @@ export interface ExchangeContract { isValidSignature: any; fill: { (orderAddresses: OrderAddresses, orderValues: OrderValues, fillAmount: BigNumber.BigNumber, - shouldCheckTransfer: boolean, v: number, r: string, s: string, txData: 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, txData: TxOpts) => number; + shouldCheckTransfer: boolean, v: number, r: string, s: string, txOpts: TxOpts) => number; }; } -- cgit From 5ded2bd52ba911e50e2cb3606a2e0e7a32cbd778 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 17:00:43 +0200 Subject: Refactor tests --- test/exchange_wrapper_test.ts | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index f324c5492..4c61320e3 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -108,6 +108,8 @@ describe('ExchangeWrapper', () => { const addressBySymbol: {[symbol: string]: string} = {}; let networkId: number; const shouldCheckTransfer = false; + let maker: string; + let taker: string; const setBalance = async (toAddress: string, amountInBaseUnits: BigNumber.BigNumber|number, tokenAddress: string) => { @@ -127,19 +129,23 @@ describe('ExchangeWrapper', () => { }); networkId = await promisify(web3.version.getNetwork)(); }); + beforeEach('setup', () => { + maker = userAddresses[0]; + taker = userAddresses[1]; + }); + afterEach('reset default account', () => { + zeroEx.setDefaultAccount(userAddresses[0]); + }); describe('failed fills', () => { it('should throw when the fill amount is zero', async () => { - const maker = userAddresses[0]; - const taker = userAddresses[0]; const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); const fillAmount = new BigNumber(0); - expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount, shouldCheckTransfer)) + zeroEx.setDefaultAccount(taker); + expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount)) .to.be.rejectedWith(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); }); it('should throw when sender is not a taker', async () => { - const maker = userAddresses[0]; - const taker = userAddresses[1]; const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); const fillAmount = new BigNumber(5); @@ -148,12 +154,7 @@ describe('ExchangeWrapper', () => { }); }); describe('successful fills', () => { - afterEach('reset default account', () => { - zeroEx.setDefaultAccount(userAddresses[0]); - }); it('should fill the valid order', async () => { - const maker = userAddresses[0]; - const taker = userAddresses[1]; await setAllowance(maker, 5, addressBySymbol.MLN); await setBalance(taker, 5, addressBySymbol.GNT); await setAllowance(taker, 5, addressBySymbol.GNT); -- cgit From af61b5a9089b2575c8f0a44e1f0bceac41bb891f Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 17:03:15 +0200 Subject: Add shouldCheckTransfer --- test/exchange_wrapper_test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 4c61320e3..e8a217d0f 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -142,7 +142,7 @@ describe('ExchangeWrapper', () => { 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); const fillAmount = new BigNumber(0); zeroEx.setDefaultAccount(taker); - expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount)) + expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); }); it('should throw when sender is not a taker', async () => { -- cgit From 59bc13c188cc54443e1514340310142c8442a88c Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 17:03:39 +0200 Subject: remove comment --- test/0x.js_test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/test/0x.js_test.ts b/test/0x.js_test.ts index a548d8268..f2bb40d75 100644 --- a/test/0x.js_test.ts +++ b/test/0x.js_test.ts @@ -10,7 +10,6 @@ import {constants} from './utils/constants'; import {web3Factory} from './utils/web3_factory'; import {Order} from '../src/types'; -// Use BigNumber chai add-on chai.use(ChaiBigNumber()); chai.use(dirtyChai); const expect = chai.expect; -- cgit From 60d658a0249cdfb54d0763eb322cf6b16a1af36e Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 17:03:49 +0200 Subject: put external imports at the top --- test/exchange_wrapper_test.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index f324c5492..251bd03ec 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -1,16 +1,16 @@ +import * as _ from 'lodash'; import 'mocha'; import * as chai from 'chai'; +import * as Web3 from 'web3'; +import * as BigNumber from 'bignumber.js'; +import * as dirtyChai from 'dirty-chai'; +import ChaiBigNumber = require('chai-bignumber'); +import promisify = require('es6-promisify'); import {web3Factory} from './utils/web3_factory'; import {ZeroEx} from '../src/0x.js'; -import promisify = require('es6-promisify'); -import * as _ from 'lodash'; import {BlockchainLifecycle} from './utils/blockchain_lifecycle'; -import * as BigNumber from 'bignumber.js'; import {orderFactory} from './utils/order_factory'; import {FillOrderValidationErrs, Token} from '../src/types'; -import * as Web3 from 'web3'; -import * as dirtyChai from 'dirty-chai'; -import ChaiBigNumber = require('chai-bignumber'); chai.use(dirtyChai); chai.use(ChaiBigNumber()); -- cgit From 00c597411fb1f14cc7f2d759a52638c4c2a61830 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 17:07:43 +0200 Subject: reorder import --- test/exchange_wrapper_test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 04fd6a7e1..3f2054e0e 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -1,5 +1,5 @@ -import * as _ from 'lodash'; import 'mocha'; +import * as _ from 'lodash'; import * as chai from 'chai'; import * as Web3 from 'web3'; import * as BigNumber from 'bignumber.js'; -- cgit From 2c65a658e7660654e2ee334e43b13c2dce0e134d Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 17:07:53 +0200 Subject: remove legacy code --- test/exchange_wrapper_test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 3f2054e0e..70f4deec3 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -25,7 +25,6 @@ describe('ExchangeWrapper', () => { web3 = web3Factory.create(); zeroEx = new ZeroEx(web3); userAddresses = await promisify(web3.eth.getAccounts)(); - web3.eth.defaultAccount = userAddresses[0]; }); beforeEach(async () => { await blockchainLifecycle.startAsync(); -- cgit From bcc8e43ab889b98bc2ebe2f4f6c172cbef925838 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 17:08:44 +0200 Subject: reorder variabled --- test/exchange_wrapper_test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 70f4deec3..4d28dd2bd 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -104,11 +104,11 @@ describe('ExchangeWrapper', () => { }); describe('#fillOrderAsync', () => { let tokens: Token[]; - const addressBySymbol: {[symbol: string]: string} = {}; - let networkId: number; - const shouldCheckTransfer = false; let maker: string; let taker: string; + let networkId: number; + const addressBySymbol: {[symbol: string]: string} = {}; + const shouldCheckTransfer = false; const setBalance = async (toAddress: string, amountInBaseUnits: BigNumber.BigNumber|number, tokenAddress: string) => { -- cgit From 9a3cd3d06c5cb74e772685501bedee7e3fce5990 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 17:09:02 +0200 Subject: Add test, for throw when order is expired --- test/exchange_wrapper_test.ts | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 4d28dd2bd..92e2514dd 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -104,6 +104,10 @@ describe('ExchangeWrapper', () => { }); describe('#fillOrderAsync', () => { let tokens: Token[]; + const addressBySymbol: {[symbol: string]: string} = {}; + let networkId: number; + const fillAmount = new BigNumber(5); + const shouldCheckTransfer = false; let maker: string; let taker: string; let networkId: number; @@ -139,18 +143,25 @@ describe('ExchangeWrapper', () => { it('should throw when the fill amount is zero', async () => { const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); - const fillAmount = new BigNumber(0); + const zeroFillAmount = new BigNumber(0); zeroEx.setDefaultAccount(taker); - expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount, shouldCheckTransfer)) + expect(zeroEx.exchange.fillOrderAsync(signedOrder, zeroFillAmount, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); }); it('should throw when sender is not a taker', async () => { const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); - const fillAmount = new BigNumber(5); expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.NOT_A_TAKER); }); + it('should throw when order is expired', async () => { + const OLD_TIMESTAMP = new BigNumber(42); + const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, + 5, addressBySymbol.MLN, 5, addressBySymbol.GNT, OLD_TIMESTAMP); + zeroEx.setDefaultAccount(taker); + expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount, shouldCheckTransfer)) + .to.be.rejectedWith(FillOrderValidationErrs.EXPIRED); + }); }); describe('successful fills', () => { it('should fill the valid order', async () => { -- cgit From d1f352810f2228b2be143557f86e55c90193eea4 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 17:13:15 +0200 Subject: give some balance and allowance by default --- test/exchange_wrapper_test.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 92e2514dd..2becd2cbe 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -132,9 +132,12 @@ describe('ExchangeWrapper', () => { }); networkId = await promisify(web3.version.getNetwork)(); }); - beforeEach('setup', () => { + beforeEach('setup', async () => { maker = userAddresses[0]; taker = userAddresses[1]; + await setAllowance(maker, 5, addressBySymbol.MLN); + await setBalance(taker, 5, addressBySymbol.GNT); + await setAllowance(taker, 5, addressBySymbol.GNT); }); afterEach('reset default account', () => { zeroEx.setDefaultAccount(userAddresses[0]); @@ -165,12 +168,8 @@ describe('ExchangeWrapper', () => { }); describe('successful fills', () => { it('should fill the valid order', async () => { - await setAllowance(maker, 5, addressBySymbol.MLN); - await setBalance(taker, 5, addressBySymbol.GNT); - await setAllowance(taker, 5, addressBySymbol.GNT); const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); - const fillAmount = new BigNumber(5); zeroEx.setDefaultAccount(taker); await zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount, shouldCheckTransfer); expect(await zeroEx.token.getBalanceAsync(addressBySymbol.MLN, taker)).to.be.bignumber.equal(5); -- cgit From cc0d6411071cb36a224c8f4f0cb742edb4193482 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 17:16:16 +0200 Subject: Add async suffix and fix alignment --- test/exchange_wrapper_test.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 4d28dd2bd..d6dca0a63 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -109,15 +109,15 @@ describe('ExchangeWrapper', () => { let networkId: number; const addressBySymbol: {[symbol: string]: string} = {}; const shouldCheckTransfer = false; - const setBalance = async (toAddress: string, - amountInBaseUnits: BigNumber.BigNumber|number, - tokenAddress: string) => { + const setBalanceAsync = async (toAddress: string, + amountInBaseUnits: BigNumber.BigNumber|number, + tokenAddress: string) => { const amount = _.isNumber(amountInBaseUnits) ? new BigNumber(amountInBaseUnits) : amountInBaseUnits; await zeroEx.token.transferAsync(tokenAddress, userAddresses[0], toAddress, amount); }; - const setAllowance = async (ownerAddress: string, - amountInBaseUnits: BigNumber.BigNumber|number, - tokenAddress: string) => { + const setAllowanceAsync = async (ownerAddress: string, + amountInBaseUnits: BigNumber.BigNumber|number, + tokenAddress: string) => { const amount = _.isNumber(amountInBaseUnits) ? new BigNumber(amountInBaseUnits) : amountInBaseUnits; await zeroEx.token.setProxyAllowanceAsync(tokenAddress, ownerAddress, amount); }; @@ -154,9 +154,9 @@ describe('ExchangeWrapper', () => { }); describe('successful fills', () => { it('should fill the valid order', async () => { - await setAllowance(maker, 5, addressBySymbol.MLN); - await setBalance(taker, 5, addressBySymbol.GNT); - await setAllowance(taker, 5, addressBySymbol.GNT); + await setAllowanceAsync(maker, 5, addressBySymbol.MLN); + await setBalanceAsync(taker, 5, addressBySymbol.GNT); + await setAllowanceAsync(taker, 5, addressBySymbol.GNT); const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); const fillAmount = new BigNumber(5); -- cgit From 3e76497f4e47cb897b1afde509c3d2eb424a4f84 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 17:19:06 +0200 Subject: remove duplicate declarations --- test/exchange_wrapper_test.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 9c3683a98..9a519e92e 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -104,10 +104,7 @@ describe('ExchangeWrapper', () => { }); describe('#fillOrderAsync', () => { let tokens: Token[]; - const addressBySymbol: {[symbol: string]: string} = {}; - let networkId: number; const fillAmount = new BigNumber(5); - const shouldCheckTransfer = false; let maker: string; let taker: string; let networkId: number; -- cgit From 1e8eb054bc99baf9d10cafe9d5d388857484a801 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 17:25:33 +0200 Subject: get rid of literal amount params --- test/exchange_wrapper_test.ts | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 9a519e92e..cb7482c99 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -141,23 +141,29 @@ describe('ExchangeWrapper', () => { }); describe('failed fills', () => { it('should throw when the fill amount is zero', async () => { + const makerAmount = 5; + const takerAmount = 5; const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, - 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); + makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT); const zeroFillAmount = new BigNumber(0); zeroEx.setDefaultAccount(taker); expect(zeroEx.exchange.fillOrderAsync(signedOrder, zeroFillAmount, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); }); it('should throw when sender is not a taker', async () => { + const makerAmount = 5; + const takerAmount = 5; const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, - 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); + makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT); expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.NOT_A_TAKER); }); it('should throw when order is expired', async () => { const OLD_TIMESTAMP = new BigNumber(42); + const makerAmount = 5; + const takerAmount = 5; const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, - 5, addressBySymbol.MLN, 5, addressBySymbol.GNT, OLD_TIMESTAMP); + makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT, OLD_TIMESTAMP); zeroEx.setDefaultAccount(taker); expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.EXPIRED); @@ -165,12 +171,16 @@ describe('ExchangeWrapper', () => { }); describe('successful fills', () => { it('should fill the valid order', async () => { + const makerAmount = 5; + const takerAmount = 5; const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, - 5, addressBySymbol.MLN, 5, addressBySymbol.GNT); + makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT); zeroEx.setDefaultAccount(taker); await zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount, shouldCheckTransfer); - expect(await zeroEx.token.getBalanceAsync(addressBySymbol.MLN, taker)).to.be.bignumber.equal(5); - expect(await zeroEx.token.getBalanceAsync(addressBySymbol.GNT, taker)).to.be.bignumber.equal(0); + expect(await zeroEx.token.getBalanceAsync(addressBySymbol.MLN, taker)) + .to.be.bignumber.equal(fillAmount); + expect(await zeroEx.token.getBalanceAsync(addressBySymbol.GNT, taker)) + .to.be.bignumber.equal(0); }); }); }); -- cgit From 7ff0f677a12386a119bcadbdabd0721f9fc4cbce Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 17:27:23 +0200 Subject: move external imports to top --- test/utils/order_factory.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/utils/order_factory.ts b/test/utils/order_factory.ts index c6c6ed927..3195803ad 100644 --- a/test/utils/order_factory.ts +++ b/test/utils/order_factory.ts @@ -1,6 +1,6 @@ -import {SignedOrder, Token} from '../../src/types'; -import * as BigNumber from 'bignumber.js'; import * as _ from 'lodash'; +import * as BigNumber from 'bignumber.js'; +import {SignedOrder, Token} from '../../src/types'; import {ZeroEx} from '../../src/0x.js'; import {constants} from './constants'; import * as ExchangeArtifacts from '../../src/artifacts/Exchange.json'; -- cgit From ab5d99954946e01bdede26c4157fcfbdf9ae8bb1 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 17:23:03 +0200 Subject: Remove duplicate declarations --- test/exchange_wrapper_test.ts | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index cb7482c99..091d23fca 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -110,18 +110,6 @@ describe('ExchangeWrapper', () => { let networkId: number; const addressBySymbol: {[symbol: string]: string} = {}; const shouldCheckTransfer = false; - const setBalanceAsync = async (toAddress: string, - amountInBaseUnits: BigNumber.BigNumber|number, - tokenAddress: string) => { - const amount = _.isNumber(amountInBaseUnits) ? new BigNumber(amountInBaseUnits) : amountInBaseUnits; - await zeroEx.token.transferAsync(tokenAddress, userAddresses[0], toAddress, amount); - }; - const setAllowanceAsync = async (ownerAddress: string, - amountInBaseUnits: BigNumber.BigNumber|number, - tokenAddress: string) => { - const amount = _.isNumber(amountInBaseUnits) ? new BigNumber(amountInBaseUnits) : amountInBaseUnits; - await zeroEx.token.setProxyAllowanceAsync(tokenAddress, ownerAddress, amount); - }; before('fetch tokens', async () => { tokens = await zeroEx.tokenRegistry.getTokensAsync(); _.forEach(tokens, token => { @@ -132,9 +120,9 @@ describe('ExchangeWrapper', () => { beforeEach('setup', async () => { maker = userAddresses[0]; taker = userAddresses[1]; - await setAllowanceAsync(maker, 5, addressBySymbol.MLN); - await setBalanceAsync(taker, 5, addressBySymbol.GNT); - await setAllowanceAsync(taker, 5, addressBySymbol.GNT); + await zeroEx.token.setProxyAllowanceAsync(addressBySymbol.MLN, maker, new BigNumber(5)); + await zeroEx.token.transferAsync(addressBySymbol.GNT, maker, taker, new BigNumber(5)); + await zeroEx.token.setProxyAllowanceAsync(addressBySymbol.GNT, taker, new BigNumber(5)); }); afterEach('reset default account', () => { zeroEx.setDefaultAccount(userAddresses[0]); -- cgit From 24a745092e0f7a626f5cbcfaef2e56567f0ace1d Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 17:38:09 +0200 Subject: Stop passing exchangeAddress into getOrderHash and instead get it from the artifacts --- src/0x.js.ts | 69 +++++++++++++++++++++++++++------------------ test/0x.js_test.ts | 43 ++++++++++++++-------------- test/utils/order_factory.ts | 4 +-- 3 files changed, 64 insertions(+), 52 deletions(-) diff --git a/src/0x.js.ts b/src/0x.js.ts index a29c25e0c..19e38aafe 100644 --- a/src/0x.js.ts +++ b/src/0x.js.ts @@ -19,6 +19,7 @@ import {TokenWrapper} from './contract_wrappers/token_wrapper'; import {SolidityTypes, ECSignature, ZeroExError} from './types'; import {Order} from './types'; import {orderSchema} from './schemas/order_schemas'; +import * as ExchangeArtifacts from '../artifacts/Exchange.json'; // Customize our BigNumber instances bigNumberConfigs.configure(); @@ -32,34 +33,6 @@ export class ZeroEx { public tokenRegistry: TokenRegistryWrapper; public token: TokenWrapper; private web3Wrapper: Web3Wrapper; - /** - * Computes the orderHash given the order parameters and returns it as a hex encoded string. - */ - public static getOrderHashHex(exchangeContractAddr: string, order: Order): 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; - } /** * Verifies that the elliptic curve signature `signature` was generated * by signing `data` with the private key corresponding to the `signerAddressHex` address. @@ -150,6 +123,35 @@ export class ZeroEx { public setDefaultAccount(account: string): void { this.web3Wrapper.setDefaultAccount(account); } + /** + * Computes the orderHash given the order parameters and returns it as a hex encoded string. + */ + public async getOrderHashHexAsync(order: Order): 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); + return hashHex; + } /** * Signs an orderHash and returns it's elliptic curve signature * This method currently supports TestRPC, Geth and Parity above and below V1.6.6 @@ -207,4 +209,15 @@ export class ZeroEx { } return ecSignature; } + private async getExchangeAddressAsync() { + const networkIdIfExists = await this.web3Wrapper.getNetworkIdIfExistsAsync(); + const exchangeNetworkConfigsIfExists = _.isUndefined(networkIdIfExists) ? + undefined : + (ExchangeArtifacts as any).networks[networkIdIfExists]; + if (_.isUndefined(exchangeNetworkConfigsIfExists)) { + throw new Error(ZeroExError.CONTRACT_NOT_DEPLOYED_ON_NETWORK); + } + const exchangeAddress = exchangeNetworkConfigsIfExists.address; + return exchangeAddress; + } } diff --git a/test/0x.js_test.ts b/test/0x.js_test.ts index f2bb40d75..8c5e9c929 100644 --- a/test/0x.js_test.ts +++ b/test/0x.js_test.ts @@ -43,27 +43,6 @@ describe('ZeroEx library', () => { expect((tokenRegistryWeb3WrapperProvider as any).zeroExTestId).to.be.a('number'); }); }); - describe('#getOrderHash', () => { - const expectedOrderHash = '0x103a5e97dab5dbeb8f385636f86a7d1e458a7ccbe1bd194727f0b2f85ab116c7'; - const order: Order = { - maker: constants.NULL_ADDRESS, - taker: constants.NULL_ADDRESS, - feeRecipient: constants.NULL_ADDRESS, - makerTokenAddress: constants.NULL_ADDRESS, - takerTokenAddress: constants.NULL_ADDRESS, - salt: new BigNumber(0), - makerFee: new BigNumber(0), - takerFee: new BigNumber(0), - makerTokenAmount: new BigNumber(0), - takerTokenAmount: new BigNumber(0), - expirationUnixTimestampSec: new BigNumber(0), - }; - const exchangeAddress = constants.NULL_ADDRESS; - it('calculates the order hash', () => { - const orderHash = ZeroEx.getOrderHashHex(exchangeAddress, order); - expect(orderHash).to.be.equal(expectedOrderHash); - }); - }); describe('#isValidSignature', () => { // This test data was borrowed from the JSON RPC documentation // Source: https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign @@ -174,6 +153,28 @@ describe('ZeroEx library', () => { expect(baseUnitAmount).to.be.bignumber.equal(expectedUnitAmount); }); }); + describe('#getOrderHashAsync', () => { + const expectedOrderHash = '0x103a5e97dab5dbeb8f385636f86a7d1e458a7ccbe1bd194727f0b2f85ab116c7'; + const order: Order = { + maker: constants.NULL_ADDRESS, + taker: constants.NULL_ADDRESS, + feeRecipient: constants.NULL_ADDRESS, + makerTokenAddress: constants.NULL_ADDRESS, + takerTokenAddress: constants.NULL_ADDRESS, + salt: new BigNumber(0), + makerFee: new BigNumber(0), + takerFee: new BigNumber(0), + makerTokenAmount: new BigNumber(0), + takerTokenAmount: new BigNumber(0), + expirationUnixTimestampSec: new BigNumber(0), + }; + it('calculates the order hash', async () => { + const web3 = web3Factory.create(); + const zeroEx = new ZeroEx(web3); + const orderHash = await zeroEx.getOrderHashHexAsync(order); + expect(orderHash).to.be.equal(expectedOrderHash); + }); + }); describe('#signOrderHashAsync', () => { let stubs: Sinon.SinonStub[] = []; afterEach(() => { diff --git a/test/utils/order_factory.ts b/test/utils/order_factory.ts index 3195803ad..941056c7e 100644 --- a/test/utils/order_factory.ts +++ b/test/utils/order_factory.ts @@ -16,8 +16,6 @@ export const orderFactory = { takerTokenAmount: BigNumber.BigNumber|number, takerTokenAddress: string, expirationUnixTimestampSec?: BigNumber.BigNumber): Promise { - // TODO refactor and check - const exchangeAddress: string = (ExchangeArtifacts as any).networks[networkId].address; const INF_TIMESTAMP = new BigNumber(2524604400); expirationUnixTimestampSec = _.isUndefined(expirationUnixTimestampSec) ? INF_TIMESTAMP : @@ -35,7 +33,7 @@ export const orderFactory = { feeRecipient: constants.NULL_ADDRESS, expirationUnixTimestampSec, }; - const orderHash = ZeroEx.getOrderHashHex(exchangeAddress, order); + const orderHash = await zeroEx.getOrderHashHexAsync(order); const ecSignature = await zeroEx.signOrderHashAsync(orderHash); const signedOrder: SignedOrder = _.assign(order, {ecSignature}); return signedOrder; -- cgit From 35b7a60e9704e5ab222dc7552cbe523d12dcb003 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 17:38:20 +0200 Subject: Add missing comma and semi-colon --- test/utils/order_factory.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/utils/order_factory.ts b/test/utils/order_factory.ts index 941056c7e..c0d70f39b 100644 --- a/test/utils/order_factory.ts +++ b/test/utils/order_factory.ts @@ -37,5 +37,5 @@ export const orderFactory = { const ecSignature = await zeroEx.signOrderHashAsync(orderHash); const signedOrder: SignedOrder = _.assign(order, {ecSignature}); return signedOrder; - } -} + }, +}; -- cgit From 85d4badbd6141bed4f7f00c08e882eb8db362252 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 17:39:58 +0200 Subject: remove unused arg --- test/exchange_wrapper_test.ts | 10 ++++------ test/utils/order_factory.ts | 1 - 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 091d23fca..e74cdacaf 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -107,7 +107,6 @@ describe('ExchangeWrapper', () => { const fillAmount = new BigNumber(5); let maker: string; let taker: string; - let networkId: number; const addressBySymbol: {[symbol: string]: string} = {}; const shouldCheckTransfer = false; before('fetch tokens', async () => { @@ -115,7 +114,6 @@ describe('ExchangeWrapper', () => { _.forEach(tokens, token => { addressBySymbol[token.symbol] = token.address; }); - networkId = await promisify(web3.version.getNetwork)(); }); beforeEach('setup', async () => { maker = userAddresses[0]; @@ -131,7 +129,7 @@ describe('ExchangeWrapper', () => { it('should throw when the fill amount is zero', async () => { const makerAmount = 5; const takerAmount = 5; - const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, + const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, maker, taker, makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT); const zeroFillAmount = new BigNumber(0); zeroEx.setDefaultAccount(taker); @@ -141,7 +139,7 @@ describe('ExchangeWrapper', () => { it('should throw when sender is not a taker', async () => { const makerAmount = 5; const takerAmount = 5; - const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, + const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, maker, taker, makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT); expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.NOT_A_TAKER); @@ -150,7 +148,7 @@ describe('ExchangeWrapper', () => { const OLD_TIMESTAMP = new BigNumber(42); const makerAmount = 5; const takerAmount = 5; - const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, + const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, maker, taker, makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT, OLD_TIMESTAMP); zeroEx.setDefaultAccount(taker); expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount, shouldCheckTransfer)) @@ -161,7 +159,7 @@ describe('ExchangeWrapper', () => { it('should fill the valid order', async () => { const makerAmount = 5; const takerAmount = 5; - const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, networkId, maker, taker, + const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, maker, taker, makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT); zeroEx.setDefaultAccount(taker); await zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount, shouldCheckTransfer); diff --git a/test/utils/order_factory.ts b/test/utils/order_factory.ts index c0d70f39b..359168ff9 100644 --- a/test/utils/order_factory.ts +++ b/test/utils/order_factory.ts @@ -8,7 +8,6 @@ import * as ExchangeArtifacts from '../../src/artifacts/Exchange.json'; export const orderFactory = { async createSignedOrderAsync( zeroEx: ZeroEx, - networkId: number, maker: string, taker: string, makerTokenAmount: BigNumber.BigNumber|number, -- cgit From 29955d3606f836a14bd491a8779f6a607d5fa469 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 17:49:41 +0200 Subject: Fix import --- src/0x.js.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/0x.js.ts b/src/0x.js.ts index 19e38aafe..336700a54 100644 --- a/src/0x.js.ts +++ b/src/0x.js.ts @@ -19,7 +19,7 @@ import {TokenWrapper} from './contract_wrappers/token_wrapper'; import {SolidityTypes, ECSignature, ZeroExError} from './types'; import {Order} from './types'; import {orderSchema} from './schemas/order_schemas'; -import * as ExchangeArtifacts from '../artifacts/Exchange.json'; +import * as ExchangeArtifacts from './artifacts/Exchange.json'; // Customize our BigNumber instances bigNumberConfigs.configure(); -- cgit From 69a596352d47502e810adc10ffd0c89b7fa2d1d0 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 17:49:53 +0200 Subject: Fix getOrderHashAsync test --- test/0x.js_test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/0x.js_test.ts b/test/0x.js_test.ts index 8c5e9c929..efc703ea1 100644 --- a/test/0x.js_test.ts +++ b/test/0x.js_test.ts @@ -154,6 +154,7 @@ describe('ZeroEx library', () => { }); }); describe('#getOrderHashAsync', () => { + const exchangeContractAddress = constants.NULL_ADDRESS; const expectedOrderHash = '0x103a5e97dab5dbeb8f385636f86a7d1e458a7ccbe1bd194727f0b2f85ab116c7'; const order: Order = { maker: constants.NULL_ADDRESS, @@ -168,9 +169,21 @@ describe('ZeroEx library', () => { takerTokenAmount: new BigNumber(0), expirationUnixTimestampSec: new BigNumber(0), }; + let stubs: Sinon.SinonStub[] = []; + afterEach(() => { + // clean up any stubs after the test has completed + _.each(stubs, s => s.restore()); + stubs = []; + }); it('calculates the order hash', async () => { const web3 = web3Factory.create(); const zeroEx = new ZeroEx(web3); + + stubs = [ + Sinon.stub((zeroEx as any), 'getExchangeAddressAsync') + .returns(Promise.resolve(exchangeContractAddress)), + ]; + const orderHash = await zeroEx.getOrderHashHexAsync(order); expect(orderHash).to.be.equal(expectedOrderHash); }); -- cgit From aef3ed9fd7e1d8c72a02bb2eec970597cb353a4d Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 17:51:49 +0200 Subject: Follow constants convention --- test/exchange_wrapper_test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index e74cdacaf..ad5eba699 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -145,11 +145,11 @@ describe('ExchangeWrapper', () => { .to.be.rejectedWith(FillOrderValidationErrs.NOT_A_TAKER); }); it('should throw when order is expired', async () => { - const OLD_TIMESTAMP = new BigNumber(42); + const oldTimestamp = new BigNumber(42); const makerAmount = 5; const takerAmount = 5; const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, maker, taker, - makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT, OLD_TIMESTAMP); + makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT, oldTimestamp); zeroEx.setDefaultAccount(taker); expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.EXPIRED); -- cgit From 19e922724e963950c97c009def39019b382fb516 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 17:52:31 +0200 Subject: rename variable --- test/utils/order_factory.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/utils/order_factory.ts b/test/utils/order_factory.ts index 359168ff9..0f370ed34 100644 --- a/test/utils/order_factory.ts +++ b/test/utils/order_factory.ts @@ -15,9 +15,9 @@ export const orderFactory = { takerTokenAmount: BigNumber.BigNumber|number, takerTokenAddress: string, expirationUnixTimestampSec?: BigNumber.BigNumber): Promise { - const INF_TIMESTAMP = new BigNumber(2524604400); + const defaultExpirationUnixTimestampSec = new BigNumber(2524604400); // Close to infinite expirationUnixTimestampSec = _.isUndefined(expirationUnixTimestampSec) ? - INF_TIMESTAMP : + defaultExpirationUnixTimestampSec : expirationUnixTimestampSec; const order = { maker, -- cgit From 389c18e98e2b5663b1732d7c34f9b21afef66e44 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 17:56:01 +0200 Subject: Add test to check the balance --- test/exchange_wrapper_test.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index ad5eba699..6b2fd6477 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -154,6 +154,16 @@ describe('ExchangeWrapper', () => { expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.EXPIRED); }); + it('should throw when not enough balance', async () => { + const makerAmount = 10; + const takerAmount = 10; + const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, maker, taker, + makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT); + zeroEx.setDefaultAccount(taker); + const tooMuch = new BigNumber(6); + expect(zeroEx.exchange.fillOrderAsync(signedOrder, tooMuch, true)) + .to.be.rejectedWith(FillOrderValidationErrs.EXPIRED); + }); }); describe('successful fills', () => { it('should fill the valid order', async () => { -- cgit From 6ced554d9f6cf00d0d9e8f9ff8170af4f1cfbee3 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 18:15:26 +0200 Subject: Revert "Add test to check the balance" This reverts commit 389c18e98e2b5663b1732d7c34f9b21afef66e44. --- test/exchange_wrapper_test.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 6b2fd6477..ad5eba699 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -154,16 +154,6 @@ describe('ExchangeWrapper', () => { expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.EXPIRED); }); - it('should throw when not enough balance', async () => { - const makerAmount = 10; - const takerAmount = 10; - const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, maker, taker, - makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT); - zeroEx.setDefaultAccount(taker); - const tooMuch = new BigNumber(6); - expect(zeroEx.exchange.fillOrderAsync(signedOrder, tooMuch, true)) - .to.be.rejectedWith(FillOrderValidationErrs.EXPIRED); - }); }); describe('successful fills', () => { it('should fill the valid order', async () => { -- cgit From 0554f947b12f36a1cd5f7be469123e794b467f0b Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 18:21:12 +0200 Subject: Add not enough taker balance tests --- src/0x.js.ts | 4 ++-- src/contract_wrappers/exchange_wrapper.ts | 16 ++++++++++++++-- src/types.ts | 4 ++++ test/exchange_wrapper_test.ts | 24 +++++++++++++++++------- 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/0x.js.ts b/src/0x.js.ts index 336700a54..a95bc3384 100644 --- a/src/0x.js.ts +++ b/src/0x.js.ts @@ -103,9 +103,9 @@ export class ZeroEx { } constructor(web3: Web3) { this.web3Wrapper = new Web3Wrapper(web3); - this.exchange = new ExchangeWrapper(this.web3Wrapper); - this.tokenRegistry = new TokenRegistryWrapper(this.web3Wrapper); this.token = new TokenWrapper(this.web3Wrapper); + this.exchange = new ExchangeWrapper(this.web3Wrapper, this.token); + this.tokenRegistry = new TokenRegistryWrapper(this.web3Wrapper); } /** * Sets a new provider for the web3 instance used by 0x.js diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index b2d201516..dd3c3c933 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -19,6 +19,7 @@ import {signedOrderSchema} from '../schemas/order_schemas'; import {SchemaValidator} from '../utils/schema_validator'; import {ContractResponse} from '../types'; import {constants} from '../utils/constants'; +import {TokenWrapper} from './token_wrapper'; export class ExchangeWrapper extends ContractWrapper { private exchangeContractErrCodesToMsg = { @@ -30,8 +31,10 @@ export class ExchangeWrapper extends ContractWrapper { [ExchangeContractErrCodes.ERROR_FILL_BALANCE_ALLOWANCE]: ExchangeContractErrs.ORDER_BALANCE_ALLOWANCE_ERROR, }; private exchangeContractIfExists?: ExchangeContract; - constructor(web3Wrapper: Web3Wrapper) { + private tokenWrapper: TokenWrapper; + constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper) { super(web3Wrapper); + this.tokenWrapper = tokenWrapper; } public invalidateContractInstance(): void { delete this.exchangeContractIfExists; @@ -117,7 +120,7 @@ export class ExchangeWrapper extends ContractWrapper { ); this.throwErrorLogsAsErrors(response.logs); } - private validateFillOrder(signedOrder: SignedOrder, fillAmount: BigNumber.BigNumber, senderAddress: string) { + private async validateFillOrder(signedOrder: SignedOrder, fillAmount: BigNumber.BigNumber, senderAddress: string) { if (fillAmount.eq(0)) { throw new Error(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); } @@ -127,6 +130,15 @@ export class ExchangeWrapper extends ContractWrapper { if (signedOrder.expirationUnixTimestampSec.lessThan(Date.now() / 1000)) { throw new Error(FillOrderValidationErrs.EXPIRED); } + const makerBalance = await this.tokenWrapper.getBalanceAsync(signedOrder.makerTokenAddress, signedOrder.maker); + const takerBalance = await this.tokenWrapper.getBalanceAsync(signedOrder.takerTokenAddress, senderAddress); + const makerAllowance = await this.tokenWrapper.getProxyAllowanceAsync(signedOrder.makerTokenAddress, + signedOrder.maker); + const takerAllowance = await this.tokenWrapper.getProxyAllowanceAsync(signedOrder.takerTokenAddress, + senderAddress); + if (fillAmount.greaterThan(takerBalance)) { + throw new Error(FillOrderValidationErrs.NOT_ENOUGH_TAKER_BALANCE); + } } private throwErrorLogsAsErrors(logs: ContractEvent[]): void { const errEvent = _.find(logs, {event: 'LogError'}); diff --git a/src/types.ts b/src/types.ts index 872422af6..ad5d8fb17 100644 --- a/src/types.ts +++ b/src/types.ts @@ -89,6 +89,10 @@ export const FillOrderValidationErrs = strEnum([ 'FILL_AMOUNT_IS_ZERO', 'NOT_A_TAKER', 'EXPIRED', + 'NOT_ENOUGH_TAKER_BALANCE', + 'NOT_ENOUGH_TAKER_ALLOWANCE', + 'NOT_ENOUGH_MAKER_BALANCE', + 'NOT_ENOUGH_MAKER_ALLOWANCE', ]); export type FillOrderValidationErrs = keyof typeof FillOrderValidationErrs; diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index ad5eba699..09fb11cb3 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -104,7 +104,7 @@ describe('ExchangeWrapper', () => { }); describe('#fillOrderAsync', () => { let tokens: Token[]; - const fillAmount = new BigNumber(5); + const fillTakerAmountInBaseUnits = new BigNumber(5); let maker: string; let taker: string; const addressBySymbol: {[symbol: string]: string} = {}; @@ -141,19 +141,29 @@ describe('ExchangeWrapper', () => { const takerAmount = 5; const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, maker, taker, makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT); - expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount, shouldCheckTransfer)) + expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.NOT_A_TAKER); }); it('should throw when order is expired', async () => { - const oldTimestamp = new BigNumber(42); + const timestampInThePast = new BigNumber(42); const makerAmount = 5; const takerAmount = 5; const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, maker, taker, - makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT, oldTimestamp); + makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT, timestampInThePast); zeroEx.setDefaultAccount(taker); - expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount, shouldCheckTransfer)) + expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.EXPIRED); }); + it('should throw when not enough balance', async () => { + const makerAmount = 10; + const takerAmount = 10; + const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, maker, taker, + makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT); + zeroEx.setDefaultAccount(taker); + const moreThanTheBalance = new BigNumber(6); + expect(zeroEx.exchange.fillOrderAsync(signedOrder, moreThanTheBalance, true)) + .to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_BALANCE); + }); }); describe('successful fills', () => { it('should fill the valid order', async () => { @@ -162,9 +172,9 @@ describe('ExchangeWrapper', () => { const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, maker, taker, makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT); zeroEx.setDefaultAccount(taker); - await zeroEx.exchange.fillOrderAsync(signedOrder, fillAmount, shouldCheckTransfer); + await zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer); expect(await zeroEx.token.getBalanceAsync(addressBySymbol.MLN, taker)) - .to.be.bignumber.equal(fillAmount); + .to.be.bignumber.equal(fillTakerAmountInBaseUnits); expect(await zeroEx.token.getBalanceAsync(addressBySymbol.GNT, taker)) .to.be.bignumber.equal(0); }); -- cgit From 520248e6787a04b2fcf45d7f185d85214a84bfd5 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 18:31:08 +0200 Subject: Make validateFillOrder asyncronous --- src/contract_wrappers/exchange_wrapper.ts | 4 ++-- test/exchange_wrapper_test.ts | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index dd3c3c933..dc2c95d4e 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -76,7 +76,7 @@ export class ExchangeWrapper extends ContractWrapper { const senderAddress = await this.web3Wrapper.getSenderAddressOrThrowAsync(); const exchangeInstance = await this.getExchangeContractAsync(); - this.validateFillOrder(signedOrder, fillTakerAmountInBaseUnits, senderAddress); + await this.validateFillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, senderAddress); const orderAddresses: OrderAddresses = [ signedOrder.maker, @@ -120,7 +120,7 @@ export class ExchangeWrapper extends ContractWrapper { ); this.throwErrorLogsAsErrors(response.logs); } - private async validateFillOrder(signedOrder: SignedOrder, fillAmount: BigNumber.BigNumber, senderAddress: string) { + private async validateFillOrderAsync(signedOrder: SignedOrder, fillAmount: BigNumber.BigNumber, senderAddress: string) { if (fillAmount.eq(0)) { throw new Error(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); } diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 09fb11cb3..2746c9e46 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -161,7 +161,8 @@ describe('ExchangeWrapper', () => { makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT); zeroEx.setDefaultAccount(taker); const moreThanTheBalance = new BigNumber(6); - expect(zeroEx.exchange.fillOrderAsync(signedOrder, moreThanTheBalance, true)) + const checkTransfer = true; + expect(zeroEx.exchange.fillOrderAsync(signedOrder, moreThanTheBalance, checkTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_BALANCE); }); }); -- cgit From c42877327e59f983a83c7221f1bec5b31addf5a7 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 18:52:56 +0200 Subject: Change test name --- test/exchange_wrapper_test.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 2746c9e46..4847d10cf 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -154,15 +154,14 @@ describe('ExchangeWrapper', () => { expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.EXPIRED); }); - it('should throw when not enough balance', async () => { + it('should throw when taker balance is less than fill amount', async () => { const makerAmount = 10; const takerAmount = 10; const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, maker, taker, makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT); zeroEx.setDefaultAccount(taker); const moreThanTheBalance = new BigNumber(6); - const checkTransfer = true; - expect(zeroEx.exchange.fillOrderAsync(signedOrder, moreThanTheBalance, checkTransfer)) + expect(zeroEx.exchange.fillOrderAsync(signedOrder, moreThanTheBalance, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_BALANCE); }); }); -- cgit From a1be87058536f5ab10c68c570c1b9994defe52b1 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 1 Jun 2017 19:47:22 +0200 Subject: Create a FillsScenario utils module and use it in the fillOrder tests --- src/0x.js.ts | 2 +- src/contract_wrappers/exchange_wrapper.ts | 10 +++-- src/types.ts | 4 ++ test/exchange_wrapper_test.ts | 64 +++++++++++++------------------ test/utils/fill_scenarios.ts | 29 ++++++++++++++ 5 files changed, 67 insertions(+), 42 deletions(-) create mode 100644 test/utils/fill_scenarios.ts diff --git a/src/0x.js.ts b/src/0x.js.ts index a95bc3384..a613d5f48 100644 --- a/src/0x.js.ts +++ b/src/0x.js.ts @@ -120,7 +120,7 @@ export class ZeroEx { /** * Sets default account for sending transactions. */ - public setDefaultAccount(account: string): void { + public setTransactionSenderAccount(account: string): void { this.web3Wrapper.setDefaultAccount(account); } /** diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index dc2c95d4e..eace55f4d 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -74,10 +74,10 @@ export class ExchangeWrapper extends ContractWrapper { assert.isBoolean('shouldCheckTransfer', shouldCheckTransfer); const senderAddress = await this.web3Wrapper.getSenderAddressOrThrowAsync(); - const exchangeInstance = await this.getExchangeContractAsync(); - await this.validateFillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, senderAddress); + const exchangeInstance = await this.getExchangeContractAsync(); + const orderAddresses: OrderAddresses = [ signedOrder.maker, signedOrder.taker, @@ -120,7 +120,8 @@ export class ExchangeWrapper extends ContractWrapper { ); this.throwErrorLogsAsErrors(response.logs); } - private async validateFillOrderAsync(signedOrder: SignedOrder, fillAmount: BigNumber.BigNumber, senderAddress: string) { + private async validateFillOrderAsync(signedOrder: SignedOrder, fillAmount: BigNumber.BigNumber, + senderAddress: string) { if (fillAmount.eq(0)) { throw new Error(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); } @@ -130,7 +131,8 @@ export class ExchangeWrapper extends ContractWrapper { if (signedOrder.expirationUnixTimestampSec.lessThan(Date.now() / 1000)) { throw new Error(FillOrderValidationErrs.EXPIRED); } - const makerBalance = await this.tokenWrapper.getBalanceAsync(signedOrder.makerTokenAddress, signedOrder.maker); + const makerBalance = await this.tokenWrapper.getBalanceAsync(signedOrder.makerTokenAddress, + signedOrder.maker); const takerBalance = await this.tokenWrapper.getBalanceAsync(signedOrder.takerTokenAddress, senderAddress); const makerAllowance = await this.tokenWrapper.getProxyAllowanceAsync(signedOrder.makerTokenAddress, signedOrder.maker); diff --git a/src/types.ts b/src/types.ts index ad5d8fb17..f80f98dc4 100644 --- a/src/types.ts +++ b/src/types.ts @@ -138,3 +138,7 @@ export interface TxOpts { from: string; gas?: number; } + +export interface TokenAddressBySymbol { + [symbol: string]: string; +} diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 4847d10cf..ad6e5496e 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -11,6 +11,7 @@ import {ZeroEx} from '../src/0x.js'; import {BlockchainLifecycle} from './utils/blockchain_lifecycle'; import {orderFactory} from './utils/order_factory'; import {FillOrderValidationErrs, Token} from '../src/types'; +import {FillScenarios} from './utils/fill_scenarios'; chai.use(dirtyChai); chai.use(ChaiBigNumber()); @@ -104,62 +105,52 @@ describe('ExchangeWrapper', () => { }); describe('#fillOrderAsync', () => { let tokens: Token[]; + let fillScenarios: FillScenarios; + let takerAddress: string; const fillTakerAmountInBaseUnits = new BigNumber(5); - let maker: string; - let taker: string; const addressBySymbol: {[symbol: string]: string} = {}; const shouldCheckTransfer = false; before('fetch tokens', async () => { + takerAddress = userAddresses[1]; tokens = await zeroEx.tokenRegistry.getTokensAsync(); _.forEach(tokens, token => { addressBySymbol[token.symbol] = token.address; }); - }); - beforeEach('setup', async () => { - maker = userAddresses[0]; - taker = userAddresses[1]; - await zeroEx.token.setProxyAllowanceAsync(addressBySymbol.MLN, maker, new BigNumber(5)); - await zeroEx.token.transferAsync(addressBySymbol.GNT, maker, taker, new BigNumber(5)); - await zeroEx.token.setProxyAllowanceAsync(addressBySymbol.GNT, taker, new BigNumber(5)); + fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens); }); afterEach('reset default account', () => { - zeroEx.setDefaultAccount(userAddresses[0]); + zeroEx.setTransactionSenderAccount(userAddresses[0]); }); describe('failed fills', () => { it('should throw when the fill amount is zero', async () => { - const makerAmount = 5; - const takerAmount = 5; - const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, maker, taker, - makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT); + const fillableAmount = new BigNumber(5); + const signedOrder = await fillScenarios.createAFillableSignedOrderAsync(takerAddress, fillableAmount); const zeroFillAmount = new BigNumber(0); - zeroEx.setDefaultAccount(taker); + zeroEx.setTransactionSenderAccount(takerAddress); expect(zeroEx.exchange.fillOrderAsync(signedOrder, zeroFillAmount, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); }); it('should throw when sender is not a taker', async () => { - const makerAmount = 5; - const takerAmount = 5; - const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, maker, taker, - makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT); + const fillableAmount = new BigNumber(5); + const signedOrder = await fillScenarios.createAFillableSignedOrderAsync(takerAddress, fillableAmount); expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.NOT_A_TAKER); }); it('should throw when order is expired', async () => { - const timestampInThePast = new BigNumber(42); - const makerAmount = 5; - const takerAmount = 5; - const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, maker, taker, - makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT, timestampInThePast); - zeroEx.setDefaultAccount(taker); + const expirationInPast = new BigNumber(42); + const fillableAmount = new BigNumber(5); + const signedOrder = await fillScenarios.createAFillableSignedOrderAsync(takerAddress, + fillableAmount, + expirationInPast); + zeroEx.setTransactionSenderAccount(takerAddress); expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.EXPIRED); }); it('should throw when taker balance is less than fill amount', async () => { - const makerAmount = 10; - const takerAmount = 10; - const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, maker, taker, - makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT); - zeroEx.setDefaultAccount(taker); + const fillableAmount = new BigNumber(5); + const signedOrder = await fillScenarios.createAFillableSignedOrderAsync(takerAddress, + fillableAmount); + zeroEx.setTransactionSenderAccount(takerAddress); const moreThanTheBalance = new BigNumber(6); expect(zeroEx.exchange.fillOrderAsync(signedOrder, moreThanTheBalance, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_BALANCE); @@ -167,15 +158,14 @@ describe('ExchangeWrapper', () => { }); describe('successful fills', () => { it('should fill the valid order', async () => { - const makerAmount = 5; - const takerAmount = 5; - const signedOrder = await orderFactory.createSignedOrderAsync(zeroEx, maker, taker, - makerAmount, addressBySymbol.MLN, takerAmount, addressBySymbol.GNT); - zeroEx.setDefaultAccount(taker); + const fillableAmount = new BigNumber(5); + const signedOrder = await fillScenarios.createAFillableSignedOrderAsync(takerAddress, + fillableAmount); + zeroEx.setTransactionSenderAccount(takerAddress); await zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer); - expect(await zeroEx.token.getBalanceAsync(addressBySymbol.MLN, taker)) + expect(await zeroEx.token.getBalanceAsync(addressBySymbol.MLN, takerAddress)) .to.be.bignumber.equal(fillTakerAmountInBaseUnits); - expect(await zeroEx.token.getBalanceAsync(addressBySymbol.GNT, taker)) + expect(await zeroEx.token.getBalanceAsync(addressBySymbol.GNT, takerAddress)) .to.be.bignumber.equal(0); }); }); diff --git a/test/utils/fill_scenarios.ts b/test/utils/fill_scenarios.ts new file mode 100644 index 000000000..8447c8c15 --- /dev/null +++ b/test/utils/fill_scenarios.ts @@ -0,0 +1,29 @@ +import * as BigNumber from 'bignumber.js'; +import {ZeroEx} from '../../src/0x.js'; +import {Token, SignedOrder} from '../../src/types'; +import {orderFactory} from '../utils/order_factory'; + +export class FillScenarios { + private zeroEx: ZeroEx; + private userAddresses: string[]; + private tokens: Token[]; + constructor(zeroEx: ZeroEx, userAddresses: string[], tokens: Token[]) { + this.zeroEx = zeroEx; + this.userAddresses = userAddresses; + this.tokens = tokens; + } + public async createAFillableSignedOrderAsync(takerAddress: string, fillableAmount: BigNumber.BigNumber, + expirationUnixTimestampSec?: BigNumber.BigNumber): + Promise { + const [makerAddress] = this.userAddresses; + const [makerToken, takerToken] = this.tokens; + await this.zeroEx.token.setProxyAllowanceAsync(makerToken.address, makerAddress, fillableAmount); + await this.zeroEx.token.transferAsync(takerToken.address, makerAddress, takerAddress, fillableAmount); + await this.zeroEx.token.setProxyAllowanceAsync(takerToken.address, takerAddress, fillableAmount); + + const signedOrder = await orderFactory.createSignedOrderAsync(this.zeroEx, makerAddress, + takerAddress, fillableAmount, makerToken.address, fillableAmount, takerToken.address, + expirationUnixTimestampSec); + return signedOrder; + } +} -- cgit From 511fa537ad3d2a669d5d680efb26012ca1b9c062 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 20:04:12 +0200 Subject: Work --- test/exchange_wrapper_test.ts | 33 ++++++++++++++++++++++++--------- test/utils/fill_scenarios.ts | 12 ++++++------ 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index ad6e5496e..debc8cced 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -105,6 +105,8 @@ describe('ExchangeWrapper', () => { }); describe('#fillOrderAsync', () => { let tokens: Token[]; + let makerTokenAddress: string; + let takerTokenAddress: string; let fillScenarios: FillScenarios; let takerAddress: string; const fillTakerAmountInBaseUnits = new BigNumber(5); @@ -116,6 +118,9 @@ describe('ExchangeWrapper', () => { _.forEach(tokens, token => { addressBySymbol[token.symbol] = token.address; }); + const [makerToken, takerToken] = tokens; + makerTokenAddress = makerToken.address; + takerTokenAddress = takerToken.address; fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens); }); afterEach('reset default account', () => { @@ -124,7 +129,9 @@ describe('ExchangeWrapper', () => { describe('failed fills', () => { it('should throw when the fill amount is zero', async () => { const fillableAmount = new BigNumber(5); - const signedOrder = await fillScenarios.createAFillableSignedOrderAsync(takerAddress, fillableAmount); + const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( + makerTokenAddress, takerTokenAddress, takerAddress, fillableAmount, + ); const zeroFillAmount = new BigNumber(0); zeroEx.setTransactionSenderAccount(takerAddress); expect(zeroEx.exchange.fillOrderAsync(signedOrder, zeroFillAmount, shouldCheckTransfer)) @@ -132,24 +139,27 @@ describe('ExchangeWrapper', () => { }); it('should throw when sender is not a taker', async () => { const fillableAmount = new BigNumber(5); - const signedOrder = await fillScenarios.createAFillableSignedOrderAsync(takerAddress, fillableAmount); + const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( + makerTokenAddress, takerTokenAddress, takerAddress, fillableAmount, + ); expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.NOT_A_TAKER); }); it('should throw when order is expired', async () => { const expirationInPast = new BigNumber(42); const fillableAmount = new BigNumber(5); - const signedOrder = await fillScenarios.createAFillableSignedOrderAsync(takerAddress, - fillableAmount, - expirationInPast); + const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( + makerTokenAddress, takerTokenAddress, takerAddress, fillableAmount, expirationInPast, + ); zeroEx.setTransactionSenderAccount(takerAddress); expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.EXPIRED); }); it('should throw when taker balance is less than fill amount', async () => { const fillableAmount = new BigNumber(5); - const signedOrder = await fillScenarios.createAFillableSignedOrderAsync(takerAddress, - fillableAmount); + const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( + makerTokenAddress, takerTokenAddress, takerAddress, fillableAmount, + ); zeroEx.setTransactionSenderAccount(takerAddress); const moreThanTheBalance = new BigNumber(6); expect(zeroEx.exchange.fillOrderAsync(signedOrder, moreThanTheBalance, shouldCheckTransfer)) @@ -159,9 +169,14 @@ describe('ExchangeWrapper', () => { describe('successful fills', () => { it('should fill the valid order', async () => { const fillableAmount = new BigNumber(5); - const signedOrder = await fillScenarios.createAFillableSignedOrderAsync(takerAddress, - fillableAmount); + const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( + makerTokenAddress, takerTokenAddress, takerAddress, fillableAmount, + ); zeroEx.setTransactionSenderAccount(takerAddress); + expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)) + .to.be.bignumber.equal(0); + expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)) + .to.be.bignumber.equal(fillTakerAmountInBaseUnits); await zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer); expect(await zeroEx.token.getBalanceAsync(addressBySymbol.MLN, takerAddress)) .to.be.bignumber.equal(fillTakerAmountInBaseUnits); diff --git a/test/utils/fill_scenarios.ts b/test/utils/fill_scenarios.ts index 8447c8c15..ac233ad50 100644 --- a/test/utils/fill_scenarios.ts +++ b/test/utils/fill_scenarios.ts @@ -12,17 +12,17 @@ export class FillScenarios { this.userAddresses = userAddresses; this.tokens = tokens; } - public async createAFillableSignedOrderAsync(takerAddress: string, fillableAmount: BigNumber.BigNumber, + public async createAFillableSignedOrderAsync(makerTokenAddress: string, takerTokenAddress: string, + takerAddress: string, fillableAmount: BigNumber.BigNumber, expirationUnixTimestampSec?: BigNumber.BigNumber): Promise { const [makerAddress] = this.userAddresses; - const [makerToken, takerToken] = this.tokens; - await this.zeroEx.token.setProxyAllowanceAsync(makerToken.address, makerAddress, fillableAmount); - await this.zeroEx.token.transferAsync(takerToken.address, makerAddress, takerAddress, fillableAmount); - await this.zeroEx.token.setProxyAllowanceAsync(takerToken.address, takerAddress, fillableAmount); + await this.zeroEx.token.setProxyAllowanceAsync(makerTokenAddress, makerAddress, fillableAmount); + await this.zeroEx.token.transferAsync(takerTokenAddress, makerAddress, takerAddress, fillableAmount); + await this.zeroEx.token.setProxyAllowanceAsync(takerTokenAddress, takerAddress, fillableAmount); const signedOrder = await orderFactory.createSignedOrderAsync(this.zeroEx, makerAddress, - takerAddress, fillableAmount, makerToken.address, fillableAmount, takerToken.address, + takerAddress, fillableAmount, makerTokenAddress, fillableAmount, takerTokenAddress, expirationUnixTimestampSec); return signedOrder; } -- cgit From f663a15c9b000d639bd0d58d0c177e6de9d47346 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 1 Jun 2017 21:12:13 +0200 Subject: Fix tests --- test/exchange_wrapper_test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index debc8cced..77c78470b 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -178,9 +178,9 @@ describe('ExchangeWrapper', () => { expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)) .to.be.bignumber.equal(fillTakerAmountInBaseUnits); await zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer); - expect(await zeroEx.token.getBalanceAsync(addressBySymbol.MLN, takerAddress)) + expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)) .to.be.bignumber.equal(fillTakerAmountInBaseUnits); - expect(await zeroEx.token.getBalanceAsync(addressBySymbol.GNT, takerAddress)) + expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)) .to.be.bignumber.equal(0); }); }); -- cgit From a740498c8061bc7a3dafae82929b358e61bac2d4 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 11:23:39 +0200 Subject: Introduce coinBase account Add makerAccount parameter Adjust tests Add more assertions to success test --- src/0x.js.ts | 6 ++++++ src/web3_wrapper.ts | 3 +++ test/exchange_wrapper_test.ts | 33 ++++++++++++++++++++------------- test/utils/fill_scenarios.ts | 12 +++++++++--- 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/0x.js.ts b/src/0x.js.ts index a613d5f48..6713ec885 100644 --- a/src/0x.js.ts +++ b/src/0x.js.ts @@ -123,6 +123,12 @@ export class ZeroEx { public setTransactionSenderAccount(account: string): void { this.web3Wrapper.setDefaultAccount(account); } + /** + * Gets default account for sending transactions. + */ + public getTransactionSenderAccount(): string { + return this.web3Wrapper.getDefaultAccount(); + } /** * Computes the orderHash given the order parameters and returns it as a hex encoded string. */ diff --git a/src/web3_wrapper.ts b/src/web3_wrapper.ts index c1263222a..900c127d5 100644 --- a/src/web3_wrapper.ts +++ b/src/web3_wrapper.ts @@ -17,6 +17,9 @@ export class Web3Wrapper { public isAddress(address: string): boolean { return this.web3.isAddress(address); } + public getDefaultAccount(): string { + return this.web3.eth.defaultAccount; + } public setDefaultAccount(address: string): void { this.web3.eth.defaultAccount = address; } diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 77c78470b..716adb63a 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -108,16 +108,14 @@ describe('ExchangeWrapper', () => { let makerTokenAddress: string; let takerTokenAddress: string; let fillScenarios: FillScenarios; + let coinBase: string; + let makerAddress: string; let takerAddress: string; const fillTakerAmountInBaseUnits = new BigNumber(5); - const addressBySymbol: {[symbol: string]: string} = {}; const shouldCheckTransfer = false; before('fetch tokens', async () => { - takerAddress = userAddresses[1]; + [coinBase, makerAddress, takerAddress] = userAddresses; tokens = await zeroEx.tokenRegistry.getTokensAsync(); - _.forEach(tokens, token => { - addressBySymbol[token.symbol] = token.address; - }); const [makerToken, takerToken] = tokens; makerTokenAddress = makerToken.address; takerTokenAddress = takerToken.address; @@ -130,7 +128,7 @@ describe('ExchangeWrapper', () => { it('should throw when the fill amount is zero', async () => { const fillableAmount = new BigNumber(5); const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( - makerTokenAddress, takerTokenAddress, takerAddress, fillableAmount, + makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, ); const zeroFillAmount = new BigNumber(0); zeroEx.setTransactionSenderAccount(takerAddress); @@ -140,7 +138,7 @@ describe('ExchangeWrapper', () => { it('should throw when sender is not a taker', async () => { const fillableAmount = new BigNumber(5); const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( - makerTokenAddress, takerTokenAddress, takerAddress, fillableAmount, + makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, ); expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer)) .to.be.rejectedWith(FillOrderValidationErrs.NOT_A_TAKER); @@ -149,7 +147,7 @@ describe('ExchangeWrapper', () => { const expirationInPast = new BigNumber(42); const fillableAmount = new BigNumber(5); const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( - makerTokenAddress, takerTokenAddress, takerAddress, fillableAmount, expirationInPast, + makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, expirationInPast, ); zeroEx.setTransactionSenderAccount(takerAddress); expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer)) @@ -158,7 +156,7 @@ describe('ExchangeWrapper', () => { it('should throw when taker balance is less than fill amount', async () => { const fillableAmount = new BigNumber(5); const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( - makerTokenAddress, takerTokenAddress, takerAddress, fillableAmount, + makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, ); zeroEx.setTransactionSenderAccount(takerAddress); const moreThanTheBalance = new BigNumber(6); @@ -170,18 +168,27 @@ describe('ExchangeWrapper', () => { it('should fill the valid order', async () => { const fillableAmount = new BigNumber(5); const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( - makerTokenAddress, takerTokenAddress, takerAddress, fillableAmount, + makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, ); - zeroEx.setTransactionSenderAccount(takerAddress); + + expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)) + .to.be.bignumber.equal(fillableAmount); + expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)) + .to.be.bignumber.equal(0); expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)) .to.be.bignumber.equal(0); expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)) - .to.be.bignumber.equal(fillTakerAmountInBaseUnits); + .to.be.bignumber.equal(fillableAmount); + zeroEx.setTransactionSenderAccount(takerAddress); await zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer); + expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)) + .to.be.bignumber.equal(fillableAmount.minus(fillTakerAmountInBaseUnits)); + expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)) + .to.be.bignumber.equal(fillTakerAmountInBaseUnits); expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)) .to.be.bignumber.equal(fillTakerAmountInBaseUnits); expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)) - .to.be.bignumber.equal(0); + .to.be.bignumber.equal(fillableAmount.minus(fillTakerAmountInBaseUnits)); }); }); }); diff --git a/test/utils/fill_scenarios.ts b/test/utils/fill_scenarios.ts index ac233ad50..26840bb0c 100644 --- a/test/utils/fill_scenarios.ts +++ b/test/utils/fill_scenarios.ts @@ -7,23 +7,29 @@ export class FillScenarios { private zeroEx: ZeroEx; private userAddresses: string[]; private tokens: Token[]; + private coinBase: string; constructor(zeroEx: ZeroEx, userAddresses: string[], tokens: Token[]) { this.zeroEx = zeroEx; this.userAddresses = userAddresses; this.tokens = tokens; + this.coinBase = userAddresses[0]; } public async createAFillableSignedOrderAsync(makerTokenAddress: string, takerTokenAddress: string, - takerAddress: string, fillableAmount: BigNumber.BigNumber, + makerAddress: string, takerAddress: string, + fillableAmount: BigNumber.BigNumber, expirationUnixTimestampSec?: BigNumber.BigNumber): Promise { - const [makerAddress] = this.userAddresses; + await this.zeroEx.token.transferAsync(makerTokenAddress, this.coinBase, makerAddress, fillableAmount); await this.zeroEx.token.setProxyAllowanceAsync(makerTokenAddress, makerAddress, fillableAmount); - await this.zeroEx.token.transferAsync(takerTokenAddress, makerAddress, takerAddress, fillableAmount); + await this.zeroEx.token.transferAsync(takerTokenAddress, this.coinBase, takerAddress, fillableAmount); await this.zeroEx.token.setProxyAllowanceAsync(takerTokenAddress, takerAddress, fillableAmount); + const transactionSenderAccount = this.zeroEx.getTransactionSenderAccount(); + this.zeroEx.setTransactionSenderAccount(makerAddress); const signedOrder = await orderFactory.createSignedOrderAsync(this.zeroEx, makerAddress, takerAddress, fillableAmount, makerTokenAddress, fillableAmount, takerTokenAddress, expirationUnixTimestampSec); + this.zeroEx.setTransactionSenderAccount(transactionSenderAccount); return signedOrder; } } -- cgit From 5155f4980440f1c91006b124406c8b4a7a90e300 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 12:03:52 +0200 Subject: Add test for insufficient balance and make all async tests async --- src/contract_wrappers/exchange_wrapper.ts | 3 ++ test/exchange_wrapper_test.ts | 47 +++++++++++++++++++++---------- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index eace55f4d..e2ac07b55 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -141,6 +141,9 @@ export class ExchangeWrapper extends ContractWrapper { if (fillAmount.greaterThan(takerBalance)) { throw new Error(FillOrderValidationErrs.NOT_ENOUGH_TAKER_BALANCE); } + if (fillAmount.greaterThan(takerAllowance)) { + throw new Error(FillOrderValidationErrs.NOT_ENOUGH_TAKER_ALLOWANCE); + } } private throwErrorLogsAsErrors(logs: ContractEvent[]): void { const errEvent = _.find(logs, {event: 'LogError'}); diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 716adb63a..8d39c9e57 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -50,37 +50,37 @@ describe('ExchangeWrapper', () => { r: signature.r, s: signature.s, }; - expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address)) + return expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address)) .to.be.rejected(); }); - it('r lacks 0x prefix', () => { + it('r lacks 0x prefix', async () => { const malformedR = signature.r.replace('0x', ''); const malformedSignature = { v: signature.v, r: malformedR, s: signature.s, }; - expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address)) + return expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address)) .to.be.rejected(); }); - it('r is too short', () => { + it('r is too short', async () => { const malformedR = signature.r.substr(10); const malformedSignature = { v: signature.v, r: malformedR, s: signature.s.replace('0', 'z'), }; - expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address)) + return expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address)) .to.be.rejected(); }); - it('s is not hex', () => { + it('s is not hex', async () => { const malformedS = signature.s.replace('0', 'z'); const malformedSignature = { v: signature.v, r: signature.r, s: malformedS, }; - expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address)) + return expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address)) .to.be.rejected(); }); }); @@ -132,16 +132,18 @@ describe('ExchangeWrapper', () => { ); const zeroFillAmount = new BigNumber(0); zeroEx.setTransactionSenderAccount(takerAddress); - expect(zeroEx.exchange.fillOrderAsync(signedOrder, zeroFillAmount, shouldCheckTransfer)) - .to.be.rejectedWith(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); + return expect(zeroEx.exchange.fillOrderAsync( + signedOrder, zeroFillAmount, shouldCheckTransfer, + )).to.be.rejectedWith(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); }); it('should throw when sender is not a taker', async () => { const fillableAmount = new BigNumber(5); const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, ); - expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer)) - .to.be.rejectedWith(FillOrderValidationErrs.NOT_A_TAKER); + return expect(zeroEx.exchange.fillOrderAsync( + signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + )).to.be.rejectedWith(FillOrderValidationErrs.NOT_A_TAKER); }); it('should throw when order is expired', async () => { const expirationInPast = new BigNumber(42); @@ -150,8 +152,9 @@ describe('ExchangeWrapper', () => { makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, expirationInPast, ); zeroEx.setTransactionSenderAccount(takerAddress); - expect(zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer)) - .to.be.rejectedWith(FillOrderValidationErrs.EXPIRED); + return expect(zeroEx.exchange.fillOrderAsync( + signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + )).to.be.rejectedWith(FillOrderValidationErrs.EXPIRED); }); it('should throw when taker balance is less than fill amount', async () => { const fillableAmount = new BigNumber(5); @@ -160,8 +163,22 @@ describe('ExchangeWrapper', () => { ); zeroEx.setTransactionSenderAccount(takerAddress); const moreThanTheBalance = new BigNumber(6); - expect(zeroEx.exchange.fillOrderAsync(signedOrder, moreThanTheBalance, shouldCheckTransfer)) - .to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_BALANCE); + return expect(zeroEx.exchange.fillOrderAsync( + signedOrder, moreThanTheBalance, shouldCheckTransfer, + )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_BALANCE); + }); + it('should throw when taker allowance is less than fill amount', async () => { + const fillableAmount = new BigNumber(5); + const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( + makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, + ); + const newAllowanceWhichIsLessThanFillAmount = fillTakerAmountInBaseUnits.minus(1); + await zeroEx.token.setProxyAllowanceAsync(takerTokenAddress, takerAddress, + newAllowanceWhichIsLessThanFillAmount); + zeroEx.setTransactionSenderAccount(takerAddress); + return expect(zeroEx.exchange.fillOrderAsync( + signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_ALLOWANCE); }); }); describe('successful fills', () => { -- cgit From 4caf1b009ea253d08e1cd6ecc4e914606e2d31c1 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 12:08:25 +0200 Subject: Add test for valid partial fill --- test/exchange_wrapper_test.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 8d39c9e57..0c1f552b6 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -207,6 +207,23 @@ describe('ExchangeWrapper', () => { expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)) .to.be.bignumber.equal(fillableAmount.minus(fillTakerAmountInBaseUnits)); }); + it('should partially fill the valid order', async () => { + const fillableAmount = new BigNumber(5); + const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( + makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, + ); + const partialFillAmount = new BigNumber(3); + zeroEx.setTransactionSenderAccount(takerAddress); + await zeroEx.exchange.fillOrderAsync(signedOrder, partialFillAmount, shouldCheckTransfer); + expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)) + .to.be.bignumber.equal(fillableAmount.minus(partialFillAmount)); + expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)) + .to.be.bignumber.equal(partialFillAmount); + expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)) + .to.be.bignumber.equal(partialFillAmount); + expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)) + .to.be.bignumber.equal(fillableAmount.minus(partialFillAmount)); + }); }); }); }); -- cgit From fc7592d73f1613b11e4b48904bfb041cccca5800 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 2 Jun 2017 12:15:50 +0200 Subject: Fix getTransactionSenderAccountIfExistsAsync to return true senderAddress or undefined if non available --- src/0x.js.ts | 7 ++++--- src/web3_wrapper.ts | 2 +- test/utils/fill_scenarios.ts | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/0x.js.ts b/src/0x.js.ts index 6713ec885..679d748e7 100644 --- a/src/0x.js.ts +++ b/src/0x.js.ts @@ -124,10 +124,11 @@ export class ZeroEx { this.web3Wrapper.setDefaultAccount(account); } /** - * Gets default account for sending transactions. + * Get the default account set for sending transactions. */ - public getTransactionSenderAccount(): string { - return this.web3Wrapper.getDefaultAccount(); + public async getTransactionSenderAccountIfExistsAsync(): Promise { + const senderAccountIfExists = await this.web3Wrapper.getSenderAddressIfExistsAsync(); + return senderAccountIfExists; } /** * Computes the orderHash given the order parameters and returns it as a hex encoded string. diff --git a/src/web3_wrapper.ts b/src/web3_wrapper.ts index 900c127d5..49bd8b67d 100644 --- a/src/web3_wrapper.ts +++ b/src/web3_wrapper.ts @@ -69,7 +69,7 @@ export class Web3Wrapper { const {timestamp} = await promisify(this.web3.eth.getBlock)(blockHash); return timestamp; } - private async getSenderAddressIfExistsAsync(): Promise { + public async getSenderAddressIfExistsAsync(): Promise { const defaultAccount = this.web3.eth.defaultAccount; if (!_.isUndefined(defaultAccount)) { return defaultAccount; diff --git a/test/utils/fill_scenarios.ts b/test/utils/fill_scenarios.ts index 26840bb0c..3b66937e6 100644 --- a/test/utils/fill_scenarios.ts +++ b/test/utils/fill_scenarios.ts @@ -24,12 +24,12 @@ export class FillScenarios { await this.zeroEx.token.transferAsync(takerTokenAddress, this.coinBase, takerAddress, fillableAmount); await this.zeroEx.token.setProxyAllowanceAsync(takerTokenAddress, takerAddress, fillableAmount); - const transactionSenderAccount = this.zeroEx.getTransactionSenderAccount(); + const transactionSenderAccount = await this.zeroEx.getTransactionSenderAccountIfExistsAsync(); this.zeroEx.setTransactionSenderAccount(makerAddress); const signedOrder = await orderFactory.createSignedOrderAsync(this.zeroEx, makerAddress, takerAddress, fillableAmount, makerTokenAddress, fillableAmount, takerTokenAddress, expirationUnixTimestampSec); - this.zeroEx.setTransactionSenderAccount(transactionSenderAccount); + this.zeroEx.setTransactionSenderAccount(transactionSenderAccount as string); return signedOrder; } } -- cgit From 2a0c6abbe7f9abeacc4fea05bc468413ec1f4732 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 12:20:18 +0200 Subject: Validate maker balance and allowance & tests --- src/contract_wrappers/exchange_wrapper.ts | 18 ++++++++++++++---- test/exchange_wrapper_test.ts | 25 +++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index e2ac07b55..3fb187de2 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -120,9 +120,9 @@ export class ExchangeWrapper extends ContractWrapper { ); this.throwErrorLogsAsErrors(response.logs); } - private async validateFillOrderAsync(signedOrder: SignedOrder, fillAmount: BigNumber.BigNumber, + private async validateFillOrderAsync(signedOrder: SignedOrder, fillTakerAmountInBaseUnits: BigNumber.BigNumber, senderAddress: string) { - if (fillAmount.eq(0)) { + if (fillTakerAmountInBaseUnits.eq(0)) { throw new Error(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); } if (signedOrder.taker !== constants.NULL_ADDRESS && signedOrder.taker !== senderAddress) { @@ -138,12 +138,22 @@ export class ExchangeWrapper extends ContractWrapper { signedOrder.maker); const takerAllowance = await this.tokenWrapper.getProxyAllowanceAsync(signedOrder.takerTokenAddress, senderAddress); - if (fillAmount.greaterThan(takerBalance)) { + // How many taker tokens would you get for 1 maker token; + const exchangeRate = signedOrder.takerTokenAmount.div(signedOrder.makerTokenAmount); + const fillMakerAmountInBaseUnits = fillTakerAmountInBaseUnits.div(exchangeRate); + + if (fillTakerAmountInBaseUnits.greaterThan(takerBalance)) { throw new Error(FillOrderValidationErrs.NOT_ENOUGH_TAKER_BALANCE); } - if (fillAmount.greaterThan(takerAllowance)) { + if (fillTakerAmountInBaseUnits.greaterThan(takerAllowance)) { throw new Error(FillOrderValidationErrs.NOT_ENOUGH_TAKER_ALLOWANCE); } + if (fillMakerAmountInBaseUnits.greaterThan(makerBalance)) { + throw new Error(FillOrderValidationErrs.NOT_ENOUGH_MAKER_BALANCE); + } + if (fillMakerAmountInBaseUnits.greaterThan(makerAllowance)) { + throw new Error(FillOrderValidationErrs.NOT_ENOUGH_MAKER_ALLOWANCE); + } } private throwErrorLogsAsErrors(logs: ContractEvent[]): void { const errEvent = _.find(logs, {event: 'LogError'}); diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 0c1f552b6..66ba167cc 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -180,6 +180,31 @@ describe('ExchangeWrapper', () => { signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_ALLOWANCE); }); + it('should throw when maker balance is less than maker fill amount', async () => { + const fillableAmount = new BigNumber(5); + const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( + makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, + ); + const lackingMakerBalance = new BigNumber(3); + await zeroEx.token.transferAsync(makerTokenAddress, makerAddress, coinBase, lackingMakerBalance); + zeroEx.setTransactionSenderAccount(takerAddress); + return expect(zeroEx.exchange.fillOrderAsync( + signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_MAKER_BALANCE); + }); + it('should throw when maker allowance is less than maker fill amount', async () => { + const fillableAmount = new BigNumber(5); + const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( + makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, + ); + const newAllowanceWhichIsLessThanFillAmount = fillTakerAmountInBaseUnits.minus(1); + await zeroEx.token.setProxyAllowanceAsync(makerTokenAddress, makerAddress, + newAllowanceWhichIsLessThanFillAmount); + zeroEx.setTransactionSenderAccount(takerAddress); + return expect(zeroEx.exchange.fillOrderAsync( + signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_MAKER_ALLOWANCE); + }); }); describe('successful fills', () => { it('should fill the valid order', async () => { -- cgit From e1ee6b84945e729d894f6535be02f3541e43dbf0 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 12:57:21 +0200 Subject: Add check for ROUNDING_ERROR and test for it --- src/contract_wrappers/exchange_wrapper.ts | 16 ++++++++++++++++ src/types.ts | 5 +++++ test/exchange_wrapper_test.ts | 31 ++++++++++++++++++++++--------- test/utils/fill_scenarios.ts | 27 ++++++++++++++++++--------- 4 files changed, 61 insertions(+), 18 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 3fb187de2..fe5fc3d78 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -154,6 +154,10 @@ export class ExchangeWrapper extends ContractWrapper { if (fillMakerAmountInBaseUnits.greaterThan(makerAllowance)) { throw new Error(FillOrderValidationErrs.NOT_ENOUGH_MAKER_ALLOWANCE); } + if (await this.isRoundingErrorAsync(signedOrder.takerTokenAmount, fillTakerAmountInBaseUnits, + signedOrder.makerTokenAmount)) { + throw new Error(FillOrderValidationErrs.ROUNDING_ERROR); + } } private throwErrorLogsAsErrors(logs: ContractEvent[]): void { const errEvent = _.find(logs, {event: 'LogError'}); @@ -163,6 +167,18 @@ export class ExchangeWrapper extends ContractWrapper { throw new Error(errMessage); } } + private async isRoundingErrorAsync(takerTokenAmount: BigNumber.BigNumber, + fillTakerAmountInBaseUnits: BigNumber.BigNumber, + makerTokenAmount: BigNumber.BigNumber): Promise { + const exchangeInstance = await this.getExchangeContractAsync(); + const senderAddress = await this.web3Wrapper.getSenderAddressOrThrowAsync(); + const isRoundingError = await exchangeInstance.isRoundingError.call( + takerTokenAmount, fillTakerAmountInBaseUnits, makerTokenAmount, { + from: senderAddress, + }, + ); + return isRoundingError; + } private async getExchangeContractAsync(): Promise { if (!_.isUndefined(this.exchangeContractIfExists)) { return this.exchangeContractIfExists; diff --git a/src/types.ts b/src/types.ts index f80f98dc4..73c448b85 100644 --- a/src/types.ts +++ b/src/types.ts @@ -34,6 +34,10 @@ export type OrderValues = [BigNumber.BigNumber, BigNumber.BigNumber, BigNumber.B export interface ExchangeContract { isValidSignature: any; + isRoundingError: { + call: (takerTokenAmount: BigNumber.BigNumber, fillTakerAmountInBaseUnits: BigNumber.BigNumber, + makerTokenAmount: BigNumber.BigNumber, txOpts: TxOpts) => Promise; + }; fill: { (orderAddresses: OrderAddresses, orderValues: OrderValues, fillAmount: BigNumber.BigNumber, shouldCheckTransfer: boolean, v: number, r: string, s: string, txOpts: TxOpts): ContractResponse; @@ -93,6 +97,7 @@ export const FillOrderValidationErrs = strEnum([ 'NOT_ENOUGH_TAKER_ALLOWANCE', 'NOT_ENOUGH_MAKER_BALANCE', 'NOT_ENOUGH_MAKER_ALLOWANCE', + 'ROUNDING_ERROR', ]); export type FillOrderValidationErrs = keyof typeof FillOrderValidationErrs; diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 66ba167cc..7f8bad377 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -127,7 +127,7 @@ describe('ExchangeWrapper', () => { describe('failed fills', () => { it('should throw when the fill amount is zero', async () => { const fillableAmount = new BigNumber(5); - const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( + const signedOrder = await fillScenarios.createFillableSignedOrderAsync( makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, ); const zeroFillAmount = new BigNumber(0); @@ -138,7 +138,7 @@ describe('ExchangeWrapper', () => { }); it('should throw when sender is not a taker', async () => { const fillableAmount = new BigNumber(5); - const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( + const signedOrder = await fillScenarios.createFillableSignedOrderAsync( makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, ); return expect(zeroEx.exchange.fillOrderAsync( @@ -148,7 +148,7 @@ describe('ExchangeWrapper', () => { it('should throw when order is expired', async () => { const expirationInPast = new BigNumber(42); const fillableAmount = new BigNumber(5); - const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( + const signedOrder = await fillScenarios.createFillableSignedOrderAsync( makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, expirationInPast, ); zeroEx.setTransactionSenderAccount(takerAddress); @@ -158,7 +158,7 @@ describe('ExchangeWrapper', () => { }); it('should throw when taker balance is less than fill amount', async () => { const fillableAmount = new BigNumber(5); - const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( + const signedOrder = await fillScenarios.createFillableSignedOrderAsync( makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, ); zeroEx.setTransactionSenderAccount(takerAddress); @@ -169,7 +169,7 @@ describe('ExchangeWrapper', () => { }); it('should throw when taker allowance is less than fill amount', async () => { const fillableAmount = new BigNumber(5); - const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( + const signedOrder = await fillScenarios.createFillableSignedOrderAsync( makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, ); const newAllowanceWhichIsLessThanFillAmount = fillTakerAmountInBaseUnits.minus(1); @@ -182,7 +182,7 @@ describe('ExchangeWrapper', () => { }); it('should throw when maker balance is less than maker fill amount', async () => { const fillableAmount = new BigNumber(5); - const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( + const signedOrder = await fillScenarios.createFillableSignedOrderAsync( makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, ); const lackingMakerBalance = new BigNumber(3); @@ -194,7 +194,7 @@ describe('ExchangeWrapper', () => { }); it('should throw when maker allowance is less than maker fill amount', async () => { const fillableAmount = new BigNumber(5); - const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( + const signedOrder = await fillScenarios.createFillableSignedOrderAsync( makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, ); const newAllowanceWhichIsLessThanFillAmount = fillTakerAmountInBaseUnits.minus(1); @@ -205,11 +205,24 @@ describe('ExchangeWrapper', () => { signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_MAKER_ALLOWANCE); }); + it('should throw when there would be a rounding error', async () => { + const makerFillableAmount = new BigNumber(3); + const takerFillableAmount = new BigNumber(5); + const signedOrder = await fillScenarios.createAsymetricFillableSignedOrderAsync( + makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, + makerFillableAmount, takerFillableAmount, + ); + const fillTakerAmountInBaseUnitsThatCausesRoundingError = new BigNumber(3); + zeroEx.setTransactionSenderAccount(takerAddress); + return expect(zeroEx.exchange.fillOrderAsync( + signedOrder, fillTakerAmountInBaseUnitsThatCausesRoundingError, shouldCheckTransfer, + )).to.be.rejectedWith(FillOrderValidationErrs.ROUNDING_ERROR); + }); }); describe('successful fills', () => { it('should fill the valid order', async () => { const fillableAmount = new BigNumber(5); - const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( + const signedOrder = await fillScenarios.createFillableSignedOrderAsync( makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, ); @@ -234,7 +247,7 @@ describe('ExchangeWrapper', () => { }); it('should partially fill the valid order', async () => { const fillableAmount = new BigNumber(5); - const signedOrder = await fillScenarios.createAFillableSignedOrderAsync( + const signedOrder = await fillScenarios.createFillableSignedOrderAsync( makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, ); const partialFillAmount = new BigNumber(3); diff --git a/test/utils/fill_scenarios.ts b/test/utils/fill_scenarios.ts index 3b66937e6..568b11ef8 100644 --- a/test/utils/fill_scenarios.ts +++ b/test/utils/fill_scenarios.ts @@ -14,20 +14,29 @@ export class FillScenarios { this.tokens = tokens; this.coinBase = userAddresses[0]; } - public async createAFillableSignedOrderAsync(makerTokenAddress: string, takerTokenAddress: string, - makerAddress: string, takerAddress: string, - fillableAmount: BigNumber.BigNumber, - expirationUnixTimestampSec?: BigNumber.BigNumber): + public async createFillableSignedOrderAsync(makerTokenAddress: string, takerTokenAddress: string, + makerAddress: string, takerAddress: string, + fillableAmount: BigNumber.BigNumber, + expirationUnixTimestampSec?: BigNumber.BigNumber): Promise { - await this.zeroEx.token.transferAsync(makerTokenAddress, this.coinBase, makerAddress, fillableAmount); - await this.zeroEx.token.setProxyAllowanceAsync(makerTokenAddress, makerAddress, fillableAmount); - await this.zeroEx.token.transferAsync(takerTokenAddress, this.coinBase, takerAddress, fillableAmount); - await this.zeroEx.token.setProxyAllowanceAsync(takerTokenAddress, takerAddress, fillableAmount); + return this.createAsymetricFillableSignedOrderAsync( + makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, + fillableAmount, fillableAmount, expirationUnixTimestampSec, + ); + } + public async createAsymetricFillableSignedOrderAsync( + makerTokenAddress: string, takerTokenAddress: string, makerAddress: string, takerAddress: string, + makerFillableAmount: BigNumber.BigNumber, takerFillableAmount: BigNumber.BigNumber, + expirationUnixTimestampSec?: BigNumber.BigNumber): Promise { + await this.zeroEx.token.transferAsync(makerTokenAddress, this.coinBase, makerAddress, makerFillableAmount); + await this.zeroEx.token.setProxyAllowanceAsync(makerTokenAddress, makerAddress, makerFillableAmount); + await this.zeroEx.token.transferAsync(takerTokenAddress, this.coinBase, takerAddress, takerFillableAmount); + await this.zeroEx.token.setProxyAllowanceAsync(takerTokenAddress, takerAddress, takerFillableAmount); const transactionSenderAccount = await this.zeroEx.getTransactionSenderAccountIfExistsAsync(); this.zeroEx.setTransactionSenderAccount(makerAddress); const signedOrder = await orderFactory.createSignedOrderAsync(this.zeroEx, makerAddress, - takerAddress, fillableAmount, makerTokenAddress, fillableAmount, takerTokenAddress, + takerAddress, makerFillableAmount, makerTokenAddress, takerFillableAmount, takerTokenAddress, expirationUnixTimestampSec); this.zeroEx.setTransactionSenderAccount(transactionSenderAccount as string); return signedOrder; -- cgit From 832d2ff5ca1e82c4580e47c0b101069ee7cc0fca Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 13:08:59 +0200 Subject: Add fill scenario with fees --- test/utils/fill_scenarios.ts | 34 +++++++++++++++++++++++++++++++--- test/utils/order_factory.ts | 17 ++++++++++------- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/test/utils/fill_scenarios.ts b/test/utils/fill_scenarios.ts index 568b11ef8..31f93618f 100644 --- a/test/utils/fill_scenarios.ts +++ b/test/utils/fill_scenarios.ts @@ -2,6 +2,7 @@ import * as BigNumber from 'bignumber.js'; import {ZeroEx} from '../../src/0x.js'; import {Token, SignedOrder} from '../../src/types'; import {orderFactory} from '../utils/order_factory'; +import {constants} from './constants'; export class FillScenarios { private zeroEx: ZeroEx; @@ -24,10 +25,36 @@ export class FillScenarios { fillableAmount, fillableAmount, expirationUnixTimestampSec, ); } + public async createFillableSignedOrderWithFeesAsync( + makerTokenAddress: string, takerTokenAddress: string, + makerFee: BigNumber.BigNumber, takerFee: BigNumber.BigNumber, + makerAddress: string, takerAddress: string, + fillableAmount: BigNumber.BigNumber, + feeRecepient: string, expirationUnixTimestampSec?: BigNumber.BigNumber, + ): Promise { + return this.createAsymetricFillableSignedOrderWithFeesAsync( + makerTokenAddress, takerTokenAddress, makerFee, takerFee, makerAddress, takerAddress, + fillableAmount, fillableAmount, feeRecepient, expirationUnixTimestampSec, + ); + } public async createAsymetricFillableSignedOrderAsync( makerTokenAddress: string, takerTokenAddress: string, makerAddress: string, takerAddress: string, makerFillableAmount: BigNumber.BigNumber, takerFillableAmount: BigNumber.BigNumber, expirationUnixTimestampSec?: BigNumber.BigNumber): Promise { + const makerFee = new BigNumber(0); + const takerFee = new BigNumber(0); + const feeRecepient = constants.NULL_ADDRESS; + return this.createAsymetricFillableSignedOrderWithFeesAsync( + makerTokenAddress, takerTokenAddress, makerFee, takerFee, makerAddress, takerAddress, + makerFillableAmount, takerFillableAmount, feeRecepient, expirationUnixTimestampSec, + ); + } + private async createAsymetricFillableSignedOrderWithFeesAsync( + makerTokenAddress: string, takerTokenAddress: string, + makerFee: BigNumber.BigNumber, takerFee: BigNumber.BigNumber, + makerAddress: string, takerAddress: string, + makerFillableAmount: BigNumber.BigNumber, takerFillableAmount: BigNumber.BigNumber, + feeRecepient: string, expirationUnixTimestampSec?: BigNumber.BigNumber): Promise { await this.zeroEx.token.transferAsync(makerTokenAddress, this.coinBase, makerAddress, makerFillableAmount); await this.zeroEx.token.setProxyAllowanceAsync(makerTokenAddress, makerAddress, makerFillableAmount); await this.zeroEx.token.transferAsync(takerTokenAddress, this.coinBase, takerAddress, takerFillableAmount); @@ -35,9 +62,10 @@ export class FillScenarios { const transactionSenderAccount = await this.zeroEx.getTransactionSenderAccountIfExistsAsync(); this.zeroEx.setTransactionSenderAccount(makerAddress); - const signedOrder = await orderFactory.createSignedOrderAsync(this.zeroEx, makerAddress, - takerAddress, makerFillableAmount, makerTokenAddress, takerFillableAmount, takerTokenAddress, - expirationUnixTimestampSec); + const signedOrder = await orderFactory.createSignedOrderAsync(this.zeroEx, + makerAddress, takerAddress, makerFee, takerFee, + makerFillableAmount, makerTokenAddress, takerFillableAmount, takerTokenAddress, + feeRecepient, expirationUnixTimestampSec); this.zeroEx.setTransactionSenderAccount(transactionSenderAccount as string); return signedOrder; } diff --git a/test/utils/order_factory.ts b/test/utils/order_factory.ts index 0f370ed34..373dbddc6 100644 --- a/test/utils/order_factory.ts +++ b/test/utils/order_factory.ts @@ -10,10 +10,13 @@ export const orderFactory = { zeroEx: ZeroEx, maker: string, taker: string, - makerTokenAmount: BigNumber.BigNumber|number, + makerFee: BigNumber.BigNumber, + takerFee: BigNumber.BigNumber, + makerTokenAmount: BigNumber.BigNumber, makerTokenAddress: string, - takerTokenAmount: BigNumber.BigNumber|number, + takerTokenAmount: BigNumber.BigNumber, takerTokenAddress: string, + feeRecipient: string, expirationUnixTimestampSec?: BigNumber.BigNumber): Promise { const defaultExpirationUnixTimestampSec = new BigNumber(2524604400); // Close to infinite expirationUnixTimestampSec = _.isUndefined(expirationUnixTimestampSec) ? @@ -22,14 +25,14 @@ export const orderFactory = { const order = { maker, taker, - makerFee: new BigNumber(0), - takerFee: new BigNumber(0), - makerTokenAmount: _.isNumber(makerTokenAmount) ? new BigNumber(makerTokenAmount) : makerTokenAmount, - takerTokenAmount: _.isNumber(takerTokenAmount) ? new BigNumber(takerTokenAmount) : takerTokenAmount, + makerFee, + takerFee, + makerTokenAmount, + takerTokenAmount, makerTokenAddress, takerTokenAddress, salt: ZeroEx.generatePseudoRandomSalt(), - feeRecipient: constants.NULL_ADDRESS, + feeRecipient, expirationUnixTimestampSec, }; const orderHash = await zeroEx.getOrderHashHexAsync(order); -- cgit From b983ce631291deb74cdeeb5cbb50956cfbd49027 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 13:24:29 +0200 Subject: Add ProtocolTokenArtifacts --- package.json | 2 +- src/artifacts/ProtocolToken.json | 321 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 322 insertions(+), 1 deletion(-) create mode 100644 src/artifacts/ProtocolToken.json diff --git a/package.json b/package.json index 8b472f2a9..6b2182f0b 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "run_mocha": "mocha lib/test/**/*_test.js --timeout 3000" }, "config": { - "artifacts": "Proxy Exchange TokenRegistry Token Mintable EtherToken", + "artifacts": "Proxy Exchange TokenRegistry Token Mintable EtherToken ProtocolToken", "mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic" }, "repository": { diff --git a/src/artifacts/ProtocolToken.json b/src/artifacts/ProtocolToken.json new file mode 100644 index 000000000..a1f8e0ff6 --- /dev/null +++ b/src/artifacts/ProtocolToken.json @@ -0,0 +1,321 @@ +{ + "contract_name": "ProtocolToken", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "balance", + "type": "uint256" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "remaining", + "type": "uint256" + } + ], + "payable": false, + "type": "function" + }, + { + "inputs": [], + "payable": false, + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "_from", + "type": "address" + }, + { + "indexed": true, + "name": "_to", + "type": "address" + }, + { + "indexed": false, + "name": "_value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "_owner", + "type": "address" + }, + { + "indexed": true, + "name": "_spender", + "type": "address" + }, + { + "indexed": false, + "name": "_value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + } + ], + "unlinked_binary": "0x606060405234610000575b6a52b7d2dcc80cd2e40000006002819055600160a060020a0333166000908152602081905260409020555b5b6105fc806100456000396000f3006060604052361561007d5763ffffffff60e060020a60003504166306fdde038114610082578063095ea7b31461010f57806318160ddd1461013f57806323b872dd1461015e578063313ce5671461019457806370a08231146101b757806395d89b41146101e2578063a9059cbb1461026f578063dd62ed3e1461029f575b610000565b346100005761008f6102d0565b6040805160208082528351818301528351919283929083019185019080838382156100d5575b8051825260208311156100d557601f1990920191602091820191016100b5565b505050905090810190601f1680156101015780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b346100005761012b600160a060020a0360043516602435610307565b604080519115158252519081900360200190f35b346100005761014c610372565b60408051918252519081900360200190f35b346100005761012b600160a060020a0360043581169060243516604435610378565b604080519115158252519081900360200190f35b34610000576101a1610485565b6040805160ff9092168252519081900360200190f35b346100005761014c600160a060020a036004351661048a565b60408051918252519081900360200190f35b346100005761008f6104a9565b6040805160208082528351818301528351919283929083019185019080838382156100d5575b8051825260208311156100d557601f1990920191602091820191016100b5565b505050905090810190601f1680156101015780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b346100005761012b600160a060020a03600435166024356104e0565b604080519115158252519081900360200190f35b346100005761014c600160a060020a03600435811690602435166105a3565b60408051918252519081900360200190f35b60408051808201909152601081527f3078204e6574776f726b20546f6b656e00000000000000000000000000000000602082015281565b600160a060020a03338116600081815260016020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b60025481565b600160a060020a0383166000908152602081905260408120548290108015906103c85750600160a060020a0380851660009081526001602090815260408083203390941683529290522054829010155b80156103ed5750600160a060020a038316600090815260208190526040902054828101115b1561047957600160a060020a0380841660008181526020818152604080832080548801905588851680845281842080548990039055600183528184203390961684529482529182902080548790039055815186815291519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a350600161047d565b5060005b5b9392505050565b601281565b600160a060020a0381166000908152602081905260409020545b919050565b60408051808201909152600381527f5a52580000000000000000000000000000000000000000000000000000000000602082015281565b600160a060020a0333166000908152602081905260408120548290108015906105225750600160a060020a038316600090815260208190526040902054828101115b1561059457600160a060020a0333811660008181526020818152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a350600161036c565b50600061036c565b5b92915050565b600160a060020a038083166000908152600160209081526040808320938516835292905220545b929150505600a165627a7a723058209912b9e0769f5bfbb24cc18ed6298aba4698371192fbf585b239f6db1b8bdc2f0029", + "networks": { + "42": { + "links": {}, + "events": { + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef": { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "_from", + "type": "address" + }, + { + "indexed": true, + "name": "_to", + "type": "address" + }, + { + "indexed": false, + "name": "_value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925": { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "_owner", + "type": "address" + }, + { + "indexed": true, + "name": "_spender", + "type": "address" + }, + { + "indexed": false, + "name": "_value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + } + }, + "updated_at": 1495042008608 + }, + "50": { + "links": {}, + "events": { + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef": { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "_from", + "type": "address" + }, + { + "indexed": true, + "name": "_to", + "type": "address" + }, + { + "indexed": false, + "name": "_value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925": { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "_owner", + "type": "address" + }, + { + "indexed": true, + "name": "_spender", + "type": "address" + }, + { + "indexed": false, + "name": "_value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + } + }, + "updated_at": 1495030736785 + } + }, + "schema_version": "0.0.5", + "updated_at": 1495042008608 +} \ No newline at end of file -- cgit From a07a9d8571928dbbe82d2cc0917dafe6b446f701 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 15:24:11 +0200 Subject: Add token utils --- test/utils/token_utils.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 test/utils/token_utils.ts diff --git a/test/utils/token_utils.ts b/test/utils/token_utils.ts new file mode 100644 index 000000000..11d334619 --- /dev/null +++ b/test/utils/token_utils.ts @@ -0,0 +1,23 @@ +import * as _ from 'lodash'; +import {Token, ZeroExError} from '../../src/types'; + +const PROTOCOL_TOKEN_SYMBOL = 'ZRX'; + +export class TokenUtils { + private tokens: Token[]; + constructor(tokens: Token[]) { + this.tokens = tokens; + } + public getProtocolTokenOrThrow(): Token { + const zrxToken = _.find(this.tokens, {symbol: PROTOCOL_TOKEN_SYMBOL}); + if (_.isUndefined(zrxToken)) { + throw new Error(ZeroExError.CONTRACT_NOT_DEPLOYED_ON_NETWORK); + } + return zrxToken; + } + public getNonProtocolTokens(): Token[] { + return _.filter(this.tokens, token => { + return token.symbol !== PROTOCOL_TOKEN_SYMBOL; + }); + } +} -- cgit From d8587875b82ae2fde6dad1334a586c36cda2bfec Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 15:24:42 +0200 Subject: Add success test for fill with fees --- test/exchange_wrapper_test.ts | 25 +++++++++++++++++++++---- test/utils/fill_scenarios.ts | 13 ++++++++++++- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 7f8bad377..ecb5a408b 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -9,9 +9,9 @@ import promisify = require('es6-promisify'); import {web3Factory} from './utils/web3_factory'; import {ZeroEx} from '../src/0x.js'; import {BlockchainLifecycle} from './utils/blockchain_lifecycle'; -import {orderFactory} from './utils/order_factory'; import {FillOrderValidationErrs, Token} from '../src/types'; import {FillScenarios} from './utils/fill_scenarios'; +import {TokenUtils} from './utils/token_utils'; chai.use(dirtyChai); chai.use(ChaiBigNumber()); @@ -111,15 +111,19 @@ describe('ExchangeWrapper', () => { let coinBase: string; let makerAddress: string; let takerAddress: string; + let feeRecipient: string; + let zrxTokenAddress: string; const fillTakerAmountInBaseUnits = new BigNumber(5); const shouldCheckTransfer = false; before('fetch tokens', async () => { - [coinBase, makerAddress, takerAddress] = userAddresses; + [coinBase, makerAddress, takerAddress, feeRecipient] = userAddresses; tokens = await zeroEx.tokenRegistry.getTokensAsync(); - const [makerToken, takerToken] = tokens; + const tokenUtils = new TokenUtils(tokens); + const [makerToken, takerToken] = tokenUtils.getNonProtocolTokens(); makerTokenAddress = makerToken.address; takerTokenAddress = takerToken.address; - fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens); + zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address; + fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress); }); afterEach('reset default account', () => { zeroEx.setTransactionSenderAccount(userAddresses[0]); @@ -262,6 +266,19 @@ describe('ExchangeWrapper', () => { expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)) .to.be.bignumber.equal(fillableAmount.minus(partialFillAmount)); }); + it('should fill the valid orders with fees', async () => { + const fillableAmount = new BigNumber(5); + const makerFee = new BigNumber(1); + const takerFee = new BigNumber(2); + const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync( + makerTokenAddress, takerTokenAddress, makerFee, takerFee, + makerAddress, takerAddress, fillableAmount, feeRecipient, + ); + zeroEx.setTransactionSenderAccount(takerAddress); + await zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer); + expect(await zeroEx.token.getBalanceAsync(zrxTokenAddress, feeRecipient)) + .to.be.bignumber.equal(makerFee.plus(takerFee)); + }); }); }); }); diff --git a/test/utils/fill_scenarios.ts b/test/utils/fill_scenarios.ts index 31f93618f..706f3f281 100644 --- a/test/utils/fill_scenarios.ts +++ b/test/utils/fill_scenarios.ts @@ -9,11 +9,13 @@ export class FillScenarios { private userAddresses: string[]; private tokens: Token[]; private coinBase: string; - constructor(zeroEx: ZeroEx, userAddresses: string[], tokens: Token[]) { + private zrxTokenAddress: string; + constructor(zeroEx: ZeroEx, userAddresses: string[], tokens: Token[], zrxTokenAddress: string) { this.zeroEx = zeroEx; this.userAddresses = userAddresses; this.tokens = tokens; this.coinBase = userAddresses[0]; + this.zrxTokenAddress = zrxTokenAddress; } public async createFillableSignedOrderAsync(makerTokenAddress: string, takerTokenAddress: string, makerAddress: string, takerAddress: string, @@ -60,6 +62,15 @@ export class FillScenarios { await this.zeroEx.token.transferAsync(takerTokenAddress, this.coinBase, takerAddress, takerFillableAmount); await this.zeroEx.token.setProxyAllowanceAsync(takerTokenAddress, takerAddress, takerFillableAmount); + if (!makerFee.isZero()) { + await this.zeroEx.token.transferAsync(this.zrxTokenAddress, this.coinBase, makerAddress, makerFee); + await this.zeroEx.token.setProxyAllowanceAsync(this.zrxTokenAddress, makerAddress, makerFee); + } + if (!takerFee.isZero()) { + await this.zeroEx.token.transferAsync(this.zrxTokenAddress, this.coinBase, takerAddress, takerFee); + await this.zeroEx.token.setProxyAllowanceAsync(this.zrxTokenAddress, takerAddress, takerFee); + } + const transactionSenderAccount = await this.zeroEx.getTransactionSenderAccountIfExistsAsync(); this.zeroEx.setTransactionSenderAccount(makerAddress); const signedOrder = await orderFactory.createSignedOrderAsync(this.zeroEx, -- cgit From c650d1ba204a862de81b225118d9bcd1a38ad25d Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 16:18:54 +0200 Subject: Add tests and checks for fees balances and allowances --- src/contract_wrappers/exchange_wrapper.ts | 54 +++++++++++++++++++++++++------ src/types.ts | 7 ++++ test/exchange_wrapper_test.ts | 45 +++++++++++++++++++++++++- 3 files changed, 96 insertions(+), 10 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index fe5fc3d78..fa5c16485 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -74,9 +74,9 @@ export class ExchangeWrapper extends ContractWrapper { assert.isBoolean('shouldCheckTransfer', shouldCheckTransfer); const senderAddress = await this.web3Wrapper.getSenderAddressOrThrowAsync(); - await this.validateFillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, senderAddress); - const exchangeInstance = await this.getExchangeContractAsync(); + const zrxTokenAddress = await exchangeInstance.ZRX.call(); + await this.validateFillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, senderAddress, zrxTokenAddress); const orderAddresses: OrderAddresses = [ signedOrder.maker, @@ -121,7 +121,7 @@ export class ExchangeWrapper extends ContractWrapper { this.throwErrorLogsAsErrors(response.logs); } private async validateFillOrderAsync(signedOrder: SignedOrder, fillTakerAmountInBaseUnits: BigNumber.BigNumber, - senderAddress: string) { + senderAddress: string, zrxTokenAddress: string): Promise { if (fillTakerAmountInBaseUnits.eq(0)) { throw new Error(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); } @@ -131,13 +131,32 @@ export class ExchangeWrapper extends ContractWrapper { if (signedOrder.expirationUnixTimestampSec.lessThan(Date.now() / 1000)) { throw new Error(FillOrderValidationErrs.EXPIRED); } + + await this.validateFillOrderBalancesAndAllowancesAsync(signedOrder, fillTakerAmountInBaseUnits, + senderAddress, zrxTokenAddress); + + if (await this.isRoundingErrorAsync(signedOrder.takerTokenAmount, fillTakerAmountInBaseUnits, + signedOrder.makerTokenAmount)) { + throw new Error(FillOrderValidationErrs.ROUNDING_ERROR); + } + } + private async validateFillOrderBalancesAndAllowancesAsync(signedOrder: SignedOrder, + fillTakerAmountInBaseUnits: BigNumber.BigNumber, + senderAddress: string, + zrxTokenAddress: string): Promise { + // TODO: There is a possibility that the user might have enough funds + // to fulfill the order or pay fees but not both. This will happen if + // makerToken === zrxToken || makerToken === zrxToken + // We don't check it for now. The contract checks it and throws. + const makerBalance = await this.tokenWrapper.getBalanceAsync(signedOrder.makerTokenAddress, - signedOrder.maker); + signedOrder.maker); const takerBalance = await this.tokenWrapper.getBalanceAsync(signedOrder.takerTokenAddress, senderAddress); const makerAllowance = await this.tokenWrapper.getProxyAllowanceAsync(signedOrder.makerTokenAddress, - signedOrder.maker); + signedOrder.maker); const takerAllowance = await this.tokenWrapper.getProxyAllowanceAsync(signedOrder.takerTokenAddress, - senderAddress); + senderAddress); + // How many taker tokens would you get for 1 maker token; const exchangeRate = signedOrder.takerTokenAmount.div(signedOrder.makerTokenAmount); const fillMakerAmountInBaseUnits = fillTakerAmountInBaseUnits.div(exchangeRate); @@ -154,9 +173,26 @@ export class ExchangeWrapper extends ContractWrapper { if (fillMakerAmountInBaseUnits.greaterThan(makerAllowance)) { throw new Error(FillOrderValidationErrs.NOT_ENOUGH_MAKER_ALLOWANCE); } - if (await this.isRoundingErrorAsync(signedOrder.takerTokenAmount, fillTakerAmountInBaseUnits, - signedOrder.makerTokenAmount)) { - throw new Error(FillOrderValidationErrs.ROUNDING_ERROR); + + const makerFeeBalance = await this.tokenWrapper.getBalanceAsync(zrxTokenAddress, + signedOrder.maker); + const takerFeeBalance = await this.tokenWrapper.getBalanceAsync(zrxTokenAddress, senderAddress); + const makerFeeAllowance = await this.tokenWrapper.getProxyAllowanceAsync(zrxTokenAddress, + signedOrder.maker); + const takerFeeAllowance = await this.tokenWrapper.getProxyAllowanceAsync(zrxTokenAddress, + senderAddress); + + if (signedOrder.takerFee.greaterThan(takerFeeBalance)) { + throw new Error(FillOrderValidationErrs.NOT_ENOUGH_TAKER_FEE_BALANCE); + } + if (signedOrder.takerFee.greaterThan(takerFeeAllowance)) { + throw new Error(FillOrderValidationErrs.NOT_ENOUGH_TAKER_FEE_ALLOWANCE); + } + if (signedOrder.makerFee.greaterThan(makerFeeBalance)) { + throw new Error(FillOrderValidationErrs.NOT_ENOUGH_MAKER_FEE_BALANCE); + } + if (signedOrder.makerFee.greaterThan(makerFeeAllowance)) { + throw new Error(FillOrderValidationErrs.NOT_ENOUGH_MAKER_FEE_ALLOWANCE); } } private throwErrorLogsAsErrors(logs: ContractEvent[]): void { diff --git a/src/types.ts b/src/types.ts index 73c448b85..7ec3b1cf2 100644 --- a/src/types.ts +++ b/src/types.ts @@ -44,6 +44,9 @@ export interface ExchangeContract { estimateGas: (orderAddresses: OrderAddresses, orderValues: OrderValues, fillAmount: BigNumber.BigNumber, shouldCheckTransfer: boolean, v: number, r: string, s: string, txOpts: TxOpts) => number; }; + ZRX: { + call: () => Promise; + }; } export interface TokenContract { @@ -97,6 +100,10 @@ export const FillOrderValidationErrs = strEnum([ 'NOT_ENOUGH_TAKER_ALLOWANCE', 'NOT_ENOUGH_MAKER_BALANCE', 'NOT_ENOUGH_MAKER_ALLOWANCE', + 'NOT_ENOUGH_TAKER_FEE_BALANCE', + 'NOT_ENOUGH_TAKER_FEE_ALLOWANCE', + 'NOT_ENOUGH_MAKER_FEE_BALANCE', + 'NOT_ENOUGH_MAKER_FEE_ALLOWANCE', 'ROUNDING_ERROR', ]); export type FillOrderValidationErrs = keyof typeof FillOrderValidationErrs; diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index ecb5a408b..6f4105e1e 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -9,7 +9,7 @@ import promisify = require('es6-promisify'); import {web3Factory} from './utils/web3_factory'; import {ZeroEx} from '../src/0x.js'; import {BlockchainLifecycle} from './utils/blockchain_lifecycle'; -import {FillOrderValidationErrs, Token} from '../src/types'; +import {FillOrderValidationErrs, SignedOrder, Token} from '../src/types'; import {FillScenarios} from './utils/fill_scenarios'; import {TokenUtils} from './utils/token_utils'; @@ -222,6 +222,49 @@ describe('ExchangeWrapper', () => { signedOrder, fillTakerAmountInBaseUnitsThatCausesRoundingError, shouldCheckTransfer, )).to.be.rejectedWith(FillOrderValidationErrs.ROUNDING_ERROR); }); + describe('should raise when not enough balance or allowance to pay fees', () => { + const fillableAmount = new BigNumber(5); + const makerFee = new BigNumber(2); + const takerFee = new BigNumber(2); + let signedOrder: SignedOrder; + beforeEach('setup', async () => { + signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync( + makerTokenAddress, takerTokenAddress, makerFee, takerFee, + makerAddress, takerAddress, fillableAmount, feeRecipient, + ); + zeroEx.setTransactionSenderAccount(takerAddress); + }); + it('should throw when maker doesn\'t have enough balance to pay fees', async () => { + const lackingBalance = new BigNumber(1); + await zeroEx.token.transferAsync(zrxTokenAddress, makerAddress, coinBase, lackingBalance); + return expect(zeroEx.exchange.fillOrderAsync( + signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_MAKER_FEE_BALANCE); + }); + it('should throw when maker doesn\'t have enough allowance to pay fees', async () => { + const newAllowanceWhichIsLessThanFees = makerFee.minus(1); + await zeroEx.token.setProxyAllowanceAsync(zrxTokenAddress, makerAddress, + newAllowanceWhichIsLessThanFees); + return expect(zeroEx.exchange.fillOrderAsync( + signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_MAKER_FEE_ALLOWANCE); + }); + it('should throw when taker doesn\'t have enough balance to pay fees', async () => { + const lackingBalance = new BigNumber(1); + await zeroEx.token.transferAsync(zrxTokenAddress, takerAddress, coinBase, lackingBalance); + return expect(zeroEx.exchange.fillOrderAsync( + signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_FEE_BALANCE); + }); + it('should throw when taker doesn\'t have enough allowance to pay fees', async () => { + const newAllowanceWhichIsLessThanFees = makerFee.minus(1); + await zeroEx.token.setProxyAllowanceAsync(zrxTokenAddress, takerAddress, + newAllowanceWhichIsLessThanFees); + return expect(zeroEx.exchange.fillOrderAsync( + signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_FEE_ALLOWANCE); + }); + }); }); describe('successful fills', () => { it('should fill the valid order', async () => { -- cgit From 07c61b1f9b75ec6a4589438ec2dff8ee926cc0d3 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 16:25:05 +0200 Subject: Refactor balance & allowance tests --- test/exchange_wrapper_test.ts | 89 ++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 47 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 6f4105e1e..29cdd925d 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -160,54 +160,49 @@ describe('ExchangeWrapper', () => { signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, )).to.be.rejectedWith(FillOrderValidationErrs.EXPIRED); }); - it('should throw when taker balance is less than fill amount', async () => { + describe('should throw when not enough balance or allowance to fulfill the order', () => { const fillableAmount = new BigNumber(5); - const signedOrder = await fillScenarios.createFillableSignedOrderAsync( - makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, - ); - zeroEx.setTransactionSenderAccount(takerAddress); - const moreThanTheBalance = new BigNumber(6); - return expect(zeroEx.exchange.fillOrderAsync( - signedOrder, moreThanTheBalance, shouldCheckTransfer, - )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_BALANCE); - }); - it('should throw when taker allowance is less than fill amount', async () => { - const fillableAmount = new BigNumber(5); - const signedOrder = await fillScenarios.createFillableSignedOrderAsync( - makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, - ); - const newAllowanceWhichIsLessThanFillAmount = fillTakerAmountInBaseUnits.minus(1); - await zeroEx.token.setProxyAllowanceAsync(takerTokenAddress, takerAddress, - newAllowanceWhichIsLessThanFillAmount); - zeroEx.setTransactionSenderAccount(takerAddress); - return expect(zeroEx.exchange.fillOrderAsync( - signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, - )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_ALLOWANCE); - }); - it('should throw when maker balance is less than maker fill amount', async () => { - const fillableAmount = new BigNumber(5); - const signedOrder = await fillScenarios.createFillableSignedOrderAsync( - makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, - ); - const lackingMakerBalance = new BigNumber(3); - await zeroEx.token.transferAsync(makerTokenAddress, makerAddress, coinBase, lackingMakerBalance); - zeroEx.setTransactionSenderAccount(takerAddress); - return expect(zeroEx.exchange.fillOrderAsync( - signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, - )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_MAKER_BALANCE); - }); - it('should throw when maker allowance is less than maker fill amount', async () => { - const fillableAmount = new BigNumber(5); - const signedOrder = await fillScenarios.createFillableSignedOrderAsync( - makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, - ); - const newAllowanceWhichIsLessThanFillAmount = fillTakerAmountInBaseUnits.minus(1); - await zeroEx.token.setProxyAllowanceAsync(makerTokenAddress, makerAddress, - newAllowanceWhichIsLessThanFillAmount); - zeroEx.setTransactionSenderAccount(takerAddress); - return expect(zeroEx.exchange.fillOrderAsync( - signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, - )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_MAKER_ALLOWANCE); + const lackingBalance = new BigNumber(3); + const lackingAllowance = new BigNumber(3); + let signedOrder: SignedOrder; + beforeEach('create fillable signed order', async () => { + signedOrder = await fillScenarios.createFillableSignedOrderAsync( + makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, + ); + }); + it('should throw when taker balance is less than fill amount', async () => { + + await zeroEx.token.transferAsync(takerTokenAddress, takerAddress, coinBase, lackingBalance); + zeroEx.setTransactionSenderAccount(takerAddress); + return expect(zeroEx.exchange.fillOrderAsync( + signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_BALANCE); + }); + it('should throw when taker allowance is less than fill amount', async () => { + const newAllowanceWhichIsLessThanFillAmount = fillTakerAmountInBaseUnits.minus(lackingAllowance); + await zeroEx.token.setProxyAllowanceAsync(takerTokenAddress, takerAddress, + newAllowanceWhichIsLessThanFillAmount); + zeroEx.setTransactionSenderAccount(takerAddress); + return expect(zeroEx.exchange.fillOrderAsync( + signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_ALLOWANCE); + }); + it('should throw when maker balance is less than maker fill amount', async () => { + await zeroEx.token.transferAsync(makerTokenAddress, makerAddress, coinBase, lackingBalance); + zeroEx.setTransactionSenderAccount(takerAddress); + return expect(zeroEx.exchange.fillOrderAsync( + signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_MAKER_BALANCE); + }); + it('should throw when maker allowance is less than maker fill amount', async () => { + const newAllowanceWhichIsLessThanFillAmount = fillTakerAmountInBaseUnits.minus(lackingAllowance); + await zeroEx.token.setProxyAllowanceAsync(makerTokenAddress, makerAddress, + newAllowanceWhichIsLessThanFillAmount); + zeroEx.setTransactionSenderAccount(takerAddress); + return expect(zeroEx.exchange.fillOrderAsync( + signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_MAKER_ALLOWANCE); + }); }); it('should throw when there would be a rounding error', async () => { const makerFillableAmount = new BigNumber(3); -- cgit From 3c71506022a827f37916f981a57e3ad8cc0c5abb Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 16:26:47 +0200 Subject: Rename coinBase to coinbase --- test/exchange_wrapper_test.ts | 12 ++++++------ test/utils/fill_scenarios.ts | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 29cdd925d..a72c11bb6 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -108,7 +108,7 @@ describe('ExchangeWrapper', () => { let makerTokenAddress: string; let takerTokenAddress: string; let fillScenarios: FillScenarios; - let coinBase: string; + let coinbase: string; let makerAddress: string; let takerAddress: string; let feeRecipient: string; @@ -116,7 +116,7 @@ describe('ExchangeWrapper', () => { const fillTakerAmountInBaseUnits = new BigNumber(5); const shouldCheckTransfer = false; before('fetch tokens', async () => { - [coinBase, makerAddress, takerAddress, feeRecipient] = userAddresses; + [coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses; tokens = await zeroEx.tokenRegistry.getTokensAsync(); const tokenUtils = new TokenUtils(tokens); const [makerToken, takerToken] = tokenUtils.getNonProtocolTokens(); @@ -172,7 +172,7 @@ describe('ExchangeWrapper', () => { }); it('should throw when taker balance is less than fill amount', async () => { - await zeroEx.token.transferAsync(takerTokenAddress, takerAddress, coinBase, lackingBalance); + await zeroEx.token.transferAsync(takerTokenAddress, takerAddress, coinbase, lackingBalance); zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, @@ -188,7 +188,7 @@ describe('ExchangeWrapper', () => { )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_ALLOWANCE); }); it('should throw when maker balance is less than maker fill amount', async () => { - await zeroEx.token.transferAsync(makerTokenAddress, makerAddress, coinBase, lackingBalance); + await zeroEx.token.transferAsync(makerTokenAddress, makerAddress, coinbase, lackingBalance); zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, @@ -231,7 +231,7 @@ describe('ExchangeWrapper', () => { }); it('should throw when maker doesn\'t have enough balance to pay fees', async () => { const lackingBalance = new BigNumber(1); - await zeroEx.token.transferAsync(zrxTokenAddress, makerAddress, coinBase, lackingBalance); + await zeroEx.token.transferAsync(zrxTokenAddress, makerAddress, coinbase, lackingBalance); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_MAKER_FEE_BALANCE); @@ -246,7 +246,7 @@ describe('ExchangeWrapper', () => { }); it('should throw when taker doesn\'t have enough balance to pay fees', async () => { const lackingBalance = new BigNumber(1); - await zeroEx.token.transferAsync(zrxTokenAddress, takerAddress, coinBase, lackingBalance); + await zeroEx.token.transferAsync(zrxTokenAddress, takerAddress, coinbase, lackingBalance); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_FEE_BALANCE); diff --git a/test/utils/fill_scenarios.ts b/test/utils/fill_scenarios.ts index 706f3f281..8260b76ab 100644 --- a/test/utils/fill_scenarios.ts +++ b/test/utils/fill_scenarios.ts @@ -8,13 +8,13 @@ export class FillScenarios { private zeroEx: ZeroEx; private userAddresses: string[]; private tokens: Token[]; - private coinBase: string; + private coinbase: string; private zrxTokenAddress: string; constructor(zeroEx: ZeroEx, userAddresses: string[], tokens: Token[], zrxTokenAddress: string) { this.zeroEx = zeroEx; this.userAddresses = userAddresses; this.tokens = tokens; - this.coinBase = userAddresses[0]; + this.coinbase = userAddresses[0]; this.zrxTokenAddress = zrxTokenAddress; } public async createFillableSignedOrderAsync(makerTokenAddress: string, takerTokenAddress: string, @@ -57,17 +57,17 @@ export class FillScenarios { makerAddress: string, takerAddress: string, makerFillableAmount: BigNumber.BigNumber, takerFillableAmount: BigNumber.BigNumber, feeRecepient: string, expirationUnixTimestampSec?: BigNumber.BigNumber): Promise { - await this.zeroEx.token.transferAsync(makerTokenAddress, this.coinBase, makerAddress, makerFillableAmount); + await this.zeroEx.token.transferAsync(makerTokenAddress, this.coinbase, makerAddress, makerFillableAmount); await this.zeroEx.token.setProxyAllowanceAsync(makerTokenAddress, makerAddress, makerFillableAmount); - await this.zeroEx.token.transferAsync(takerTokenAddress, this.coinBase, takerAddress, takerFillableAmount); + await this.zeroEx.token.transferAsync(takerTokenAddress, this.coinbase, takerAddress, takerFillableAmount); await this.zeroEx.token.setProxyAllowanceAsync(takerTokenAddress, takerAddress, takerFillableAmount); if (!makerFee.isZero()) { - await this.zeroEx.token.transferAsync(this.zrxTokenAddress, this.coinBase, makerAddress, makerFee); + await this.zeroEx.token.transferAsync(this.zrxTokenAddress, this.coinbase, makerAddress, makerFee); await this.zeroEx.token.setProxyAllowanceAsync(this.zrxTokenAddress, makerAddress, makerFee); } if (!takerFee.isZero()) { - await this.zeroEx.token.transferAsync(this.zrxTokenAddress, this.coinBase, takerAddress, takerFee); + await this.zeroEx.token.transferAsync(this.zrxTokenAddress, this.coinbase, takerAddress, takerFee); await this.zeroEx.token.setProxyAllowanceAsync(this.zrxTokenAddress, takerAddress, takerFee); } -- cgit From 48d5c8b9b504e94789261241cdd2f81900475f29 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 16:47:38 +0200 Subject: Remove protocol token artifacts --- src/artifacts/ProtocolToken.json | 321 --------------------------------------- 1 file changed, 321 deletions(-) delete mode 100644 src/artifacts/ProtocolToken.json diff --git a/src/artifacts/ProtocolToken.json b/src/artifacts/ProtocolToken.json deleted file mode 100644 index a1f8e0ff6..000000000 --- a/src/artifacts/ProtocolToken.json +++ /dev/null @@ -1,321 +0,0 @@ -{ - "contract_name": "ProtocolToken", - "abi": [ - { - "constant": true, - "inputs": [], - "name": "name", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_spender", - "type": "address" - }, - { - "name": "_value", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "name": "success", - "type": "bool" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - }, - { - "name": "_value", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "name": "success", - "type": "bool" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "decimals", - "outputs": [ - { - "name": "", - "type": "uint8" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "name": "balance", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "symbol", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_to", - "type": "address" - }, - { - "name": "_value", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "name": "success", - "type": "bool" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - }, - { - "name": "_spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "name": "remaining", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "inputs": [], - "payable": false, - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_owner", - "type": "address" - }, - { - "indexed": true, - "name": "_spender", - "type": "address" - }, - { - "indexed": false, - "name": "_value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - } - ], - "unlinked_binary": "0x606060405234610000575b6a52b7d2dcc80cd2e40000006002819055600160a060020a0333166000908152602081905260409020555b5b6105fc806100456000396000f3006060604052361561007d5763ffffffff60e060020a60003504166306fdde038114610082578063095ea7b31461010f57806318160ddd1461013f57806323b872dd1461015e578063313ce5671461019457806370a08231146101b757806395d89b41146101e2578063a9059cbb1461026f578063dd62ed3e1461029f575b610000565b346100005761008f6102d0565b6040805160208082528351818301528351919283929083019185019080838382156100d5575b8051825260208311156100d557601f1990920191602091820191016100b5565b505050905090810190601f1680156101015780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b346100005761012b600160a060020a0360043516602435610307565b604080519115158252519081900360200190f35b346100005761014c610372565b60408051918252519081900360200190f35b346100005761012b600160a060020a0360043581169060243516604435610378565b604080519115158252519081900360200190f35b34610000576101a1610485565b6040805160ff9092168252519081900360200190f35b346100005761014c600160a060020a036004351661048a565b60408051918252519081900360200190f35b346100005761008f6104a9565b6040805160208082528351818301528351919283929083019185019080838382156100d5575b8051825260208311156100d557601f1990920191602091820191016100b5565b505050905090810190601f1680156101015780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b346100005761012b600160a060020a03600435166024356104e0565b604080519115158252519081900360200190f35b346100005761014c600160a060020a03600435811690602435166105a3565b60408051918252519081900360200190f35b60408051808201909152601081527f3078204e6574776f726b20546f6b656e00000000000000000000000000000000602082015281565b600160a060020a03338116600081815260016020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b60025481565b600160a060020a0383166000908152602081905260408120548290108015906103c85750600160a060020a0380851660009081526001602090815260408083203390941683529290522054829010155b80156103ed5750600160a060020a038316600090815260208190526040902054828101115b1561047957600160a060020a0380841660008181526020818152604080832080548801905588851680845281842080548990039055600183528184203390961684529482529182902080548790039055815186815291519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a350600161047d565b5060005b5b9392505050565b601281565b600160a060020a0381166000908152602081905260409020545b919050565b60408051808201909152600381527f5a52580000000000000000000000000000000000000000000000000000000000602082015281565b600160a060020a0333166000908152602081905260408120548290108015906105225750600160a060020a038316600090815260208190526040902054828101115b1561059457600160a060020a0333811660008181526020818152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a350600161036c565b50600061036c565b5b92915050565b600160a060020a038083166000908152600160209081526040808320938516835292905220545b929150505600a165627a7a723058209912b9e0769f5bfbb24cc18ed6298aba4698371192fbf585b239f6db1b8bdc2f0029", - "networks": { - "42": { - "links": {}, - "events": { - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_owner", - "type": "address" - }, - { - "indexed": true, - "name": "_spender", - "type": "address" - }, - { - "indexed": false, - "name": "_value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - } - }, - "updated_at": 1495042008608 - }, - "50": { - "links": {}, - "events": { - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "name": "_value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925": { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "_owner", - "type": "address" - }, - { - "indexed": true, - "name": "_spender", - "type": "address" - }, - { - "indexed": false, - "name": "_value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - } - }, - "updated_at": 1495030736785 - } - }, - "schema_version": "0.0.5", - "updated_at": 1495042008608 -} \ No newline at end of file -- cgit From dea6406a5f1027c4706dfd90b4e5c59e42d15bf0 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 2 Jun 2017 16:53:56 +0200 Subject: remove ProtocolToken --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6b2182f0b..8b472f2a9 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "run_mocha": "mocha lib/test/**/*_test.js --timeout 3000" }, "config": { - "artifacts": "Proxy Exchange TokenRegistry Token Mintable EtherToken ProtocolToken", + "artifacts": "Proxy Exchange TokenRegistry Token Mintable EtherToken", "mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic" }, "repository": { -- cgit From 00fde26a541797902e1732b0a978376c8960195e Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 2 Jun 2017 16:54:05 +0200 Subject: Improve comment --- src/0x.js.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/0x.js.ts b/src/0x.js.ts index 679d748e7..7cf313666 100644 --- a/src/0x.js.ts +++ b/src/0x.js.ts @@ -116,7 +116,6 @@ export class ZeroEx { this.tokenRegistry.invalidateContractInstance(); this.token.invalidateContractInstances(); } - /** * Sets default account for sending transactions. */ @@ -131,7 +130,7 @@ export class ZeroEx { return senderAccountIfExists; } /** - * Computes the orderHash given the order parameters and returns it as a hex encoded string. + * Computes the orderHash for a given order and returns it as a hex encoded string. */ public async getOrderHashHexAsync(order: Order): Promise { const exchangeContractAddr = await this.getExchangeAddressAsync(); -- cgit From ade42047436f8f81bcc158fdfdc297dc6a2b1f66 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 2 Jun 2017 16:54:21 +0200 Subject: Improve error names and remove duplicate import --- src/contract_wrappers/exchange_wrapper.ts | 10 +++++----- src/types.ts | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index fa5c16485..93e49cf33 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -10,6 +10,7 @@ import { OrderAddresses, SignedOrder, ContractEvent, + ContractResponse, } from '../types'; import {assert} from '../utils/assert'; import {ContractWrapper} from './contract_wrapper'; @@ -17,18 +18,17 @@ import * as ExchangeArtifacts from '../artifacts/Exchange.json'; import {ecSignatureSchema} from '../schemas/ec_signature_schema'; import {signedOrderSchema} from '../schemas/order_schemas'; import {SchemaValidator} from '../utils/schema_validator'; -import {ContractResponse} from '../types'; import {constants} from '../utils/constants'; import {TokenWrapper} from './token_wrapper'; export class ExchangeWrapper extends ContractWrapper { private exchangeContractErrCodesToMsg = { - [ExchangeContractErrCodes.ERROR_FILL_EXPIRED]: ExchangeContractErrs.ORDER_EXPIRED, - [ExchangeContractErrCodes.ERROR_CANCEL_EXPIRED]: ExchangeContractErrs.ORDER_EXPIRED, + [ExchangeContractErrCodes.ERROR_FILL_EXPIRED]: ExchangeContractErrs.ORDER_FILL_EXPIRED, + [ExchangeContractErrCodes.ERROR_CANCEL_EXPIRED]: ExchangeContractErrs.ORDER_FILL_EXPIRED, [ExchangeContractErrCodes.ERROR_FILL_NO_VALUE]: ExchangeContractErrs.ORDER_REMAINING_FILL_AMOUNT_ZERO, [ExchangeContractErrCodes.ERROR_CANCEL_NO_VALUE]: ExchangeContractErrs.ORDER_REMAINING_FILL_AMOUNT_ZERO, - [ExchangeContractErrCodes.ERROR_FILL_TRUNCATION]: ExchangeContractErrs.ORDER_ROUNDING_ERROR, - [ExchangeContractErrCodes.ERROR_FILL_BALANCE_ALLOWANCE]: ExchangeContractErrs.ORDER_BALANCE_ALLOWANCE_ERROR, + [ExchangeContractErrCodes.ERROR_FILL_TRUNCATION]: ExchangeContractErrs.ORDER_FILL_ROUNDING_ERROR, + [ExchangeContractErrCodes.ERROR_FILL_BALANCE_ALLOWANCE]: ExchangeContractErrs.FILL_BALANCE_ALLOWANCE_ERROR, }; private exchangeContractIfExists?: ExchangeContract; private tokenWrapper: TokenWrapper; diff --git a/src/types.ts b/src/types.ts index 4819b13ac..b39484f8a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -85,10 +85,10 @@ export enum ExchangeContractErrCodes { } export const ExchangeContractErrs = strEnum([ - 'ORDER_EXPIRED', + 'ORDER_FILL_EXPIRED', 'ORDER_REMAINING_FILL_AMOUNT_ZERO', - 'ORDER_ROUNDING_ERROR', - 'ORDER_BALANCE_ALLOWANCE_ERROR', + 'ORDER_FILL_ROUNDING_ERROR', + 'FILL_BALANCE_ALLOWANCE_ERROR', ]); export type ExchangeContractErrs = keyof typeof ExchangeContractErrs; -- cgit From 38c48eb2266632a10fee75ecea7bbce4c343c1cb Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 2 Jun 2017 17:02:16 +0200 Subject: Improve fillOrderAsync comment --- src/contract_wrappers/exchange_wrapper.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 93e49cf33..131211771 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -61,9 +61,12 @@ export class ExchangeWrapper extends ContractWrapper { return isValidSignature; } /** - * Fills a signed order with a fillAmount denominated in baseUnits of the taker token. The caller can - * decide whether they want the call to throw if the balance/allowance checks fail by setting - * shouldCheckTransfer to false. If set to true, the call will fail without throwing, preserving gas costs. + * Fills a signed order with a fillAmount denominated in baseUnits of the taker token. + * Since the order in which transactions are included in the next block is indeterminate, race-conditions + * could arise where a users balance or allowance changes before the fillOrder executes. Because of this, + * we allow you to specify `shouldCheckTransfer`. If true, the smart contract will not throw if while + * executing, the parties do not have sufficient balances/allowances, preserving gas costs. Setting it to + * false foregoes this check and causes the smart contract to throw instead. */ public async fillOrderAsync(signedOrder: SignedOrder, fillTakerAmountInBaseUnits: BigNumber.BigNumber, shouldCheckTransfer: boolean): Promise { -- cgit From 827a0d4e91169e338cbdc8042d158aaf7fdcf96c Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 2 Jun 2017 17:03:36 +0200 Subject: rename fillTakerAmountInBaseUnits to fillTakerAmount --- src/contract_wrappers/exchange_wrapper.ts | 30 +++++++++++----------- src/types.ts | 2 +- test/exchange_wrapper_test.ts | 42 +++++++++++++++---------------- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 131211771..f0f6e79f7 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -68,18 +68,18 @@ export class ExchangeWrapper extends ContractWrapper { * executing, the parties do not have sufficient balances/allowances, preserving gas costs. Setting it to * false foregoes this check and causes the smart contract to throw instead. */ - public async fillOrderAsync(signedOrder: SignedOrder, fillTakerAmountInBaseUnits: BigNumber.BigNumber, + public async fillOrderAsync(signedOrder: SignedOrder, fillTakerAmount: BigNumber.BigNumber, shouldCheckTransfer: boolean): Promise { assert.doesConformToSchema('signedOrder', SchemaValidator.convertToJSONSchemaCompatibleObject(signedOrder as object), signedOrderSchema); - assert.isBigNumber('fillTakerAmountInBaseUnits', fillTakerAmountInBaseUnits); + assert.isBigNumber('fillTakerAmount', fillTakerAmount); assert.isBoolean('shouldCheckTransfer', shouldCheckTransfer); const senderAddress = await this.web3Wrapper.getSenderAddressOrThrowAsync(); const exchangeInstance = await this.getExchangeContractAsync(); const zrxTokenAddress = await exchangeInstance.ZRX.call(); - await this.validateFillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, senderAddress, zrxTokenAddress); + await this.validateFillOrderAsync(signedOrder, fillTakerAmount, senderAddress, zrxTokenAddress); const orderAddresses: OrderAddresses = [ signedOrder.maker, @@ -99,7 +99,7 @@ export class ExchangeWrapper extends ContractWrapper { const gas = await exchangeInstance.fill.estimateGas( orderAddresses, orderValues, - fillTakerAmountInBaseUnits, + fillTakerAmount, shouldCheckTransfer, signedOrder.ecSignature.v, signedOrder.ecSignature.r, @@ -111,7 +111,7 @@ export class ExchangeWrapper extends ContractWrapper { const response: ContractResponse = await exchangeInstance.fill( orderAddresses, orderValues, - fillTakerAmountInBaseUnits, + fillTakerAmount, shouldCheckTransfer, signedOrder.ecSignature.v, signedOrder.ecSignature.r, @@ -123,9 +123,9 @@ export class ExchangeWrapper extends ContractWrapper { ); this.throwErrorLogsAsErrors(response.logs); } - private async validateFillOrderAsync(signedOrder: SignedOrder, fillTakerAmountInBaseUnits: BigNumber.BigNumber, + private async validateFillOrderAsync(signedOrder: SignedOrder, fillTakerAmount: BigNumber.BigNumber, senderAddress: string, zrxTokenAddress: string): Promise { - if (fillTakerAmountInBaseUnits.eq(0)) { + if (fillTakerAmount.eq(0)) { throw new Error(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); } if (signedOrder.taker !== constants.NULL_ADDRESS && signedOrder.taker !== senderAddress) { @@ -135,16 +135,16 @@ export class ExchangeWrapper extends ContractWrapper { throw new Error(FillOrderValidationErrs.EXPIRED); } - await this.validateFillOrderBalancesAndAllowancesAsync(signedOrder, fillTakerAmountInBaseUnits, + await this.validateFillOrderBalancesAndAllowancesAsync(signedOrder, fillTakerAmount, senderAddress, zrxTokenAddress); - if (await this.isRoundingErrorAsync(signedOrder.takerTokenAmount, fillTakerAmountInBaseUnits, + if (await this.isRoundingErrorAsync(signedOrder.takerTokenAmount, fillTakerAmount, signedOrder.makerTokenAmount)) { throw new Error(FillOrderValidationErrs.ROUNDING_ERROR); } } private async validateFillOrderBalancesAndAllowancesAsync(signedOrder: SignedOrder, - fillTakerAmountInBaseUnits: BigNumber.BigNumber, + fillTakerAmount: BigNumber.BigNumber, senderAddress: string, zrxTokenAddress: string): Promise { // TODO: There is a possibility that the user might have enough funds @@ -162,12 +162,12 @@ export class ExchangeWrapper extends ContractWrapper { // How many taker tokens would you get for 1 maker token; const exchangeRate = signedOrder.takerTokenAmount.div(signedOrder.makerTokenAmount); - const fillMakerAmountInBaseUnits = fillTakerAmountInBaseUnits.div(exchangeRate); + const fillMakerAmountInBaseUnits = fillTakerAmount.div(exchangeRate); - if (fillTakerAmountInBaseUnits.greaterThan(takerBalance)) { + if (fillTakerAmount.greaterThan(takerBalance)) { throw new Error(FillOrderValidationErrs.NOT_ENOUGH_TAKER_BALANCE); } - if (fillTakerAmountInBaseUnits.greaterThan(takerAllowance)) { + if (fillTakerAmount.greaterThan(takerAllowance)) { throw new Error(FillOrderValidationErrs.NOT_ENOUGH_TAKER_ALLOWANCE); } if (fillMakerAmountInBaseUnits.greaterThan(makerBalance)) { @@ -207,12 +207,12 @@ export class ExchangeWrapper extends ContractWrapper { } } private async isRoundingErrorAsync(takerTokenAmount: BigNumber.BigNumber, - fillTakerAmountInBaseUnits: BigNumber.BigNumber, + fillTakerAmount: BigNumber.BigNumber, makerTokenAmount: BigNumber.BigNumber): Promise { const exchangeInstance = await this.getExchangeContractAsync(); const senderAddress = await this.web3Wrapper.getSenderAddressOrThrowAsync(); const isRoundingError = await exchangeInstance.isRoundingError.call( - takerTokenAmount, fillTakerAmountInBaseUnits, makerTokenAmount, { + takerTokenAmount, fillTakerAmount, makerTokenAmount, { from: senderAddress, }, ); diff --git a/src/types.ts b/src/types.ts index b39484f8a..57a9c721a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -35,7 +35,7 @@ export type OrderValues = [BigNumber.BigNumber, BigNumber.BigNumber, BigNumber.B export interface ExchangeContract { isValidSignature: any; isRoundingError: { - call: (takerTokenAmount: BigNumber.BigNumber, fillTakerAmountInBaseUnits: BigNumber.BigNumber, + call: (takerTokenAmount: BigNumber.BigNumber, fillTakerAmount: BigNumber.BigNumber, makerTokenAmount: BigNumber.BigNumber, txOpts: TxOpts) => Promise; }; fill: { diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index a72c11bb6..76601d1b3 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -113,7 +113,7 @@ describe('ExchangeWrapper', () => { let takerAddress: string; let feeRecipient: string; let zrxTokenAddress: string; - const fillTakerAmountInBaseUnits = new BigNumber(5); + const fillTakerAmount = new BigNumber(5); const shouldCheckTransfer = false; before('fetch tokens', async () => { [coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses; @@ -146,7 +146,7 @@ describe('ExchangeWrapper', () => { makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, ); return expect(zeroEx.exchange.fillOrderAsync( - signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + signedOrder, fillTakerAmount, shouldCheckTransfer, )).to.be.rejectedWith(FillOrderValidationErrs.NOT_A_TAKER); }); it('should throw when order is expired', async () => { @@ -157,7 +157,7 @@ describe('ExchangeWrapper', () => { ); zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( - signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + signedOrder, fillTakerAmount, shouldCheckTransfer, )).to.be.rejectedWith(FillOrderValidationErrs.EXPIRED); }); describe('should throw when not enough balance or allowance to fulfill the order', () => { @@ -175,32 +175,32 @@ describe('ExchangeWrapper', () => { await zeroEx.token.transferAsync(takerTokenAddress, takerAddress, coinbase, lackingBalance); zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( - signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + signedOrder, fillTakerAmount, shouldCheckTransfer, )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_BALANCE); }); it('should throw when taker allowance is less than fill amount', async () => { - const newAllowanceWhichIsLessThanFillAmount = fillTakerAmountInBaseUnits.minus(lackingAllowance); + const newAllowanceWhichIsLessThanFillAmount = fillTakerAmount.minus(lackingAllowance); await zeroEx.token.setProxyAllowanceAsync(takerTokenAddress, takerAddress, newAllowanceWhichIsLessThanFillAmount); zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( - signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + signedOrder, fillTakerAmount, shouldCheckTransfer, )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_ALLOWANCE); }); it('should throw when maker balance is less than maker fill amount', async () => { await zeroEx.token.transferAsync(makerTokenAddress, makerAddress, coinbase, lackingBalance); zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( - signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + signedOrder, fillTakerAmount, shouldCheckTransfer, )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_MAKER_BALANCE); }); it('should throw when maker allowance is less than maker fill amount', async () => { - const newAllowanceWhichIsLessThanFillAmount = fillTakerAmountInBaseUnits.minus(lackingAllowance); + const newAllowanceWhichIsLessThanFillAmount = fillTakerAmount.minus(lackingAllowance); await zeroEx.token.setProxyAllowanceAsync(makerTokenAddress, makerAddress, newAllowanceWhichIsLessThanFillAmount); zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( - signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + signedOrder, fillTakerAmount, shouldCheckTransfer, )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_MAKER_ALLOWANCE); }); }); @@ -211,10 +211,10 @@ describe('ExchangeWrapper', () => { makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, makerFillableAmount, takerFillableAmount, ); - const fillTakerAmountInBaseUnitsThatCausesRoundingError = new BigNumber(3); + const fillTakerAmountThatCausesRoundingError = new BigNumber(3); zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( - signedOrder, fillTakerAmountInBaseUnitsThatCausesRoundingError, shouldCheckTransfer, + signedOrder, fillTakerAmountThatCausesRoundingError, shouldCheckTransfer, )).to.be.rejectedWith(FillOrderValidationErrs.ROUNDING_ERROR); }); describe('should raise when not enough balance or allowance to pay fees', () => { @@ -233,7 +233,7 @@ describe('ExchangeWrapper', () => { const lackingBalance = new BigNumber(1); await zeroEx.token.transferAsync(zrxTokenAddress, makerAddress, coinbase, lackingBalance); return expect(zeroEx.exchange.fillOrderAsync( - signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + signedOrder, fillTakerAmount, shouldCheckTransfer, )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_MAKER_FEE_BALANCE); }); it('should throw when maker doesn\'t have enough allowance to pay fees', async () => { @@ -241,14 +241,14 @@ describe('ExchangeWrapper', () => { await zeroEx.token.setProxyAllowanceAsync(zrxTokenAddress, makerAddress, newAllowanceWhichIsLessThanFees); return expect(zeroEx.exchange.fillOrderAsync( - signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + signedOrder, fillTakerAmount, shouldCheckTransfer, )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_MAKER_FEE_ALLOWANCE); }); it('should throw when taker doesn\'t have enough balance to pay fees', async () => { const lackingBalance = new BigNumber(1); await zeroEx.token.transferAsync(zrxTokenAddress, takerAddress, coinbase, lackingBalance); return expect(zeroEx.exchange.fillOrderAsync( - signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + signedOrder, fillTakerAmount, shouldCheckTransfer, )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_FEE_BALANCE); }); it('should throw when taker doesn\'t have enough allowance to pay fees', async () => { @@ -256,7 +256,7 @@ describe('ExchangeWrapper', () => { await zeroEx.token.setProxyAllowanceAsync(zrxTokenAddress, takerAddress, newAllowanceWhichIsLessThanFees); return expect(zeroEx.exchange.fillOrderAsync( - signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, + signedOrder, fillTakerAmount, shouldCheckTransfer, )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_FEE_ALLOWANCE); }); }); @@ -277,15 +277,15 @@ describe('ExchangeWrapper', () => { expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)) .to.be.bignumber.equal(fillableAmount); zeroEx.setTransactionSenderAccount(takerAddress); - await zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer); + await zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmount, shouldCheckTransfer); expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)) - .to.be.bignumber.equal(fillableAmount.minus(fillTakerAmountInBaseUnits)); + .to.be.bignumber.equal(fillableAmount.minus(fillTakerAmount)); expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)) - .to.be.bignumber.equal(fillTakerAmountInBaseUnits); + .to.be.bignumber.equal(fillTakerAmount); expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)) - .to.be.bignumber.equal(fillTakerAmountInBaseUnits); + .to.be.bignumber.equal(fillTakerAmount); expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)) - .to.be.bignumber.equal(fillableAmount.minus(fillTakerAmountInBaseUnits)); + .to.be.bignumber.equal(fillableAmount.minus(fillTakerAmount)); }); it('should partially fill the valid order', async () => { const fillableAmount = new BigNumber(5); @@ -313,7 +313,7 @@ describe('ExchangeWrapper', () => { makerAddress, takerAddress, fillableAmount, feeRecipient, ); zeroEx.setTransactionSenderAccount(takerAddress); - await zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer); + await zeroEx.exchange.fillOrderAsync(signedOrder, fillTakerAmount, shouldCheckTransfer); expect(await zeroEx.token.getBalanceAsync(zrxTokenAddress, feeRecipient)) .to.be.bignumber.equal(makerFee.plus(takerFee)); }); -- cgit From 9756aa86b051940b88f87fbecb313bf07590eca3 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 17:34:01 +0200 Subject: Add getZRXTokenAddressAsync --- src/contract_wrappers/exchange_wrapper.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index f0f6e79f7..0c7f27507 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -78,7 +78,7 @@ export class ExchangeWrapper extends ContractWrapper { const senderAddress = await this.web3Wrapper.getSenderAddressOrThrowAsync(); const exchangeInstance = await this.getExchangeContractAsync(); - const zrxTokenAddress = await exchangeInstance.ZRX.call(); + const zrxTokenAddress = await this.getZRXTokenAddressAsync(exchangeInstance); await this.validateFillOrderAsync(signedOrder, fillTakerAmount, senderAddress, zrxTokenAddress); const orderAddresses: OrderAddresses = [ @@ -226,4 +226,7 @@ export class ExchangeWrapper extends ContractWrapper { this.exchangeContractIfExists = contractInstance as ExchangeContract; return this.exchangeContractIfExists; } + private async getZRXTokenAddressAsync(exchangeInstance: ExchangeContract): Promise { + return exchangeInstance.ZRX.call(); + } } -- cgit From ef3a27ed0545e2e30e965b928ae13c8a53e16e8d Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 17:35:05 +0200 Subject: Rename validation functions --- src/contract_wrappers/exchange_wrapper.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 0c7f27507..965b31710 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -79,7 +79,7 @@ export class ExchangeWrapper extends ContractWrapper { const senderAddress = await this.web3Wrapper.getSenderAddressOrThrowAsync(); const exchangeInstance = await this.getExchangeContractAsync(); const zrxTokenAddress = await this.getZRXTokenAddressAsync(exchangeInstance); - await this.validateFillOrderAsync(signedOrder, fillTakerAmount, senderAddress, zrxTokenAddress); + await this.validateFillOrderAndThrowIfInvalidAsync(signedOrder, fillTakerAmount, senderAddress, zrxTokenAddress); const orderAddresses: OrderAddresses = [ signedOrder.maker, @@ -123,8 +123,8 @@ export class ExchangeWrapper extends ContractWrapper { ); this.throwErrorLogsAsErrors(response.logs); } - private async validateFillOrderAsync(signedOrder: SignedOrder, fillTakerAmount: BigNumber.BigNumber, - senderAddress: string, zrxTokenAddress: string): Promise { + private async validateFillOrderAndThrowIfInvalidAsync(signedOrder: SignedOrder, fillTakerAmount: BigNumber.BigNumber, + senderAddress: string, zrxTokenAddress: string): Promise { if (fillTakerAmount.eq(0)) { throw new Error(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); } @@ -135,7 +135,7 @@ export class ExchangeWrapper extends ContractWrapper { throw new Error(FillOrderValidationErrs.EXPIRED); } - await this.validateFillOrderBalancesAndAllowancesAsync(signedOrder, fillTakerAmount, + await this.validateFillOrderBalancesAndAllowancesAndThrowIfInvalidAsync(signedOrder, fillTakerAmount, senderAddress, zrxTokenAddress); if (await this.isRoundingErrorAsync(signedOrder.takerTokenAmount, fillTakerAmount, @@ -143,10 +143,10 @@ export class ExchangeWrapper extends ContractWrapper { throw new Error(FillOrderValidationErrs.ROUNDING_ERROR); } } - private async validateFillOrderBalancesAndAllowancesAsync(signedOrder: SignedOrder, - fillTakerAmount: BigNumber.BigNumber, - senderAddress: string, - zrxTokenAddress: string): Promise { + private async validateFillOrderBalancesAndAllowancesAndThrowIfInvalidAsync(signedOrder: SignedOrder, + fillTakerAmount: BigNumber.BigNumber, + senderAddress: string, + zrxTokenAddress: string): Promise { // TODO: There is a possibility that the user might have enough funds // to fulfill the order or pay fees but not both. This will happen if // makerToken === zrxToken || makerToken === zrxToken -- cgit From 0f7bd0597234dbeafcee31e6f715f3c2004696df Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 17:37:28 +0200 Subject: Don't pass zrxTokenAsign --- src/contract_wrappers/exchange_wrapper.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 965b31710..d7d56c276 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -78,8 +78,7 @@ export class ExchangeWrapper extends ContractWrapper { const senderAddress = await this.web3Wrapper.getSenderAddressOrThrowAsync(); const exchangeInstance = await this.getExchangeContractAsync(); - const zrxTokenAddress = await this.getZRXTokenAddressAsync(exchangeInstance); - await this.validateFillOrderAndThrowIfInvalidAsync(signedOrder, fillTakerAmount, senderAddress, zrxTokenAddress); + await this.validateFillOrderAndThrowIfInvalidAsync(signedOrder, fillTakerAmount, senderAddress); const orderAddresses: OrderAddresses = [ signedOrder.maker, @@ -123,8 +122,9 @@ export class ExchangeWrapper extends ContractWrapper { ); this.throwErrorLogsAsErrors(response.logs); } - private async validateFillOrderAndThrowIfInvalidAsync(signedOrder: SignedOrder, fillTakerAmount: BigNumber.BigNumber, - senderAddress: string, zrxTokenAddress: string): Promise { + private async validateFillOrderAndThrowIfInvalidAsync(signedOrder: SignedOrder, + fillTakerAmount: BigNumber.BigNumber, + senderAddress: string): Promise { if (fillTakerAmount.eq(0)) { throw new Error(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); } @@ -134,7 +134,7 @@ export class ExchangeWrapper extends ContractWrapper { if (signedOrder.expirationUnixTimestampSec.lessThan(Date.now() / 1000)) { throw new Error(FillOrderValidationErrs.EXPIRED); } - + const zrxTokenAddress = await this.getZRXTokenAddressAsync(); await this.validateFillOrderBalancesAndAllowancesAndThrowIfInvalidAsync(signedOrder, fillTakerAmount, senderAddress, zrxTokenAddress); @@ -226,7 +226,8 @@ export class ExchangeWrapper extends ContractWrapper { this.exchangeContractIfExists = contractInstance as ExchangeContract; return this.exchangeContractIfExists; } - private async getZRXTokenAddressAsync(exchangeInstance: ExchangeContract): Promise { + private async getZRXTokenAddressAsync(): Promise { + const exchangeInstance = await this.getExchangeContractAsync(); return exchangeInstance.ZRX.call(); } } -- cgit From e5cc0e0562eccf67eff9cf0521c4884ffc3b0f3b Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 17:38:47 +0200 Subject: Rename NOT_A_TAKER to TRANSACTION_SENDER_IS_NOT_FILL_ORDER_TAKER --- src/contract_wrappers/exchange_wrapper.ts | 2 +- src/types.ts | 2 +- test/exchange_wrapper_test.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index d7d56c276..ac15faff4 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -129,7 +129,7 @@ export class ExchangeWrapper extends ContractWrapper { throw new Error(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); } if (signedOrder.taker !== constants.NULL_ADDRESS && signedOrder.taker !== senderAddress) { - throw new Error(FillOrderValidationErrs.NOT_A_TAKER); + throw new Error(FillOrderValidationErrs.TRANSACTION_SENDER_IS_NOT_FILL_ORDER_TAKER); } if (signedOrder.expirationUnixTimestampSec.lessThan(Date.now() / 1000)) { throw new Error(FillOrderValidationErrs.EXPIRED); diff --git a/src/types.ts b/src/types.ts index 57a9c721a..6e1499a7c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -94,7 +94,7 @@ export type ExchangeContractErrs = keyof typeof ExchangeContractErrs; export const FillOrderValidationErrs = strEnum([ 'FILL_AMOUNT_IS_ZERO', - 'NOT_A_TAKER', + 'TRANSACTION_SENDER_IS_NOT_FILL_ORDER_TAKER', 'EXPIRED', 'NOT_ENOUGH_TAKER_BALANCE', 'NOT_ENOUGH_TAKER_ALLOWANCE', diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 76601d1b3..d8934d409 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -147,7 +147,7 @@ describe('ExchangeWrapper', () => { ); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, - )).to.be.rejectedWith(FillOrderValidationErrs.NOT_A_TAKER); + )).to.be.rejectedWith(FillOrderValidationErrs.TRANSACTION_SENDER_IS_NOT_FILL_ORDER_TAKER); }); it('should throw when order is expired', async () => { const expirationInPast = new BigNumber(42); -- cgit From f5158eebf335c9fbcfb7cfb6f32a0ecd1161391d Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 17:39:21 +0200 Subject: Assign timestamp to a variable --- src/contract_wrappers/exchange_wrapper.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index ac15faff4..4c46404bb 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -131,7 +131,8 @@ export class ExchangeWrapper extends ContractWrapper { if (signedOrder.taker !== constants.NULL_ADDRESS && signedOrder.taker !== senderAddress) { throw new Error(FillOrderValidationErrs.TRANSACTION_SENDER_IS_NOT_FILL_ORDER_TAKER); } - if (signedOrder.expirationUnixTimestampSec.lessThan(Date.now() / 1000)) { + const currentUnixTimestampSec = Date.now() / 1000; + if (signedOrder.expirationUnixTimestampSec.lessThan(currentUnixTimestampSec)) { throw new Error(FillOrderValidationErrs.EXPIRED); } const zrxTokenAddress = await this.getZRXTokenAddressAsync(); -- cgit From 7fd84e29ab8c27cb872cf8cd0f631d4b78abba0e Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 17:40:06 +0200 Subject: Rename EXPIRED to FILL_ORDER_EXPIRED --- src/contract_wrappers/exchange_wrapper.ts | 2 +- src/types.ts | 2 +- test/exchange_wrapper_test.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 4c46404bb..e957530ae 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -133,7 +133,7 @@ export class ExchangeWrapper extends ContractWrapper { } const currentUnixTimestampSec = Date.now() / 1000; if (signedOrder.expirationUnixTimestampSec.lessThan(currentUnixTimestampSec)) { - throw new Error(FillOrderValidationErrs.EXPIRED); + throw new Error(FillOrderValidationErrs.FILL_ORDER_EXPIRED); } const zrxTokenAddress = await this.getZRXTokenAddressAsync(); await this.validateFillOrderBalancesAndAllowancesAndThrowIfInvalidAsync(signedOrder, fillTakerAmount, diff --git a/src/types.ts b/src/types.ts index 6e1499a7c..e4a7da5d7 100644 --- a/src/types.ts +++ b/src/types.ts @@ -95,7 +95,7 @@ export type ExchangeContractErrs = keyof typeof ExchangeContractErrs; export const FillOrderValidationErrs = strEnum([ 'FILL_AMOUNT_IS_ZERO', 'TRANSACTION_SENDER_IS_NOT_FILL_ORDER_TAKER', - 'EXPIRED', + 'FILL_ORDER_EXPIRED', 'NOT_ENOUGH_TAKER_BALANCE', 'NOT_ENOUGH_TAKER_ALLOWANCE', 'NOT_ENOUGH_MAKER_BALANCE', diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index d8934d409..e83134909 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -158,7 +158,7 @@ describe('ExchangeWrapper', () => { zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, - )).to.be.rejectedWith(FillOrderValidationErrs.EXPIRED); + )).to.be.rejectedWith(FillOrderValidationErrs.FILL_ORDER_EXPIRED); }); describe('should throw when not enough balance or allowance to fulfill the order', () => { const fillableAmount = new BigNumber(5); -- cgit From 54e8bf773091eb2c8587c72e50892afec42abb9d Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 17:41:23 +0200 Subject: Assign wouldRoundingErrorOccur to a variable --- src/contract_wrappers/exchange_wrapper.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index e957530ae..828994829 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -139,8 +139,10 @@ export class ExchangeWrapper extends ContractWrapper { await this.validateFillOrderBalancesAndAllowancesAndThrowIfInvalidAsync(signedOrder, fillTakerAmount, senderAddress, zrxTokenAddress); - if (await this.isRoundingErrorAsync(signedOrder.takerTokenAmount, fillTakerAmount, - signedOrder.makerTokenAmount)) { + const wouldRoundingErrorOccur = await this.isRoundingErrorAsync( + signedOrder.takerTokenAmount, fillTakerAmount, signedOrder.makerTokenAmount, + ); + if (wouldRoundingErrorOccur) { throw new Error(FillOrderValidationErrs.ROUNDING_ERROR); } } -- cgit From abf2cf4c5e2ea6d09d862871adfa16ca108907e2 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 18:00:37 +0200 Subject: Move FillOrderValidatinErrs to ExchangeContractErrs --- src/contract_wrappers/exchange_wrapper.ts | 25 ++++++++++++------------- src/types.ts | 12 +++--------- test/exchange_wrapper_test.ts | 26 +++++++++++++------------- 3 files changed, 28 insertions(+), 35 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 828994829..716f9c77a 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -5,7 +5,6 @@ import { ExchangeContract, ExchangeContractErrCodes, ExchangeContractErrs, - FillOrderValidationErrs, OrderValues, OrderAddresses, SignedOrder, @@ -126,14 +125,14 @@ export class ExchangeWrapper extends ContractWrapper { fillTakerAmount: BigNumber.BigNumber, senderAddress: string): Promise { if (fillTakerAmount.eq(0)) { - throw new Error(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); + throw new Error(ExchangeContractErrs.ORDER_REMAINING_FILL_AMOUNT_ZERO); } if (signedOrder.taker !== constants.NULL_ADDRESS && signedOrder.taker !== senderAddress) { - throw new Error(FillOrderValidationErrs.TRANSACTION_SENDER_IS_NOT_FILL_ORDER_TAKER); + throw new Error(ExchangeContractErrs.TRANSACTION_SENDER_IS_NOT_FILL_ORDER_TAKER); } const currentUnixTimestampSec = Date.now() / 1000; if (signedOrder.expirationUnixTimestampSec.lessThan(currentUnixTimestampSec)) { - throw new Error(FillOrderValidationErrs.FILL_ORDER_EXPIRED); + throw new Error(ExchangeContractErrs.ORDER_FILL_EXPIRED); } const zrxTokenAddress = await this.getZRXTokenAddressAsync(); await this.validateFillOrderBalancesAndAllowancesAndThrowIfInvalidAsync(signedOrder, fillTakerAmount, @@ -143,7 +142,7 @@ export class ExchangeWrapper extends ContractWrapper { signedOrder.takerTokenAmount, fillTakerAmount, signedOrder.makerTokenAmount, ); if (wouldRoundingErrorOccur) { - throw new Error(FillOrderValidationErrs.ROUNDING_ERROR); + throw new Error(ExchangeContractErrs.ORDER_FILL_ROUNDING_ERROR); } } private async validateFillOrderBalancesAndAllowancesAndThrowIfInvalidAsync(signedOrder: SignedOrder, @@ -168,16 +167,16 @@ export class ExchangeWrapper extends ContractWrapper { const fillMakerAmountInBaseUnits = fillTakerAmount.div(exchangeRate); if (fillTakerAmount.greaterThan(takerBalance)) { - throw new Error(FillOrderValidationErrs.NOT_ENOUGH_TAKER_BALANCE); + throw new Error(ExchangeContractErrs.NOT_ENOUGH_TAKER_BALANCE); } if (fillTakerAmount.greaterThan(takerAllowance)) { - throw new Error(FillOrderValidationErrs.NOT_ENOUGH_TAKER_ALLOWANCE); + throw new Error(ExchangeContractErrs.NOT_ENOUGH_TAKER_ALLOWANCE); } if (fillMakerAmountInBaseUnits.greaterThan(makerBalance)) { - throw new Error(FillOrderValidationErrs.NOT_ENOUGH_MAKER_BALANCE); + throw new Error(ExchangeContractErrs.NOT_ENOUGH_MAKER_BALANCE); } if (fillMakerAmountInBaseUnits.greaterThan(makerAllowance)) { - throw new Error(FillOrderValidationErrs.NOT_ENOUGH_MAKER_ALLOWANCE); + throw new Error(ExchangeContractErrs.NOT_ENOUGH_MAKER_ALLOWANCE); } const makerFeeBalance = await this.tokenWrapper.getBalanceAsync(zrxTokenAddress, @@ -189,16 +188,16 @@ export class ExchangeWrapper extends ContractWrapper { senderAddress); if (signedOrder.takerFee.greaterThan(takerFeeBalance)) { - throw new Error(FillOrderValidationErrs.NOT_ENOUGH_TAKER_FEE_BALANCE); + throw new Error(ExchangeContractErrs.NOT_ENOUGH_TAKER_FEE_BALANCE); } if (signedOrder.takerFee.greaterThan(takerFeeAllowance)) { - throw new Error(FillOrderValidationErrs.NOT_ENOUGH_TAKER_FEE_ALLOWANCE); + throw new Error(ExchangeContractErrs.NOT_ENOUGH_TAKER_FEE_ALLOWANCE); } if (signedOrder.makerFee.greaterThan(makerFeeBalance)) { - throw new Error(FillOrderValidationErrs.NOT_ENOUGH_MAKER_FEE_BALANCE); + throw new Error(ExchangeContractErrs.NOT_ENOUGH_MAKER_FEE_BALANCE); } if (signedOrder.makerFee.greaterThan(makerFeeAllowance)) { - throw new Error(FillOrderValidationErrs.NOT_ENOUGH_MAKER_FEE_ALLOWANCE); + throw new Error(ExchangeContractErrs.NOT_ENOUGH_MAKER_FEE_ALLOWANCE); } } private throwErrorLogsAsErrors(logs: ContractEvent[]): void { diff --git a/src/types.ts b/src/types.ts index e4a7da5d7..6cd5a93fe 100644 --- a/src/types.ts +++ b/src/types.ts @@ -89,13 +89,6 @@ export const ExchangeContractErrs = strEnum([ 'ORDER_REMAINING_FILL_AMOUNT_ZERO', 'ORDER_FILL_ROUNDING_ERROR', 'FILL_BALANCE_ALLOWANCE_ERROR', -]); -export type ExchangeContractErrs = keyof typeof ExchangeContractErrs; - -export const FillOrderValidationErrs = strEnum([ - 'FILL_AMOUNT_IS_ZERO', - 'TRANSACTION_SENDER_IS_NOT_FILL_ORDER_TAKER', - 'FILL_ORDER_EXPIRED', 'NOT_ENOUGH_TAKER_BALANCE', 'NOT_ENOUGH_TAKER_ALLOWANCE', 'NOT_ENOUGH_MAKER_BALANCE', @@ -104,9 +97,10 @@ export const FillOrderValidationErrs = strEnum([ 'NOT_ENOUGH_TAKER_FEE_ALLOWANCE', 'NOT_ENOUGH_MAKER_FEE_BALANCE', 'NOT_ENOUGH_MAKER_FEE_ALLOWANCE', - 'ROUNDING_ERROR', + 'TRANSACTION_SENDER_IS_NOT_FILL_ORDER_TAKER', + ]); -export type FillOrderValidationErrs = keyof typeof FillOrderValidationErrs; +export type ExchangeContractErrs = keyof typeof ExchangeContractErrs; export interface ContractResponse { logs: ContractEvent[]; diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index e83134909..c05c5c26f 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -9,7 +9,7 @@ import promisify = require('es6-promisify'); import {web3Factory} from './utils/web3_factory'; import {ZeroEx} from '../src/0x.js'; import {BlockchainLifecycle} from './utils/blockchain_lifecycle'; -import {FillOrderValidationErrs, SignedOrder, Token} from '../src/types'; +import {ExchangeContractErrs, SignedOrder, Token} from '../src/types'; import {FillScenarios} from './utils/fill_scenarios'; import {TokenUtils} from './utils/token_utils'; @@ -138,7 +138,7 @@ describe('ExchangeWrapper', () => { zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, zeroFillAmount, shouldCheckTransfer, - )).to.be.rejectedWith(FillOrderValidationErrs.FILL_AMOUNT_IS_ZERO); + )).to.be.rejectedWith(ExchangeContractErrs.ORDER_REMAINING_FILL_AMOUNT_ZERO); }); it('should throw when sender is not a taker', async () => { const fillableAmount = new BigNumber(5); @@ -147,7 +147,7 @@ describe('ExchangeWrapper', () => { ); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, - )).to.be.rejectedWith(FillOrderValidationErrs.TRANSACTION_SENDER_IS_NOT_FILL_ORDER_TAKER); + )).to.be.rejectedWith(ExchangeContractErrs.TRANSACTION_SENDER_IS_NOT_FILL_ORDER_TAKER); }); it('should throw when order is expired', async () => { const expirationInPast = new BigNumber(42); @@ -158,7 +158,7 @@ describe('ExchangeWrapper', () => { zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, - )).to.be.rejectedWith(FillOrderValidationErrs.FILL_ORDER_EXPIRED); + )).to.be.rejectedWith(ExchangeContractErrs.ORDER_FILL_EXPIRED); }); describe('should throw when not enough balance or allowance to fulfill the order', () => { const fillableAmount = new BigNumber(5); @@ -176,7 +176,7 @@ describe('ExchangeWrapper', () => { zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, - )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_BALANCE); + )).to.be.rejectedWith(ExchangeContractErrs.NOT_ENOUGH_TAKER_BALANCE); }); it('should throw when taker allowance is less than fill amount', async () => { const newAllowanceWhichIsLessThanFillAmount = fillTakerAmount.minus(lackingAllowance); @@ -185,14 +185,14 @@ describe('ExchangeWrapper', () => { zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, - )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_ALLOWANCE); + )).to.be.rejectedWith(ExchangeContractErrs.NOT_ENOUGH_TAKER_ALLOWANCE); }); it('should throw when maker balance is less than maker fill amount', async () => { await zeroEx.token.transferAsync(makerTokenAddress, makerAddress, coinbase, lackingBalance); zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, - )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_MAKER_BALANCE); + )).to.be.rejectedWith(ExchangeContractErrs.NOT_ENOUGH_MAKER_BALANCE); }); it('should throw when maker allowance is less than maker fill amount', async () => { const newAllowanceWhichIsLessThanFillAmount = fillTakerAmount.minus(lackingAllowance); @@ -201,7 +201,7 @@ describe('ExchangeWrapper', () => { zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, - )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_MAKER_ALLOWANCE); + )).to.be.rejectedWith(ExchangeContractErrs.NOT_ENOUGH_MAKER_ALLOWANCE); }); }); it('should throw when there would be a rounding error', async () => { @@ -215,7 +215,7 @@ describe('ExchangeWrapper', () => { zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmountThatCausesRoundingError, shouldCheckTransfer, - )).to.be.rejectedWith(FillOrderValidationErrs.ROUNDING_ERROR); + )).to.be.rejectedWith(ExchangeContractErrs.ORDER_FILL_ROUNDING_ERROR); }); describe('should raise when not enough balance or allowance to pay fees', () => { const fillableAmount = new BigNumber(5); @@ -234,7 +234,7 @@ describe('ExchangeWrapper', () => { await zeroEx.token.transferAsync(zrxTokenAddress, makerAddress, coinbase, lackingBalance); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, - )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_MAKER_FEE_BALANCE); + )).to.be.rejectedWith(ExchangeContractErrs.NOT_ENOUGH_MAKER_FEE_BALANCE); }); it('should throw when maker doesn\'t have enough allowance to pay fees', async () => { const newAllowanceWhichIsLessThanFees = makerFee.minus(1); @@ -242,14 +242,14 @@ describe('ExchangeWrapper', () => { newAllowanceWhichIsLessThanFees); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, - )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_MAKER_FEE_ALLOWANCE); + )).to.be.rejectedWith(ExchangeContractErrs.NOT_ENOUGH_MAKER_FEE_ALLOWANCE); }); it('should throw when taker doesn\'t have enough balance to pay fees', async () => { const lackingBalance = new BigNumber(1); await zeroEx.token.transferAsync(zrxTokenAddress, takerAddress, coinbase, lackingBalance); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, - )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_FEE_BALANCE); + )).to.be.rejectedWith(ExchangeContractErrs.NOT_ENOUGH_TAKER_FEE_BALANCE); }); it('should throw when taker doesn\'t have enough allowance to pay fees', async () => { const newAllowanceWhichIsLessThanFees = makerFee.minus(1); @@ -257,7 +257,7 @@ describe('ExchangeWrapper', () => { newAllowanceWhichIsLessThanFees); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, - )).to.be.rejectedWith(FillOrderValidationErrs.NOT_ENOUGH_TAKER_FEE_ALLOWANCE); + )).to.be.rejectedWith(ExchangeContractErrs.NOT_ENOUGH_TAKER_FEE_ALLOWANCE); }); }); }); -- cgit From 89d93494788f06d227628dfcfbd712e26ef02b77 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 18:05:27 +0200 Subject: Rewrite comment --- src/contract_wrappers/exchange_wrapper.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 716f9c77a..ba3b05758 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -65,7 +65,7 @@ export class ExchangeWrapper extends ContractWrapper { * could arise where a users balance or allowance changes before the fillOrder executes. Because of this, * we allow you to specify `shouldCheckTransfer`. If true, the smart contract will not throw if while * executing, the parties do not have sufficient balances/allowances, preserving gas costs. Setting it to - * false foregoes this check and causes the smart contract to throw instead. + * false forgoes this check and causes the smart contract to throw instead. */ public async fillOrderAsync(signedOrder: SignedOrder, fillTakerAmount: BigNumber.BigNumber, shouldCheckTransfer: boolean): Promise { @@ -145,14 +145,20 @@ export class ExchangeWrapper extends ContractWrapper { throw new Error(ExchangeContractErrs.ORDER_FILL_ROUNDING_ERROR); } } + + /** + * 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. + * Handling the edge-cases that arise when this happens would require making sure that the user has sufficient + * funds to pay both the fees and the transfer amount. We decided to punt on this for now as the contracts + * will throw for these edge-cases. + * TODO: Throw errors before calling the smart contract for these edge-cases + * TODO: in order to minimize the callers gas costs. + */ private async validateFillOrderBalancesAndAllowancesAndThrowIfInvalidAsync(signedOrder: SignedOrder, fillTakerAmount: BigNumber.BigNumber, senderAddress: string, zrxTokenAddress: string): Promise { - // TODO: There is a possibility that the user might have enough funds - // to fulfill the order or pay fees but not both. This will happen if - // makerToken === zrxToken || makerToken === zrxToken - // We don't check it for now. The contract checks it and throws. const makerBalance = await this.tokenWrapper.getBalanceAsync(signedOrder.makerTokenAddress, signedOrder.maker); -- cgit From 45fadeb690e27acccc776515ada8d39e3633194a Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 18:06:06 +0200 Subject: Allign arguments --- src/contract_wrappers/exchange_wrapper.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index ba3b05758..55ddcc46a 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -161,12 +161,12 @@ export class ExchangeWrapper extends ContractWrapper { zrxTokenAddress: string): Promise { const makerBalance = await this.tokenWrapper.getBalanceAsync(signedOrder.makerTokenAddress, - signedOrder.maker); + signedOrder.maker); const takerBalance = await this.tokenWrapper.getBalanceAsync(signedOrder.takerTokenAddress, senderAddress); const makerAllowance = await this.tokenWrapper.getProxyAllowanceAsync(signedOrder.makerTokenAddress, - signedOrder.maker); + signedOrder.maker); const takerAllowance = await this.tokenWrapper.getProxyAllowanceAsync(signedOrder.takerTokenAddress, - senderAddress); + senderAddress); // How many taker tokens would you get for 1 maker token; const exchangeRate = signedOrder.takerTokenAmount.div(signedOrder.makerTokenAmount); -- cgit From 76280dd5dbc5a5a2fb5f7230fa73d594f822c7e6 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 18:10:06 +0200 Subject: Address feedback --- src/contract_wrappers/exchange_wrapper.ts | 24 ++++++++++++------------ src/types.ts | 16 ++++++++-------- test/exchange_wrapper_test.ts | 16 ++++++++-------- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts index 55ddcc46a..4aa532bdd 100644 --- a/src/contract_wrappers/exchange_wrapper.ts +++ b/src/contract_wrappers/exchange_wrapper.ts @@ -168,42 +168,42 @@ export class ExchangeWrapper extends ContractWrapper { const takerAllowance = await this.tokenWrapper.getProxyAllowanceAsync(signedOrder.takerTokenAddress, senderAddress); - // How many taker tokens would you get for 1 maker token; + // exchangeRate is the price of one maker token denominated in taker tokens const exchangeRate = signedOrder.takerTokenAmount.div(signedOrder.makerTokenAmount); const fillMakerAmountInBaseUnits = fillTakerAmount.div(exchangeRate); if (fillTakerAmount.greaterThan(takerBalance)) { - throw new Error(ExchangeContractErrs.NOT_ENOUGH_TAKER_BALANCE); + throw new Error(ExchangeContractErrs.INSUFFICIENT_TAKER_BALANCE); } if (fillTakerAmount.greaterThan(takerAllowance)) { - throw new Error(ExchangeContractErrs.NOT_ENOUGH_TAKER_ALLOWANCE); + throw new Error(ExchangeContractErrs.INSUFFICIENT_TAKER_ALLOWANCE); } if (fillMakerAmountInBaseUnits.greaterThan(makerBalance)) { - throw new Error(ExchangeContractErrs.NOT_ENOUGH_MAKER_BALANCE); + throw new Error(ExchangeContractErrs.INSUFFICIENT_MAKER_BALANCE); } if (fillMakerAmountInBaseUnits.greaterThan(makerAllowance)) { - throw new Error(ExchangeContractErrs.NOT_ENOUGH_MAKER_ALLOWANCE); + throw new Error(ExchangeContractErrs.INSUFFICIENT_MAKER_ALLOWANCE); } const makerFeeBalance = await this.tokenWrapper.getBalanceAsync(zrxTokenAddress, - signedOrder.maker); + signedOrder.maker); const takerFeeBalance = await this.tokenWrapper.getBalanceAsync(zrxTokenAddress, senderAddress); const makerFeeAllowance = await this.tokenWrapper.getProxyAllowanceAsync(zrxTokenAddress, - signedOrder.maker); + signedOrder.maker); const takerFeeAllowance = await this.tokenWrapper.getProxyAllowanceAsync(zrxTokenAddress, - senderAddress); + senderAddress); if (signedOrder.takerFee.greaterThan(takerFeeBalance)) { - throw new Error(ExchangeContractErrs.NOT_ENOUGH_TAKER_FEE_BALANCE); + throw new Error(ExchangeContractErrs.INSUFFICIENT_TAKER_FEE_BALANCE); } if (signedOrder.takerFee.greaterThan(takerFeeAllowance)) { - throw new Error(ExchangeContractErrs.NOT_ENOUGH_TAKER_FEE_ALLOWANCE); + throw new Error(ExchangeContractErrs.INSUFFICIENT_TAKER_FEE_ALLOWANCE); } if (signedOrder.makerFee.greaterThan(makerFeeBalance)) { - throw new Error(ExchangeContractErrs.NOT_ENOUGH_MAKER_FEE_BALANCE); + throw new Error(ExchangeContractErrs.INSUFFICIENT_MAKER_FEE_BALANCE); } if (signedOrder.makerFee.greaterThan(makerFeeAllowance)) { - throw new Error(ExchangeContractErrs.NOT_ENOUGH_MAKER_FEE_ALLOWANCE); + throw new Error(ExchangeContractErrs.INSUFFICIENT_MAKER_FEE_ALLOWANCE); } } private throwErrorLogsAsErrors(logs: ContractEvent[]): void { diff --git a/src/types.ts b/src/types.ts index 6cd5a93fe..f58fa035c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -89,14 +89,14 @@ export const ExchangeContractErrs = strEnum([ 'ORDER_REMAINING_FILL_AMOUNT_ZERO', 'ORDER_FILL_ROUNDING_ERROR', 'FILL_BALANCE_ALLOWANCE_ERROR', - 'NOT_ENOUGH_TAKER_BALANCE', - 'NOT_ENOUGH_TAKER_ALLOWANCE', - 'NOT_ENOUGH_MAKER_BALANCE', - 'NOT_ENOUGH_MAKER_ALLOWANCE', - 'NOT_ENOUGH_TAKER_FEE_BALANCE', - 'NOT_ENOUGH_TAKER_FEE_ALLOWANCE', - 'NOT_ENOUGH_MAKER_FEE_BALANCE', - 'NOT_ENOUGH_MAKER_FEE_ALLOWANCE', + 'INSUFFICIENT_TAKER_BALANCE', + 'INSUFFICIENT_TAKER_ALLOWANCE', + 'INSUFFICIENT_MAKER_BALANCE', + 'INSUFFICIENT_MAKER_ALLOWANCE', + 'INSUFFICIENT_TAKER_FEE_BALANCE', + 'INSUFFICIENT_TAKER_FEE_ALLOWANCE', + 'INSUFFICIENT_MAKER_FEE_BALANCE', + 'INSUFFICIENT_MAKER_FEE_ALLOWANCE', 'TRANSACTION_SENDER_IS_NOT_FILL_ORDER_TAKER', ]); diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index c05c5c26f..87a6fbb85 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -176,7 +176,7 @@ describe('ExchangeWrapper', () => { zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, - )).to.be.rejectedWith(ExchangeContractErrs.NOT_ENOUGH_TAKER_BALANCE); + )).to.be.rejectedWith(ExchangeContractErrs.INSUFFICIENT_TAKER_BALANCE); }); it('should throw when taker allowance is less than fill amount', async () => { const newAllowanceWhichIsLessThanFillAmount = fillTakerAmount.minus(lackingAllowance); @@ -185,14 +185,14 @@ describe('ExchangeWrapper', () => { zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, - )).to.be.rejectedWith(ExchangeContractErrs.NOT_ENOUGH_TAKER_ALLOWANCE); + )).to.be.rejectedWith(ExchangeContractErrs.INSUFFICIENT_TAKER_ALLOWANCE); }); it('should throw when maker balance is less than maker fill amount', async () => { await zeroEx.token.transferAsync(makerTokenAddress, makerAddress, coinbase, lackingBalance); zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, - )).to.be.rejectedWith(ExchangeContractErrs.NOT_ENOUGH_MAKER_BALANCE); + )).to.be.rejectedWith(ExchangeContractErrs.INSUFFICIENT_MAKER_BALANCE); }); it('should throw when maker allowance is less than maker fill amount', async () => { const newAllowanceWhichIsLessThanFillAmount = fillTakerAmount.minus(lackingAllowance); @@ -201,7 +201,7 @@ describe('ExchangeWrapper', () => { zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, - )).to.be.rejectedWith(ExchangeContractErrs.NOT_ENOUGH_MAKER_ALLOWANCE); + )).to.be.rejectedWith(ExchangeContractErrs.INSUFFICIENT_MAKER_ALLOWANCE); }); }); it('should throw when there would be a rounding error', async () => { @@ -234,7 +234,7 @@ describe('ExchangeWrapper', () => { await zeroEx.token.transferAsync(zrxTokenAddress, makerAddress, coinbase, lackingBalance); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, - )).to.be.rejectedWith(ExchangeContractErrs.NOT_ENOUGH_MAKER_FEE_BALANCE); + )).to.be.rejectedWith(ExchangeContractErrs.INSUFFICIENT_MAKER_FEE_BALANCE); }); it('should throw when maker doesn\'t have enough allowance to pay fees', async () => { const newAllowanceWhichIsLessThanFees = makerFee.minus(1); @@ -242,14 +242,14 @@ describe('ExchangeWrapper', () => { newAllowanceWhichIsLessThanFees); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, - )).to.be.rejectedWith(ExchangeContractErrs.NOT_ENOUGH_MAKER_FEE_ALLOWANCE); + )).to.be.rejectedWith(ExchangeContractErrs.INSUFFICIENT_MAKER_FEE_ALLOWANCE); }); it('should throw when taker doesn\'t have enough balance to pay fees', async () => { const lackingBalance = new BigNumber(1); await zeroEx.token.transferAsync(zrxTokenAddress, takerAddress, coinbase, lackingBalance); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, - )).to.be.rejectedWith(ExchangeContractErrs.NOT_ENOUGH_TAKER_FEE_BALANCE); + )).to.be.rejectedWith(ExchangeContractErrs.INSUFFICIENT_TAKER_FEE_BALANCE); }); it('should throw when taker doesn\'t have enough allowance to pay fees', async () => { const newAllowanceWhichIsLessThanFees = makerFee.minus(1); @@ -257,7 +257,7 @@ describe('ExchangeWrapper', () => { newAllowanceWhichIsLessThanFees); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, - )).to.be.rejectedWith(ExchangeContractErrs.NOT_ENOUGH_TAKER_FEE_ALLOWANCE); + )).to.be.rejectedWith(ExchangeContractErrs.INSUFFICIENT_TAKER_FEE_ALLOWANCE); }); }); }); -- cgit From 199843718fba26db72db6196be5036339e0cf9f9 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 18:13:22 +0200 Subject: Remove spaces --- test/exchange_wrapper_test.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 87a6fbb85..ed6f68954 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -115,7 +115,7 @@ describe('ExchangeWrapper', () => { let zrxTokenAddress: string; const fillTakerAmount = new BigNumber(5); const shouldCheckTransfer = false; - before('fetch tokens', async () => { + before(async () => { [coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses; tokens = await zeroEx.tokenRegistry.getTokensAsync(); const tokenUtils = new TokenUtils(tokens); @@ -171,7 +171,6 @@ describe('ExchangeWrapper', () => { ); }); it('should throw when taker balance is less than fill amount', async () => { - await zeroEx.token.transferAsync(takerTokenAddress, takerAddress, coinbase, lackingBalance); zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( @@ -267,7 +266,6 @@ describe('ExchangeWrapper', () => { const signedOrder = await fillScenarios.createFillableSignedOrderAsync( makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, ); - expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)) .to.be.bignumber.equal(fillableAmount); expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)) -- cgit From 16c296be1461a3ccc76fbdf68e78d8c8ccd3ed83 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 18:14:51 +0200 Subject: Add ZRX_TOKEN_NOT_IN_REGISTRY --- src/types.ts | 11 ++++++----- test/utils/token_utils.ts | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/types.ts b/src/types.ts index f58fa035c..3da24abc1 100644 --- a/src/types.ts +++ b/src/types.ts @@ -10,11 +10,12 @@ function strEnum(values: string[]): {[key: string]: string} { } export const ZeroExError = strEnum([ - 'CONTRACT_DOES_NOT_EXIST', - 'UNHANDLED_ERROR', - 'USER_HAS_NO_ASSOCIATED_ADDRESSES', - 'INVALID_SIGNATURE', - 'CONTRACT_NOT_DEPLOYED_ON_NETWORK', + 'CONTRACT_DOES_NOT_EXIST', + 'UNHANDLED_ERROR', + 'USER_HAS_NO_ASSOCIATED_ADDRESSES', + 'INVALID_SIGNATURE', + 'CONTRACT_NOT_DEPLOYED_ON_NETWORK', + 'ZRX_NOT_IN_TOKEN_REGISTRY', ]); export type ZeroExError = keyof typeof ZeroExError; diff --git a/test/utils/token_utils.ts b/test/utils/token_utils.ts index 11d334619..3d2faa959 100644 --- a/test/utils/token_utils.ts +++ b/test/utils/token_utils.ts @@ -11,7 +11,7 @@ export class TokenUtils { public getProtocolTokenOrThrow(): Token { const zrxToken = _.find(this.tokens, {symbol: PROTOCOL_TOKEN_SYMBOL}); if (_.isUndefined(zrxToken)) { - throw new Error(ZeroExError.CONTRACT_NOT_DEPLOYED_ON_NETWORK); + throw new Error(ZeroExError.ZRX_NOT_IN_TOKEN_REGISTRY); } return zrxToken; } -- cgit From a52f834debc1727cee97c28f59e0973ba33bde7c Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 18:16:55 +0200 Subject: Fix test name --- test/exchange_wrapper_test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index ed6f68954..f445e1202 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -203,7 +203,7 @@ describe('ExchangeWrapper', () => { )).to.be.rejectedWith(ExchangeContractErrs.INSUFFICIENT_MAKER_ALLOWANCE); }); }); - it('should throw when there would be a rounding error', async () => { + it('should throw when there a rounding error would have occurred', async () => { const makerFillableAmount = new BigNumber(3); const takerFillableAmount = new BigNumber(5); const signedOrder = await fillScenarios.createAsymetricFillableSignedOrderAsync( -- cgit From 7cf60b589b280c578bcde4b9209e70d07c92c241 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 18:20:17 +0200 Subject: Address feedback --- test/exchange_wrapper_test.ts | 10 +++++----- test/utils/fill_scenarios.ts | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index f445e1202..842d6de32 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -204,11 +204,11 @@ describe('ExchangeWrapper', () => { }); }); it('should throw when there a rounding error would have occurred', async () => { - const makerFillableAmount = new BigNumber(3); - const takerFillableAmount = new BigNumber(5); - const signedOrder = await fillScenarios.createAsymetricFillableSignedOrderAsync( + const makerAmount = new BigNumber(3); + const takerAmount = new BigNumber(5); + const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync( makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, - makerFillableAmount, takerFillableAmount, + makerAmount, takerAmount, ); const fillTakerAmountThatCausesRoundingError = new BigNumber(3); zeroEx.setTransactionSenderAccount(takerAddress); @@ -216,7 +216,7 @@ describe('ExchangeWrapper', () => { signedOrder, fillTakerAmountThatCausesRoundingError, shouldCheckTransfer, )).to.be.rejectedWith(ExchangeContractErrs.ORDER_FILL_ROUNDING_ERROR); }); - describe('should raise when not enough balance or allowance to pay fees', () => { + describe('should throw when not enough balance or allowance to pay fees', () => { const fillableAmount = new BigNumber(5); const makerFee = new BigNumber(2); const takerFee = new BigNumber(2); diff --git a/test/utils/fill_scenarios.ts b/test/utils/fill_scenarios.ts index 8260b76ab..f95b06663 100644 --- a/test/utils/fill_scenarios.ts +++ b/test/utils/fill_scenarios.ts @@ -22,7 +22,7 @@ export class FillScenarios { fillableAmount: BigNumber.BigNumber, expirationUnixTimestampSec?: BigNumber.BigNumber): Promise { - return this.createAsymetricFillableSignedOrderAsync( + return this.createAsymmetricFillableSignedOrderAsync( makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, fillableAmount, expirationUnixTimestampSec, ); @@ -34,24 +34,24 @@ export class FillScenarios { fillableAmount: BigNumber.BigNumber, feeRecepient: string, expirationUnixTimestampSec?: BigNumber.BigNumber, ): Promise { - return this.createAsymetricFillableSignedOrderWithFeesAsync( + return this.createAsymmetricFillableSignedOrderWithFeesAsync( makerTokenAddress, takerTokenAddress, makerFee, takerFee, makerAddress, takerAddress, fillableAmount, fillableAmount, feeRecepient, expirationUnixTimestampSec, ); } - public async createAsymetricFillableSignedOrderAsync( + public async createAsymmetricFillableSignedOrderAsync( makerTokenAddress: string, takerTokenAddress: string, makerAddress: string, takerAddress: string, makerFillableAmount: BigNumber.BigNumber, takerFillableAmount: BigNumber.BigNumber, expirationUnixTimestampSec?: BigNumber.BigNumber): Promise { const makerFee = new BigNumber(0); const takerFee = new BigNumber(0); const feeRecepient = constants.NULL_ADDRESS; - return this.createAsymetricFillableSignedOrderWithFeesAsync( + return this.createAsymmetricFillableSignedOrderWithFeesAsync( makerTokenAddress, takerTokenAddress, makerFee, takerFee, makerAddress, takerAddress, makerFillableAmount, takerFillableAmount, feeRecepient, expirationUnixTimestampSec, ); } - private async createAsymetricFillableSignedOrderWithFeesAsync( + private async createAsymmetricFillableSignedOrderWithFeesAsync( makerTokenAddress: string, takerTokenAddress: string, makerFee: BigNumber.BigNumber, takerFee: BigNumber.BigNumber, makerAddress: string, takerAddress: string, -- cgit From cc6b27cbb179de3e5ac124bfddac63f66e16737a Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 18:24:24 +0200 Subject: Address feedback --- test/exchange_wrapper_test.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 842d6de32..0fa2f93e0 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -162,7 +162,7 @@ describe('ExchangeWrapper', () => { }); describe('should throw when not enough balance or allowance to fulfill the order', () => { const fillableAmount = new BigNumber(5); - const lackingBalance = new BigNumber(3); + const balanceToSubtractFromMaker = new BigNumber(3); const lackingAllowance = new BigNumber(3); let signedOrder: SignedOrder; beforeEach('create fillable signed order', async () => { @@ -171,7 +171,7 @@ describe('ExchangeWrapper', () => { ); }); it('should throw when taker balance is less than fill amount', async () => { - await zeroEx.token.transferAsync(takerTokenAddress, takerAddress, coinbase, lackingBalance); + await zeroEx.token.transferAsync(takerTokenAddress, takerAddress, coinbase, balanceToSubtractFromMaker); zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, @@ -187,7 +187,7 @@ describe('ExchangeWrapper', () => { )).to.be.rejectedWith(ExchangeContractErrs.INSUFFICIENT_TAKER_ALLOWANCE); }); it('should throw when maker balance is less than maker fill amount', async () => { - await zeroEx.token.transferAsync(makerTokenAddress, makerAddress, coinbase, lackingBalance); + await zeroEx.token.transferAsync(makerTokenAddress, makerAddress, coinbase, balanceToSubtractFromMaker); zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, @@ -229,8 +229,8 @@ describe('ExchangeWrapper', () => { zeroEx.setTransactionSenderAccount(takerAddress); }); it('should throw when maker doesn\'t have enough balance to pay fees', async () => { - const lackingBalance = new BigNumber(1); - await zeroEx.token.transferAsync(zrxTokenAddress, makerAddress, coinbase, lackingBalance); + const balanceToSubtractFromMaker = new BigNumber(1); + await zeroEx.token.transferAsync(zrxTokenAddress, makerAddress, coinbase, balanceToSubtractFromMaker); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, )).to.be.rejectedWith(ExchangeContractErrs.INSUFFICIENT_MAKER_FEE_BALANCE); @@ -244,8 +244,8 @@ describe('ExchangeWrapper', () => { )).to.be.rejectedWith(ExchangeContractErrs.INSUFFICIENT_MAKER_FEE_ALLOWANCE); }); it('should throw when taker doesn\'t have enough balance to pay fees', async () => { - const lackingBalance = new BigNumber(1); - await zeroEx.token.transferAsync(zrxTokenAddress, takerAddress, coinbase, lackingBalance); + const balanceToSubtractFromTaker = new BigNumber(1); + await zeroEx.token.transferAsync(zrxTokenAddress, takerAddress, coinbase, balanceToSubtractFromTaker); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, )).to.be.rejectedWith(ExchangeContractErrs.INSUFFICIENT_TAKER_FEE_BALANCE); @@ -261,7 +261,7 @@ describe('ExchangeWrapper', () => { }); }); describe('successful fills', () => { - it('should fill the valid order', async () => { + it('should fill a valid order', async () => { const fillableAmount = new BigNumber(5); const signedOrder = await fillScenarios.createFillableSignedOrderAsync( makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount, -- cgit From ebe50848761876301dc3ef24d64a4cd416b475a5 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 2 Jun 2017 18:33:57 +0200 Subject: Fix comment --- src/utils/schema_validator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/schema_validator.ts b/src/utils/schema_validator.ts index db8a960ba..932ddf62a 100644 --- a/src/utils/schema_validator.ts +++ b/src/utils/schema_validator.ts @@ -6,7 +6,7 @@ import {tokenSchema} from '../schemas/token_schema'; export class SchemaValidator { private validator: Validator; // In order to validate a complex JS object using jsonschema, we must replace any complex - // sub-types (e.g BigNumber) with a simpler string represenation. Since BigNumber and other + // sub-types (e.g BigNumber) with a simpler string representation. Since BigNumber and other // complex types implement the `toString` method, we can stringify the object and // then parse it. The resultant object can then be checked using jsonschema. public static convertToJSONSchemaCompatibleObject(obj: object): object { -- cgit From 3551f0791408a5c91f357130740cb81f72b59f9f Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 2 Jun 2017 18:34:18 +0200 Subject: Fix ordering --- test/exchange_wrapper_test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 76601d1b3..92b6e5c35 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -23,9 +23,9 @@ describe('ExchangeWrapper', () => { let userAddresses: string[]; let web3: Web3; before(async () => { - web3 = web3Factory.create(); zeroEx = new ZeroEx(web3); userAddresses = await promisify(web3.eth.getAccounts)(); + web3 = web3Factory.create(); }); beforeEach(async () => { await blockchainLifecycle.startAsync(); -- cgit From 9620b18fecb59b5ce4c2fec483e426f79852c034 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 18:34:43 +0200 Subject: Address feedback --- test/utils/fill_scenarios.ts | 5 +++-- test/utils/token_utils.ts | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/test/utils/fill_scenarios.ts b/test/utils/fill_scenarios.ts index f95b06663..a44d6b18a 100644 --- a/test/utils/fill_scenarios.ts +++ b/test/utils/fill_scenarios.ts @@ -71,13 +71,14 @@ export class FillScenarios { await this.zeroEx.token.setProxyAllowanceAsync(this.zrxTokenAddress, takerAddress, takerFee); } - const transactionSenderAccount = await this.zeroEx.getTransactionSenderAccountIfExistsAsync(); + const prevTransactionSenderAccount = await this.zeroEx.getTransactionSenderAccountIfExistsAsync(); this.zeroEx.setTransactionSenderAccount(makerAddress); const signedOrder = await orderFactory.createSignedOrderAsync(this.zeroEx, makerAddress, takerAddress, makerFee, takerFee, makerFillableAmount, makerTokenAddress, takerFillableAmount, takerTokenAddress, feeRecepient, expirationUnixTimestampSec); - this.zeroEx.setTransactionSenderAccount(transactionSenderAccount as string); + // We re-set the transactionSender to avoid introducing side-effects + this.zeroEx.setTransactionSenderAccount(prevTransactionSenderAccount as string); return signedOrder; } } diff --git a/test/utils/token_utils.ts b/test/utils/token_utils.ts index 3d2faa959..14788b299 100644 --- a/test/utils/token_utils.ts +++ b/test/utils/token_utils.ts @@ -16,8 +16,9 @@ export class TokenUtils { return zrxToken; } public getNonProtocolTokens(): Token[] { - return _.filter(this.tokens, token => { + const nonProtocolTokens = _.filter(this.tokens, token => { return token.symbol !== PROTOCOL_TOKEN_SYMBOL; }); + return nonProtocolTokens; } } -- cgit From 45c4f203dff813ba25c04a3c49f0b7e3ad0f2494 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 2 Jun 2017 18:37:38 +0200 Subject: Fix linter errors --- test/exchange_wrapper_test.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 7b4730f3a..3935ebc89 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -171,7 +171,9 @@ describe('ExchangeWrapper', () => { ); }); it('should throw when taker balance is less than fill amount', async () => { - await zeroEx.token.transferAsync(takerTokenAddress, takerAddress, coinbase, balanceToSubtractFromMaker); + await zeroEx.token.transferAsync( + takerTokenAddress, takerAddress, coinbase, balanceToSubtractFromMaker, + ); zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, @@ -187,7 +189,9 @@ describe('ExchangeWrapper', () => { )).to.be.rejectedWith(ExchangeContractErrs.INSUFFICIENT_TAKER_ALLOWANCE); }); it('should throw when maker balance is less than maker fill amount', async () => { - await zeroEx.token.transferAsync(makerTokenAddress, makerAddress, coinbase, balanceToSubtractFromMaker); + await zeroEx.token.transferAsync( + makerTokenAddress, makerAddress, coinbase, balanceToSubtractFromMaker, + ); zeroEx.setTransactionSenderAccount(takerAddress); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, @@ -230,7 +234,9 @@ describe('ExchangeWrapper', () => { }); it('should throw when maker doesn\'t have enough balance to pay fees', async () => { const balanceToSubtractFromMaker = new BigNumber(1); - await zeroEx.token.transferAsync(zrxTokenAddress, makerAddress, coinbase, balanceToSubtractFromMaker); + await zeroEx.token.transferAsync( + zrxTokenAddress, makerAddress, coinbase, balanceToSubtractFromMaker, + ); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, )).to.be.rejectedWith(ExchangeContractErrs.INSUFFICIENT_MAKER_FEE_BALANCE); @@ -245,7 +251,9 @@ describe('ExchangeWrapper', () => { }); it('should throw when taker doesn\'t have enough balance to pay fees', async () => { const balanceToSubtractFromTaker = new BigNumber(1); - await zeroEx.token.transferAsync(zrxTokenAddress, takerAddress, coinbase, balanceToSubtractFromTaker); + await zeroEx.token.transferAsync( + zrxTokenAddress, takerAddress, coinbase, balanceToSubtractFromTaker, + ); return expect(zeroEx.exchange.fillOrderAsync( signedOrder, fillTakerAmount, shouldCheckTransfer, )).to.be.rejectedWith(ExchangeContractErrs.INSUFFICIENT_TAKER_FEE_BALANCE); -- cgit From 3fad55d118b6a2f8f44ba5dec7fdae276c806eb3 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 2 Jun 2017 18:46:47 +0200 Subject: Fix undefined web3 issue --- test/exchange_wrapper_test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 3935ebc89..6327ef004 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -19,13 +19,13 @@ const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(); describe('ExchangeWrapper', () => { + let web3: Web3; let zeroEx: ZeroEx; let userAddresses: string[]; - let web3: Web3; before(async () => { + web3 = web3Factory.create(); zeroEx = new ZeroEx(web3); userAddresses = await promisify(web3.eth.getAccounts)(); - web3 = web3Factory.create(); }); beforeEach(async () => { await blockchainLifecycle.startAsync(); -- cgit From d4320fec724c5bf34e7dcd006cba8ffe7a3c76d1 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 2 Jun 2017 19:38:28 +0200 Subject: Add includeStack config to chai setup so that we get stackTraces --- test/0x.js_test.ts | 1 + test/exchange_wrapper_test.ts | 1 + test/token_registry_wrapper_test.ts | 1 + test/token_wrapper_test.ts | 1 + 4 files changed, 4 insertions(+) diff --git a/test/0x.js_test.ts b/test/0x.js_test.ts index efc703ea1..9196d3df3 100644 --- a/test/0x.js_test.ts +++ b/test/0x.js_test.ts @@ -10,6 +10,7 @@ import {constants} from './utils/constants'; import {web3Factory} from './utils/web3_factory'; import {Order} from '../src/types'; +chai.config.includeStack = true; chai.use(ChaiBigNumber()); chai.use(dirtyChai); const expect = chai.expect; diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts index 6327ef004..607cdf052 100644 --- a/test/exchange_wrapper_test.ts +++ b/test/exchange_wrapper_test.ts @@ -13,6 +13,7 @@ import {ExchangeContractErrs, SignedOrder, Token} from '../src/types'; import {FillScenarios} from './utils/fill_scenarios'; import {TokenUtils} from './utils/token_utils'; +chai.config.includeStack = true; chai.use(dirtyChai); chai.use(ChaiBigNumber()); const expect = chai.expect; diff --git a/test/token_registry_wrapper_test.ts b/test/token_registry_wrapper_test.ts index c91555d8b..195b2f205 100644 --- a/test/token_registry_wrapper_test.ts +++ b/test/token_registry_wrapper_test.ts @@ -10,6 +10,7 @@ import {Token} from '../src/types'; import {SchemaValidator} from '../src/utils/schema_validator'; import {tokenSchema} from '../src/schemas/token_schema'; +chai.config.includeStack = true; const expect = chai.expect; chai.use(chaiAsPromised); const blockchainLifecycle = new BlockchainLifecycle(); diff --git a/test/token_wrapper_test.ts b/test/token_wrapper_test.ts index 4af07a8b2..cfd87da84 100644 --- a/test/token_wrapper_test.ts +++ b/test/token_wrapper_test.ts @@ -8,6 +8,7 @@ import {ZeroEx} from '../src/0x.js'; import {ZeroExError, Token} from '../src/types'; import {BlockchainLifecycle} from './utils/blockchain_lifecycle'; +chai.config.includeStack = true; const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(); -- cgit