From 5a8eb77ff0a6b00e4df5d933426e451c8ef09f7b Mon Sep 17 00:00:00 2001
From: Leonid Logvinov <logvinov.leon@gmail.com>
Date: Mon, 3 Jul 2017 11:39:26 -0700
Subject: Add initial implementation and tests for zeroEx.token.subscribeAsync

---
 test/token_wrapper_test.ts | 113 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 112 insertions(+), 1 deletion(-)

(limited to 'test')

diff --git a/test/token_wrapper_test.ts b/test/token_wrapper_test.ts
index a1c035672..4a20141db 100644
--- a/test/token_wrapper_test.ts
+++ b/test/token_wrapper_test.ts
@@ -5,8 +5,17 @@ import * as Web3 from 'web3';
 import * as BigNumber from 'bignumber.js';
 import promisify = require('es6-promisify');
 import {web3Factory} from './utils/web3_factory';
-import {ZeroEx, ZeroExError, Token} from '../src';
+import {
+    ZeroEx,
+    ZeroExError,
+    Token,
+    SubscriptionOpts,
+    TokenEvents,
+    ContractEvent,
+    TransferContractEventArgs,
+} from '../src';
 import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
+import {DoneCallback} from '../src/types';
 
 chaiSetup.configure();
 const expect = chai.expect;
@@ -231,4 +240,106 @@ describe('TokenWrapper', () => {
             return expect(allowanceAfterSet).to.be.bignumber.equal(expectedAllowanceAfterAllowanceSet);
         });
     });
+    describe('#subscribeAsync', () => {
+        const indexFilterValues = {};
+        const shouldCheckTransfer = false;
+        let tokenAddress: string;
+        const subscriptionOpts: SubscriptionOpts = {
+            fromBlock: 0,
+            toBlock: 'latest',
+        };
+        const transferAmount = new BigNumber(42);
+        const allowanceAmount = new BigNumber(42);
+        before(() => {
+            const token = tokens[0];
+            tokenAddress = token.address;
+        });
+        afterEach(async () => {
+            await zeroEx.token.stopWatchingAllEventsAsync();
+        });
+        // Hack: Mocha does not allow a test to be both async and have a `done` callback
+        // Since we need to await the receipt of the event in the `subscribeAsync` callback,
+        // we do need both. A hack is to make the top-level a sync fn w/ a done callback and then
+        // wrap the rest of the test in an async block
+        // Source: https://github.com/mochajs/mocha/issues/2407
+        it('Should receive the Transfer event when an order is filled', (done: DoneCallback) => {
+            (async () => {
+                const zeroExEvent = await zeroEx.token.subscribeAsync(
+                    tokenAddress, TokenEvents.Transfer, subscriptionOpts, indexFilterValues);
+                zeroExEvent.watch((err: Error, event: ContractEvent) => {
+                    expect(err).to.be.null();
+                    expect(event).to.not.be.undefined();
+                    expect(event.args as TransferContractEventArgs).to.be.deep.equal({
+                        _from: coinbase,
+                        _to: addressWithoutFunds,
+                        _value: transferAmount,
+                    });
+                    done();
+                });
+                await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
+            })();
+        });
+        it('Should receive the Approval event when an order is cancelled', (done: DoneCallback) => {
+            (async () => {
+                const zeroExEvent = await zeroEx.token.subscribeAsync(
+                    tokenAddress, TokenEvents.Approval, subscriptionOpts, indexFilterValues);
+                zeroExEvent.watch((err: Error, event: ContractEvent) => {
+                        expect(err).to.be.null();
+                        expect(event).to.not.be.undefined();
+                        expect(event.args as TransferContractEventArgs).to.be.deep.equal({
+                            _owner: coinbase,
+                            _spender: addressWithoutFunds,
+                            _value: allowanceAmount,
+                        });
+                        done();
+                });
+                await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount);
+            })();
+        });
+        it('Outstanding subscriptions are cancelled when zeroEx.setProviderAsync called', (done: DoneCallback) => {
+            (async () => {
+                const eventSubscriptionToBeCancelled = await zeroEx.token.subscribeAsync(
+                    tokenAddress, TokenEvents.Transfer, subscriptionOpts, indexFilterValues);
+                eventSubscriptionToBeCancelled.watch((err: Error, event: ContractEvent) => {
+                    done(new Error('Expected this subscription to have been cancelled'));
+                });
+
+                const newProvider = web3Factory.getRpcProvider();
+                await zeroEx.setProviderAsync(newProvider);
+
+                const eventSubscriptionToStay = await zeroEx.token.subscribeAsync(
+                    tokenAddress, TokenEvents.Transfer, subscriptionOpts, indexFilterValues);
+                eventSubscriptionToStay.watch((err: Error, event: ContractEvent) => {
+                    expect(err).to.be.null();
+                    expect(event).to.not.be.undefined();
+                    done();
+                });
+                await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
+            })();
+        });
+        it('Should stop watch for events when stopWatchingAsync called on the eventEmitter', (done: DoneCallback) => {
+            (async () => {
+                const eventSubscriptionToBeStopped = await zeroEx.token.subscribeAsync(
+                    tokenAddress, TokenEvents.Transfer, subscriptionOpts, indexFilterValues);
+                eventSubscriptionToBeStopped.watch((err: Error, event: ContractEvent) => {
+                    done(new Error('Expected this subscription to have been stopped'));
+                });
+                await eventSubscriptionToBeStopped.stopWatchingAsync();
+                await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
+                done();
+            })();
+        });
+        it('Should wrap all event args BigNumber instances in a newer version of BigNumber', (done: DoneCallback) => {
+            (async () => {
+                const zeroExEvent = await zeroEx.token.subscribeAsync(
+                    tokenAddress, TokenEvents.Transfer, subscriptionOpts, indexFilterValues);
+                zeroExEvent.watch((err: Error, event: ContractEvent) => {
+                    const args = event.args as TransferContractEventArgs;
+                    expect(args._value.isBigNumber).to.be.true();
+                    done();
+                });
+                await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
+            })();
+        });
+    });
 });
