From 9778695b4ad1fd999eb79b01c768a2f2b9938917 Mon Sep 17 00:00:00 2001 From: fragosti Date: Mon, 4 Jun 2018 19:48:21 -0700 Subject: Try enabling no-unused-variable... --- packages/order-utils/test/assert_test.ts | 1 - packages/order-utils/test/order_hash_test.ts | 2 -- packages/order-utils/test/signature_utils_test.ts | 3 +-- packages/order-utils/test/utils/web3_wrapper.ts | 2 +- 4 files changed, 2 insertions(+), 6 deletions(-) (limited to 'packages/order-utils/test') diff --git a/packages/order-utils/test/assert_test.ts b/packages/order-utils/test/assert_test.ts index 033fd6732..4b22ef27d 100644 --- a/packages/order-utils/test/assert_test.ts +++ b/packages/order-utils/test/assert_test.ts @@ -1,4 +1,3 @@ -import { web3Factory } from '@0xproject/dev-utils'; import * as chai from 'chai'; import 'make-promises-safe'; import 'mocha'; diff --git a/packages/order-utils/test/order_hash_test.ts b/packages/order-utils/test/order_hash_test.ts index d571fc62a..7cf6435c2 100644 --- a/packages/order-utils/test/order_hash_test.ts +++ b/packages/order-utils/test/order_hash_test.ts @@ -1,4 +1,3 @@ -import { web3Factory } from '@0xproject/dev-utils'; import { Order } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; @@ -8,7 +7,6 @@ import 'mocha'; import { constants, orderHashUtils } from '../src'; import { chaiSetup } from './utils/chai_setup'; -import { web3Wrapper } from './utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; diff --git a/packages/order-utils/test/signature_utils_test.ts b/packages/order-utils/test/signature_utils_test.ts index c1a3cc7fb..74033104a 100644 --- a/packages/order-utils/test/signature_utils_test.ts +++ b/packages/order-utils/test/signature_utils_test.ts @@ -1,4 +1,3 @@ -import { web3Factory } from '@0xproject/dev-utils'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; import { JSONRPCErrorCallback, JSONRPCRequestPayload } from 'ethereum-types'; @@ -7,7 +6,7 @@ import 'make-promises-safe'; import 'mocha'; import * as Sinon from 'sinon'; -import { ecSignOrderHashAsync, generatePseudoRandomSalt, MessagePrefixType, orderHashUtils } from '../src'; +import { ecSignOrderHashAsync, generatePseudoRandomSalt, MessagePrefixType } from '../src'; import { isValidECSignature, isValidSignatureAsync } from '../src/signature_utils'; import { chaiSetup } from './utils/chai_setup'; diff --git a/packages/order-utils/test/utils/web3_wrapper.ts b/packages/order-utils/test/utils/web3_wrapper.ts index 419f76dde..ab801fa7f 100644 --- a/packages/order-utils/test/utils/web3_wrapper.ts +++ b/packages/order-utils/test/utils/web3_wrapper.ts @@ -1,4 +1,4 @@ -import { devConstants, web3Factory } from '@0xproject/dev-utils'; +import { web3Factory } from '@0xproject/dev-utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { Provider } from 'ethereum-types'; -- cgit v1.2.3 From 73cc2a140c778a5396c2766562a3fc648337e18a Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 7 Jun 2018 18:03:50 +0200 Subject: - Refactor remainingFillableCalculator so it can be used for the maker and taker side - Moved the tests over from order-watcher - Did some token -> asset renaming --- .../test/remaining_fillable_calculator_test.ts | 257 +++++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 packages/order-utils/test/remaining_fillable_calculator_test.ts (limited to 'packages/order-utils/test') diff --git a/packages/order-utils/test/remaining_fillable_calculator_test.ts b/packages/order-utils/test/remaining_fillable_calculator_test.ts new file mode 100644 index 000000000..81f8132b2 --- /dev/null +++ b/packages/order-utils/test/remaining_fillable_calculator_test.ts @@ -0,0 +1,257 @@ +import { ECSignature, SignedOrder } from '@0xproject/types'; +import { BigNumber } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; +import * as chai from 'chai'; +import 'make-promises-safe'; +import 'mocha'; + +import { RemainingFillableCalculator } from '../src/remaining_fillable_calculator'; + +import { chaiSetup } from './utils/chai_setup'; + +chaiSetup.configure(); +const expect = chai.expect; + +describe('RemainingFillableCalculator', () => { + let calculator: RemainingFillableCalculator; + let signedOrder: SignedOrder; + let transferrableMakeAssetAmount: BigNumber; + let transferrableMakerFeeTokenAmount: BigNumber; + let remainingMakeAssetAmount: BigNumber; + let makerAmount: BigNumber; + let takerAmount: BigNumber; + let makerFeeAmount: BigNumber; + let isMakeAssetZRX: boolean; + const makerAssetData: string = '0x1'; + const takerAssetData: string = '0x2'; + const decimals: number = 4; + const zero: BigNumber = new BigNumber(0); + const zeroAddress = '0x0'; + const signature: string = + '0x1B61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403'; + beforeEach(async () => { + [makerAmount, takerAmount, makerFeeAmount] = [ + Web3Wrapper.toBaseUnitAmount(new BigNumber(50), decimals), + Web3Wrapper.toBaseUnitAmount(new BigNumber(5), decimals), + Web3Wrapper.toBaseUnitAmount(new BigNumber(1), decimals), + ]; + [transferrableMakeAssetAmount, transferrableMakerFeeTokenAmount] = [ + Web3Wrapper.toBaseUnitAmount(new BigNumber(50), decimals), + Web3Wrapper.toBaseUnitAmount(new BigNumber(5), decimals), + ]; + }); + function buildSignedOrder(): SignedOrder { + return { + signature, + exchangeAddress: zeroAddress, + feeRecipientAddress: zeroAddress, + senderAddress: zeroAddress, + makerAddress: zeroAddress, + takerAddress: zeroAddress, + makerFee: makerFeeAmount, + takerFee: zero, + makerAssetAmount: makerAmount, + takerAssetAmount: takerAmount, + makerAssetData, + takerAssetData, + salt: zero, + expirationTimeSeconds: zero, + }; + } + describe('Maker token is NOT ZRX', () => { + before(async () => { + isMakeAssetZRX = false; + }); + it('calculates the correct amount when unfilled and funds available', () => { + signedOrder = buildSignedOrder(); + remainingMakeAssetAmount = signedOrder.makerAssetAmount; + const isTraderMaker = true; + calculator = new RemainingFillableCalculator( + isTraderMaker, + signedOrder, + isMakeAssetZRX, + transferrableMakeAssetAmount, + transferrableMakerFeeTokenAmount, + remainingMakeAssetAmount, + ); + expect(calculator.computeRemainingFillable()).to.be.bignumber.equal(remainingMakeAssetAmount); + }); + it('calculates the correct amount when partially filled and funds available', () => { + signedOrder = buildSignedOrder(); + remainingMakeAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1), decimals); + const isTraderMaker = true; + calculator = new RemainingFillableCalculator( + isTraderMaker, + signedOrder, + isMakeAssetZRX, + transferrableMakeAssetAmount, + transferrableMakerFeeTokenAmount, + remainingMakeAssetAmount, + ); + expect(calculator.computeRemainingFillable()).to.be.bignumber.equal(remainingMakeAssetAmount); + }); + it('calculates the amount to be 0 when all fee funds are transferred', () => { + signedOrder = buildSignedOrder(); + transferrableMakerFeeTokenAmount = zero; + remainingMakeAssetAmount = signedOrder.makerAssetAmount; + const isTraderMaker = true; + calculator = new RemainingFillableCalculator( + isTraderMaker, + signedOrder, + isMakeAssetZRX, + transferrableMakeAssetAmount, + transferrableMakerFeeTokenAmount, + remainingMakeAssetAmount, + ); + expect(calculator.computeRemainingFillable()).to.be.bignumber.equal(zero); + }); + it('calculates the correct amount when balance is less than remaining fillable', () => { + signedOrder = buildSignedOrder(); + const partiallyFilledAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), decimals); + remainingMakeAssetAmount = signedOrder.makerAssetAmount.minus(partiallyFilledAmount); + transferrableMakeAssetAmount = remainingMakeAssetAmount.minus(partiallyFilledAmount); + const isTraderMaker = true; + calculator = new RemainingFillableCalculator( + isTraderMaker, + signedOrder, + isMakeAssetZRX, + transferrableMakeAssetAmount, + transferrableMakerFeeTokenAmount, + remainingMakeAssetAmount, + ); + expect(calculator.computeRemainingFillable()).to.be.bignumber.equal(transferrableMakeAssetAmount); + }); + describe('Order to Fee Ratio is < 1', () => { + beforeEach(async () => { + [makerAmount, takerAmount, makerFeeAmount] = [ + Web3Wrapper.toBaseUnitAmount(new BigNumber(3), decimals), + Web3Wrapper.toBaseUnitAmount(new BigNumber(6), decimals), + Web3Wrapper.toBaseUnitAmount(new BigNumber(6), decimals), + ]; + }); + it('calculates the correct amount when funds unavailable', () => { + signedOrder = buildSignedOrder(); + remainingMakeAssetAmount = signedOrder.makerAssetAmount; + const transferredAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), decimals); + transferrableMakeAssetAmount = remainingMakeAssetAmount.minus(transferredAmount); + const isTraderMaker = true; + calculator = new RemainingFillableCalculator( + isTraderMaker, + signedOrder, + isMakeAssetZRX, + transferrableMakeAssetAmount, + transferrableMakerFeeTokenAmount, + remainingMakeAssetAmount, + ); + expect(calculator.computeRemainingFillable()).to.be.bignumber.equal(transferrableMakeAssetAmount); + }); + }); + describe('Ratio is not evenly divisble', () => { + beforeEach(async () => { + [makerAmount, takerAmount, makerFeeAmount] = [ + Web3Wrapper.toBaseUnitAmount(new BigNumber(3), decimals), + Web3Wrapper.toBaseUnitAmount(new BigNumber(7), decimals), + Web3Wrapper.toBaseUnitAmount(new BigNumber(7), decimals), + ]; + }); + it('calculates the correct amount when funds unavailable', () => { + signedOrder = buildSignedOrder(); + remainingMakeAssetAmount = signedOrder.makerAssetAmount; + const transferredAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), decimals); + transferrableMakeAssetAmount = remainingMakeAssetAmount.minus(transferredAmount); + const isTraderMaker = true; + calculator = new RemainingFillableCalculator( + isTraderMaker, + signedOrder, + isMakeAssetZRX, + transferrableMakeAssetAmount, + transferrableMakerFeeTokenAmount, + remainingMakeAssetAmount, + ); + const calculatedFillableAmount = calculator.computeRemainingFillable(); + expect(calculatedFillableAmount.lessThanOrEqualTo(transferrableMakeAssetAmount)).to.be.true(); + expect(calculatedFillableAmount).to.be.bignumber.greaterThan(new BigNumber(0)); + const orderToFeeRatio = signedOrder.makerAssetAmount.dividedBy(signedOrder.makerFee); + const calculatedFeeAmount = calculatedFillableAmount.dividedBy(orderToFeeRatio); + expect(calculatedFeeAmount).to.be.bignumber.lessThan(transferrableMakerFeeTokenAmount); + }); + }); + }); + describe('Maker Token is ZRX', () => { + before(async () => { + isMakeAssetZRX = true; + }); + it('calculates the correct amount when unfilled and funds available', () => { + signedOrder = buildSignedOrder(); + transferrableMakeAssetAmount = makerAmount.plus(makerFeeAmount); + transferrableMakerFeeTokenAmount = transferrableMakeAssetAmount; + remainingMakeAssetAmount = signedOrder.makerAssetAmount; + const isTraderMaker = true; + calculator = new RemainingFillableCalculator( + isTraderMaker, + signedOrder, + isMakeAssetZRX, + transferrableMakeAssetAmount, + transferrableMakerFeeTokenAmount, + remainingMakeAssetAmount, + ); + expect(calculator.computeRemainingFillable()).to.be.bignumber.equal(remainingMakeAssetAmount); + }); + it('calculates the correct amount when partially filled and funds available', () => { + signedOrder = buildSignedOrder(); + remainingMakeAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1), decimals); + const isTraderMaker = true; + calculator = new RemainingFillableCalculator( + isTraderMaker, + signedOrder, + isMakeAssetZRX, + transferrableMakeAssetAmount, + transferrableMakerFeeTokenAmount, + remainingMakeAssetAmount, + ); + expect(calculator.computeRemainingFillable()).to.be.bignumber.equal(remainingMakeAssetAmount); + }); + it('calculates the amount to be 0 when all fee funds are transferred', () => { + signedOrder = buildSignedOrder(); + transferrableMakeAssetAmount = zero; + transferrableMakerFeeTokenAmount = zero; + remainingMakeAssetAmount = signedOrder.makerAssetAmount; + const isTraderMaker = true; + calculator = new RemainingFillableCalculator( + isTraderMaker, + signedOrder, + isMakeAssetZRX, + transferrableMakeAssetAmount, + transferrableMakerFeeTokenAmount, + remainingMakeAssetAmount, + ); + expect(calculator.computeRemainingFillable()).to.be.bignumber.equal(zero); + }); + it('calculates the correct amount when balance is less than remaining fillable', () => { + signedOrder = buildSignedOrder(); + const partiallyFilledAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), decimals); + remainingMakeAssetAmount = signedOrder.makerAssetAmount.minus(partiallyFilledAmount); + transferrableMakeAssetAmount = remainingMakeAssetAmount.minus(partiallyFilledAmount); + transferrableMakerFeeTokenAmount = transferrableMakeAssetAmount; + + const orderToFeeRatio = signedOrder.makerAssetAmount.dividedToIntegerBy(signedOrder.makerFee); + const expectedFillableAmount = new BigNumber(450980); + const isTraderMaker = true; + calculator = new RemainingFillableCalculator( + isTraderMaker, + signedOrder, + isMakeAssetZRX, + transferrableMakeAssetAmount, + transferrableMakerFeeTokenAmount, + remainingMakeAssetAmount, + ); + const calculatedFillableAmount = calculator.computeRemainingFillable(); + const numberOfFillsInRatio = calculatedFillableAmount.dividedToIntegerBy(orderToFeeRatio); + const calculatedFillableAmountPlusFees = calculatedFillableAmount.plus(numberOfFillsInRatio); + expect(calculatedFillableAmountPlusFees).to.be.bignumber.lessThan(transferrableMakeAssetAmount); + expect(calculatedFillableAmountPlusFees).to.be.bignumber.lessThan(remainingMakeAssetAmount); + expect(calculatedFillableAmount).to.be.bignumber.equal(expectedFillableAmount); + expect(numberOfFillsInRatio.decimalPlaces()).to.be.equal(0); + }); + }); +}); -- cgit v1.2.3 From f5ad553be35bcc35fdac9620ae3d1e5546fd902c Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 7 Jun 2018 18:33:42 +0200 Subject: Pass in fee and assetAmount rather then the whole signedOrder --- .../test/remaining_fillable_calculator_test.ts | 50 +++++++++------------- 1 file changed, 20 insertions(+), 30 deletions(-) (limited to 'packages/order-utils/test') diff --git a/packages/order-utils/test/remaining_fillable_calculator_test.ts b/packages/order-utils/test/remaining_fillable_calculator_test.ts index 81f8132b2..45ad90626 100644 --- a/packages/order-utils/test/remaining_fillable_calculator_test.ts +++ b/packages/order-utils/test/remaining_fillable_calculator_test.ts @@ -65,10 +65,9 @@ describe('RemainingFillableCalculator', () => { it('calculates the correct amount when unfilled and funds available', () => { signedOrder = buildSignedOrder(); remainingMakeAssetAmount = signedOrder.makerAssetAmount; - const isTraderMaker = true; calculator = new RemainingFillableCalculator( - isTraderMaker, - signedOrder, + signedOrder.makerFee, + signedOrder.makerAssetAmount, isMakeAssetZRX, transferrableMakeAssetAmount, transferrableMakerFeeTokenAmount, @@ -79,10 +78,9 @@ describe('RemainingFillableCalculator', () => { it('calculates the correct amount when partially filled and funds available', () => { signedOrder = buildSignedOrder(); remainingMakeAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1), decimals); - const isTraderMaker = true; calculator = new RemainingFillableCalculator( - isTraderMaker, - signedOrder, + signedOrder.makerFee, + signedOrder.makerAssetAmount, isMakeAssetZRX, transferrableMakeAssetAmount, transferrableMakerFeeTokenAmount, @@ -94,10 +92,9 @@ describe('RemainingFillableCalculator', () => { signedOrder = buildSignedOrder(); transferrableMakerFeeTokenAmount = zero; remainingMakeAssetAmount = signedOrder.makerAssetAmount; - const isTraderMaker = true; calculator = new RemainingFillableCalculator( - isTraderMaker, - signedOrder, + signedOrder.makerFee, + signedOrder.makerAssetAmount, isMakeAssetZRX, transferrableMakeAssetAmount, transferrableMakerFeeTokenAmount, @@ -110,10 +107,9 @@ describe('RemainingFillableCalculator', () => { const partiallyFilledAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), decimals); remainingMakeAssetAmount = signedOrder.makerAssetAmount.minus(partiallyFilledAmount); transferrableMakeAssetAmount = remainingMakeAssetAmount.minus(partiallyFilledAmount); - const isTraderMaker = true; calculator = new RemainingFillableCalculator( - isTraderMaker, - signedOrder, + signedOrder.makerFee, + signedOrder.makerAssetAmount, isMakeAssetZRX, transferrableMakeAssetAmount, transferrableMakerFeeTokenAmount, @@ -134,10 +130,9 @@ describe('RemainingFillableCalculator', () => { remainingMakeAssetAmount = signedOrder.makerAssetAmount; const transferredAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), decimals); transferrableMakeAssetAmount = remainingMakeAssetAmount.minus(transferredAmount); - const isTraderMaker = true; calculator = new RemainingFillableCalculator( - isTraderMaker, - signedOrder, + signedOrder.makerFee, + signedOrder.makerAssetAmount, isMakeAssetZRX, transferrableMakeAssetAmount, transferrableMakerFeeTokenAmount, @@ -159,10 +154,9 @@ describe('RemainingFillableCalculator', () => { remainingMakeAssetAmount = signedOrder.makerAssetAmount; const transferredAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), decimals); transferrableMakeAssetAmount = remainingMakeAssetAmount.minus(transferredAmount); - const isTraderMaker = true; calculator = new RemainingFillableCalculator( - isTraderMaker, - signedOrder, + signedOrder.makerFee, + signedOrder.makerAssetAmount, isMakeAssetZRX, transferrableMakeAssetAmount, transferrableMakerFeeTokenAmount, @@ -186,10 +180,9 @@ describe('RemainingFillableCalculator', () => { transferrableMakeAssetAmount = makerAmount.plus(makerFeeAmount); transferrableMakerFeeTokenAmount = transferrableMakeAssetAmount; remainingMakeAssetAmount = signedOrder.makerAssetAmount; - const isTraderMaker = true; calculator = new RemainingFillableCalculator( - isTraderMaker, - signedOrder, + signedOrder.makerFee, + signedOrder.makerAssetAmount, isMakeAssetZRX, transferrableMakeAssetAmount, transferrableMakerFeeTokenAmount, @@ -200,10 +193,9 @@ describe('RemainingFillableCalculator', () => { it('calculates the correct amount when partially filled and funds available', () => { signedOrder = buildSignedOrder(); remainingMakeAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1), decimals); - const isTraderMaker = true; calculator = new RemainingFillableCalculator( - isTraderMaker, - signedOrder, + signedOrder.makerFee, + signedOrder.makerAssetAmount, isMakeAssetZRX, transferrableMakeAssetAmount, transferrableMakerFeeTokenAmount, @@ -216,10 +208,9 @@ describe('RemainingFillableCalculator', () => { transferrableMakeAssetAmount = zero; transferrableMakerFeeTokenAmount = zero; remainingMakeAssetAmount = signedOrder.makerAssetAmount; - const isTraderMaker = true; calculator = new RemainingFillableCalculator( - isTraderMaker, - signedOrder, + signedOrder.makerFee, + signedOrder.makerAssetAmount, isMakeAssetZRX, transferrableMakeAssetAmount, transferrableMakerFeeTokenAmount, @@ -236,10 +227,9 @@ describe('RemainingFillableCalculator', () => { const orderToFeeRatio = signedOrder.makerAssetAmount.dividedToIntegerBy(signedOrder.makerFee); const expectedFillableAmount = new BigNumber(450980); - const isTraderMaker = true; calculator = new RemainingFillableCalculator( - isTraderMaker, - signedOrder, + signedOrder.makerFee, + signedOrder.makerAssetAmount, isMakeAssetZRX, transferrableMakeAssetAmount, transferrableMakerFeeTokenAmount, -- cgit v1.2.3 From a200eaacaa3975b63f24d8be6cdfc7b0921d91ef Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 7 Jun 2018 18:51:52 +0200 Subject: Fix tslint failure --- packages/order-utils/test/remaining_fillable_calculator_test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/order-utils/test') diff --git a/packages/order-utils/test/remaining_fillable_calculator_test.ts b/packages/order-utils/test/remaining_fillable_calculator_test.ts index 45ad90626..c99d10f3f 100644 --- a/packages/order-utils/test/remaining_fillable_calculator_test.ts +++ b/packages/order-utils/test/remaining_fillable_calculator_test.ts @@ -1,4 +1,4 @@ -import { ECSignature, SignedOrder } from '@0xproject/types'; +import { SignedOrder } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as chai from 'chai'; -- cgit v1.2.3 From 21f7722f1023cc9d1848737b7c986f7df7a07122 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Mon, 11 Jun 2018 19:21:32 +0200 Subject: Move OrderValidationUtils (+ tests) and ExchangeTransferSimulator to order-utils --- .../test/exchange_transfer_simulator_test.ts | 164 +++++++++++++++++++++ packages/order-utils/test/global_hooks_test.ts | 45 ++++++ .../test/order_validation_utils_test.ts | 70 +++++++++ ...le_erc20_balance_and_proxy_allowance_fetcher.ts | 26 ++++ 4 files changed, 305 insertions(+) create mode 100644 packages/order-utils/test/exchange_transfer_simulator_test.ts create mode 100644 packages/order-utils/test/global_hooks_test.ts create mode 100644 packages/order-utils/test/order_validation_utils_test.ts create mode 100644 packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts (limited to 'packages/order-utils/test') diff --git a/packages/order-utils/test/exchange_transfer_simulator_test.ts b/packages/order-utils/test/exchange_transfer_simulator_test.ts new file mode 100644 index 000000000..3e35f900e --- /dev/null +++ b/packages/order-utils/test/exchange_transfer_simulator_test.ts @@ -0,0 +1,164 @@ +import { BlockchainLifecycle } from '@0xproject/dev-utils'; +import { ExchangeContractErrs, Token } from '@0xproject/types'; +import { BigNumber } from '@0xproject/utils'; +import * as chai from 'chai'; +import { BlockParamLiteral } from 'ethereum-types'; +import * as _ from 'lodash'; +import 'make-promises-safe'; + +import { artifacts } from '../src/artifacts'; +import { constants } from '../src/constants'; +import { ExchangeTransferSimulator } from '../src/exchange_transfer_simulator'; +import { DummyERC20TokenContract } from '../src/generated_contract_wrappers/dummy_e_r_c20_token'; +import { BalanceAndProxyAllowanceLazyStore } from '../src/store/balance_and_proxy_allowance_lazy_store'; +import { TradeSide, TransferType } from '../src/types'; + +import { chaiSetup } from './utils/chai_setup'; +import { SimpleERC20BalanceAndProxyAllowanceFetcher } from './utils/simple_erc20_balance_and_proxy_allowance_fetcher'; +import { provider, web3Wrapper } from './utils/web3_wrapper'; + +chaiSetup.configure(); +const expect = chai.expect; +const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); + +describe('ExchangeTransferSimulator', async () => { + const transferAmount = new BigNumber(5); + let userAddresses: string[]; + let dummyERC20Token: DummyERC20TokenContract; + let coinbase: string; + let sender: string; + let recipient: string; + let exampleTokenAddress: string; + let exchangeTransferSimulator: ExchangeTransferSimulator; + let txHash: string; + let erc20ProxyAddress: string; + before(async () => { + userAddresses = await web3Wrapper.getAvailableAddressesAsync(); + [coinbase, sender, recipient] = userAddresses; + + erc20ProxyAddress = getAddressFromArtifact(artifacts.ERC20Proxy, constants.TESTRPC_NETWORK_ID); + + const wethArtifact = artifacts.DummyERC20Token; + const wethAddress = getAddressFromArtifact(wethArtifact, constants.TESTRPC_NETWORK_ID); + dummyERC20Token = new DummyERC20TokenContract( + artifacts.DummyERC20Token.compilerOutput.abi, + wethAddress, + provider, + ); + exampleTokenAddress = dummyERC20Token.address; + }); + beforeEach(async () => { + await blockchainLifecycle.startAsync(); + }); + afterEach(async () => { + await blockchainLifecycle.revertAsync(); + }); + describe('#transferFromAsync', function(): void { + // HACK: For some reason these tests need a slightly longer timeout + const mochaTestTimeoutMs = 3000; + this.timeout(mochaTestTimeoutMs); + + beforeEach(() => { + const simpleERC20BalanceAndProxyAllowanceFetcher = new SimpleERC20BalanceAndProxyAllowanceFetcher( + dummyERC20Token, + erc20ProxyAddress, + ); + const balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore( + simpleERC20BalanceAndProxyAllowanceFetcher, + ); + exchangeTransferSimulator = new ExchangeTransferSimulator(balanceAndProxyAllowanceLazyStore); + }); + it("throws if the user doesn't have enough allowance", async () => { + return expect( + exchangeTransferSimulator.transferFromAsync( + exampleTokenAddress, + sender, + recipient, + transferAmount, + TradeSide.Taker, + TransferType.Trade, + ), + ).to.be.rejectedWith(ExchangeContractErrs.InsufficientTakerAllowance); + }); + it("throws if the user doesn't have enough balance", async () => { + txHash = await dummyERC20Token.approve.sendTransactionAsync(erc20ProxyAddress, transferAmount, { + from: sender, + }); + await web3Wrapper.awaitTransactionSuccessAsync(txHash); + return expect( + exchangeTransferSimulator.transferFromAsync( + exampleTokenAddress, + sender, + recipient, + transferAmount, + TradeSide.Maker, + TransferType.Trade, + ), + ).to.be.rejectedWith(ExchangeContractErrs.InsufficientMakerBalance); + }); + it('updates balances and proxyAllowance after transfer', async function(): Promise { + txHash = await dummyERC20Token.transfer.sendTransactionAsync(sender, transferAmount, { + from: coinbase, + }); + await web3Wrapper.awaitTransactionSuccessAsync(txHash); + + txHash = await dummyERC20Token.approve.sendTransactionAsync(erc20ProxyAddress, transferAmount, { + from: sender, + }); + await web3Wrapper.awaitTransactionSuccessAsync(txHash); + + await exchangeTransferSimulator.transferFromAsync( + exampleTokenAddress, + sender, + recipient, + transferAmount, + TradeSide.Taker, + TransferType.Trade, + ); + const store = (exchangeTransferSimulator as any)._store; + const senderBalance = await store.getBalanceAsync(exampleTokenAddress, sender); + const recipientBalance = await store.getBalanceAsync(exampleTokenAddress, recipient); + const senderProxyAllowance = await store.getProxyAllowanceAsync(exampleTokenAddress, sender); + expect(senderBalance).to.be.bignumber.equal(0); + expect(recipientBalance).to.be.bignumber.equal(transferAmount); + expect(senderProxyAllowance).to.be.bignumber.equal(0); + }); + it("doesn't update proxyAllowance after transfer if unlimited", async () => { + txHash = await dummyERC20Token.transfer.sendTransactionAsync(sender, transferAmount, { + from: coinbase, + }); + await web3Wrapper.awaitTransactionSuccessAsync(txHash); + txHash = await dummyERC20Token.approve.sendTransactionAsync( + erc20ProxyAddress, + constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS, + { + from: sender, + }, + ); + await web3Wrapper.awaitTransactionSuccessAsync(txHash); + await exchangeTransferSimulator.transferFromAsync( + exampleTokenAddress, + sender, + recipient, + transferAmount, + TradeSide.Taker, + TransferType.Trade, + ); + const store = (exchangeTransferSimulator as any)._store; + const senderBalance = await store.getBalanceAsync(exampleTokenAddress, sender); + const recipientBalance = await store.getBalanceAsync(exampleTokenAddress, recipient); + const senderProxyAllowance = await store.getProxyAllowanceAsync(exampleTokenAddress, sender); + expect(senderBalance).to.be.bignumber.equal(0); + expect(recipientBalance).to.be.bignumber.equal(transferAmount); + expect(senderProxyAllowance).to.be.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); + }); + }); +}); + +function getAddressFromArtifact(artifact: any, networkId: number): string { + if (_.isUndefined(artifact.networks[networkId])) { + throw new Error(`Contract ${artifact.contractName} not deployed to network ${networkId}`); + } + const contractAddress = artifact.networks[networkId].address.toLowerCase(); + return contractAddress; +} diff --git a/packages/order-utils/test/global_hooks_test.ts b/packages/order-utils/test/global_hooks_test.ts new file mode 100644 index 000000000..662a2cb0f --- /dev/null +++ b/packages/order-utils/test/global_hooks_test.ts @@ -0,0 +1,45 @@ +import { devConstants } from '@0xproject/dev-utils'; +import { ArtifactWriter } from '@0xproject/migrations'; +import { BigNumber } from '@0xproject/utils'; + +import { artifacts } from '../src/artifacts'; +import { constants } from '../src/constants'; +import { DummyERC20TokenContract } from '../src/generated_contract_wrappers/dummy_e_r_c20_token'; +import { ERC20ProxyContract } from '../src/generated_contract_wrappers/e_r_c20_proxy'; + +import { provider } from './utils/web3_wrapper'; + +before('migrate contracts', async function(): Promise { + // HACK: Since contract migrations take longer then our global mocha timeout limit + // we manually increase it for this before hook. + const mochaTestTimeoutMs = 20000; + this.timeout(mochaTestTimeoutMs); + + const txDefaults = { + gas: devConstants.GAS_LIMIT, + from: devConstants.TESTRPC_FIRST_ADDRESS, + }; + + const networkId = constants.TESTRPC_NETWORK_ID; + const artifactsDir = `lib/src/artifacts`; + const artifactsWriter = new ArtifactWriter(artifactsDir, networkId); + + const erc20proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync(artifacts.ERC20Proxy, provider, txDefaults); + artifactsWriter.saveArtifact(erc20proxy); + + const totalSupply = new BigNumber(100000000000000000000); + const name = 'Test'; + const symbol = 'TST'; + const decimals = new BigNumber(18); + // tslint:disable-next-line:no-unused-variable + const dummyErc20Token = await DummyERC20TokenContract.deployFrom0xArtifactAsync( + artifacts.DummyERC20Token, + provider, + txDefaults, + name, + symbol, + decimals, + totalSupply, + ); + artifactsWriter.saveArtifact(dummyErc20Token); +}); diff --git a/packages/order-utils/test/order_validation_utils_test.ts b/packages/order-utils/test/order_validation_utils_test.ts new file mode 100644 index 000000000..d3ff867d7 --- /dev/null +++ b/packages/order-utils/test/order_validation_utils_test.ts @@ -0,0 +1,70 @@ +import { BigNumber } from '@0xproject/utils'; +import * as chai from 'chai'; +import 'mocha'; + +import { OrderValidationUtils } from '../src/order_validation_utils'; + +import { chaiSetup } from './utils/chai_setup'; + +chaiSetup.configure(); +const expect = chai.expect; + +describe('OrderValidationUtils', () => { + describe('#isRoundingError', () => { + it('should return false if there is a rounding error of 0.1%', async () => { + const numerator = new BigNumber(20); + const denominator = new BigNumber(999); + const target = new BigNumber(50); + // rounding error = ((20*50/999) - floor(20*50/999)) / (20*50/999) = 0.1% + const isRoundingError = OrderValidationUtils.isRoundingError(numerator, denominator, target); + expect(isRoundingError).to.be.false(); + }); + + it('should return false if there is a rounding of 0.09%', async () => { + const numerator = new BigNumber(20); + const denominator = new BigNumber(9991); + const target = new BigNumber(500); + // rounding error = ((20*500/9991) - floor(20*500/9991)) / (20*500/9991) = 0.09% + const isRoundingError = OrderValidationUtils.isRoundingError(numerator, denominator, target); + expect(isRoundingError).to.be.false(); + }); + + it('should return true if there is a rounding error of 0.11%', async () => { + const numerator = new BigNumber(20); + const denominator = new BigNumber(9989); + const target = new BigNumber(500); + // rounding error = ((20*500/9989) - floor(20*500/9989)) / (20*500/9989) = 0.011% + const isRoundingError = OrderValidationUtils.isRoundingError(numerator, denominator, target); + expect(isRoundingError).to.be.true(); + }); + + it('should return true if there is a rounding error > 0.1%', async () => { + const numerator = new BigNumber(3); + const denominator = new BigNumber(7); + const target = new BigNumber(10); + // rounding error = ((3*10/7) - floor(3*10/7)) / (3*10/7) = 6.67% + const isRoundingError = OrderValidationUtils.isRoundingError(numerator, denominator, target); + expect(isRoundingError).to.be.true(); + }); + + it('should return false when there is no rounding error', async () => { + const numerator = new BigNumber(1); + const denominator = new BigNumber(2); + const target = new BigNumber(10); + + const isRoundingError = OrderValidationUtils.isRoundingError(numerator, denominator, target); + expect(isRoundingError).to.be.false(); + }); + + it('should return false when there is rounding error <= 0.1%', async () => { + // randomly generated numbers + const numerator = new BigNumber(76564); + const denominator = new BigNumber(676373677); + const target = new BigNumber(105762562); + // rounding error = ((76564*105762562/676373677) - floor(76564*105762562/676373677)) / + // (76564*105762562/676373677) = 0.0007% + const isRoundingError = OrderValidationUtils.isRoundingError(numerator, denominator, target); + expect(isRoundingError).to.be.false(); + }); + }); +}); diff --git a/packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts b/packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts new file mode 100644 index 000000000..29b9a128b --- /dev/null +++ b/packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts @@ -0,0 +1,26 @@ +import { BigNumber } from '@0xproject/utils'; + +import { AbstractBalanceAndProxyAllowanceFetcher } from '../../src/abstract/abstract_balance_and_proxy_allowance_fetcher'; + +import { ERC20TokenContract } from '../../src/generated_contract_wrappers/e_r_c20_token'; + +export class SimpleERC20BalanceAndProxyAllowanceFetcher implements AbstractBalanceAndProxyAllowanceFetcher { + private _erc20TokenContract: ERC20TokenContract; + private _erc20ProxyAddress: string; + constructor(erc20TokenWrapper: ERC20TokenContract, erc20ProxyAddress: string) { + this._erc20TokenContract = erc20TokenWrapper; + this._erc20ProxyAddress = erc20ProxyAddress; + } + public async getBalanceAsync(assetData: string, userAddress: string): Promise { + // HACK: We cheat and don't pass in the userData since it's always the same token used + // in our tests. + const balance = await this._erc20TokenContract.balanceOf.callAsync(userAddress); + return balance; + } + public async getProxyAllowanceAsync(assetData: string, userAddress: string): Promise { + // HACK: We cheat and don't pass in the userData since it's always the same token used + // in our tests. + const proxyAllowance = await this._erc20TokenContract.allowance.callAsync(userAddress, this._erc20ProxyAddress); + return proxyAllowance; + } +} -- cgit v1.2.3 From 89b7b56a2cb38d95f65067e5493e8135cb1e7e98 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Mon, 11 Jun 2018 19:43:40 +0200 Subject: Fix tslint issues --- packages/order-utils/test/exchange_transfer_simulator_test.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'packages/order-utils/test') diff --git a/packages/order-utils/test/exchange_transfer_simulator_test.ts b/packages/order-utils/test/exchange_transfer_simulator_test.ts index 3e35f900e..13e2dcc62 100644 --- a/packages/order-utils/test/exchange_transfer_simulator_test.ts +++ b/packages/order-utils/test/exchange_transfer_simulator_test.ts @@ -1,8 +1,7 @@ import { BlockchainLifecycle } from '@0xproject/dev-utils'; -import { ExchangeContractErrs, Token } from '@0xproject/types'; +import { ExchangeContractErrs } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; -import { BlockParamLiteral } from 'ethereum-types'; import * as _ from 'lodash'; import 'make-promises-safe'; @@ -96,7 +95,7 @@ describe('ExchangeTransferSimulator', async () => { ), ).to.be.rejectedWith(ExchangeContractErrs.InsufficientMakerBalance); }); - it('updates balances and proxyAllowance after transfer', async function(): Promise { + it('updates balances and proxyAllowance after transfer', async () => { txHash = await dummyERC20Token.transfer.sendTransactionAsync(sender, transferAmount, { from: coinbase, }); -- cgit v1.2.3 From 31fe232bac9c4e8a0ef409fb41188fcb8aa0b3f2 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Mon, 11 Jun 2018 22:13:12 +0200 Subject: Remove global hooks from tests and deploy contracts from within the specific tests --- .../test/exchange_transfer_simulator_test.ts | 41 +++++++++++++++----- packages/order-utils/test/global_hooks_test.ts | 45 ---------------------- 2 files changed, 32 insertions(+), 54 deletions(-) delete mode 100644 packages/order-utils/test/global_hooks_test.ts (limited to 'packages/order-utils/test') diff --git a/packages/order-utils/test/exchange_transfer_simulator_test.ts b/packages/order-utils/test/exchange_transfer_simulator_test.ts index 13e2dcc62..3369901b1 100644 --- a/packages/order-utils/test/exchange_transfer_simulator_test.ts +++ b/packages/order-utils/test/exchange_transfer_simulator_test.ts @@ -1,4 +1,4 @@ -import { BlockchainLifecycle } from '@0xproject/dev-utils'; +import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils'; import { ExchangeContractErrs } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; @@ -9,6 +9,8 @@ import { artifacts } from '../src/artifacts'; import { constants } from '../src/constants'; import { ExchangeTransferSimulator } from '../src/exchange_transfer_simulator'; import { DummyERC20TokenContract } from '../src/generated_contract_wrappers/dummy_e_r_c20_token'; +import { ERC20ProxyContract } from '../src/generated_contract_wrappers/e_r_c20_proxy'; +import { ERC20TokenContract } from '../src/generated_contract_wrappers/e_r_c20_token'; import { BalanceAndProxyAllowanceLazyStore } from '../src/store/balance_and_proxy_allowance_lazy_store'; import { TradeSide, TransferType } from '../src/types'; @@ -31,19 +33,40 @@ describe('ExchangeTransferSimulator', async () => { let exchangeTransferSimulator: ExchangeTransferSimulator; let txHash: string; let erc20ProxyAddress: string; - before(async () => { + before(async function(): Promise { + const mochaTestTimeoutMs = 20000; + this.timeout(mochaTestTimeoutMs); + userAddresses = await web3Wrapper.getAvailableAddressesAsync(); [coinbase, sender, recipient] = userAddresses; - erc20ProxyAddress = getAddressFromArtifact(artifacts.ERC20Proxy, constants.TESTRPC_NETWORK_ID); + const txDefaults = { + gas: devConstants.GAS_LIMIT, + from: devConstants.TESTRPC_FIRST_ADDRESS, + }; + + const erc20Proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync( + artifacts.ERC20Proxy, + provider, + txDefaults, + ); + erc20ProxyAddress = erc20Proxy.address; - const wethArtifact = artifacts.DummyERC20Token; - const wethAddress = getAddressFromArtifact(wethArtifact, constants.TESTRPC_NETWORK_ID); - dummyERC20Token = new DummyERC20TokenContract( - artifacts.DummyERC20Token.compilerOutput.abi, - wethAddress, + const totalSupply = new BigNumber(100000000000000000000); + const name = 'Test'; + const symbol = 'TST'; + const decimals = new BigNumber(18); + // tslint:disable-next-line:no-unused-variable + dummyERC20Token = await DummyERC20TokenContract.deployFrom0xArtifactAsync( + artifacts.DummyERC20Token, provider, + txDefaults, + name, + symbol, + decimals, + totalSupply, ); + exampleTokenAddress = dummyERC20Token.address; }); beforeEach(async () => { @@ -59,7 +82,7 @@ describe('ExchangeTransferSimulator', async () => { beforeEach(() => { const simpleERC20BalanceAndProxyAllowanceFetcher = new SimpleERC20BalanceAndProxyAllowanceFetcher( - dummyERC20Token, + (dummyERC20Token as any) as ERC20TokenContract, erc20ProxyAddress, ); const balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore( diff --git a/packages/order-utils/test/global_hooks_test.ts b/packages/order-utils/test/global_hooks_test.ts deleted file mode 100644 index 662a2cb0f..000000000 --- a/packages/order-utils/test/global_hooks_test.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { devConstants } from '@0xproject/dev-utils'; -import { ArtifactWriter } from '@0xproject/migrations'; -import { BigNumber } from '@0xproject/utils'; - -import { artifacts } from '../src/artifacts'; -import { constants } from '../src/constants'; -import { DummyERC20TokenContract } from '../src/generated_contract_wrappers/dummy_e_r_c20_token'; -import { ERC20ProxyContract } from '../src/generated_contract_wrappers/e_r_c20_proxy'; - -import { provider } from './utils/web3_wrapper'; - -before('migrate contracts', async function(): Promise { - // HACK: Since contract migrations take longer then our global mocha timeout limit - // we manually increase it for this before hook. - const mochaTestTimeoutMs = 20000; - this.timeout(mochaTestTimeoutMs); - - const txDefaults = { - gas: devConstants.GAS_LIMIT, - from: devConstants.TESTRPC_FIRST_ADDRESS, - }; - - const networkId = constants.TESTRPC_NETWORK_ID; - const artifactsDir = `lib/src/artifacts`; - const artifactsWriter = new ArtifactWriter(artifactsDir, networkId); - - const erc20proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync(artifacts.ERC20Proxy, provider, txDefaults); - artifactsWriter.saveArtifact(erc20proxy); - - const totalSupply = new BigNumber(100000000000000000000); - const name = 'Test'; - const symbol = 'TST'; - const decimals = new BigNumber(18); - // tslint:disable-next-line:no-unused-variable - const dummyErc20Token = await DummyERC20TokenContract.deployFrom0xArtifactAsync( - artifacts.DummyERC20Token, - provider, - txDefaults, - name, - symbol, - decimals, - totalSupply, - ); - artifactsWriter.saveArtifact(dummyErc20Token); -}); -- cgit v1.2.3 From e1879ef4d91fc58203d9748eca38695b79c43674 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Mon, 11 Jun 2018 23:42:30 +0200 Subject: Fix no-unused-variable tslint rule to include parameters and fix issues --- packages/order-utils/test/exchange_transfer_simulator_test.ts | 9 --------- .../utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts | 8 ++++---- 2 files changed, 4 insertions(+), 13 deletions(-) (limited to 'packages/order-utils/test') diff --git a/packages/order-utils/test/exchange_transfer_simulator_test.ts b/packages/order-utils/test/exchange_transfer_simulator_test.ts index 3369901b1..eeae42698 100644 --- a/packages/order-utils/test/exchange_transfer_simulator_test.ts +++ b/packages/order-utils/test/exchange_transfer_simulator_test.ts @@ -2,7 +2,6 @@ import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils'; import { ExchangeContractErrs } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; -import * as _ from 'lodash'; import 'make-promises-safe'; import { artifacts } from '../src/artifacts'; @@ -176,11 +175,3 @@ describe('ExchangeTransferSimulator', async () => { }); }); }); - -function getAddressFromArtifact(artifact: any, networkId: number): string { - if (_.isUndefined(artifact.networks[networkId])) { - throw new Error(`Contract ${artifact.contractName} not deployed to network ${networkId}`); - } - const contractAddress = artifact.networks[networkId].address.toLowerCase(); - return contractAddress; -} diff --git a/packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts b/packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts index 29b9a128b..d41eaca40 100644 --- a/packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts +++ b/packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts @@ -11,14 +11,14 @@ export class SimpleERC20BalanceAndProxyAllowanceFetcher implements AbstractBalan this._erc20TokenContract = erc20TokenWrapper; this._erc20ProxyAddress = erc20ProxyAddress; } - public async getBalanceAsync(assetData: string, userAddress: string): Promise { - // HACK: We cheat and don't pass in the userData since it's always the same token used + public async getBalanceAsync(_assetData: string, userAddress: string): Promise { + // HACK: We cheat and don't pass in the assetData since it's always the same token used // in our tests. const balance = await this._erc20TokenContract.balanceOf.callAsync(userAddress); return balance; } - public async getProxyAllowanceAsync(assetData: string, userAddress: string): Promise { - // HACK: We cheat and don't pass in the userData since it's always the same token used + public async getProxyAllowanceAsync(_assetData: string, userAddress: string): Promise { + // HACK: We cheat and don't pass in the assetData since it's always the same token used // in our tests. const proxyAllowance = await this._erc20TokenContract.allowance.callAsync(userAddress, this._erc20ProxyAddress); return proxyAllowance; -- cgit v1.2.3