From 67dfe6030c3d193e8ccf9411b114a44e2ed11c73 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Sat, 1 Dec 2018 22:30:32 -0800 Subject: feat: Add support for MultiAssetProxy --- .../dependent_order_hashes_tracker.ts | 76 +++++++++----- .../src/order_watcher/order_watcher.ts | 110 +++++++++++++++------ 2 files changed, 131 insertions(+), 55 deletions(-) (limited to 'packages/order-watcher') diff --git a/packages/order-watcher/src/order_watcher/dependent_order_hashes_tracker.ts b/packages/order-watcher/src/order_watcher/dependent_order_hashes_tracker.ts index a956a94db..eed1d055b 100644 --- a/packages/order-watcher/src/order_watcher/dependent_order_hashes_tracker.ts +++ b/packages/order-watcher/src/order_watcher/dependent_order_hashes_tracker.ts @@ -1,6 +1,6 @@ // tslint:disable:no-unnecessary-type-assertion import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; -import { AssetProxyId, ERC20AssetData, ERC721AssetData, SignedOrder } from '@0x/types'; +import { AssetProxyId, ERC20AssetData, ERC721AssetData, MultiAssetData, SignedOrder } from '@0x/types'; import { BigNumber } from '@0x/utils'; import * as _ from 'lodash'; @@ -62,39 +62,20 @@ export class DependentOrderHashesTracker { return dependentOrderHashes; } public addToDependentOrderHashes(signedOrder: SignedOrder): void { - const decodedMakerAssetData = assetDataUtils.decodeAssetDataOrThrow(signedOrder.makerAssetData); - if (decodedMakerAssetData.assetProxyId === AssetProxyId.ERC20) { - this._addToERC20DependentOrderHashes(signedOrder, (decodedMakerAssetData as ERC20AssetData).tokenAddress); - } else { - this._addToERC721DependentOrderHashes( - signedOrder, - (decodedMakerAssetData as ERC721AssetData).tokenAddress, - (decodedMakerAssetData as ERC721AssetData).tokenId, - ); - } + this._addAssetDataToDependentOrderHashes(signedOrder, signedOrder.makerAssetData); this._addToERC20DependentOrderHashes(signedOrder, this._zrxTokenAddress); this._addToMakerDependentOrderHashes(signedOrder); } public removeFromDependentOrderHashes(signedOrder: SignedOrder): void { - const decodedMakerAssetData = assetDataUtils.decodeAssetDataOrThrow(signedOrder.makerAssetData); - if (decodedMakerAssetData.assetProxyId === AssetProxyId.ERC20) { - this._removeFromERC20DependentOrderhashes( - signedOrder, - (decodedMakerAssetData as ERC20AssetData).tokenAddress, - ); - } else { - this._removeFromERC721DependentOrderhashes( - signedOrder, - (decodedMakerAssetData as ERC721AssetData).tokenAddress, - (decodedMakerAssetData as ERC721AssetData).tokenId, - ); - } + this._removeAssetDataFromDependentOrderHashes(signedOrder, signedOrder.makerAssetData); // If makerToken === ZRX then we already removed it and we don't need to remove it again. + const decodedMakerAssetData = assetDataUtils.decodeAssetDataOrThrow(signedOrder.makerAssetData); if ((decodedMakerAssetData as ERC20AssetData).tokenAddress !== this._zrxTokenAddress) { this._removeFromERC20DependentOrderhashes(signedOrder, this._zrxTokenAddress); } this._removeFromMakerDependentOrderhashes(signedOrder); } + private _getDependentOrderHashesByERC20AssetData(makerAddress: string, erc20AssetData: string): string[] { const tokenAddress = assetDataUtils.decodeERC20AssetData(erc20AssetData).tokenAddress; let dependentOrderHashes: string[] = []; @@ -167,6 +148,28 @@ export class DependentOrderHashesTracker { tokenId.toString() ].add(orderHash); } + private _addAssetDataToDependentOrderHashes(signedOrder: SignedOrder, assetData: string): void { + const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData); + switch (decodedAssetData.assetProxyId) { + case AssetProxyId.ERC20: + this._addToERC20DependentOrderHashes(signedOrder, (decodedAssetData as ERC20AssetData).tokenAddress); + break; + case AssetProxyId.ERC721: + this._addToERC721DependentOrderHashes( + signedOrder, + (decodedAssetData as ERC721AssetData).tokenAddress, + (decodedAssetData as ERC721AssetData).tokenId, + ); + break; + case AssetProxyId.MultiAsset: + _.each((decodedAssetData as MultiAssetData).nestedAssetData, nestedAssetDataElement => + this._addAssetDataToDependentOrderHashes(signedOrder, nestedAssetDataElement), + ); + break; + default: + break; + } + } private _addToMakerDependentOrderHashes(signedOrder: SignedOrder): void { const orderHash = orderHashUtils.getOrderHashHex(signedOrder); if (_.isUndefined(this._orderHashesByMakerAddress[signedOrder.makerAddress])) { @@ -230,4 +233,29 @@ export class DependentOrderHashesTracker { delete this._orderHashesByMakerAddress[signedOrder.makerAddress]; } } + private _removeAssetDataFromDependentOrderHashes(signedOrder: SignedOrder, assetData: string): void { + const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData); + switch (decodedAssetData.assetProxyId) { + case AssetProxyId.ERC20: + this._removeFromERC20DependentOrderhashes( + signedOrder, + (decodedAssetData as ERC20AssetData).tokenAddress, + ); + break; + case AssetProxyId.ERC721: + this._removeFromERC721DependentOrderhashes( + signedOrder, + (decodedAssetData as ERC721AssetData).tokenAddress, + (decodedAssetData as ERC721AssetData).tokenId, + ); + break; + case AssetProxyId.MultiAsset: + _.each((decodedAssetData as MultiAssetData).nestedAssetData, nestedAssetDataElement => + this._removeAssetDataFromDependentOrderHashes(signedOrder, nestedAssetDataElement), + ); + break; + default: + break; + } + } } diff --git a/packages/order-watcher/src/order_watcher/order_watcher.ts b/packages/order-watcher/src/order_watcher/order_watcher.ts index 96c5ca7b4..bf890f0e6 100644 --- a/packages/order-watcher/src/order_watcher/order_watcher.ts +++ b/packages/order-watcher/src/order_watcher/order_watcher.ts @@ -32,7 +32,16 @@ import { orderHashUtils, OrderStateUtils, } from '@0x/order-utils'; -import { AssetProxyId, ExchangeContractErrs, OrderState, SignedOrder, Stats } from '@0x/types'; +import { + AssetProxyId, + ERC20AssetData, + ERC721AssetData, + ExchangeContractErrs, + MultiAssetData, + OrderState, + SignedOrder, + Stats, +} from '@0x/types'; import { errorUtils, intervalUtils } from '@0x/utils'; import { BlockParamLiteral, LogEntryEvent, LogWithDecodedArgs, Provider } from 'ethereum-types'; import * as _ from 'lodash'; @@ -161,14 +170,7 @@ export class OrderWatcher { this._dependentOrderHashesTracker.addToDependentOrderHashes(signedOrder); const orderAssetDatas = [signedOrder.makerAssetData, signedOrder.takerAssetData]; - _.each(orderAssetDatas, assetData => { - const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData); - if (decodedAssetData.assetProxyId === AssetProxyId.ERC20) { - this._collisionResistantAbiDecoder.addERC20Token(decodedAssetData.tokenAddress); - } else if (decodedAssetData.assetProxyId === AssetProxyId.ERC721) { - this._collisionResistantAbiDecoder.addERC721Token(decodedAssetData.tokenAddress); - } - }); + _.each(orderAssetDatas, assetData => this._addAssetDataToAbiDecoder(assetData)); } /** * Removes an order from the orderWatcher @@ -236,31 +238,77 @@ export class OrderWatcher { await this._emitRevalidateOrdersAsync([orderHash]); } } + private _addAssetDataToAbiDecoder(assetData: string): void { + const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData); + switch (decodedAssetData.assetProxyId) { + case AssetProxyId.ERC20: + this._collisionResistantAbiDecoder.addERC20Token((decodedAssetData as ERC20AssetData).tokenAddress); + break; + case AssetProxyId.ERC721: + this._collisionResistantAbiDecoder.addERC721Token((decodedAssetData as ERC721AssetData).tokenAddress); + break; + case AssetProxyId.MultiAsset: + _.each((decodedAssetData as MultiAssetData).nestedAssetData, nestedAssetDataElement => + this._addAssetDataToAbiDecoder(nestedAssetDataElement), + ); + break; + default: + break; + } + } + private _deleteLazyStoreBalance(assetData: string, userAddress: string): void { + const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData); + switch (assetProxyId) { + case AssetProxyId.ERC20: + case AssetProxyId.ERC721: + this._balanceAndProxyAllowanceLazyStore.deleteBalance(assetData, userAddress); + break; + case AssetProxyId.MultiAsset: + const decodedAssetData = assetDataUtils.decodeMultiAssetData(assetData); + _.each(decodedAssetData.nestedAssetData, nestedAssetDataElement => + this._deleteLazyStoreBalance(nestedAssetDataElement, userAddress), + ); + break; + default: + break; + } + } + private _deleteLazyStoreProxyAllowance(assetData: string, userAddress: string): void { + const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData); + switch (assetProxyId) { + case AssetProxyId.ERC20: + case AssetProxyId.ERC721: + this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(assetData, userAddress); + break; + case AssetProxyId.MultiAsset: + const decodedAssetData = assetDataUtils.decodeMultiAssetData(assetData); + _.each(decodedAssetData.nestedAssetData, nestedAssetDataElement => + this._deleteLazyStoreProxyAllowance(nestedAssetDataElement, userAddress), + ); + break; + default: + break; + } + } private _cleanupOrderRelatedState(orderHash: string): void { const signedOrder = this._orderByOrderHash[orderHash]; this._orderFilledCancelledLazyStore.deleteFilledTakerAmount(orderHash); this._orderFilledCancelledLazyStore.deleteIsCancelled(orderHash); - this._balanceAndProxyAllowanceLazyStore.deleteBalance(signedOrder.makerAssetData, signedOrder.makerAddress); - this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance( - signedOrder.makerAssetData, - signedOrder.makerAddress, - ); - this._balanceAndProxyAllowanceLazyStore.deleteBalance(signedOrder.takerAssetData, signedOrder.takerAddress); - this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance( - signedOrder.takerAssetData, - signedOrder.takerAddress, - ); + this._deleteLazyStoreBalance(signedOrder.makerAssetData, signedOrder.makerAddress); + this._deleteLazyStoreProxyAllowance(signedOrder.makerAssetData, signedOrder.makerAddress); + this._deleteLazyStoreBalance(signedOrder.takerAssetData, signedOrder.takerAddress); + this._deleteLazyStoreProxyAllowance(signedOrder.takerAssetData, signedOrder.takerAddress); const zrxAssetData = this._orderFilledCancelledLazyStore.getZRXAssetData(); if (!signedOrder.makerFee.isZero()) { - this._balanceAndProxyAllowanceLazyStore.deleteBalance(zrxAssetData, signedOrder.makerAddress); - this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(zrxAssetData, signedOrder.makerAddress); + this._deleteLazyStoreBalance(zrxAssetData, signedOrder.makerAddress); + this._deleteLazyStoreProxyAllowance(zrxAssetData, signedOrder.makerAddress); } if (!signedOrder.takerFee.isZero()) { - this._balanceAndProxyAllowanceLazyStore.deleteBalance(zrxAssetData, signedOrder.takerAddress); - this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(zrxAssetData, signedOrder.takerAddress); + this._deleteLazyStoreBalance(zrxAssetData, signedOrder.takerAddress); + this._deleteLazyStoreProxyAllowance(zrxAssetData, signedOrder.takerAddress); } } private _onOrderExpired(orderHash: string): void { @@ -302,7 +350,7 @@ export class OrderWatcher { // Invalidate cache const args = decodedLog.args as ERC20TokenApprovalEventArgs; const tokenAssetData = assetDataUtils.encodeERC20AssetData(decodedLog.address); - this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(tokenAssetData, args._owner); + this._deleteLazyStoreProxyAllowance(tokenAssetData, args._owner); // Revalidate orders const orderHashes = this._dependentOrderHashesTracker.getDependentOrderHashesByAssetDataByMaker( args._owner, @@ -315,7 +363,7 @@ export class OrderWatcher { // Invalidate cache const args = decodedLog.args as ERC721TokenApprovalEventArgs; const tokenAssetData = assetDataUtils.encodeERC721AssetData(decodedLog.address, args._tokenId); - this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(tokenAssetData, args._owner); + this._deleteLazyStoreProxyAllowance(tokenAssetData, args._owner); // Revalidate orders const orderHashes = this._dependentOrderHashesTracker.getDependentOrderHashesByAssetDataByMaker( args._owner, @@ -333,8 +381,8 @@ export class OrderWatcher { // Invalidate cache const args = decodedLog.args as ERC20TokenTransferEventArgs; const tokenAssetData = assetDataUtils.encodeERC20AssetData(decodedLog.address); - this._balanceAndProxyAllowanceLazyStore.deleteBalance(tokenAssetData, args._from); - this._balanceAndProxyAllowanceLazyStore.deleteBalance(tokenAssetData, args._to); + this._deleteLazyStoreBalance(tokenAssetData, args._from); + this._deleteLazyStoreBalance(tokenAssetData, args._to); // Revalidate orders const orderHashes = this._dependentOrderHashesTracker.getDependentOrderHashesByAssetDataByMaker( args._from, @@ -347,8 +395,8 @@ export class OrderWatcher { // Invalidate cache const args = decodedLog.args as ERC721TokenTransferEventArgs; const tokenAssetData = assetDataUtils.encodeERC721AssetData(decodedLog.address, args._tokenId); - this._balanceAndProxyAllowanceLazyStore.deleteBalance(tokenAssetData, args._from); - this._balanceAndProxyAllowanceLazyStore.deleteBalance(tokenAssetData, args._to); + this._deleteLazyStoreBalance(tokenAssetData, args._from); + this._deleteLazyStoreBalance(tokenAssetData, args._to); // Revalidate orders const orderHashes = this._dependentOrderHashesTracker.getDependentOrderHashesByAssetDataByMaker( args._from, @@ -375,7 +423,7 @@ export class OrderWatcher { // Invalidate cache const args = decodedLog.args as WETH9DepositEventArgs; const tokenAssetData = assetDataUtils.encodeERC20AssetData(decodedLog.address); - this._balanceAndProxyAllowanceLazyStore.deleteBalance(tokenAssetData, args._owner); + this._deleteLazyStoreBalance(tokenAssetData, args._owner); // Revalidate orders const orderHashes = this._dependentOrderHashesTracker.getDependentOrderHashesByAssetDataByMaker( args._owner, @@ -388,7 +436,7 @@ export class OrderWatcher { // Invalidate cache const args = decodedLog.args as WETH9WithdrawalEventArgs; const tokenAssetData = assetDataUtils.encodeERC20AssetData(decodedLog.address); - this._balanceAndProxyAllowanceLazyStore.deleteBalance(tokenAssetData, args._owner); + this._deleteLazyStoreBalance(tokenAssetData, args._owner); // Revalidate orders const orderHashes = this._dependentOrderHashesTracker.getDependentOrderHashesByAssetDataByMaker( args._owner, -- cgit v1.2.3 From fc71d87d2bf38f59bd68d491f6eb6acbc04a9ece Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Sat, 1 Dec 2018 22:32:16 -0800 Subject: Update CHANGELOG --- packages/order-watcher/CHANGELOG.json | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'packages/order-watcher') diff --git a/packages/order-watcher/CHANGELOG.json b/packages/order-watcher/CHANGELOG.json index 304dc45fd..b4807dc89 100644 --- a/packages/order-watcher/CHANGELOG.json +++ b/packages/order-watcher/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "2.4.0", + "changes": [ + { + "note": "Add support for MultiAssetProxy", + "pr": 1363 + } + ] + }, { "version": "2.3.0", "changes": [ -- cgit v1.2.3 From aae32037da737e77b3ffaf0115494a1d7966a972 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Sat, 1 Dec 2018 23:40:12 -0800 Subject: Run linter --- packages/order-watcher/src/order_watcher/order_watcher.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/order-watcher') diff --git a/packages/order-watcher/src/order_watcher/order_watcher.ts b/packages/order-watcher/src/order_watcher/order_watcher.ts index bf890f0e6..c48606555 100644 --- a/packages/order-watcher/src/order_watcher/order_watcher.ts +++ b/packages/order-watcher/src/order_watcher/order_watcher.ts @@ -502,4 +502,4 @@ export class OrderWatcher { this._callbackIfExists(null, orderState); } } -} +} // tslint:disable:max-file-line-count -- cgit v1.2.3 From eeb07d76fc81b786d83c4ab848cc538e5896e240 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Tue, 4 Dec 2018 15:44:46 -0800 Subject: Fix transferFrom to work with MAP --- .../order-watcher/src/order_watcher/dependent_order_hashes_tracker.ts | 1 - 1 file changed, 1 deletion(-) (limited to 'packages/order-watcher') diff --git a/packages/order-watcher/src/order_watcher/dependent_order_hashes_tracker.ts b/packages/order-watcher/src/order_watcher/dependent_order_hashes_tracker.ts index eed1d055b..12723f73e 100644 --- a/packages/order-watcher/src/order_watcher/dependent_order_hashes_tracker.ts +++ b/packages/order-watcher/src/order_watcher/dependent_order_hashes_tracker.ts @@ -75,7 +75,6 @@ export class DependentOrderHashesTracker { } this._removeFromMakerDependentOrderhashes(signedOrder); } - private _getDependentOrderHashesByERC20AssetData(makerAddress: string, erc20AssetData: string): string[] { const tokenAddress = assetDataUtils.decodeERC20AssetData(erc20AssetData).tokenAddress; let dependentOrderHashes: string[] = []; -- cgit v1.2.3 From ccdb81ac400308276bd6996c1a6b86baa01b9ee5 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Thu, 3 Jan 2019 11:49:56 -0800 Subject: Add tests for MAP in order watcher --- packages/order-watcher/test/order_watcher_test.ts | 208 +++++++++++++++++++++ .../test/order_watcher_web_socket_server_test.ts | 2 +- 2 files changed, 209 insertions(+), 1 deletion(-) (limited to 'packages/order-watcher') diff --git a/packages/order-watcher/test/order_watcher_test.ts b/packages/order-watcher/test/order_watcher_test.ts index 271e5dec5..dfa36f2fd 100644 --- a/packages/order-watcher/test/order_watcher_test.ts +++ b/packages/order-watcher/test/order_watcher_test.ts @@ -675,5 +675,213 @@ describe('OrderWatcher', () => { })().catch(done); }); }); + describe('multiAsset', async () => { + const tokenId = new BigNumber(42); + const [makerErc721TokenAddress] = tokenUtils.getDummyERC721TokenAddresses(); + const makerErc721AssetData = assetDataUtils.encodeERC721AssetData(makerErc721TokenAddress, tokenId); + const fillableErc721Amount = new BigNumber(1); + const [makerErc20TokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); + const makerErc20AssetData = assetDataUtils.encodeERC20AssetData(makerErc20TokenAddress); + const fillableErc20Amount = new BigNumber(2); + const multiAssetAmounts = [fillableErc721Amount, fillableErc20Amount]; + const nestedAssetData = [makerErc721AssetData, makerErc20AssetData]; + const makerMultiAssetData = assetDataUtils.encodeMultiAssetData(multiAssetAmounts, nestedAssetData); + it('should emit orderStateInvalid when maker allowance of ERC721 token set to 0 for watched order', (done: DoneCallback) => { + (async () => { + signedOrder = await fillScenarios.createFillableSignedOrderAsync( + makerMultiAssetData, + takerAssetData, + makerAddress, + takerAddress, + fillableErc721Amount, + ); + const orderHash = orderHashUtils.getOrderHashHex(signedOrder); + await orderWatcher.addOrderAsync(signedOrder); + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { + expect(orderState.isValid).to.be.false(); + const invalidOrderState = orderState as OrderStateInvalid; + expect(invalidOrderState.orderHash).to.be.equal(orderHash); + expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.InsufficientMakerAllowance); + }); + orderWatcher.subscribe(callback); + await contractWrappers.erc721Token.setApprovalAsync( + makerErc721TokenAddress, + constants.NULL_ADDRESS, + tokenId, + ); + })().catch(done); + }); + it('should emit orderStateInvalid when maker allowance for all of ERC721 token set to 0 for watched order', (done: DoneCallback) => { + (async () => { + signedOrder = await fillScenarios.createFillableSignedOrderAsync( + makerMultiAssetData, + takerAssetData, + makerAddress, + takerAddress, + fillableErc721Amount, + ); + await contractWrappers.erc721Token.setApprovalAsync( + makerErc721TokenAddress, + constants.NULL_ADDRESS, + tokenId, + ); + let isApproved = true; + await contractWrappers.erc721Token.setProxyApprovalForAllAsync( + makerErc721TokenAddress, + makerAddress, + isApproved, + ); + const orderHash = orderHashUtils.getOrderHashHex(signedOrder); + await orderWatcher.addOrderAsync(signedOrder); + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { + expect(orderState.isValid).to.be.false(); + const invalidOrderState = orderState as OrderStateInvalid; + expect(invalidOrderState.orderHash).to.be.equal(orderHash); + expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.InsufficientMakerAllowance); + }); + orderWatcher.subscribe(callback); + isApproved = false; + await contractWrappers.erc721Token.setProxyApprovalForAllAsync( + makerErc721TokenAddress, + makerAddress, + isApproved, + ); + })().catch(done); + }); + it('should emit orderStateInvalid when maker moves ERC721 backing watched order', (done: DoneCallback) => { + (async () => { + signedOrder = await fillScenarios.createFillableSignedOrderAsync( + makerMultiAssetData, + takerAssetData, + makerAddress, + takerAddress, + fillableErc721Amount, + ); + const orderHash = orderHashUtils.getOrderHashHex(signedOrder); + await orderWatcher.addOrderAsync(signedOrder); + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { + expect(orderState.isValid).to.be.false(); + const invalidOrderState = orderState as OrderStateInvalid; + expect(invalidOrderState.orderHash).to.be.equal(orderHash); + expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.InsufficientMakerBalance); + }); + orderWatcher.subscribe(callback); + await contractWrappers.erc721Token.transferFromAsync( + makerErc721TokenAddress, + coinbase, + makerAddress, + tokenId, + ); + })().catch(done); + }); + it('should emit orderStateInvalid when maker allowance of ERC20 token set to 0 for watched order', (done: DoneCallback) => { + (async () => { + signedOrder = await fillScenarios.createFillableSignedOrderAsync( + makerMultiAssetData, + takerAssetData, + makerAddress, + takerAddress, + fillableErc721Amount, + ); + const orderHash = orderHashUtils.getOrderHashHex(signedOrder); + await orderWatcher.addOrderAsync(signedOrder); + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { + expect(orderState.isValid).to.be.false(); + const invalidOrderState = orderState as OrderStateInvalid; + expect(invalidOrderState.orderHash).to.be.equal(orderHash); + expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.InsufficientMakerAllowance); + }); + orderWatcher.subscribe(callback); + await contractWrappers.erc20Token.setProxyAllowanceAsync( + makerErc20TokenAddress, + makerAddress, + new BigNumber(0), + ); + })().catch(done); + }); + it('should not emit an orderState event when irrelevant ERC20 Transfer event received', (done: DoneCallback) => { + (async () => { + signedOrder = await fillScenarios.createFillableSignedOrderAsync( + makerMultiAssetData, + takerAssetData, + makerAddress, + takerAddress, + fillableAmount, + ); + await orderWatcher.addOrderAsync(signedOrder); + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((_orderState: OrderState) => { + throw new Error('OrderState callback fired for irrelevant order'); + }); + orderWatcher.subscribe(callback); + const notTheMaker = userAddresses[0]; + const anyRecipient = takerAddress; + const transferAmount = new BigNumber(2); + await contractWrappers.erc20Token.transferAsync( + makerTokenAddress, + notTheMaker, + anyRecipient, + transferAmount, + ); + setTimeout(() => { + done(); + }, TIMEOUT_MS); + })().catch(done); + }); + it('should emit orderStateInvalid when makerAddress moves ERC20 balance backing watched order', (done: DoneCallback) => { + (async () => { + signedOrder = await fillScenarios.createFillableSignedOrderAsync( + makerMultiAssetData, + takerAssetData, + makerAddress, + takerAddress, + fillableAmount, + ); + const orderHash = orderHashUtils.getOrderHashHex(signedOrder); + await orderWatcher.addOrderAsync(signedOrder); + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { + expect(orderState.isValid).to.be.false(); + const invalidOrderState = orderState as OrderStateInvalid; + expect(invalidOrderState.orderHash).to.be.equal(orderHash); + expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.InsufficientMakerBalance); + }); + orderWatcher.subscribe(callback); + const anyRecipient = takerAddress; + const makerBalance = await contractWrappers.erc20Token.getBalanceAsync( + makerTokenAddress, + makerAddress, + ); + await contractWrappers.erc20Token.transferAsync( + makerTokenAddress, + makerAddress, + anyRecipient, + makerBalance, + ); + })().catch(done); + }); + // TODO(abandeali1): The following test will fail until the MAP has been deployed and activated. + // it('should emit orderStateInvalid when watched order fully filled', (done: DoneCallback) => { + // (async () => { + // signedOrder = await fillScenarios.createFillableSignedOrderAsync( + // makerMultiAssetData, + // takerAssetData, + // makerAddress, + // takerAddress, + // fillableAmount, + // ); + // const orderHash = orderHashUtils.getOrderHashHex(signedOrder); + // await orderWatcher.addOrderAsync(signedOrder); + + // const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { + // expect(orderState.isValid).to.be.false(); + // const invalidOrderState = orderState as OrderStateInvalid; + // expect(invalidOrderState.orderHash).to.be.equal(orderHash); + // expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderRemainingFillAmountZero); + // }); + // orderWatcher.subscribe(callback); + + // await contractWrappers.exchange.fillOrderAsync(signedOrder, fillableAmount, takerAddress); + // })().catch(done); + // }); + }); }); }); // tslint:disable:max-file-line-count diff --git a/packages/order-watcher/test/order_watcher_web_socket_server_test.ts b/packages/order-watcher/test/order_watcher_web_socket_server_test.ts index 578e0de61..6894f42fb 100644 --- a/packages/order-watcher/test/order_watcher_web_socket_server_test.ts +++ b/packages/order-watcher/test/order_watcher_web_socket_server_test.ts @@ -26,7 +26,7 @@ interface WsMessage { data: string; } -describe.only('OrderWatcherWebSocketServer', async () => { +describe('OrderWatcherWebSocketServer', async () => { let contractWrappers: ContractWrappers; let wsServer: OrderWatcherWebSocketServer; let wsClient: WebSocket.w3cwebsocket; -- cgit v1.2.3 From a91bc415ed3c9dc94dda2661c0d7ac13bcc58e08 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Thu, 3 Jan 2019 14:29:56 -0800 Subject: Fix linting errors --- packages/order-watcher/src/index.ts | 1 + 1 file changed, 1 insertion(+) (limited to 'packages/order-watcher') diff --git a/packages/order-watcher/src/index.ts b/packages/order-watcher/src/index.ts index e275a0c6a..1f4e5eff1 100644 --- a/packages/order-watcher/src/index.ts +++ b/packages/order-watcher/src/index.ts @@ -7,6 +7,7 @@ export { OrderStateInvalid, OrderState, ExchangeContractErrs, + ObjectMap, OrderRelevantState, Stats, } from '@0x/types'; -- cgit v1.2.3 From 24564b986daa703f66e54f85abf4782d99a40f94 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Fri, 4 Jan 2019 14:31:25 -0800 Subject: Minimize unnecessary type assertions --- .../dependent_order_hashes_tracker.ts | 67 ++++++++-------------- .../src/order_watcher/order_watcher.ts | 33 +++-------- 2 files changed, 34 insertions(+), 66 deletions(-) (limited to 'packages/order-watcher') diff --git a/packages/order-watcher/src/order_watcher/dependent_order_hashes_tracker.ts b/packages/order-watcher/src/order_watcher/dependent_order_hashes_tracker.ts index 12723f73e..d1085014c 100644 --- a/packages/order-watcher/src/order_watcher/dependent_order_hashes_tracker.ts +++ b/packages/order-watcher/src/order_watcher/dependent_order_hashes_tracker.ts @@ -1,6 +1,5 @@ -// tslint:disable:no-unnecessary-type-assertion import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; -import { AssetProxyId, ERC20AssetData, ERC721AssetData, MultiAssetData, SignedOrder } from '@0x/types'; +import { AssetProxyId, SignedOrder } from '@0x/types'; import { BigNumber } from '@0x/utils'; import * as _ from 'lodash'; @@ -70,7 +69,10 @@ export class DependentOrderHashesTracker { this._removeAssetDataFromDependentOrderHashes(signedOrder, signedOrder.makerAssetData); // If makerToken === ZRX then we already removed it and we don't need to remove it again. const decodedMakerAssetData = assetDataUtils.decodeAssetDataOrThrow(signedOrder.makerAssetData); - if ((decodedMakerAssetData as ERC20AssetData).tokenAddress !== this._zrxTokenAddress) { + if ( + assetDataUtils.isERC20AssetData(decodedMakerAssetData) && + decodedMakerAssetData.tokenAddress !== this._zrxTokenAddress + ) { this._removeFromERC20DependentOrderhashes(signedOrder, this._zrxTokenAddress); } this._removeFromMakerDependentOrderhashes(signedOrder); @@ -149,24 +151,14 @@ export class DependentOrderHashesTracker { } private _addAssetDataToDependentOrderHashes(signedOrder: SignedOrder, assetData: string): void { const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData); - switch (decodedAssetData.assetProxyId) { - case AssetProxyId.ERC20: - this._addToERC20DependentOrderHashes(signedOrder, (decodedAssetData as ERC20AssetData).tokenAddress); - break; - case AssetProxyId.ERC721: - this._addToERC721DependentOrderHashes( - signedOrder, - (decodedAssetData as ERC721AssetData).tokenAddress, - (decodedAssetData as ERC721AssetData).tokenId, - ); - break; - case AssetProxyId.MultiAsset: - _.each((decodedAssetData as MultiAssetData).nestedAssetData, nestedAssetDataElement => - this._addAssetDataToDependentOrderHashes(signedOrder, nestedAssetDataElement), - ); - break; - default: - break; + if (assetDataUtils.isERC20AssetData(decodedAssetData)) { + this._addToERC20DependentOrderHashes(signedOrder, decodedAssetData.tokenAddress); + } else if (assetDataUtils.isERC721AssetData(decodedAssetData)) { + this._addToERC721DependentOrderHashes(signedOrder, decodedAssetData.tokenAddress, decodedAssetData.tokenId); + } else if (assetDataUtils.isMultiAssetData(decodedAssetData)) { + _.each(decodedAssetData.nestedAssetData, nestedAssetDataElement => + this._addAssetDataToDependentOrderHashes(signedOrder, nestedAssetDataElement), + ); } } private _addToMakerDependentOrderHashes(signedOrder: SignedOrder): void { @@ -234,27 +226,18 @@ export class DependentOrderHashesTracker { } private _removeAssetDataFromDependentOrderHashes(signedOrder: SignedOrder, assetData: string): void { const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData); - switch (decodedAssetData.assetProxyId) { - case AssetProxyId.ERC20: - this._removeFromERC20DependentOrderhashes( - signedOrder, - (decodedAssetData as ERC20AssetData).tokenAddress, - ); - break; - case AssetProxyId.ERC721: - this._removeFromERC721DependentOrderhashes( - signedOrder, - (decodedAssetData as ERC721AssetData).tokenAddress, - (decodedAssetData as ERC721AssetData).tokenId, - ); - break; - case AssetProxyId.MultiAsset: - _.each((decodedAssetData as MultiAssetData).nestedAssetData, nestedAssetDataElement => - this._removeAssetDataFromDependentOrderHashes(signedOrder, nestedAssetDataElement), - ); - break; - default: - break; + if (assetDataUtils.isERC20AssetData(decodedAssetData)) { + this._removeFromERC20DependentOrderhashes(signedOrder, decodedAssetData.tokenAddress); + } else if (assetDataUtils.isERC721AssetData(decodedAssetData)) { + this._removeFromERC721DependentOrderhashes( + signedOrder, + decodedAssetData.tokenAddress, + decodedAssetData.tokenId, + ); + } else if (assetDataUtils.isMultiAssetData(decodedAssetData)) { + _.each(decodedAssetData.nestedAssetData, nestedAssetDataElement => + this._removeAssetDataFromDependentOrderHashes(signedOrder, nestedAssetDataElement), + ); } } } diff --git a/packages/order-watcher/src/order_watcher/order_watcher.ts b/packages/order-watcher/src/order_watcher/order_watcher.ts index c48606555..656f21a53 100644 --- a/packages/order-watcher/src/order_watcher/order_watcher.ts +++ b/packages/order-watcher/src/order_watcher/order_watcher.ts @@ -32,16 +32,7 @@ import { orderHashUtils, OrderStateUtils, } from '@0x/order-utils'; -import { - AssetProxyId, - ERC20AssetData, - ERC721AssetData, - ExchangeContractErrs, - MultiAssetData, - OrderState, - SignedOrder, - Stats, -} from '@0x/types'; +import { AssetProxyId, ExchangeContractErrs, OrderState, SignedOrder, Stats } from '@0x/types'; import { errorUtils, intervalUtils } from '@0x/utils'; import { BlockParamLiteral, LogEntryEvent, LogWithDecodedArgs, Provider } from 'ethereum-types'; import * as _ from 'lodash'; @@ -240,20 +231,14 @@ export class OrderWatcher { } private _addAssetDataToAbiDecoder(assetData: string): void { const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData); - switch (decodedAssetData.assetProxyId) { - case AssetProxyId.ERC20: - this._collisionResistantAbiDecoder.addERC20Token((decodedAssetData as ERC20AssetData).tokenAddress); - break; - case AssetProxyId.ERC721: - this._collisionResistantAbiDecoder.addERC721Token((decodedAssetData as ERC721AssetData).tokenAddress); - break; - case AssetProxyId.MultiAsset: - _.each((decodedAssetData as MultiAssetData).nestedAssetData, nestedAssetDataElement => - this._addAssetDataToAbiDecoder(nestedAssetDataElement), - ); - break; - default: - break; + if (assetDataUtils.isERC20AssetData(decodedAssetData)) { + this._collisionResistantAbiDecoder.addERC20Token(decodedAssetData.tokenAddress); + } else if (assetDataUtils.isERC721AssetData(decodedAssetData)) { + this._collisionResistantAbiDecoder.addERC721Token(decodedAssetData.tokenAddress); + } else if (assetDataUtils.isMultiAssetData(decodedAssetData)) { + _.each(decodedAssetData.nestedAssetData, nestedAssetDataElement => + this._addAssetDataToAbiDecoder(nestedAssetDataElement), + ); } } private _deleteLazyStoreBalance(assetData: string, userAddress: string): void { -- cgit v1.2.3 From fd37e88bdbdcc821e4aa734aed6ad1f499b2b3e4 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Mon, 7 Jan 2019 11:11:19 -0800 Subject: Use enums in pipeline --- packages/order-watcher/CHANGELOG.json | 2 +- .../src/order_watcher/order_watcher.ts | 2 +- packages/order-watcher/test/order_watcher_test.ts | 42 +++++++++++----------- 3 files changed, 23 insertions(+), 23 deletions(-) (limited to 'packages/order-watcher') diff --git a/packages/order-watcher/CHANGELOG.json b/packages/order-watcher/CHANGELOG.json index b4807dc89..4cfecd034 100644 --- a/packages/order-watcher/CHANGELOG.json +++ b/packages/order-watcher/CHANGELOG.json @@ -3,7 +3,7 @@ "version": "2.4.0", "changes": [ { - "note": "Add support for MultiAssetProxy", + "note": "Add support for `MultiAssetProxy`", "pr": 1363 } ] diff --git a/packages/order-watcher/src/order_watcher/order_watcher.ts b/packages/order-watcher/src/order_watcher/order_watcher.ts index 656f21a53..a06fd0cfe 100644 --- a/packages/order-watcher/src/order_watcher/order_watcher.ts +++ b/packages/order-watcher/src/order_watcher/order_watcher.ts @@ -487,4 +487,4 @@ export class OrderWatcher { this._callbackIfExists(null, orderState); } } -} // tslint:disable:max-file-line-count +} diff --git a/packages/order-watcher/test/order_watcher_test.ts b/packages/order-watcher/test/order_watcher_test.ts index dfa36f2fd..41dc884d5 100644 --- a/packages/order-watcher/test/order_watcher_test.ts +++ b/packages/order-watcher/test/order_watcher_test.ts @@ -859,29 +859,29 @@ describe('OrderWatcher', () => { })().catch(done); }); // TODO(abandeali1): The following test will fail until the MAP has been deployed and activated. - // it('should emit orderStateInvalid when watched order fully filled', (done: DoneCallback) => { - // (async () => { - // signedOrder = await fillScenarios.createFillableSignedOrderAsync( - // makerMultiAssetData, - // takerAssetData, - // makerAddress, - // takerAddress, - // fillableAmount, - // ); - // const orderHash = orderHashUtils.getOrderHashHex(signedOrder); - // await orderWatcher.addOrderAsync(signedOrder); + it.skip('should emit orderStateInvalid when watched order fully filled', (done: DoneCallback) => { + (async () => { + signedOrder = await fillScenarios.createFillableSignedOrderAsync( + makerMultiAssetData, + takerAssetData, + makerAddress, + takerAddress, + fillableAmount, + ); + const orderHash = orderHashUtils.getOrderHashHex(signedOrder); + await orderWatcher.addOrderAsync(signedOrder); - // const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { - // expect(orderState.isValid).to.be.false(); - // const invalidOrderState = orderState as OrderStateInvalid; - // expect(invalidOrderState.orderHash).to.be.equal(orderHash); - // expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderRemainingFillAmountZero); - // }); - // orderWatcher.subscribe(callback); + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { + expect(orderState.isValid).to.be.false(); + const invalidOrderState = orderState as OrderStateInvalid; + expect(invalidOrderState.orderHash).to.be.equal(orderHash); + expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderRemainingFillAmountZero); + }); + orderWatcher.subscribe(callback); - // await contractWrappers.exchange.fillOrderAsync(signedOrder, fillableAmount, takerAddress); - // })().catch(done); - // }); + await contractWrappers.exchange.fillOrderAsync(signedOrder, fillableAmount, takerAddress); + })().catch(done); + }); }); }); }); // tslint:disable:max-file-line-count -- cgit v1.2.3