-- 
cgit v1.2.3


From 7d7bef2b1a83a570be58c8c0c90c9e338c3b93f3 Mon Sep 17 00:00:00 2001
From: Leonid Logvinov <logvinov.leon@gmail.com>
Date: Mon, 3 Jul 2017 18:26:31 -0700
Subject: Handle errors from pseudo-async subscription tests

---
 test/exchange_wrapper_test.ts | 10 +++++-----
 test/token_wrapper_test.ts    | 10 +++++-----
 2 files changed, 10 insertions(+), 10 deletions(-)

(limited to 'test')

diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts
index 3a88db5c9..0321eb569 100644
--- a/test/exchange_wrapper_test.ts
+++ b/test/exchange_wrapper_test.ts
@@ -721,7 +721,7 @@ describe('ExchangeWrapper', () => {
                 await zeroEx.exchange.fillOrderAsync(
                     signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, takerAddress,
                 );
-            })();
+            })().catch(done);
         });
         it('Should receive the LogCancel event when an order is cancelled', (done: DoneCallback) => {
             (async () => {
@@ -735,7 +735,7 @@ describe('ExchangeWrapper', () => {
                         done();
                 });
                 await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelTakerAmountInBaseUnits);
-            })();
+            })().catch(done);
         });
         it('Outstanding subscriptions are cancelled when zeroEx.setProviderAsync called', (done: DoneCallback) => {
             (async () => {
@@ -761,7 +761,7 @@ describe('ExchangeWrapper', () => {
                 await zeroEx.exchange.fillOrderAsync(
                     signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, takerAddress,
                 );
-            })();
+            })().catch(done);
         });
         it('Should stop watch for events when stopWatchingAsync called on the eventEmitter', (done: DoneCallback) => {
             (async () => {
@@ -776,7 +776,7 @@ describe('ExchangeWrapper', () => {
                     signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, takerAddress,
                 );
                 done();
-            })();
+            })().catch(done);
         });
         it('Should wrap all event args BigNumber instances in a newer version of BigNumber', (done: DoneCallback) => {
             (async () => {
@@ -794,7 +794,7 @@ describe('ExchangeWrapper', () => {
                 await zeroEx.exchange.fillOrderAsync(
                     signedOrder, fillTakerAmountInBaseUnits, shouldCheckTransfer, takerAddress,
                 );
-            })();
+            })().catch(done);
         });
     });
     describe('#getOrderHashHexUsingContractCallAsync', () => {
diff --git a/test/token_wrapper_test.ts b/test/token_wrapper_test.ts
index 4a20141db..c5a08dc43 100644
--- a/test/token_wrapper_test.ts
+++ b/test/token_wrapper_test.ts
@@ -277,7 +277,7 @@ describe('TokenWrapper', () => {
                     done();
                 });
                 await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
-            })();
+            })().catch(done);
         });
         it('Should receive the Approval event when an order is cancelled', (done: DoneCallback) => {
             (async () => {
@@ -294,7 +294,7 @@ describe('TokenWrapper', () => {
                         done();
                 });
                 await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount);
-            })();
+            })().catch(done);
         });
         it('Outstanding subscriptions are cancelled when zeroEx.setProviderAsync called', (done: DoneCallback) => {
             (async () => {
@@ -315,7 +315,7 @@ describe('TokenWrapper', () => {
                     done();
                 });
                 await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
-            })();
+            })().catch(done);
         });
         it('Should stop watch for events when stopWatchingAsync called on the eventEmitter', (done: DoneCallback) => {
             (async () => {
@@ -327,7 +327,7 @@ describe('TokenWrapper', () => {
                 await eventSubscriptionToBeStopped.stopWatchingAsync();
                 await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
                 done();
-            })();
+            })().catch(done);
         });
         it('Should wrap all event args BigNumber instances in a newer version of BigNumber', (done: DoneCallback) => {
             (async () => {
@@ -339,7 +339,7 @@ describe('TokenWrapper', () => {
                     done();
                 });
                 await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
-            })();
+            })().catch(done);
         });
     });
 });
-- 
cgit v1.2.3


From 64cf47f297827a869120b85e734406db87b87db8 Mon Sep 17 00:00:00 2001
From: Leonid Logvinov <logvinov.leon@gmail.com>
Date: Mon, 3 Jul 2017 21:59:42 -0700
Subject: Add tests for subscriptionOptsSchema and blockParamSchema

---
 test/schema_test.ts | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

(limited to 'test')

diff --git a/test/schema_test.ts b/test/schema_test.ts
index b251a68f9..7f9a66ae3 100644
--- a/test/schema_test.ts
+++ b/test/schema_test.ts
@@ -12,6 +12,7 @@ import {orderFillOrKillRequestsSchema} from '../src/schemas/order_fill_or_kill_r
 import {ecSignatureParameterSchema, ecSignatureSchema} from '../src/schemas/ec_signature_schema';
 import {orderCancellationRequestsSchema} from '../src/schemas/order_cancel_schema';
 import {orderFillRequestsSchema} from '../src/schemas/order_fill_requests_schema';
+import {blockParamSchema, subscriptionOptsSchema} from '../src/schemas/subscription_opts_schema';
 
 chai.config.includeStack = true;
 const expect = chai.expect;
@@ -96,6 +97,43 @@ describe('Schema', () => {
             validateAgainstSchema(testCases, ecSignatureSchema, shouldFail);
         });
     });
+    describe('#blockParamSchema', () => {
+        it('should validate valid block param', () => {
+            const testCases = [
+                42,
+                'latest',
+                'pending',
+                'earliest',
+            ];
+            validateAgainstSchema(testCases, blockParamSchema);
+        });
+        it('should fail for invalid block param', () => {
+            const testCases = [
+                {},
+                '42',
+                'pemding',
+            ];
+            const shouldFail = true;
+            validateAgainstSchema(testCases, blockParamSchema, shouldFail);
+        });
+    });
+    describe('#subscriptionOptsSchema', () => {
+        it('should validate valid subscription opts', () => {
+            const testCases = [
+                {fromBlock: 42, toBlock: 'latest'},
+            ];
+            validateAgainstSchema(testCases, subscriptionOptsSchema);
+        });
+        it('should fail for invalid subscription opts', () => {
+            const testCases = [
+                {},
+                {fromBlock: 42},
+                {fromBlock: 42, to: 43},
+            ];
+            const shouldFail = true;
+            validateAgainstSchema(testCases, subscriptionOptsSchema, shouldFail);
+        });
+    });
     describe('#tokenSchema', () => {
         const token = {
             name: 'Zero Ex',
-- 
cgit v1.2.3


From f39a2134b946ab2c7f24b9fcc49f95156e7682d5 Mon Sep 17 00:00:00 2001
From: Leonid Logvinov <logvinov.leon@gmail.com>
Date: Mon, 3 Jul 2017 22:32:24 -0700
Subject: Add tests for order hash Schema

---
 test/schema_test.ts | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

(limited to 'test')

diff --git a/test/schema_test.ts b/test/schema_test.ts
index 7f9a66ae3..4746c7949 100644
--- a/test/schema_test.ts
+++ b/test/schema_test.ts
@@ -6,7 +6,7 @@ import promisify = require('es6-promisify');
 import {constants} from './utils/constants';
 import {SchemaValidator} from '../src/utils/schema_validator';
 import {tokenSchema} from '../src/schemas/token_schema';
-import {orderSchema, signedOrderSchema} from '../src/schemas/order_schemas';
+import {orderSchema, signedOrderSchema, orderHashSchema} from '../src/schemas/order_schemas';
 import {addressSchema, numberSchema} from '../src/schemas/basic_type_schemas';
 import {orderFillOrKillRequestsSchema} from '../src/schemas/order_fill_or_kill_requests_schema';
 import {ecSignatureParameterSchema, ecSignatureSchema} from '../src/schemas/ec_signature_schema';
@@ -97,6 +97,25 @@ describe('Schema', () => {
             validateAgainstSchema(testCases, ecSignatureSchema, shouldFail);
         });
     });
+    describe('#orderHashSchema', () => {
+        it('should validate valid order hash', () => {
+            const testCases = [
+                '0x61a3ed31B43c8780e905a260a35faefEc527be7516aa11c0256729b5b351bc33',
+                '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
+            ];
+            validateAgainstSchema(testCases, orderHashSchema);
+        });
+        it('should fail for invalid order hash', () => {
+            const testCases = [
+                {},
+                '0x',
+                '0x8b0292B11a196601eD2ce54B665CaFEca0347D42',
+                '61a3ed31B43c8780e905a260a35faefEc527be7516aa11c0256729b5b351bc33',
+            ];
+            const shouldFail = true;
+            validateAgainstSchema(testCases, orderHashSchema, shouldFail);
+        });
+    });
     describe('#blockParamSchema', () => {
         it('should validate valid block param', () => {
             const testCases = [
-- 
cgit v1.2.3


From 5611df82f9f276fb161fa268f7ab468a6c1d7784 Mon Sep 17 00:00:00 2001
From: Leonid Logvinov <logvinov.leon@gmail.com>
Date: Tue, 4 Jul 2017 10:19:03 -0700
Subject: Refactor event tests

---
 test/token_wrapper_test.ts | 25 ++++++++++++-------------
 1 file changed, 12 insertions(+), 13 deletions(-)

(limited to 'test')

diff --git a/test/token_wrapper_test.ts b/test/token_wrapper_test.ts
index c5a08dc43..6ac1beb43 100644
--- a/test/token_wrapper_test.ts
+++ b/test/token_wrapper_test.ts
@@ -13,6 +13,7 @@ import {
     TokenEvents,
     ContractEvent,
     TransferContractEventArgs,
+    ApprovalContractEventArgs,
 } from '../src';
 import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
 import {DoneCallback} from '../src/types';
@@ -269,11 +270,10 @@ describe('TokenWrapper', () => {
                 zeroExEvent.watch((err: Error, event: ContractEvent) => {
                     expect(err).to.be.null();
                     expect(event).to.not.be.undefined();
-                    expect(event.args as TransferContractEventArgs).to.be.deep.equal({
-                        _from: coinbase,
-                        _to: addressWithoutFunds,
-                        _value: transferAmount,
-                    });
+                    const args = event.args as TransferContractEventArgs;
+                    expect(args._from).to.be.equal(coinbase);
+                    expect(args._to).to.be.equal(addressWithoutFunds);
+                    expect(args._value).to.be.equal(transferAmount);
                     done();
                 });
                 await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
@@ -284,14 +284,13 @@ describe('TokenWrapper', () => {
                 const zeroExEvent = await zeroEx.token.subscribeAsync(
                     tokenAddress, TokenEvents.Approval, subscriptionOpts, indexFilterValues);
                 zeroExEvent.watch((err: Error, event: ContractEvent) => {
-                        expect(err).to.be.null();
-                        expect(event).to.not.be.undefined();
-                        expect(event.args as TransferContractEventArgs).to.be.deep.equal({
-                            _owner: coinbase,
-                            _spender: addressWithoutFunds,
-                            _value: allowanceAmount,
-                        });
-                        done();
+                    expect(err).to.be.null();
+                    expect(event).to.not.be.undefined();
+                    const args = event.args as ApprovalContractEventArgs;
+                    expect(args._owner).to.be.equal(coinbase);
+                    expect(args._spender).to.be.equal(addressWithoutFunds);
+                    expect(args._value).to.be.equal(allowanceAmount);
+                    done();
                 });
                 await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount);
             })().catch(done);
-- 
cgit v1.2.3


From c5dca95f893cbc66d7e6d2de234f1411f28e1d19 Mon Sep 17 00:00:00 2001
From: Leonid Logvinov <logvinov.leon@gmail.com>
Date: Tue, 4 Jul 2017 10:31:07 -0700
Subject: Use .bignumber for BigNumber comparation

---
 test/token_wrapper_test.ts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'test')

diff --git a/test/token_wrapper_test.ts b/test/token_wrapper_test.ts
index 6ac1beb43..06e373bfa 100644
--- a/test/token_wrapper_test.ts
+++ b/test/token_wrapper_test.ts
@@ -273,7 +273,7 @@ describe('TokenWrapper', () => {
                     const args = event.args as TransferContractEventArgs;
                     expect(args._from).to.be.equal(coinbase);
                     expect(args._to).to.be.equal(addressWithoutFunds);
-                    expect(args._value).to.be.equal(transferAmount);
+                    expect(args._value).to.be.bignumber.equal(transferAmount);
                     done();
                 });
                 await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
@@ -289,7 +289,7 @@ describe('TokenWrapper', () => {
                     const args = event.args as ApprovalContractEventArgs;
                     expect(args._owner).to.be.equal(coinbase);
                     expect(args._spender).to.be.equal(addressWithoutFunds);
-                    expect(args._value).to.be.equal(allowanceAmount);
+                    expect(args._value).to.be.bignumber.equal(allowanceAmount);
                     done();
                 });
                 await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount);
-- 
cgit v1.2.3


From 82c1d7ca7c206fcb7f436ddd31c97609257d0d2e Mon Sep 17 00:00:00 2001
From: Leonid Logvinov <logvinov.leon@gmail.com>
Date: Tue, 4 Jul 2017 12:29:14 -0700
Subject: Add exchangeContractAddress to an order in schema tests

---
 test/schema_test.ts | 1 +
 1 file changed, 1 insertion(+)

(limited to 'test')

diff --git a/test/schema_test.ts b/test/schema_test.ts
index 4746c7949..da7e97ce3 100644
--- a/test/schema_test.ts
+++ b/test/schema_test.ts
@@ -200,6 +200,7 @@ describe('Schema', () => {
             takerTokenAddress: constants.NULL_ADDRESS,
             salt: '256',
             feeRecipient: constants.NULL_ADDRESS,
+            exchangeContractAddress: constants.NULL_ADDRESS,
             expirationUnixTimestampSec: '42',
         };
         describe('#orderSchema', () => {
-- 
cgit v1.2.3


From 464c16be73bddce1ed675f642937b164f7add9d8 Mon Sep 17 00:00:00 2001
From: Leonid Logvinov <logvinov.leon@gmail.com>
Date: Tue, 4 Jul 2017 17:33:35 -0700
Subject: move order hash schema to a separate file

---
 test/schema_test.ts | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'test')

diff --git a/test/schema_test.ts b/test/schema_test.ts
index da7e97ce3..3d1d32d9c 100644
--- a/test/schema_test.ts
+++ b/test/schema_test.ts
@@ -6,7 +6,8 @@ import promisify = require('es6-promisify');
 import {constants} from './utils/constants';
 import {SchemaValidator} from '../src/utils/schema_validator';
 import {tokenSchema} from '../src/schemas/token_schema';
-import {orderSchema, signedOrderSchema, orderHashSchema} from '../src/schemas/order_schemas';
+import {orderHashSchema} from '../src/schemas/order_hash_schema';
+import {orderSchema, signedOrderSchema} from '../src/schemas/order_schemas';
 import {addressSchema, numberSchema} from '../src/schemas/basic_type_schemas';
 import {orderFillOrKillRequestsSchema} from '../src/schemas/order_fill_or_kill_requests_schema';
 import {ecSignatureParameterSchema, ecSignatureSchema} from '../src/schemas/ec_signature_schema';
-- 
cgit v1.2.3


From ea6583d47e786c846c18fb4893847d3271dedbc3 Mon Sep 17 00:00:00 2001
From: Leonid Logvinov <logvinov.leon@gmail.com>
Date: Tue, 4 Jul 2017 17:35:02 -0700
Subject: Make all fields of subscriptionOpts schema optional

---
 test/schema_test.ts | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'test')

diff --git a/test/schema_test.ts b/test/schema_test.ts
index 3d1d32d9c..c170bebb1 100644
--- a/test/schema_test.ts
+++ b/test/schema_test.ts
@@ -141,14 +141,14 @@ describe('Schema', () => {
         it('should validate valid subscription opts', () => {
             const testCases = [
                 {fromBlock: 42, toBlock: 'latest'},
+                {fromBlock: 42},
+                {},
             ];
             validateAgainstSchema(testCases, subscriptionOptsSchema);
         });
         it('should fail for invalid subscription opts', () => {
             const testCases = [
-                {},
-                {fromBlock: 42},
-                {fromBlock: 42, to: 43},
+                {fromBlock: '42'},
             ];
             const shouldFail = true;
             validateAgainstSchema(testCases, subscriptionOptsSchema, shouldFail);
-- 
cgit v1.2.3