diff options
author | Leonid Logvinov <logvinov.leon@gmail.com> | 2018-07-18 21:27:38 +0800 |
---|---|---|
committer | Leonid Logvinov <logvinov.leon@gmail.com> | 2018-07-18 21:27:38 +0800 |
commit | dad557164ea4ccc012243d43df013078a7c37eb6 (patch) | |
tree | 88e8477941dc0c98273fcb054086b2e89d034e19 /packages | |
parent | acff177c547dee049b97e4b051fe22e1efaf992c (diff) | |
parent | f3241ff86a0d99f4291c5a5f4eaaa5ebe1736da0 (diff) | |
download | dexon-sol-tools-dad557164ea4ccc012243d43df013078a7c37eb6.tar dexon-sol-tools-dad557164ea4ccc012243d43df013078a7c37eb6.tar.gz dexon-sol-tools-dad557164ea4ccc012243d43df013078a7c37eb6.tar.bz2 dexon-sol-tools-dad557164ea4ccc012243d43df013078a7c37eb6.tar.lz dexon-sol-tools-dad557164ea4ccc012243d43df013078a7c37eb6.tar.xz dexon-sol-tools-dad557164ea4ccc012243d43df013078a7c37eb6.tar.zst dexon-sol-tools-dad557164ea4ccc012243d43df013078a7c37eb6.zip |
Merge branch 'v2-prototype' into feature/order-watcher-v2
Diffstat (limited to 'packages')
164 files changed, 1065 insertions, 602 deletions
diff --git a/packages/0x.js/CHANGELOG.json b/packages/0x.js/CHANGELOG.json index 3ec09cd7e..9419311dd 100644 --- a/packages/0x.js/CHANGELOG.json +++ b/packages/0x.js/CHANGELOG.json @@ -32,6 +32,10 @@ { "note": "0x.js exports renamed contract events and event arg types", "pr": 863 + }, + { + "note": "Remove stateLayer config from OrderWatcher. It now always operates on the latest block", + "pr": 875 } ] }, diff --git a/packages/0x.js/package.json b/packages/0x.js/package.json index 62c2691b2..502a346e4 100644 --- a/packages/0x.js/package.json +++ b/packages/0x.js/package.json @@ -94,7 +94,7 @@ "shx": "^0.2.2", "sinon": "^4.0.0", "source-map-support": "^0.5.0", - "tslint": "5.10.0", + "tslint": "5.11.0", "typedoc": "0xProject/typedoc", "typescript": "2.7.1", "webpack": "^3.1.0" diff --git a/packages/0x.js/src/0x.ts b/packages/0x.js/src/0x.ts index 5d9a03719..1d33eb7ca 100644 --- a/packages/0x.js/src/0x.ts +++ b/packages/0x.js/src/0x.ts @@ -61,7 +61,7 @@ export class ZeroEx { * ERC721 proxy smart contract. */ public erc721Proxy: ERC721ProxyWrapper; - private _contractWrappers: ContractWrappers; + private readonly _contractWrappers: ContractWrappers; /** * Generates a pseudo-random 256-bit salt. * The salt can be included in a 0x order, ensuring that the order generates a unique orderHash diff --git a/packages/0x.js/test/global_hooks.ts b/packages/0x.js/test/global_hooks.ts index 3d74634fe..364828231 100644 --- a/packages/0x.js/test/global_hooks.ts +++ b/packages/0x.js/test/global_hooks.ts @@ -7,7 +7,7 @@ before('migrate contracts', async function(): Promise<void> { // HACK: Since the migrations take longer then our global mocha timeout limit // we manually increase it for this before hook. const mochaTestTimeoutMs = 20000; - this.timeout(mochaTestTimeoutMs); + this.timeout(mochaTestTimeoutMs); // tslint:disable-line:no-invalid-this const txDefaults = { gas: devConstants.GAS_LIMIT, from: devConstants.TESTRPC_FIRST_ADDRESS, diff --git a/packages/abi-gen/CHANGELOG.json b/packages/abi-gen/CHANGELOG.json index ef8f5dd39..933ffe30c 100644 --- a/packages/abi-gen/CHANGELOG.json +++ b/packages/abi-gen/CHANGELOG.json @@ -1,14 +1,5 @@ [ { - "version": "0.4.1", - "changes": [ - { - "note": "skip generation of wrappers that are already up to date", - "pr": 788 - } - ] - }, - { "version": "0.4.0", "changes": [ { @@ -18,6 +9,10 @@ { "note": "Remove the output directory before writing to it", "pr": 822 + }, + { + "note": "skip generation of wrappers that are already up to date", + "pr": 788 } ] }, diff --git a/packages/abi-gen/package.json b/packages/abi-gen/package.json index 930fe0f0a..1397e75f6 100644 --- a/packages/abi-gen/package.json +++ b/packages/abi-gen/package.json @@ -34,7 +34,6 @@ "dependencies": { "@0xproject/typescript-typings": "^0.4.2", "@0xproject/utils": "^0.7.2", - "ethereum-types": "^0.0.2", "chalk": "^2.3.0", "ethereum-types": "^0.0.2", "glob": "^7.1.2", @@ -63,7 +62,7 @@ "mocha": "^5.2.0", "npm-run-all": "^4.1.2", "shx": "^0.2.2", - "tslint": "5.10.0", + "tslint": "5.11.0", "typescript": "2.7.1" }, "publishConfig": { diff --git a/packages/assert/package.json b/packages/assert/package.json index 10998fa68..053c9673d 100644 --- a/packages/assert/package.json +++ b/packages/assert/package.json @@ -44,7 +44,7 @@ "npm-run-all": "^4.1.2", "nyc": "^11.0.1", "shx": "^0.2.2", - "tslint": "5.10.0", + "tslint": "5.11.0", "typescript": "2.7.1" }, "dependencies": { diff --git a/packages/assert/src/index.ts b/packages/assert/src/index.ts index 8e18416c5..ccf2c9ad8 100644 --- a/packages/assert/src/index.ts +++ b/packages/assert/src/index.ts @@ -8,33 +8,33 @@ const HEX_REGEX = /^0x[0-9A-F]*$/i; export const assert = { isBigNumber(variableName: string, value: BigNumber): void { const isBigNumber = _.isObject(value) && (value as any).isBigNumber; - this.assert(isBigNumber, this.typeAssertionMessage(variableName, 'BigNumber', value)); + assert.assert(isBigNumber, assert.typeAssertionMessage(variableName, 'BigNumber', value)); }, isValidBaseUnitAmount(variableName: string, value: BigNumber): void { assert.isBigNumber(variableName, value); const isNegative = value.lessThan(0); - this.assert(!isNegative, `${variableName} cannot be a negative number, found value: ${value.toNumber()}`); + assert.assert(!isNegative, `${variableName} cannot be a negative number, found value: ${value.toNumber()}`); const hasDecimals = value.decimalPlaces() !== 0; - this.assert( + assert.assert( !hasDecimals, `${variableName} should be in baseUnits (no decimals), found value: ${value.toNumber()}`, ); }, isString(variableName: string, value: string): void { - this.assert(_.isString(value), this.typeAssertionMessage(variableName, 'string', value)); + assert.assert(_.isString(value), assert.typeAssertionMessage(variableName, 'string', value)); }, isFunction(variableName: string, value: any): void { - this.assert(_.isFunction(value), this.typeAssertionMessage(variableName, 'function', value)); + assert.assert(_.isFunction(value), assert.typeAssertionMessage(variableName, 'function', value)); }, isHexString(variableName: string, value: string): void { - this.assert( + assert.assert( _.isString(value) && HEX_REGEX.test(value), - this.typeAssertionMessage(variableName, 'HexString', value), + assert.typeAssertionMessage(variableName, 'HexString', value), ); }, isETHAddressHex(variableName: string, value: string): void { - this.assert(_.isString(value), this.typeAssertionMessage(variableName, 'string', value)); - this.assert(addressUtils.isAddress(value), this.typeAssertionMessage(variableName, 'ETHAddressHex', value)); + assert.assert(_.isString(value), assert.typeAssertionMessage(variableName, 'string', value)); + assert.assert(addressUtils.isAddress(value), assert.typeAssertionMessage(variableName, 'ETHAddressHex', value)); }, doesBelongToStringEnum( variableName: string, @@ -51,17 +51,17 @@ export const assert = { ); }, hasAtMostOneUniqueValue(value: any[], errMsg: string): void { - this.assert(_.uniq(value).length <= 1, errMsg); + assert.assert(_.uniq(value).length <= 1, errMsg); }, isNumber(variableName: string, value: number): void { - this.assert(_.isFinite(value), this.typeAssertionMessage(variableName, 'number', value)); + assert.assert(_.isFinite(value), assert.typeAssertionMessage(variableName, 'number', value)); }, isBoolean(variableName: string, value: boolean): void { - this.assert(_.isBoolean(value), this.typeAssertionMessage(variableName, 'boolean', value)); + assert.assert(_.isBoolean(value), assert.typeAssertionMessage(variableName, 'boolean', value)); }, isWeb3Provider(variableName: string, value: any): void { const isWeb3Provider = _.isFunction(value.send) || _.isFunction(value.sendAsync); - this.assert(isWeb3Provider, this.typeAssertionMessage(variableName, 'Provider', value)); + assert.assert(isWeb3Provider, assert.typeAssertionMessage(variableName, 'Provider', value)); }, doesConformToSchema(variableName: string, value: any, schema: Schema, subSchemas?: Schema[]): void { if (_.isUndefined(value)) { @@ -76,15 +76,15 @@ export const assert = { const msg = `Expected ${variableName} to conform to schema ${schema.id} Encountered: ${JSON.stringify(value, null, '\t')} Validation errors: ${validationResult.errors.join(', ')}`; - this.assert(!hasValidationErrors, msg); + assert.assert(!hasValidationErrors, msg); }, isWebUri(variableName: string, value: any): void { const isValidUrl = !_.isUndefined(validUrl.isWebUri(value)); - this.assert(isValidUrl, this.typeAssertionMessage(variableName, 'web uri', value)); + assert.assert(isValidUrl, assert.typeAssertionMessage(variableName, 'web uri', value)); }, isUri(variableName: string, value: any): void { const isValidUri = !_.isUndefined(validUrl.isUri(value)); - this.assert(isValidUri, this.typeAssertionMessage(variableName, 'uri', value)); + assert.assert(isValidUri, assert.typeAssertionMessage(variableName, 'uri', value)); }, assert(condition: boolean, message: string): void { if (!condition) { diff --git a/packages/assert/test/assert_test.ts b/packages/assert/test/assert_test.ts index 15fd3e6a8..cbbfe39db 100644 --- a/packages/assert/test/assert_test.ts +++ b/packages/assert/test/assert_test.ts @@ -49,7 +49,7 @@ describe('Assertions', () => { }); describe('#isFunction', () => { it('should not throw for valid input', () => { - const validInputs = [BigNumber, assert.isString]; + const validInputs = [BigNumber, assert.isString.bind(assert)]; validInputs.forEach(input => expect(assert.isFunction.bind(assert, variableName, input)).to.not.throw()); }); it('should throw for invalid input', () => { diff --git a/packages/base-contract/package.json b/packages/base-contract/package.json index 0448cb33c..a7ce7cc73 100644 --- a/packages/base-contract/package.json +++ b/packages/base-contract/package.json @@ -39,7 +39,7 @@ "mocha": "^4.0.1", "npm-run-all": "^4.1.2", "shx": "^0.2.2", - "tslint": "5.10.0", + "tslint": "5.11.0", "typescript": "2.7.1" }, "dependencies": { diff --git a/packages/base-contract/src/index.ts b/packages/base-contract/src/index.ts index 6b970ec27..a240fb8b6 100644 --- a/packages/base-contract/src/index.ts +++ b/packages/base-contract/src/index.ts @@ -72,15 +72,13 @@ export class BaseContract { // 1. Optional param passed in to public method call // 2. Global config passed in at library instantiation // 3. Gas estimate calculation + safety margin - const removeUndefinedProperties = _.pickBy; - const txDataWithDefaults: TxData = { + const removeUndefinedProperties = _.pickBy.bind(_); + const txDataWithDefaults = { ...removeUndefinedProperties(txDefaults), - ...removeUndefinedProperties(txData as any), - // HACK: TS can't prove that T is spreadable. - // Awaiting https://github.com/Microsoft/TypeScript/pull/13288 to be merged - } as any; + ...removeUndefinedProperties(txData), + }; if (_.isUndefined(txDataWithDefaults.gas) && !_.isUndefined(estimateGasAsync)) { - txDataWithDefaults.gas = await estimateGasAsync(txDataWithDefaults as any); + txDataWithDefaults.gas = await estimateGasAsync(txDataWithDefaults); } return txDataWithDefaults; } diff --git a/packages/connect/package.json b/packages/connect/package.json index 4148f9d57..5102c7d2c 100644 --- a/packages/connect/package.json +++ b/packages/connect/package.json @@ -81,7 +81,7 @@ "npm-run-all": "^4.1.2", "nyc": "^11.0.1", "shx": "^0.2.2", - "tslint": "5.10.0", + "tslint": "5.11.0", "typedoc": "~0.8.0", "typescript": "2.7.1" }, diff --git a/packages/connect/src/http_client.ts b/packages/connect/src/http_client.ts index f3800d581..03cc590e4 100644 --- a/packages/connect/src/http_client.ts +++ b/packages/connect/src/http_client.ts @@ -38,7 +38,7 @@ const OPTS_TO_QUERY_FIELD_MAP = { * that implement the standard relayer API v0 */ export class HttpClient implements Client { - private _apiEndpointUrl: string; + private readonly _apiEndpointUrl: string; /** * Format parameters to be appended to http requests into query string form */ diff --git a/packages/connect/src/utils/type_converters.ts b/packages/connect/src/utils/type_converters.ts index c1808ce8a..210d452b9 100644 --- a/packages/connect/src/utils/type_converters.ts +++ b/packages/connect/src/utils/type_converters.ts @@ -6,12 +6,12 @@ export const typeConverters = { const bids = _.get(orderbook, 'bids', []); const asks = _.get(orderbook, 'asks', []); return { - bids: bids.map((order: any) => this.convertOrderStringFieldsToBigNumber(order)), - asks: asks.map((order: any) => this.convertOrderStringFieldsToBigNumber(order)), + bids: bids.map((order: any) => typeConverters.convertOrderStringFieldsToBigNumber(order)), + asks: asks.map((order: any) => typeConverters.convertOrderStringFieldsToBigNumber(order)), }; }, convertOrderStringFieldsToBigNumber(order: any): any { - return this.convertStringsFieldsToBigNumbers(order, [ + return typeConverters.convertStringsFieldsToBigNumbers(order, [ 'makerTokenAmount', 'takerTokenAmount', 'makerFee', diff --git a/packages/connect/src/ws_orderbook_channel.ts b/packages/connect/src/ws_orderbook_channel.ts index e1c55cce3..fa9f5e37f 100644 --- a/packages/connect/src/ws_orderbook_channel.ts +++ b/packages/connect/src/ws_orderbook_channel.ts @@ -15,9 +15,9 @@ import { orderbookChannelMessageParser } from './utils/orderbook_channel_message * that implements the standard relayer API v0 */ export class WebSocketOrderbookChannel implements OrderbookChannel { - private _client: WebSocket.w3cwebsocket; - private _handler: OrderbookChannelHandler; - private _subscriptionOptsList: OrderbookChannelSubscriptionOpts[] = []; + private readonly _client: WebSocket.w3cwebsocket; + private readonly _handler: OrderbookChannelHandler; + private readonly _subscriptionOptsList: OrderbookChannelSubscriptionOpts[] = []; /** * Instantiates a new WebSocketOrderbookChannel instance * @param client A WebSocket client diff --git a/packages/connect/test/ws_orderbook_channel_test.ts b/packages/connect/test/ws_orderbook_channel_test.ts index fed4f2217..5a63cbdcc 100644 --- a/packages/connect/test/ws_orderbook_channel_test.ts +++ b/packages/connect/test/ws_orderbook_channel_test.ts @@ -29,7 +29,7 @@ describe('WebSocketOrderbookChannel', () => { const websocketUrl = 'ws://localhost:8080'; const openClient = new WebSocket.w3cwebsocket(websocketUrl); Sinon.stub(openClient, 'readyState').get(() => WebSocket.w3cwebsocket.OPEN); - Sinon.stub(openClient, 'send').callsFake(_.noop); + Sinon.stub(openClient, 'send').callsFake(_.noop.bind(_)); const openOrderbookChannel = new WebSocketOrderbookChannel(openClient, emptyOrderbookChannelHandler); const subscriptionOpts = { baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', diff --git a/packages/contract-wrappers/package.json b/packages/contract-wrappers/package.json index cf4286e1b..9c05d65eb 100644 --- a/packages/contract-wrappers/package.json +++ b/packages/contract-wrappers/package.json @@ -69,9 +69,9 @@ "shx": "^0.2.2", "sinon": "^4.0.0", "source-map-support": "^0.5.0", - "tslint": "5.10.0", - "typescript": "2.7.1", - "web3-provider-engine": "14.0.6" + "web3-provider-engine": "14.0.6", + "tslint": "5.11.0", + "typescript": "2.7.1" }, "dependencies": { "@0xproject/assert": "^0.3.0", diff --git a/packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts index b8ca4d29b..daf70253a 100644 --- a/packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts @@ -1,5 +1,5 @@ import { ContractArtifact } from '@0xproject/sol-compiler'; -import { AbiDecoder, intervalUtils } from '@0xproject/utils'; +import { AbiDecoder, intervalUtils, logUtils } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { BlockParamLiteral, ContractAbi, FilterObject, LogEntry, LogWithDecodedArgs, RawLog } from 'ethereum-types'; import { Block, BlockAndLogStreamer, Log } from 'ethereumjs-blockstream'; @@ -41,6 +41,13 @@ export abstract class ContractWrapper { }; private _onLogAddedSubscriptionToken: string | undefined; private _onLogRemovedSubscriptionToken: string | undefined; + private static _onBlockAndLogStreamerError(isVerbose: boolean, err: Error): void { + // Since Blockstream errors are all recoverable, we simply log them if the verbose + // config is passed in. + if (isVerbose) { + logUtils.warn(err); + } + } constructor(web3Wrapper: Web3Wrapper, networkId: number, blockPollingIntervalMs?: number) { this._web3Wrapper = web3Wrapper; this._networkId = networkId; @@ -79,10 +86,11 @@ export abstract class ContractWrapper { indexFilterValues: IndexedFilterValues, abi: ContractAbi, callback: EventCallback<ArgsType>, + isVerbose: boolean = false, ): string { const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi); if (_.isUndefined(this._blockAndLogStreamerIfExists)) { - this._startBlockAndLogStream(); + this._startBlockAndLogStream(isVerbose); } const filterToken = filterUtils.generateUUID(); this._filters[filterToken] = filter; @@ -151,21 +159,21 @@ export abstract class ContractWrapper { } }); } - private _startBlockAndLogStream(): void { + private _startBlockAndLogStream(isVerbose: boolean): void { if (!_.isUndefined(this._blockAndLogStreamerIfExists)) { throw new Error(ContractWrappersError.SubscriptionAlreadyPresent); } this._blockAndLogStreamerIfExists = new BlockAndLogStreamer( this._web3Wrapper.getBlockAsync.bind(this._web3Wrapper), this._web3Wrapper.getLogsAsync.bind(this._web3Wrapper), - this._onBlockAndLogStreamerError.bind(this), + ContractWrapper._onBlockAndLogStreamerError.bind(this, isVerbose), ); const catchAllLogFilter = {}; this._blockAndLogStreamerIfExists.addLogFilter(catchAllLogFilter); this._blockAndLogStreamIntervalIfExists = intervalUtils.setAsyncExcludingInterval( this._reconcileBlockAsync.bind(this), this._blockPollingIntervalMs, - this._onReconcileBlockError.bind(this), + ContractWrapper._onBlockAndLogStreamerError.bind(this, isVerbose), ); let isRemoved = false; this._onLogAddedSubscriptionToken = this._blockAndLogStreamerIfExists.subscribeToOnLogAdded( @@ -176,20 +184,10 @@ export abstract class ContractWrapper { this._onLogStateChanged.bind(this, isRemoved), ); } - private _onBlockAndLogStreamerError(err: Error): void { - // Propogate all Blockstream subscriber errors to all - // top-level subscriptions - const filterCallbacks = _.values(this._filterCallbacks); - _.each(filterCallbacks, filterCallback => { - filterCallback(err); - }); - } - private _onReconcileBlockError(err: Error): void { - const filterTokens = _.keys(this._filterCallbacks); - _.each(filterTokens, filterToken => { - this._unsubscribe(filterToken, err); - }); - } + // HACK: This should be a package-scoped method (which doesn't exist in TS) + // We don't want this method available in the public interface for all classes + // who inherit from ContractWrapper, and it is only used by the internal implementation + // of those higher classes. // tslint:disable-next-line:no-unused-variable private _setNetworkId(networkId: number): void { this._networkId = networkId; diff --git a/packages/contract-wrappers/src/contract_wrappers/erc20_token_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/erc20_token_wrapper.ts index 29c63564e..17bda5085 100644 --- a/packages/contract-wrappers/src/contract_wrappers/erc20_token_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/erc20_token_wrapper.ts @@ -347,6 +347,7 @@ export class ERC20TokenWrapper extends ContractWrapper { * @param indexFilterValues An object where the keys are indexed args returned by the event and * the value is the value you are interested in. E.g `{maker: aUserAddressHex}` * @param callback Callback that gets called when a log is added/removed + * @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered) * @return Subscription token used later to unsubscribe */ public subscribe<ArgsType extends ERC20TokenEventArgs>( @@ -354,6 +355,7 @@ export class ERC20TokenWrapper extends ContractWrapper { eventName: ERC20TokenEvents, indexFilterValues: IndexedFilterValues, callback: EventCallback<ArgsType>, + isVerbose: boolean = false, ): string { assert.isETHAddressHex('tokenAddress', tokenAddress); assert.doesBelongToStringEnum('eventName', eventName, ERC20TokenEvents); @@ -366,6 +368,7 @@ export class ERC20TokenWrapper extends ContractWrapper { indexFilterValues, artifacts.ERC20Token.compilerOutput.abi, callback, + isVerbose, ); return subscriptionToken; } diff --git a/packages/contract-wrappers/src/contract_wrappers/erc721_token_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/erc721_token_wrapper.ts index b7e5519c4..3d24702b3 100644 --- a/packages/contract-wrappers/src/contract_wrappers/erc721_token_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/erc721_token_wrapper.ts @@ -372,6 +372,7 @@ export class ERC721TokenWrapper extends ContractWrapper { * @param indexFilterValues An object where the keys are indexed args returned by the event and * the value is the value you are interested in. E.g `{maker: aUserAddressHex}` * @param callback Callback that gets called when a log is added/removed + * @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered) * @return Subscription token used later to unsubscribe */ public subscribe<ArgsType extends ERC721TokenEventArgs>( @@ -379,6 +380,7 @@ export class ERC721TokenWrapper extends ContractWrapper { eventName: ERC721TokenEvents, indexFilterValues: IndexedFilterValues, callback: EventCallback<ArgsType>, + isVerbose: boolean = false, ): string { assert.isETHAddressHex('tokenAddress', tokenAddress); assert.doesBelongToStringEnum('eventName', eventName, ERC721TokenEvents); @@ -391,6 +393,7 @@ export class ERC721TokenWrapper extends ContractWrapper { indexFilterValues, artifacts.ERC721Token.compilerOutput.abi, callback, + isVerbose, ); return subscriptionToken; } diff --git a/packages/contract-wrappers/src/contract_wrappers/ether_token_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/ether_token_wrapper.ts index 01440a5e1..5046d3667 100644 --- a/packages/contract-wrappers/src/contract_wrappers/ether_token_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/ether_token_wrapper.ts @@ -146,6 +146,7 @@ export class EtherTokenWrapper extends ContractWrapper { * @param indexFilterValues An object where the keys are indexed args returned by the event and * the value is the value you are interested in. E.g `{_owner: aUserAddressHex}` * @param callback Callback that gets called when a log is added/removed + * @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered) * @return Subscription token used later to unsubscribe */ public subscribe<ArgsType extends WETH9EventArgs>( @@ -153,6 +154,7 @@ export class EtherTokenWrapper extends ContractWrapper { eventName: WETH9Events, indexFilterValues: IndexedFilterValues, callback: EventCallback<ArgsType>, + isVerbose: boolean = false, ): string { assert.isETHAddressHex('etherTokenAddress', etherTokenAddress); const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase(); @@ -165,6 +167,7 @@ export class EtherTokenWrapper extends ContractWrapper { indexFilterValues, artifacts.EtherToken.compilerOutput.abi, callback, + isVerbose, ); return subscriptionToken; } diff --git a/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts index abe373dcf..b5ea56789 100644 --- a/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts @@ -989,12 +989,14 @@ export class ExchangeWrapper extends ContractWrapper { * @param indexFilterValues An object where the keys are indexed args returned by the event and * the value is the value you are interested in. E.g `{maker: aUserAddressHex}` * @param callback Callback that gets called when a log is added/removed + * @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered) * @return Subscription token used later to unsubscribe */ public subscribe<ArgsType extends ExchangeEventArgs>( eventName: ExchangeEvents, indexFilterValues: IndexedFilterValues, callback: EventCallback<ArgsType>, + isVerbose: boolean = false, ): string { assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents); assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); @@ -1006,6 +1008,7 @@ export class ExchangeWrapper extends ContractWrapper { indexFilterValues, artifacts.Exchange.compilerOutput.abi, callback, + isVerbose, ); return subscriptionToken; } diff --git a/packages/contract-wrappers/test/global_hooks.ts b/packages/contract-wrappers/test/global_hooks.ts index bf80e0908..05b23d5b8 100644 --- a/packages/contract-wrappers/test/global_hooks.ts +++ b/packages/contract-wrappers/test/global_hooks.ts @@ -7,7 +7,7 @@ before('migrate contracts', async function(): Promise<void> { // HACK: Since the migrations take longer then our global mocha timeout limit // we manually increase it for this before hook. const mochaTestTimeoutMs = 50000; - this.timeout(mochaTestTimeoutMs); + this.timeout(mochaTestTimeoutMs); // tslint:disable-line:no-invalid-this const txDefaults = { gas: devConstants.GAS_LIMIT, from: devConstants.TESTRPC_FIRST_ADDRESS, diff --git a/packages/contract-wrappers/test/subscription_test.ts b/packages/contract-wrappers/test/subscription_test.ts index adda4ab78..80d17576f 100644 --- a/packages/contract-wrappers/test/subscription_test.ts +++ b/packages/contract-wrappers/test/subscription_test.ts @@ -49,44 +49,6 @@ describe('SubscriptionTest', () => { _.each(stubs, s => s.restore()); stubs = []; }); - it('Should receive the Error when an error occurs while fetching the block', (done: DoneCallback) => { - (async () => { - const errMsg = 'Error fetching block'; - const callback = callbackErrorReporter.assertNodeCallbackError(done, errMsg); - stubs = [Sinon.stub((contractWrappers as any)._web3Wrapper, 'getBlockAsync').throws(new Error(errMsg))]; - contractWrappers.erc20Token.subscribe( - tokenAddress, - ERC20TokenEvents.Approval, - indexFilterValues, - callback, - ); - await contractWrappers.erc20Token.setAllowanceAsync( - tokenAddress, - coinbase, - addressWithoutFunds, - allowanceAmount, - ); - })().catch(done); - }); - it('Should receive the Error when an error occurs while reconciling the new block', (done: DoneCallback) => { - (async () => { - const errMsg = 'Error fetching logs'; - const callback = callbackErrorReporter.assertNodeCallbackError(done, errMsg); - stubs = [Sinon.stub((contractWrappers as any)._web3Wrapper, 'getLogsAsync').throws(new Error(errMsg))]; - contractWrappers.erc20Token.subscribe( - tokenAddress, - ERC20TokenEvents.Approval, - indexFilterValues, - callback, - ); - await contractWrappers.erc20Token.setAllowanceAsync( - tokenAddress, - coinbase, - addressWithoutFunds, - allowanceAmount, - ); - })().catch(done); - }); it('Should allow unsubscribeAll to be called successfully after an error', (done: DoneCallback) => { (async () => { const callback = (err: Error | null, _logEvent?: DecodedLogEvent<ERC20TokenApprovalEventArgs>) => diff --git a/packages/contracts/package.json b/packages/contracts/package.json index f09022d08..4d23860bf 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -67,7 +67,7 @@ "shx": "^0.2.2", "solc": "^0.4.24", "solhint": "^1.2.1", - "tslint": "5.10.0", + "tslint": "5.11.0", "typescript": "2.7.1", "yargs": "^10.0.3" }, diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinExchangeCore.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinExchangeCore.sol index ec84b1e19..6f435892b 100644 --- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinExchangeCore.sol +++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinExchangeCore.sol @@ -154,6 +154,9 @@ contract MixinExchangeCore is // Compute the order hash orderInfo.orderHash = getOrderHash(order); + // Fetch filled amount + orderInfo.orderTakerAssetFilledAmount = filled[orderInfo.orderHash]; + // If order.makerAssetAmount is zero, we also reject the order. // While the Exchange contract handles them correctly, they create // edge cases in the supporting infrastructure because they have @@ -172,6 +175,12 @@ contract MixinExchangeCore is return orderInfo; } + // Validate order availability + if (orderInfo.orderTakerAssetFilledAmount >= order.takerAssetAmount) { + orderInfo.orderStatus = uint8(OrderStatus.FULLY_FILLED); + return orderInfo; + } + // Validate order expiration // solhint-disable-next-line not-rely-on-time if (block.timestamp >= order.expirationTimeSeconds) { @@ -189,13 +198,6 @@ contract MixinExchangeCore is return orderInfo; } - // Fetch filled amount and validate order availability - orderInfo.orderTakerAssetFilledAmount = filled[orderInfo.orderHash]; - if (orderInfo.orderTakerAssetFilledAmount >= order.takerAssetAmount) { - orderInfo.orderStatus = uint8(OrderStatus.FULLY_FILLED); - return orderInfo; - } - // All other statuses are ruled out: order is Fillable orderInfo.orderStatus = uint8(OrderStatus.FILLABLE); return orderInfo; diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol index a16d2f897..d420f7e85 100644 --- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol +++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol @@ -529,4 +529,20 @@ contract MixinWrapperFunctions is cancelOrder(orders[i]); } } + + /// @dev Fetches information for all passed in orders. + /// @param orders Array of order specifications. + /// @return Array of OrderInfo instances that correspond to each order. + function getOrdersInfo(LibOrder.Order[] memory orders) + public + view + returns (LibOrder.OrderInfo[] memory) + { + uint256 length = orders.length; + LibOrder.OrderInfo[] memory ordersInfo = new LibOrder.OrderInfo[](length); + for (uint256 i = 0; i < length; i++) { + ordersInfo[i] = getOrderInfo(orders[i]); + } + return ordersInfo; + } } diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/interfaces/IWrapperFunctions.sol b/packages/contracts/src/2.0.0/protocol/Exchange/interfaces/IWrapperFunctions.sol index ad7a56a06..56a533646 100644 --- a/packages/contracts/src/2.0.0/protocol/Exchange/interfaces/IWrapperFunctions.sol +++ b/packages/contracts/src/2.0.0/protocol/Exchange/interfaces/IWrapperFunctions.sol @@ -149,4 +149,12 @@ contract IWrapperFunctions { /// @param orders Array of order specifications. function batchCancelOrders(LibOrder.Order[] memory orders) public; + + /// @dev Fetches information for all passed in orders + /// @param orders Array of order specifications. + /// @return Array of OrderInfo instances that correspond to each order. + function getOrdersInfo(LibOrder.Order[] memory orders) + public + view + returns (LibOrder.OrderInfo[] memory); } diff --git a/packages/contracts/test/exchange/core.ts b/packages/contracts/test/exchange/core.ts index d9f3851d1..1eb6f2a5c 100644 --- a/packages/contracts/test/exchange/core.ts +++ b/packages/contracts/test/exchange/core.ts @@ -15,13 +15,14 @@ import { ERC721ProxyContract } from '../../generated_contract_wrappers/erc721_pr import { ExchangeCancelEventArgs, ExchangeContract } from '../../generated_contract_wrappers/exchange'; import { artifacts } from '../utils/artifacts'; import { expectTransactionFailedAsync } from '../utils/assertions'; +import { getLatestBlockTimestampAsync, increaseTimeAndMineBlockAsync } from '../utils/block_timestamp'; import { chaiSetup } from '../utils/chai_setup'; import { constants } from '../utils/constants'; import { ERC20Wrapper } from '../utils/erc20_wrapper'; import { ERC721Wrapper } from '../utils/erc721_wrapper'; import { ExchangeWrapper } from '../utils/exchange_wrapper'; import { OrderFactory } from '../utils/order_factory'; -import { ERC20BalancesByOwner } from '../utils/types'; +import { ERC20BalancesByOwner, OrderStatus } from '../utils/types'; import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); @@ -129,11 +130,11 @@ describe('Exchange core', () => { describe('fillOrder', () => { beforeEach(async () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); - signedOrder = orderFactory.newSignedOrder(); + signedOrder = await orderFactory.newSignedOrderAsync(); }); it('should throw if signature is invalid', async () => { - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), }); @@ -151,7 +152,7 @@ describe('Exchange core', () => { }); it('should throw if no value is filled', async () => { - signedOrder = orderFactory.newSignedOrder(); + signedOrder = await orderFactory.newSignedOrderAsync(); await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress); return expectTransactionFailedAsync( exchangeWrapper.fillOrderAsync(signedOrder, takerAddress), @@ -163,7 +164,7 @@ describe('Exchange core', () => { describe('cancelOrder', () => { beforeEach(async () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); - signedOrder = orderFactory.newSignedOrder(); + signedOrder = await orderFactory.newSignedOrderAsync(); }); it('should throw if not sent by maker', async () => { @@ -174,7 +175,7 @@ describe('Exchange core', () => { }); it('should throw if makerAssetAmount is 0', async () => { - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(0), }); @@ -185,7 +186,7 @@ describe('Exchange core', () => { }); it('should throw if takerAssetAmount is 0', async () => { - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ takerAssetAmount: new BigNumber(0), }); @@ -229,8 +230,9 @@ describe('Exchange core', () => { }); it('should throw if order is expired', async () => { - signedOrder = orderFactory.newSignedOrder({ - expirationTimeSeconds: new BigNumber(Math.floor((Date.now() - 10000) / 1000)), + const currentTimestamp = await getLatestBlockTimestampAsync(); + signedOrder = await orderFactory.newSignedOrderAsync({ + expirationTimeSeconds: new BigNumber(currentTimestamp).sub(10), }); return expectTransactionFailedAsync( exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress), @@ -239,7 +241,7 @@ describe('Exchange core', () => { }); it('should throw if rounding error is greater than 0.1%', async () => { - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1001), takerAssetAmount: new BigNumber(3), }); @@ -288,22 +290,22 @@ describe('Exchange core', () => { // Since we cancelled with orderEpoch=1, orders with orderEpoch<=1 will not be processed erc20Balances = await erc20Wrapper.getBalancesAsync(); const signedOrders = [ - orderFactory.newSignedOrder({ + await orderFactory.newSignedOrderAsync({ makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(9), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(9), 18), salt: new BigNumber(0), }), - orderFactory.newSignedOrder({ + await orderFactory.newSignedOrderAsync({ makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(79), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(79), 18), salt: new BigNumber(1), }), - orderFactory.newSignedOrder({ + await orderFactory.newSignedOrderAsync({ makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(979), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(979), 18), salt: new BigNumber(2), }), - orderFactory.newSignedOrder({ + await orderFactory.newSignedOrderAsync({ makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(7979), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(7979), 18), salt: new BigNumber(3), @@ -350,7 +352,7 @@ describe('Exchange core', () => { // Construct Exchange parameters const makerAssetId = erc721TakerAssetIds[0]; const takerAssetId = erc721TakerAssetIds[1]; - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), takerAssetAmount: new BigNumber(1), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), @@ -373,7 +375,7 @@ describe('Exchange core', () => { // Construct Exchange parameters const makerAssetId = erc721MakerAssetIds[0]; const takerAssetId = erc721MakerAssetIds[1]; - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), takerAssetAmount: new BigNumber(1), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), @@ -396,7 +398,7 @@ describe('Exchange core', () => { // Construct Exchange parameters const makerAssetId = erc721MakerAssetIds[0]; const takerAssetId = erc721TakerAssetIds[0]; - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(2), takerAssetAmount: new BigNumber(1), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), @@ -419,7 +421,7 @@ describe('Exchange core', () => { // Construct Exchange parameters const makerAssetId = erc721MakerAssetIds[0]; const takerAssetId = erc721TakerAssetIds[0]; - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), takerAssetAmount: new BigNumber(500), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), @@ -441,7 +443,7 @@ describe('Exchange core', () => { it('should throw on partial fill', async () => { // Construct Exchange parameters const makerAssetId = erc721MakerAssetIds[0]; - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), @@ -462,7 +464,7 @@ describe('Exchange core', () => { const makerAssetData = assetProxyUtils .encodeERC721AssetData(erc721Token.address, makerAssetId) .slice(0, -2); - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), takerAssetAmount: new BigNumber(1), makerAssetData, @@ -481,6 +483,124 @@ describe('Exchange core', () => { ); }); }); + + describe('getOrderInfo', () => { + beforeEach(async () => { + signedOrder = await orderFactory.newSignedOrderAsync(); + }); + it('should return the correct orderInfo for an unfilled valid order', async () => { + const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = new BigNumber(0); + const expectedOrderStatus = OrderStatus.FILLABLE; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + it('should return the correct orderInfo for a fully filled order', async () => { + await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress); + const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = signedOrder.takerAssetAmount; + const expectedOrderStatus = OrderStatus.FULLY_FILLED; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + it('should return the correct orderInfo for a partially filled order', async () => { + const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2); + await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }); + const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = takerAssetFillAmount; + const expectedOrderStatus = OrderStatus.FILLABLE; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + it('should return the correct orderInfo for a cancelled and unfilled order', async () => { + await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress); + const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = new BigNumber(0); + const expectedOrderStatus = OrderStatus.CANCELLED; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + it('should return the correct orderInfo for a cancelled and partially filled order', async () => { + const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2); + await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }); + await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress); + const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = takerAssetFillAmount; + const expectedOrderStatus = OrderStatus.CANCELLED; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + it('should return the correct orderInfo for an expired and unfilled order', async () => { + const currentTimestamp = await getLatestBlockTimestampAsync(); + const timeUntilExpiration = signedOrder.expirationTimeSeconds.minus(currentTimestamp).toNumber(); + await increaseTimeAndMineBlockAsync(timeUntilExpiration); + const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = new BigNumber(0); + const expectedOrderStatus = OrderStatus.EXPIRED; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + it('should return the correct orderInfo for an expired and partially filled order', async () => { + const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2); + await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }); + const currentTimestamp = await getLatestBlockTimestampAsync(); + const timeUntilExpiration = signedOrder.expirationTimeSeconds.minus(currentTimestamp).toNumber(); + await increaseTimeAndMineBlockAsync(timeUntilExpiration); + const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = takerAssetFillAmount; + const expectedOrderStatus = OrderStatus.EXPIRED; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + it('should return the correct orderInfo for an expired and fully filled order', async () => { + await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress); + const currentTimestamp = await getLatestBlockTimestampAsync(); + const timeUntilExpiration = signedOrder.expirationTimeSeconds.minus(currentTimestamp).toNumber(); + await increaseTimeAndMineBlockAsync(timeUntilExpiration); + const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = signedOrder.takerAssetAmount; + // FULLY_FILLED takes precedence over EXPIRED + const expectedOrderStatus = OrderStatus.FULLY_FILLED; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + it('should return the correct orderInfo for an order with a makerAssetAmount of 0', async () => { + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(0) }); + const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = new BigNumber(0); + const expectedOrderStatus = OrderStatus.INVALID_MAKER_ASSET_AMOUNT; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + it('should return the correct orderInfo for an order with a takerAssetAmount of 0', async () => { + signedOrder = await orderFactory.newSignedOrderAsync({ takerAssetAmount: new BigNumber(0) }); + const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = new BigNumber(0); + const expectedOrderStatus = OrderStatus.INVALID_TAKER_ASSET_AMOUNT; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + }); }); // tslint:disable:max-file-line-count // tslint:enable:no-unnecessary-type-assertion diff --git a/packages/contracts/test/exchange/libs.ts b/packages/contracts/test/exchange/libs.ts index 6ded6329c..af595fedd 100644 --- a/packages/contracts/test/exchange/libs.ts +++ b/packages/contracts/test/exchange/libs.ts @@ -71,7 +71,7 @@ describe('Exchange libs', () => { }); describe('getOrderHash', () => { it('should output the correct orderHash', async () => { - signedOrder = orderFactory.newSignedOrder(); + signedOrder = await orderFactory.newSignedOrderAsync(); const orderHashHex = await libs.publicGetOrderHash.callAsync(signedOrder); expect(orderHashUtils.getOrderHashHex(signedOrder)).to.be.equal(orderHashHex); }); diff --git a/packages/contracts/test/exchange/match_orders.ts b/packages/contracts/test/exchange/match_orders.ts index 16041e968..6975aa115 100644 --- a/packages/contracts/test/exchange/match_orders.ts +++ b/packages/contracts/test/exchange/match_orders.ts @@ -150,13 +150,13 @@ describe('matchOrders', () => { it('should transfer the correct amounts when orders completely fill each other', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -182,13 +182,13 @@ describe('matchOrders', () => { it('should transfer the correct amounts when orders completely fill each other and taker doesnt take a profit', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -225,13 +225,13 @@ describe('matchOrders', () => { it('should transfer the correct amounts when left order is completely filled and right order is partially filled', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -257,13 +257,13 @@ describe('matchOrders', () => { it('should transfer the correct amounts when right order is completely filled and left order is partially filled', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -289,13 +289,13 @@ describe('matchOrders', () => { it('should transfer the correct amounts when consecutive calls are used to completely fill the left order', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -326,7 +326,7 @@ describe('matchOrders', () => { // Note: This order needs makerAssetAmount=90/takerAssetAmount=[anything <= 45] to fully fill the right order. // However, we use 100/50 to ensure a partial fill as we want to go down the "left fill" // branch in the contract twice for this test. - const signedOrderRight2 = orderFactoryRight.newSignedOrder({ + const signedOrderRight2 = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -356,14 +356,14 @@ describe('matchOrders', () => { it('should transfer the correct amounts when consecutive calls are used to completely fill the right order', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -394,7 +394,7 @@ describe('matchOrders', () => { // Note: This order needs makerAssetAmount=96/takerAssetAmount=48 to fully fill the right order. // However, we use 100/50 to ensure a partial fill as we want to go down the "right fill" // branch in the contract twice for this test. - const signedOrderLeft2 = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft2 = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18), @@ -425,13 +425,13 @@ describe('matchOrders', () => { it('should transfer the correct amounts if fee recipient is the same across both matched orders', async () => { const feeRecipientAddress = feeRecipientAddressLeft; - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -451,13 +451,13 @@ describe('matchOrders', () => { it('should transfer the correct amounts if taker is also the left order maker', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -478,13 +478,13 @@ describe('matchOrders', () => { it('should transfer the correct amounts if taker is also the right order maker', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -505,13 +505,13 @@ describe('matchOrders', () => { it('should transfer the correct amounts if taker is also the left fee recipient', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -532,13 +532,13 @@ describe('matchOrders', () => { it('should transfer the correct amounts if taker is also the right fee recipient', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -559,13 +559,13 @@ describe('matchOrders', () => { it('should transfer the correct amounts if left maker is the left fee recipient and right maker is the right fee recipient', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: makerAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -585,13 +585,13 @@ describe('matchOrders', () => { it('Should throw if left order is not fillable', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -610,13 +610,13 @@ describe('matchOrders', () => { it('Should throw if right order is not fillable', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -635,13 +635,13 @@ describe('matchOrders', () => { it('should throw if there is not a positive spread', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -658,13 +658,13 @@ describe('matchOrders', () => { it('should throw if the left maker asset is not equal to the right taker asset ', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), @@ -685,7 +685,7 @@ describe('matchOrders', () => { it('should throw if the right maker asset is not equal to the left taker asset', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -693,7 +693,7 @@ describe('matchOrders', () => { takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -711,7 +711,7 @@ describe('matchOrders', () => { it('should transfer correct amounts when left order maker asset is an ERC721 token', async () => { // Create orders to match const erc721TokenToTransfer = erc721LeftMakerAssetIds[0]; - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), @@ -719,7 +719,7 @@ describe('matchOrders', () => { takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer), @@ -746,7 +746,7 @@ describe('matchOrders', () => { it('should transfer correct amounts when right order maker asset is an ERC721 token', async () => { // Create orders to match const erc721TokenToTransfer = erc721RightMakerAssetIds[0]; - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer), @@ -754,7 +754,7 @@ describe('matchOrders', () => { takerAssetAmount: new BigNumber(1), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), diff --git a/packages/contracts/test/exchange/signature_validator.ts b/packages/contracts/test/exchange/signature_validator.ts index 8cd6409a5..2f4a9055d 100644 --- a/packages/contracts/test/exchange/signature_validator.ts +++ b/packages/contracts/test/exchange/signature_validator.ts @@ -95,7 +95,7 @@ describe('MixinSignatureValidator', () => { describe('isValidSignature', () => { beforeEach(async () => { - signedOrder = orderFactory.newSignedOrder(); + signedOrder = await orderFactory.newSignedOrderAsync(); }); it('should revert when signature is empty', async () => { diff --git a/packages/contracts/test/exchange/transactions.ts b/packages/contracts/test/exchange/transactions.ts index 0d66b11b8..831576cd2 100644 --- a/packages/contracts/test/exchange/transactions.ts +++ b/packages/contracts/test/exchange/transactions.ts @@ -121,7 +121,7 @@ describe('Exchange transactions', () => { let takerAssetFillAmount: BigNumber; beforeEach(async () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); - signedOrder = orderFactory.newSignedOrder(); + signedOrder = await orderFactory.newSignedOrderAsync(); orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder); takerAssetFillAmount = signedOrder.takerAssetAmount.div(2); @@ -226,7 +226,7 @@ describe('Exchange transactions', () => { it("should cancel an order if called from the order's sender", async () => { const orderSalt = new BigNumber(0); - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ senderAddress: exchangeWrapperContract.address, salt: orderSalt, }); @@ -265,7 +265,7 @@ describe('Exchange transactions', () => { it("should not cancel an order if not called from the order's sender", async () => { const orderSalt = new BigNumber(0); - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ senderAddress: exchangeWrapperContract.address, salt: orderSalt, }); @@ -356,7 +356,7 @@ describe('Exchange transactions', () => { }); beforeEach(async () => { - signedOrder = whitelistOrderFactory.newSignedOrder(); + signedOrder = await whitelistOrderFactory.newSignedOrderAsync(); erc20Balances = await erc20Wrapper.getBalancesAsync(); }); diff --git a/packages/contracts/test/exchange/wrapper.ts b/packages/contracts/test/exchange/wrapper.ts index 655d55b83..abcb8364a 100644 --- a/packages/contracts/test/exchange/wrapper.ts +++ b/packages/contracts/test/exchange/wrapper.ts @@ -1,5 +1,5 @@ import { BlockchainLifecycle } from '@0xproject/dev-utils'; -import { assetProxyUtils } from '@0xproject/order-utils'; +import { assetProxyUtils, orderHashUtils } from '@0xproject/order-utils'; import { RevertReason, SignedOrder } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; @@ -13,13 +13,14 @@ import { ERC721ProxyContract } from '../../generated_contract_wrappers/erc721_pr import { ExchangeContract } from '../../generated_contract_wrappers/exchange'; import { artifacts } from '../utils/artifacts'; import { expectTransactionFailedAsync } from '../utils/assertions'; +import { getLatestBlockTimestampAsync, increaseTimeAndMineBlockAsync } from '../utils/block_timestamp'; import { chaiSetup } from '../utils/chai_setup'; import { constants } from '../utils/constants'; import { ERC20Wrapper } from '../utils/erc20_wrapper'; import { ERC721Wrapper } from '../utils/erc721_wrapper'; import { ExchangeWrapper } from '../utils/exchange_wrapper'; import { OrderFactory } from '../utils/order_factory'; -import { ERC20BalancesByOwner } from '../utils/types'; +import { ERC20BalancesByOwner, OrderStatus } from '../utils/types'; import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); @@ -126,7 +127,7 @@ describe('Exchange wrappers', () => { }); describe('fillOrKillOrder', () => { it('should transfer the correct amounts', async () => { - const signedOrder = orderFactory.newSignedOrder({ + const signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18), }); @@ -170,8 +171,9 @@ describe('Exchange wrappers', () => { }); it('should throw if a signedOrder is expired', async () => { - const signedOrder = orderFactory.newSignedOrder({ - expirationTimeSeconds: new BigNumber(Math.floor((Date.now() - 10000) / 1000)), + const currentTimestamp = await getLatestBlockTimestampAsync(); + const signedOrder = await orderFactory.newSignedOrderAsync({ + expirationTimeSeconds: new BigNumber(currentTimestamp).sub(10), }); return expectTransactionFailedAsync( @@ -181,7 +183,7 @@ describe('Exchange wrappers', () => { }); it('should throw if entire takerAssetFillAmount not filled', async () => { - const signedOrder = orderFactory.newSignedOrder(); + const signedOrder = await orderFactory.newSignedOrderAsync(); await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount: signedOrder.takerAssetAmount.div(2), @@ -196,7 +198,7 @@ describe('Exchange wrappers', () => { describe('fillOrderNoThrow', () => { it('should transfer the correct amounts', async () => { - const signedOrder = orderFactory.newSignedOrder({ + const signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18), }); @@ -245,7 +247,7 @@ describe('Exchange wrappers', () => { }); it('should not change erc20Balances if maker erc20Balances are too low to fill order', async () => { - const signedOrder = orderFactory.newSignedOrder({ + const signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100000), 18), }); @@ -255,7 +257,7 @@ describe('Exchange wrappers', () => { }); it('should not change erc20Balances if taker erc20Balances are too low to fill order', async () => { - const signedOrder = orderFactory.newSignedOrder({ + const signedOrder = await orderFactory.newSignedOrderAsync({ takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100000), 18), }); @@ -265,7 +267,7 @@ describe('Exchange wrappers', () => { }); it('should not change erc20Balances if maker allowances are too low to fill order', async () => { - const signedOrder = orderFactory.newSignedOrder(); + const signedOrder = await orderFactory.newSignedOrderAsync(); await web3Wrapper.awaitTransactionSuccessAsync( await erc20TokenA.approve.sendTransactionAsync(erc20Proxy.address, new BigNumber(0), { from: makerAddress, @@ -285,7 +287,7 @@ describe('Exchange wrappers', () => { }); it('should not change erc20Balances if taker allowances are too low to fill order', async () => { - const signedOrder = orderFactory.newSignedOrder(); + const signedOrder = await orderFactory.newSignedOrderAsync(); await web3Wrapper.awaitTransactionSuccessAsync( await erc20TokenB.approve.sendTransactionAsync(erc20Proxy.address, new BigNumber(0), { from: takerAddress, @@ -306,7 +308,7 @@ describe('Exchange wrappers', () => { it('should not change erc20Balances if makerAssetAddress is ZRX, makerAssetAmount + makerFee > maker balance', async () => { const makerZRXBalance = new BigNumber(erc20Balances[makerAddress][zrxToken.address]); - const signedOrder = orderFactory.newSignedOrder({ + const signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: makerZRXBalance, makerFee: new BigNumber(1), makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), @@ -318,7 +320,7 @@ describe('Exchange wrappers', () => { it('should not change erc20Balances if makerAssetAddress is ZRX, makerAssetAmount + makerFee > maker allowance', async () => { const makerZRXAllowance = await zrxToken.allowance.callAsync(makerAddress, erc20Proxy.address); - const signedOrder = orderFactory.newSignedOrder({ + const signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(makerZRXAllowance), makerFee: new BigNumber(1), makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), @@ -330,7 +332,7 @@ describe('Exchange wrappers', () => { it('should not change erc20Balances if takerAssetAddress is ZRX, takerAssetAmount + takerFee > taker balance', async () => { const takerZRXBalance = new BigNumber(erc20Balances[takerAddress][zrxToken.address]); - const signedOrder = orderFactory.newSignedOrder({ + const signedOrder = await orderFactory.newSignedOrderAsync({ takerAssetAmount: takerZRXBalance, takerFee: new BigNumber(1), takerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), @@ -342,7 +344,7 @@ describe('Exchange wrappers', () => { it('should not change erc20Balances if takerAssetAddress is ZRX, takerAssetAmount + takerFee > taker allowance', async () => { const takerZRXAllowance = await zrxToken.allowance.callAsync(takerAddress, erc20Proxy.address); - const signedOrder = orderFactory.newSignedOrder({ + const signedOrder = await orderFactory.newSignedOrderAsync({ takerAssetAmount: new BigNumber(takerZRXAllowance), takerFee: new BigNumber(1), takerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), @@ -356,7 +358,7 @@ describe('Exchange wrappers', () => { // Construct Exchange parameters const makerAssetId = erc721MakerAssetId; const takerAssetId = erc721TakerAssetId; - const signedOrder = orderFactory.newSignedOrder({ + const signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), takerAssetAmount: new BigNumber(1), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), @@ -388,9 +390,9 @@ describe('Exchange wrappers', () => { let signedOrders: SignedOrder[]; beforeEach(async () => { signedOrders = [ - orderFactory.newSignedOrder(), - orderFactory.newSignedOrder(), - orderFactory.newSignedOrder(), + await orderFactory.newSignedOrderAsync(), + await orderFactory.newSignedOrderAsync(), + await orderFactory.newSignedOrderAsync(), ]; }); @@ -696,11 +698,11 @@ describe('Exchange wrappers', () => { it('should throw when a signedOrder does not use the same takerAssetAddress', async () => { signedOrders = [ - orderFactory.newSignedOrder(), - orderFactory.newSignedOrder({ + await orderFactory.newSignedOrderAsync(), + await orderFactory.newSignedOrderAsync({ takerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), }), - orderFactory.newSignedOrder(), + await orderFactory.newSignedOrderAsync(), ]; return expectTransactionFailedAsync( @@ -796,9 +798,9 @@ describe('Exchange wrappers', () => { it('should not fill a signedOrder that does not use the same takerAssetAddress', async () => { signedOrders = [ - orderFactory.newSignedOrder(), - orderFactory.newSignedOrder(), - orderFactory.newSignedOrder({ + await orderFactory.newSignedOrderAsync(), + await orderFactory.newSignedOrderAsync(), + await orderFactory.newSignedOrderAsync({ takerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), }), ]; @@ -914,11 +916,11 @@ describe('Exchange wrappers', () => { it('should throw when a signedOrder does not use the same makerAssetAddress', async () => { signedOrders = [ - orderFactory.newSignedOrder(), - orderFactory.newSignedOrder({ + await orderFactory.newSignedOrderAsync(), + await orderFactory.newSignedOrderAsync({ makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), }), - orderFactory.newSignedOrder(), + await orderFactory.newSignedOrderAsync(), ]; return expectTransactionFailedAsync( @@ -1012,9 +1014,9 @@ describe('Exchange wrappers', () => { it('should not fill a signedOrder that does not use the same makerAssetAddress', async () => { signedOrders = [ - orderFactory.newSignedOrder(), - orderFactory.newSignedOrder(), - orderFactory.newSignedOrder({ + await orderFactory.newSignedOrderAsync(), + await orderFactory.newSignedOrderAsync(), + await orderFactory.newSignedOrderAsync({ makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), }), ]; @@ -1069,5 +1071,189 @@ describe('Exchange wrappers', () => { expect(erc20Balances).to.be.deep.equal(newBalances); }); }); + + describe('getOrdersInfo', () => { + beforeEach(async () => { + signedOrders = [ + await orderFactory.newSignedOrderAsync(), + await orderFactory.newSignedOrderAsync(), + await orderFactory.newSignedOrderAsync(), + ]; + }); + it('should get the correct information for multiple unfilled orders', async () => { + const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders); + expect(ordersInfo.length).to.be.equal(3); + _.forEach(signedOrders, (signedOrder, index) => { + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = new BigNumber(0); + const expectedOrderStatus = OrderStatus.FILLABLE; + const orderInfo = ordersInfo[index]; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + }); + it('should get the correct information for multiple partially filled orders', async () => { + const takerAssetFillAmounts = _.map(signedOrders, signedOrder => signedOrder.takerAssetAmount.div(2)); + await exchangeWrapper.batchFillOrdersAsync(signedOrders, takerAddress, { takerAssetFillAmounts }); + const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders); + expect(ordersInfo.length).to.be.equal(3); + _.forEach(signedOrders, (signedOrder, index) => { + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = signedOrder.takerAssetAmount.div(2); + const expectedOrderStatus = OrderStatus.FILLABLE; + const orderInfo = ordersInfo[index]; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + }); + it('should get the correct information for multiple fully filled orders', async () => { + await exchangeWrapper.batchFillOrdersAsync(signedOrders, takerAddress); + const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders); + expect(ordersInfo.length).to.be.equal(3); + _.forEach(signedOrders, (signedOrder, index) => { + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = signedOrder.takerAssetAmount; + const expectedOrderStatus = OrderStatus.FULLY_FILLED; + const orderInfo = ordersInfo[index]; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + }); + it('should get the correct information for multiple cancelled and unfilled orders', async () => { + await exchangeWrapper.batchCancelOrdersAsync(signedOrders, makerAddress); + const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders); + expect(ordersInfo.length).to.be.equal(3); + _.forEach(signedOrders, (signedOrder, index) => { + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = new BigNumber(0); + const expectedOrderStatus = OrderStatus.CANCELLED; + const orderInfo = ordersInfo[index]; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + }); + it('should get the correct information for multiple cancelled and partially filled orders', async () => { + const takerAssetFillAmounts = _.map(signedOrders, signedOrder => signedOrder.takerAssetAmount.div(2)); + await exchangeWrapper.batchFillOrdersAsync(signedOrders, takerAddress, { takerAssetFillAmounts }); + await exchangeWrapper.batchCancelOrdersAsync(signedOrders, makerAddress); + const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders); + expect(ordersInfo.length).to.be.equal(3); + _.forEach(signedOrders, (signedOrder, index) => { + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = signedOrder.takerAssetAmount.div(2); + const expectedOrderStatus = OrderStatus.CANCELLED; + const orderInfo = ordersInfo[index]; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + }); + it('should get the correct information for multiple expired and unfilled orders', async () => { + const currentTimestamp = await getLatestBlockTimestampAsync(); + const timeUntilExpiration = signedOrders[0].expirationTimeSeconds.minus(currentTimestamp).toNumber(); + await increaseTimeAndMineBlockAsync(timeUntilExpiration); + const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders); + expect(ordersInfo.length).to.be.equal(3); + _.forEach(signedOrders, (signedOrder, index) => { + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = new BigNumber(0); + const expectedOrderStatus = OrderStatus.EXPIRED; + const orderInfo = ordersInfo[index]; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + }); + it('should get the correct information for multiple expired and partially filled orders', async () => { + const takerAssetFillAmounts = _.map(signedOrders, signedOrder => signedOrder.takerAssetAmount.div(2)); + await exchangeWrapper.batchFillOrdersAsync(signedOrders, takerAddress, { takerAssetFillAmounts }); + const currentTimestamp = await getLatestBlockTimestampAsync(); + const timeUntilExpiration = signedOrders[0].expirationTimeSeconds.minus(currentTimestamp).toNumber(); + await increaseTimeAndMineBlockAsync(timeUntilExpiration); + const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders); + expect(ordersInfo.length).to.be.equal(3); + _.forEach(signedOrders, (signedOrder, index) => { + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = signedOrder.takerAssetAmount.div(2); + const expectedOrderStatus = OrderStatus.EXPIRED; + const orderInfo = ordersInfo[index]; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + }); + it('should get the correct information for a mix of unfilled, partially filled, fully filled, cancelled, and expired orders', async () => { + const unfilledOrder = await orderFactory.newSignedOrderAsync(); + const partiallyFilledOrder = await orderFactory.newSignedOrderAsync(); + await exchangeWrapper.fillOrderAsync(partiallyFilledOrder, takerAddress, { + takerAssetFillAmount: partiallyFilledOrder.takerAssetAmount.div(2), + }); + const fullyFilledOrder = await orderFactory.newSignedOrderAsync(); + await exchangeWrapper.fillOrderAsync(fullyFilledOrder, takerAddress); + const cancelledOrder = await orderFactory.newSignedOrderAsync(); + await exchangeWrapper.cancelOrderAsync(cancelledOrder, makerAddress); + const currentTimestamp = await getLatestBlockTimestampAsync(); + const expiredOrder = await orderFactory.newSignedOrderAsync({ + expirationTimeSeconds: new BigNumber(currentTimestamp), + }); + signedOrders = [unfilledOrder, partiallyFilledOrder, fullyFilledOrder, cancelledOrder, expiredOrder]; + const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders); + expect(ordersInfo.length).to.be.equal(5); + + const expectedUnfilledOrderHash = orderHashUtils.getOrderHashHex(unfilledOrder); + const expectedUnfilledTakerAssetFilledAmount = new BigNumber(0); + const expectedUnfilledOrderStatus = OrderStatus.FILLABLE; + const unfilledOrderInfo = ordersInfo[0]; + expect(unfilledOrderInfo.orderHash).to.be.equal(expectedUnfilledOrderHash); + expect(unfilledOrderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal( + expectedUnfilledTakerAssetFilledAmount, + ); + expect(unfilledOrderInfo.orderStatus).to.be.equal(expectedUnfilledOrderStatus); + + const expectedPartialOrderHash = orderHashUtils.getOrderHashHex(partiallyFilledOrder); + const expectedPartialTakerAssetFilledAmount = partiallyFilledOrder.takerAssetAmount.div(2); + const expectedPartialOrderStatus = OrderStatus.FILLABLE; + const partialOrderInfo = ordersInfo[1]; + expect(partialOrderInfo.orderHash).to.be.equal(expectedPartialOrderHash); + expect(partialOrderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal( + expectedPartialTakerAssetFilledAmount, + ); + expect(partialOrderInfo.orderStatus).to.be.equal(expectedPartialOrderStatus); + + const expectedFilledOrderHash = orderHashUtils.getOrderHashHex(fullyFilledOrder); + const expectedFilledTakerAssetFilledAmount = fullyFilledOrder.takerAssetAmount; + const expectedFilledOrderStatus = OrderStatus.FULLY_FILLED; + const filledOrderInfo = ordersInfo[2]; + expect(filledOrderInfo.orderHash).to.be.equal(expectedFilledOrderHash); + expect(filledOrderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal( + expectedFilledTakerAssetFilledAmount, + ); + expect(filledOrderInfo.orderStatus).to.be.equal(expectedFilledOrderStatus); + + const expectedCancelledOrderHash = orderHashUtils.getOrderHashHex(cancelledOrder); + const expectedCancelledTakerAssetFilledAmount = new BigNumber(0); + const expectedCancelledOrderStatus = OrderStatus.CANCELLED; + const cancelledOrderInfo = ordersInfo[3]; + expect(cancelledOrderInfo.orderHash).to.be.equal(expectedCancelledOrderHash); + expect(cancelledOrderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal( + expectedCancelledTakerAssetFilledAmount, + ); + expect(cancelledOrderInfo.orderStatus).to.be.equal(expectedCancelledOrderStatus); + + const expectedExpiredOrderHash = orderHashUtils.getOrderHashHex(expiredOrder); + const expectedExpiredTakerAssetFilledAmount = new BigNumber(0); + const expectedExpiredOrderStatus = OrderStatus.EXPIRED; + const expiredOrderInfo = ordersInfo[4]; + expect(expiredOrderInfo.orderHash).to.be.equal(expectedExpiredOrderHash); + expect(expiredOrderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal( + expectedExpiredTakerAssetFilledAmount, + ); + expect(expiredOrderInfo.orderStatus).to.be.equal(expectedExpiredOrderStatus); + }); + }); }); }); // tslint:disable-line:max-file-line-count diff --git a/packages/contracts/test/forwarder/forwarder.ts b/packages/contracts/test/forwarder/forwarder.ts index f0bf6ac03..4075fccad 100644 --- a/packages/contracts/test/forwarder/forwarder.ts +++ b/packages/contracts/test/forwarder/forwarder.ts @@ -148,14 +148,14 @@ describe(ContractName.Forwarder, () => { await blockchainLifecycle.startAsync(); feeProportion = 0; erc20Balances = await erc20Wrapper.getBalancesAsync(); - signedOrder = orderFactory.newSignedOrder(); + signedOrder = await orderFactory.newSignedOrderAsync(); signedOrders = [signedOrder]; - feeOrder = orderFactory.newSignedOrder({ + feeOrder = await orderFactory.newSignedOrderAsync({ makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT), }); feeOrders = [feeOrder]; - orderWithFee = orderFactory.newSignedOrder({ + orderWithFee = await orderFactory.newSignedOrderAsync({ takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT), }); signedOrdersWithFee = [orderWithFee]; @@ -238,7 +238,7 @@ describe(ContractName.Forwarder, () => { expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(new BigNumber(0)); }); it('should fill the order when token is ZRX with fees', async () => { - orderWithFee = orderFactory.newSignedOrder({ + orderWithFee = await orderFactory.newSignedOrderAsync({ makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT), }); @@ -260,7 +260,7 @@ describe(ContractName.Forwarder, () => { expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(new BigNumber(0)); }); it('should fail if sent an ETH amount too high', async () => { - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT), }); @@ -274,11 +274,11 @@ describe(ContractName.Forwarder, () => { ); }); it('should fail if fee abstraction amount is too high', async () => { - orderWithFee = orderFactory.newSignedOrder({ + orderWithFee = await orderFactory.newSignedOrderAsync({ takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), DECIMALS_DEFAULT), }); signedOrdersWithFee = [orderWithFee]; - feeOrder = orderFactory.newSignedOrder({ + feeOrder = await orderFactory.newSignedOrderAsync({ makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT), }); @@ -294,11 +294,11 @@ describe(ContractName.Forwarder, () => { }); it('throws when mixed ERC721 and ERC20 assets with ERC20 first', async () => { const makerAssetId = erc721MakerAssetIds[0]; - const erc721SignedOrder = orderFactory.newSignedOrder({ + const erc721SignedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), }); - const erc20SignedOrder = orderFactory.newSignedOrder(); + const erc20SignedOrder = await orderFactory.newSignedOrderAsync(); signedOrders = [erc20SignedOrder, erc721SignedOrder]; const fillAmountWei = erc20SignedOrder.takerAssetAmount.plus(erc721SignedOrder.takerAssetAmount); return expectTransactionFailedAsync( @@ -418,7 +418,7 @@ describe(ContractName.Forwarder, () => { expect(takerBalanceAfter).to.be.bignumber.eq(takerBalanceBefore.plus(makerAssetAmount)); }); it('should buy the exact amount of assets when buying zrx with fee abstraction', async () => { - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT), }); @@ -447,7 +447,7 @@ describe(ContractName.Forwarder, () => { expect(takerWeiBalanceAfter).to.be.bignumber.equal(takerWeiBalanceBefore.minus(expectedCostAfterGas)); }); it('throws if fees are higher than 5% when buying zrx', async () => { - const highFeeZRXOrder = orderFactory.newSignedOrder({ + const highFeeZRXOrder = await orderFactory.newSignedOrderAsync({ makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), makerAssetAmount: signedOrder.makerAssetAmount, takerFee: signedOrder.makerAssetAmount.times(0.06), @@ -470,7 +470,7 @@ describe(ContractName.Forwarder, () => { ); }); it('throws if fees are higher than 5% when buying erc20', async () => { - const highFeeERC20Order = orderFactory.newSignedOrder({ + const highFeeERC20Order = await orderFactory.newSignedOrderAsync({ takerFee: signedOrder.makerAssetAmount.times(0.06), }); signedOrdersWithFee = [highFeeERC20Order]; @@ -544,7 +544,7 @@ describe(ContractName.Forwarder, () => { describe('marketBuyTokensWithEth - ERC721', async () => { it('buys ERC721 assets', async () => { const makerAssetId = erc721MakerAssetIds[0]; - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), }); @@ -566,7 +566,7 @@ describe(ContractName.Forwarder, () => { }); it('buys ERC721 assets with fee abstraction', async () => { const makerAssetId = erc721MakerAssetIds[0]; - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), @@ -588,7 +588,7 @@ describe(ContractName.Forwarder, () => { }); it('buys ERC721 assets with fee abstraction and pays fee to fee recipient', async () => { const makerAssetId = erc721MakerAssetIds[0]; - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), @@ -630,12 +630,12 @@ describe(ContractName.Forwarder, () => { it('buys multiple ERC721 assets with fee abstraction and pays fee to fee recipient', async () => { const makerAssetId1 = erc721MakerAssetIds[0]; const makerAssetId2 = erc721MakerAssetIds[1]; - const signedOrder1 = orderFactory.newSignedOrder({ + const signedOrder1 = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(3), DECIMALS_DEFAULT), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId1), }); - const signedOrder2 = orderFactory.newSignedOrder({ + const signedOrder2 = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(4), DECIMALS_DEFAULT), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId2), @@ -665,20 +665,20 @@ describe(ContractName.Forwarder, () => { // There are two fee orders, but the first fee order is partially filled while // the Forwarding contract tx is in the mempool. const erc721MakerAssetAmount = new BigNumber(1); - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: erc721MakerAssetAmount, takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), DECIMALS_DEFAULT), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(6), DECIMALS_DEFAULT), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), }); signedOrders = [signedOrder]; - const firstFeeOrder = orderFactory.newSignedOrder({ + const firstFeeOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(8), DECIMALS_DEFAULT), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(0.1), DECIMALS_DEFAULT), makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), DECIMALS_DEFAULT), }); - const secondFeeOrder = orderFactory.newSignedOrder({ + const secondFeeOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(8), DECIMALS_DEFAULT), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(0.12), DECIMALS_DEFAULT), makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), @@ -729,7 +729,7 @@ describe(ContractName.Forwarder, () => { // There are two fee orders, but the first fee order is partially filled while // the Forwarding contract tx is in the mempool. const erc721MakerAssetAmount = new BigNumber(1); - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: erc721MakerAssetAmount, takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), DECIMALS_DEFAULT), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(6), DECIMALS_DEFAULT), @@ -737,13 +737,13 @@ describe(ContractName.Forwarder, () => { }); const zrxMakerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(8), DECIMALS_DEFAULT); signedOrders = [signedOrder]; - const firstFeeOrder = orderFactory.newSignedOrder({ + const firstFeeOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: zrxMakerAssetAmount, takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(0.1), DECIMALS_DEFAULT), makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), DECIMALS_DEFAULT), }); - const secondFeeOrder = orderFactory.newSignedOrder({ + const secondFeeOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: zrxMakerAssetAmount, takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(0.12), DECIMALS_DEFAULT), makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), @@ -778,11 +778,11 @@ describe(ContractName.Forwarder, () => { }); it('throws when mixed ERC721 and ERC20 assets', async () => { const makerAssetId = erc721MakerAssetIds[0]; - const erc721SignedOrder = orderFactory.newSignedOrder({ + const erc721SignedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), }); - const erc20SignedOrder = orderFactory.newSignedOrder(); + const erc20SignedOrder = await orderFactory.newSignedOrderAsync(); signedOrders = [erc721SignedOrder, erc20SignedOrder]; const makerAssetAmount = new BigNumber(signedOrders.length); const fillAmountWei = erc20SignedOrder.takerAssetAmount.plus(erc721SignedOrder.takerAssetAmount); @@ -796,11 +796,11 @@ describe(ContractName.Forwarder, () => { }); it('throws when mixed ERC721 and ERC20 assets with ERC20 first', async () => { const makerAssetId = erc721MakerAssetIds[0]; - const erc721SignedOrder = orderFactory.newSignedOrder({ + const erc721SignedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), }); - const erc20SignedOrder = orderFactory.newSignedOrder(); + const erc20SignedOrder = await orderFactory.newSignedOrderAsync(); signedOrders = [erc20SignedOrder, erc721SignedOrder]; const makerAssetAmount = new BigNumber(signedOrders.length); const fillAmountWei = erc20SignedOrder.takerAssetAmount.plus(erc721SignedOrder.takerAssetAmount); diff --git a/packages/contracts/test/multisig/asset_proxy_owner.ts b/packages/contracts/test/multisig/asset_proxy_owner.ts index 6a9843153..6b98605d3 100644 --- a/packages/contracts/test/multisig/asset_proxy_owner.ts +++ b/packages/contracts/test/multisig/asset_proxy_owner.ts @@ -18,9 +18,9 @@ import { expectContractCreationFailedWithoutReason, expectTransactionFailedWithoutReasonAsync, } from '../utils/assertions'; +import { increaseTimeAndMineBlockAsync } from '../utils/block_timestamp'; import { chaiSetup } from '../utils/chai_setup'; import { constants } from '../utils/constants'; -import { increaseTimeAndMineBlockAsync } from '../utils/increase_time'; import { MultiSigWrapper } from '../utils/multi_sig_wrapper'; import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; diff --git a/packages/contracts/test/multisig/multi_sig_with_time_lock.ts b/packages/contracts/test/multisig/multi_sig_with_time_lock.ts index a8e9243a9..8eeeeca6b 100644 --- a/packages/contracts/test/multisig/multi_sig_with_time_lock.ts +++ b/packages/contracts/test/multisig/multi_sig_with_time_lock.ts @@ -9,9 +9,9 @@ import { } from '../../generated_contract_wrappers/multi_sig_wallet_with_time_lock'; import { artifacts } from '../utils/artifacts'; import { expectTransactionFailedWithoutReasonAsync } from '../utils/assertions'; +import { increaseTimeAndMineBlockAsync } from '../utils/block_timestamp'; import { chaiSetup } from '../utils/chai_setup'; import { constants } from '../utils/constants'; -import { increaseTimeAndMineBlockAsync } from '../utils/increase_time'; import { MultiSigWrapper } from '../utils/multi_sig_wrapper'; import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; diff --git a/packages/contracts/test/utils/asset_wrapper.ts b/packages/contracts/test/utils/asset_wrapper.ts index f291170a2..3e548d186 100644 --- a/packages/contracts/test/utils/asset_wrapper.ts +++ b/packages/contracts/test/utils/asset_wrapper.ts @@ -17,7 +17,7 @@ interface ProxyIdToAssetWrappers { * the logic that uses it does not need to care what standard a token belongs to. */ export class AssetWrapper { - private _proxyIdToAssetWrappers: ProxyIdToAssetWrappers; + private readonly _proxyIdToAssetWrappers: ProxyIdToAssetWrappers; constructor(assetWrappers: AbstractAssetWrapper[]) { this._proxyIdToAssetWrappers = {}; _.each(assetWrappers, assetWrapper => { diff --git a/packages/contracts/test/utils/increase_time.ts b/packages/contracts/test/utils/block_timestamp.ts index 4565d8dbc..1159792c4 100644 --- a/packages/contracts/test/utils/increase_time.ts +++ b/packages/contracts/test/utils/block_timestamp.ts @@ -29,3 +29,12 @@ export async function increaseTimeAndMineBlockAsync(seconds: number): Promise<nu return offset; } + +/** + * Returns the timestamp of the latest block in seconds since the Unix epoch. + * @returns a new Promise which will resolve with the timestamp in seconds. + */ +export async function getLatestBlockTimestampAsync(): Promise<number> { + const currentBlock = await web3Wrapper.getBlockAsync('latest'); + return currentBlock.timestamp; +} diff --git a/packages/contracts/test/utils/erc20_wrapper.ts b/packages/contracts/test/utils/erc20_wrapper.ts index cf1433791..e1863be36 100644 --- a/packages/contracts/test/utils/erc20_wrapper.ts +++ b/packages/contracts/test/utils/erc20_wrapper.ts @@ -13,11 +13,11 @@ import { ERC20BalancesByOwner } from './types'; import { txDefaults } from './web3_wrapper'; export class ERC20Wrapper { - private _tokenOwnerAddresses: string[]; - private _contractOwnerAddress: string; - private _web3Wrapper: Web3Wrapper; - private _provider: Provider; - private _dummyTokenContracts: DummyERC20TokenContract[]; + private readonly _tokenOwnerAddresses: string[]; + private readonly _contractOwnerAddress: string; + private readonly _web3Wrapper: Web3Wrapper; + private readonly _provider: Provider; + private readonly _dummyTokenContracts: DummyERC20TokenContract[]; private _proxyContract?: ERC20ProxyContract; private _proxyIdIfExists?: string; constructor(provider: Provider, tokenOwnerAddresses: string[], contractOwnerAddress: string) { diff --git a/packages/contracts/test/utils/erc721_wrapper.ts b/packages/contracts/test/utils/erc721_wrapper.ts index a38dfb811..d023b4d02 100644 --- a/packages/contracts/test/utils/erc721_wrapper.ts +++ b/packages/contracts/test/utils/erc721_wrapper.ts @@ -13,11 +13,11 @@ import { ERC721TokenIdsByOwner } from './types'; import { txDefaults } from './web3_wrapper'; export class ERC721Wrapper { - private _tokenOwnerAddresses: string[]; - private _contractOwnerAddress: string; - private _web3Wrapper: Web3Wrapper; - private _provider: Provider; - private _dummyTokenContracts: DummyERC721TokenContract[]; + private readonly _tokenOwnerAddresses: string[]; + private readonly _contractOwnerAddress: string; + private readonly _web3Wrapper: Web3Wrapper; + private readonly _provider: Provider; + private readonly _dummyTokenContracts: DummyERC721TokenContract[]; private _proxyContract?: ERC721ProxyContract; private _proxyIdIfExists?: string; private _initialTokenIdsByOwner: ERC721TokenIdsByOwner = {}; diff --git a/packages/contracts/test/utils/exchange_wrapper.ts b/packages/contracts/test/utils/exchange_wrapper.ts index 155d0eeb0..490ea959b 100644 --- a/packages/contracts/test/utils/exchange_wrapper.ts +++ b/packages/contracts/test/utils/exchange_wrapper.ts @@ -11,9 +11,9 @@ import { orderUtils } from './order_utils'; import { OrderInfo, SignedTransaction } from './types'; export class ExchangeWrapper { - private _exchange: ExchangeContract; - private _web3Wrapper: Web3Wrapper; - private _logDecoder: LogDecoder; + private readonly _exchange: ExchangeContract; + private readonly _web3Wrapper: Web3Wrapper; + private readonly _logDecoder: LogDecoder; constructor(exchangeContract: ExchangeContract, provider: Provider) { this._exchange = exchangeContract; this._web3Wrapper = new Web3Wrapper(provider); @@ -223,6 +223,10 @@ export class ExchangeWrapper { const orderInfo = (await this._exchange.getOrderInfo.callAsync(signedOrder)) as OrderInfo; return orderInfo; } + public async getOrdersInfoAsync(signedOrders: SignedOrder[]): Promise<OrderInfo[]> { + const ordersInfo = (await this._exchange.getOrdersInfo.callAsync(signedOrders)) as OrderInfo[]; + return ordersInfo; + } public async matchOrdersAsync( signedOrderLeft: SignedOrder, signedOrderRight: SignedOrder, diff --git a/packages/contracts/test/utils/forwarder_wrapper.ts b/packages/contracts/test/utils/forwarder_wrapper.ts index d227420ee..0d4214402 100644 --- a/packages/contracts/test/utils/forwarder_wrapper.ts +++ b/packages/contracts/test/utils/forwarder_wrapper.ts @@ -18,10 +18,10 @@ const ZERO_AMOUNT = new BigNumber(0); const INSUFFICENT_ORDERS_FOR_MAKER_AMOUNT = 'Unable to satisfy makerAssetFillAmount with provided orders'; export class ForwarderWrapper { - private _web3Wrapper: Web3Wrapper; - private _forwarderContract: ForwarderContract; - private _logDecoder: LogDecoder; - private _zrxAddress: string; + private readonly _web3Wrapper: Web3Wrapper; + private readonly _forwarderContract: ForwarderContract; + private readonly _logDecoder: LogDecoder; + private readonly _zrxAddress: string; private static _createOptimizedSellOrders(signedOrders: SignedOrder[]): MarketSellOrders { const marketSellOrders = formatters.createMarketSellOrders(signedOrders, ZERO_AMOUNT); const assetDataId = assetProxyUtils.decodeAssetDataId(signedOrders[0].makerAssetData); diff --git a/packages/contracts/test/utils/log_decoder.ts b/packages/contracts/test/utils/log_decoder.ts index 07127ba79..5a4801319 100644 --- a/packages/contracts/test/utils/log_decoder.ts +++ b/packages/contracts/test/utils/log_decoder.ts @@ -15,9 +15,9 @@ import { artifacts } from './artifacts'; import { constants } from './constants'; export class LogDecoder { - private _web3Wrapper: Web3Wrapper; - private _contractAddress: string; - private _abiDecoder: AbiDecoder; + private readonly _web3Wrapper: Web3Wrapper; + private readonly _contractAddress: string; + private readonly _abiDecoder: AbiDecoder; public static wrapLogBigNumbers(log: any): any { const argNames = _.keys(log.args); for (const argName of argNames) { diff --git a/packages/contracts/test/utils/match_order_tester.ts b/packages/contracts/test/utils/match_order_tester.ts index 6145779b0..0d5ad5e9f 100644 --- a/packages/contracts/test/utils/match_order_tester.ts +++ b/packages/contracts/test/utils/match_order_tester.ts @@ -14,10 +14,10 @@ chaiSetup.configure(); const expect = chai.expect; export class MatchOrderTester { - private _exchangeWrapper: ExchangeWrapper; - private _erc20Wrapper: ERC20Wrapper; - private _erc721Wrapper: ERC721Wrapper; - private _feeTokenAddress: string; + private readonly _exchangeWrapper: ExchangeWrapper; + private readonly _erc20Wrapper: ERC20Wrapper; + private readonly _erc721Wrapper: ERC721Wrapper; + private readonly _feeTokenAddress: string; /// @dev Compares a pair of ERC20 balances and a pair of ERC721 token owners. /// @param expectedNewERC20BalancesByOwner Expected ERC20 balances. diff --git a/packages/contracts/test/utils/multi_sig_wrapper.ts b/packages/contracts/test/utils/multi_sig_wrapper.ts index 2024c177d..8c8055d4a 100644 --- a/packages/contracts/test/utils/multi_sig_wrapper.ts +++ b/packages/contracts/test/utils/multi_sig_wrapper.ts @@ -10,9 +10,9 @@ import { constants } from './constants'; import { LogDecoder } from './log_decoder'; export class MultiSigWrapper { - private _multiSig: MultiSigWalletContract; - private _web3Wrapper: Web3Wrapper; - private _logDecoder: LogDecoder; + private readonly _multiSig: MultiSigWalletContract; + private readonly _web3Wrapper: Web3Wrapper; + private readonly _logDecoder: LogDecoder; constructor(multiSigContract: MultiSigWalletContract, provider: Provider) { this._multiSig = multiSigContract; this._web3Wrapper = new Web3Wrapper(provider); diff --git a/packages/contracts/test/utils/order_factory.ts b/packages/contracts/test/utils/order_factory.ts index 009dbc396..63a893695 100644 --- a/packages/contracts/test/utils/order_factory.ts +++ b/packages/contracts/test/utils/order_factory.ts @@ -2,25 +2,26 @@ import { generatePseudoRandomSalt, orderHashUtils } from '@0xproject/order-utils import { Order, SignatureType, SignedOrder } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; +import { getLatestBlockTimestampAsync } from './block_timestamp'; import { constants } from './constants'; import { signingUtils } from './signing_utils'; export class OrderFactory { - private _defaultOrderParams: Partial<Order>; - private _privateKey: Buffer; + private readonly _defaultOrderParams: Partial<Order>; + private readonly _privateKey: Buffer; constructor(privateKey: Buffer, defaultOrderParams: Partial<Order>) { this._defaultOrderParams = defaultOrderParams; this._privateKey = privateKey; } - public newSignedOrder( + public async newSignedOrderAsync( customOrderParams: Partial<Order> = {}, signatureType: SignatureType = SignatureType.EthSign, - ): SignedOrder { - const tenMinutes = 10 * 60 * 1000; - const randomExpiration = new BigNumber(Date.now() + tenMinutes); + ): Promise<SignedOrder> { + const tenMinutesInSeconds = 10 * 60; + const currentBlockTimestamp = await getLatestBlockTimestampAsync(); const order = ({ senderAddress: constants.NULL_ADDRESS, - expirationTimeSeconds: randomExpiration, + expirationTimeSeconds: new BigNumber(currentBlockTimestamp).add(tenMinutesInSeconds), salt: generatePseudoRandomSalt(), takerAddress: constants.NULL_ADDRESS, ...this._defaultOrderParams, diff --git a/packages/contracts/test/utils/order_factory_from_scenario.ts b/packages/contracts/test/utils/order_factory_from_scenario.ts index 526505871..e0edbff26 100644 --- a/packages/contracts/test/utils/order_factory_from_scenario.ts +++ b/packages/contracts/test/utils/order_factory_from_scenario.ts @@ -24,13 +24,13 @@ const FIVE_UNITS_FIVE_DECIMALS = new BigNumber(500_000); const ONE_NFT_UNIT = new BigNumber(1); export class OrderFactoryFromScenario { - private _userAddresses: string[]; - private _zrxAddress: string; - private _nonZrxERC20EighteenDecimalTokenAddresses: string[]; - private _erc20FiveDecimalTokenAddresses: string[]; - private _erc721Token: DummyERC721TokenContract; - private _erc721Balances: ERC721TokenIdsByOwner; - private _exchangeAddress: string; + private readonly _userAddresses: string[]; + private readonly _zrxAddress: string; + private readonly _nonZrxERC20EighteenDecimalTokenAddresses: string[]; + private readonly _erc20FiveDecimalTokenAddresses: string[]; + private readonly _erc721Token: DummyERC721TokenContract; + private readonly _erc721Balances: ERC721TokenIdsByOwner; + private readonly _exchangeAddress: string; constructor( userAddresses: string[], zrxAddress: string, diff --git a/packages/contracts/test/utils/simple_asset_balance_and_proxy_allowance_fetcher.ts b/packages/contracts/test/utils/simple_asset_balance_and_proxy_allowance_fetcher.ts index a295a40c4..598ee6d29 100644 --- a/packages/contracts/test/utils/simple_asset_balance_and_proxy_allowance_fetcher.ts +++ b/packages/contracts/test/utils/simple_asset_balance_and_proxy_allowance_fetcher.ts @@ -4,7 +4,7 @@ import { BigNumber } from '@0xproject/utils'; import { AssetWrapper } from './asset_wrapper'; export class SimpleAssetBalanceAndProxyAllowanceFetcher implements AbstractBalanceAndProxyAllowanceFetcher { - private _assetWrapper: AssetWrapper; + private readonly _assetWrapper: AssetWrapper; constructor(assetWrapper: AssetWrapper) { this._assetWrapper = assetWrapper; } diff --git a/packages/contracts/test/utils/simple_order_filled_cancelled_fetcher.ts b/packages/contracts/test/utils/simple_order_filled_cancelled_fetcher.ts index 24afe36b7..ed69ecc63 100644 --- a/packages/contracts/test/utils/simple_order_filled_cancelled_fetcher.ts +++ b/packages/contracts/test/utils/simple_order_filled_cancelled_fetcher.ts @@ -4,8 +4,8 @@ import { BigNumber } from '@0xproject/utils'; import { ExchangeWrapper } from './exchange_wrapper'; export class SimpleOrderFilledCancelledFetcher implements AbstractOrderFilledCancelledFetcher { - private _exchangeWrapper: ExchangeWrapper; - private _zrxAssetData: string; + private readonly _exchangeWrapper: ExchangeWrapper; + private readonly _zrxAssetData: string; constructor(exchange: ExchangeWrapper, zrxAssetData: string) { this._exchangeWrapper = exchange; this._zrxAssetData = zrxAssetData; diff --git a/packages/contracts/test/utils/token_registry_wrapper.ts b/packages/contracts/test/utils/token_registry_wrapper.ts index 0abf20e03..f1c40e8ff 100644 --- a/packages/contracts/test/utils/token_registry_wrapper.ts +++ b/packages/contracts/test/utils/token_registry_wrapper.ts @@ -8,8 +8,8 @@ import { Token } from './types'; import { constants } from './constants'; export class TokenRegWrapper { - private _tokenReg: TokenRegistryContract; - private _web3Wrapper: Web3Wrapper; + private readonly _tokenReg: TokenRegistryContract; + private readonly _web3Wrapper: Web3Wrapper; constructor(tokenRegContract: TokenRegistryContract, provider: Provider) { this._tokenReg = tokenRegContract; this._web3Wrapper = new Web3Wrapper(provider); diff --git a/packages/contracts/test/utils/transaction_factory.ts b/packages/contracts/test/utils/transaction_factory.ts index 348c0715d..281c1e30d 100644 --- a/packages/contracts/test/utils/transaction_factory.ts +++ b/packages/contracts/test/utils/transaction_factory.ts @@ -15,9 +15,9 @@ const EIP712_ZEROEX_TRANSACTION_SCHEMA: EIP712Schema = { }; export class TransactionFactory { - private _signerBuff: Buffer; - private _exchangeAddress: string; - private _privateKey: Buffer; + private readonly _signerBuff: Buffer; + private readonly _exchangeAddress: string; + private readonly _privateKey: Buffer; constructor(privateKey: Buffer, exchangeAddress: string) { this._privateKey = privateKey; this._exchangeAddress = exchangeAddress; diff --git a/packages/contracts/test/utils/web3_wrapper.ts b/packages/contracts/test/utils/web3_wrapper.ts index c9d83a02d..acb3103b7 100644 --- a/packages/contracts/test/utils/web3_wrapper.ts +++ b/packages/contracts/test/utils/web3_wrapper.ts @@ -51,8 +51,10 @@ export const provider = web3Factory.getRpcProvider(providerConfigs); const isCoverageEnabled = env.parseBoolean(EnvVars.SolidityCoverage); const isProfilerEnabled = env.parseBoolean(EnvVars.SolidityProfiler); const isRevertTraceEnabled = env.parseBoolean(EnvVars.SolidityRevertTrace); -const enabledSubproviderCount = _.filter([isCoverageEnabled, isProfilerEnabled, isRevertTraceEnabled], _.identity) - .length; +const enabledSubproviderCount = _.filter( + [isCoverageEnabled, isProfilerEnabled, isRevertTraceEnabled], + _.identity.bind(_), +).length; if (enabledSubproviderCount > 1) { throw new Error(`Only one of coverage, profiler, or revert trace subproviders can be enabled at a time`); } diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index d62533c16..82e8c73b9 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -41,7 +41,7 @@ "npm-run-all": "^4.1.2", "nyc": "^11.0.1", "shx": "^0.2.2", - "tslint": "5.10.0", + "tslint": "5.11.0", "typescript": "2.7.1" }, "dependencies": { diff --git a/packages/dev-utils/src/blockchain_lifecycle.ts b/packages/dev-utils/src/blockchain_lifecycle.ts index 9bd65ee5d..a48cb0856 100644 --- a/packages/dev-utils/src/blockchain_lifecycle.ts +++ b/packages/dev-utils/src/blockchain_lifecycle.ts @@ -10,8 +10,8 @@ import * as _ from 'lodash'; const MINIMUM_BLOCKS = 3; export class BlockchainLifecycle { - private _web3Wrapper: Web3Wrapper; - private _snapshotIdsStack: number[]; + private readonly _web3Wrapper: Web3Wrapper; + private readonly _snapshotIdsStack: number[]; private _addresses: string[] = []; private _nodeType: NodeType | undefined; constructor(web3Wrapper: Web3Wrapper) { @@ -34,6 +34,12 @@ export class BlockchainLifecycle { blockNumber = await this._web3Wrapper.getBlockNumberAsync(); } this._snapshotIdsStack.push(blockNumber); + // HACK(albrow) It's possible that we applied a time offset but + // the transaction we mined to put that time offset into the + // blockchain was reverted. As a workaround, we mine a new dummy + // block so that the latest block timestamp accounts for any + // possible time offsets. + await this._mineDummyBlockAsync(); break; default: throw new Error(`Unknown node type: ${nodeType}`); @@ -59,22 +65,9 @@ export class BlockchainLifecycle { } private async _mineMinimumBlocksAsync(): Promise<void> { logUtils.warn('WARNING: minimum block number for tests not met. Mining additional blocks...'); - if (this._addresses.length === 0) { - this._addresses = await this._web3Wrapper.getAvailableAddressesAsync(); - if (this._addresses.length === 0) { - throw new Error('No accounts found'); - } - } while ((await this._web3Wrapper.getBlockNumberAsync()) < MINIMUM_BLOCKS) { logUtils.warn('Mining block...'); - await this._web3Wrapper.awaitTransactionMinedAsync( - await this._web3Wrapper.sendTransactionAsync({ - from: this._addresses[0], - to: this._addresses[0], - value: '0', - }), - 0, - ); + await this._mineDummyBlockAsync(); } logUtils.warn('Done mining the minimum number of blocks.'); } @@ -84,4 +77,22 @@ export class BlockchainLifecycle { } return this._nodeType; } + // Sends a transaction that has no real effect on the state and waits for it + // to be mined. + private async _mineDummyBlockAsync(): Promise<void> { + if (this._addresses.length === 0) { + this._addresses = await this._web3Wrapper.getAvailableAddressesAsync(); + if (this._addresses.length === 0) { + throw new Error('No accounts found'); + } + } + await this._web3Wrapper.awaitTransactionMinedAsync( + await this._web3Wrapper.sendTransactionAsync({ + from: this._addresses[0], + to: this._addresses[0], + value: '0', + }), + 0, + ); + } } diff --git a/packages/ethereum-types/package.json b/packages/ethereum-types/package.json index f6f788659..e8652383d 100644 --- a/packages/ethereum-types/package.json +++ b/packages/ethereum-types/package.json @@ -40,7 +40,7 @@ "copyfiles": "^1.2.0", "make-promises-safe": "^1.1.0", "shx": "^0.2.2", - "tslint": "5.10.0", + "tslint": "5.11.0", "typescript": "2.7.1" }, "dependencies": { diff --git a/packages/fill-scenarios/package.json b/packages/fill-scenarios/package.json index 12a342415..63ae9d4ad 100644 --- a/packages/fill-scenarios/package.json +++ b/packages/fill-scenarios/package.json @@ -37,7 +37,7 @@ "make-promises-safe": "^1.1.0", "npm-run-all": "^4.1.2", "shx": "^0.2.2", - "tslint": "5.10.0", + "tslint": "5.11.0", "typescript": "2.7.1" }, "dependencies": { diff --git a/packages/fill-scenarios/src/index.ts b/packages/fill-scenarios/src/index.ts index f9b69e1f3..3ffcb3aa9 100644 --- a/packages/fill-scenarios/src/index.ts +++ b/packages/fill-scenarios/src/index.ts @@ -11,12 +11,12 @@ import { ERC20TokenContract } from './generated_contract_wrappers/erc20_token'; import { ExchangeContract } from './generated_contract_wrappers/exchange'; export class FillScenarios { - private _web3Wrapper: Web3Wrapper; - private _userAddresses: string[]; - private _coinbase: string; - private _zrxTokenAddress: string; - private _exchangeAddress: string; - private _erc20ProxyAddress: string; + private readonly _web3Wrapper: Web3Wrapper; + private readonly _userAddresses: string[]; + private readonly _coinbase: string; + private readonly _zrxTokenAddress: string; + private readonly _exchangeAddress: string; + private readonly _erc20ProxyAddress: string; constructor( provider: Provider, userAddresses: string[], diff --git a/packages/json-schemas/package.json b/packages/json-schemas/package.json index cb29242da..e15faeeb5 100644 --- a/packages/json-schemas/package.json +++ b/packages/json-schemas/package.json @@ -68,7 +68,7 @@ "npm-run-all": "^4.1.2", "nyc": "^11.0.1", "shx": "^0.2.2", - "tslint": "5.10.0", + "tslint": "5.11.0", "typedoc": "0xProject/typedoc", "typescript": "2.7.1" }, diff --git a/packages/json-schemas/src/schema_validator.ts b/packages/json-schemas/src/schema_validator.ts index f0392d1d1..3f303137b 100644 --- a/packages/json-schemas/src/schema_validator.ts +++ b/packages/json-schemas/src/schema_validator.ts @@ -7,7 +7,7 @@ import { schemas } from './schemas'; * A validator for [JSON-schemas](http://json-schema.org/) */ export class SchemaValidator { - private _validator: Validator; + private readonly _validator: Validator; /** * Instantiates a SchemaValidator instance */ diff --git a/packages/metacoin/package.json b/packages/metacoin/package.json index 05d509a22..3f85bf4b7 100644 --- a/packages/metacoin/package.json +++ b/packages/metacoin/package.json @@ -55,7 +55,7 @@ "make-promises-safe": "^1.1.0", "npm-run-all": "^4.1.2", "shx": "^0.2.2", - "tslint": "5.10.0", + "tslint": "5.11.0", "typescript": "2.7.1" } } diff --git a/packages/migrations/package.json b/packages/migrations/package.json index 2859bf286..e8b749cda 100644 --- a/packages/migrations/package.json +++ b/packages/migrations/package.json @@ -46,7 +46,7 @@ "make-promises-safe": "^1.1.0", "npm-run-all": "^4.1.2", "shx": "^0.2.2", - "tslint": "5.10.0", + "tslint": "5.11.0", "typescript": "2.7.1" }, "dependencies": { diff --git a/packages/migrations/src/utils/artifact_writer.ts b/packages/migrations/src/utils/artifact_writer.ts index 2da5a09dd..b7522df05 100644 --- a/packages/migrations/src/utils/artifact_writer.ts +++ b/packages/migrations/src/utils/artifact_writer.ts @@ -4,8 +4,8 @@ import * as fs from 'fs'; import * as path from 'path'; export class ArtifactWriter { - private _artifactsDir: string; - private _networkId: number; + private readonly _artifactsDir: string; + private readonly _networkId: number; constructor(artifactsDir: string, networkId: number) { this._artifactsDir = artifactsDir; this._networkId = networkId; diff --git a/packages/monorepo-scripts/package.json b/packages/monorepo-scripts/package.json index 73c6e9c5f..f3a6aa793 100644 --- a/packages/monorepo-scripts/package.json +++ b/packages/monorepo-scripts/package.json @@ -39,7 +39,7 @@ "npm-run-all": "^4.1.2", "shx": "^0.2.2", "@types/semver": "5.5.0", - "tslint": "5.10.0", + "tslint": "5.11.0", "typescript": "2.7.1" }, "dependencies": { diff --git a/packages/monorepo-scripts/src/postpublish_utils.ts b/packages/monorepo-scripts/src/postpublish_utils.ts index b55a88539..85b32ed83 100644 --- a/packages/monorepo-scripts/src/postpublish_utils.ts +++ b/packages/monorepo-scripts/src/postpublish_utils.ts @@ -51,8 +51,13 @@ export const postpublishUtils = { return configs; }, async runAsync(packageJSON: any, tsConfigJSON: any, cwd: string): Promise<void> { - const configs = this.generateConfig(packageJSON, tsConfigJSON, cwd); - await this.publishReleaseNotesAsync(configs.cwd, configs.packageName, configs.version, configs.assets); + const configs = postpublishUtils.generateConfig(packageJSON, tsConfigJSON, cwd); + await postpublishUtils.publishReleaseNotesAsync( + configs.cwd, + configs.packageName, + configs.version, + configs.assets, + ); if ( !_.isUndefined(configs.docPublishConfigs.s3BucketPath) || !_.isUndefined(configs.docPublishConfigs.s3StagingBucketPath) @@ -69,7 +74,7 @@ export const postpublishUtils = { } }, async publishDocsToStagingAsync(packageJSON: any, tsConfigJSON: any, cwd: string): Promise<void> { - const configs = this.generateConfig(packageJSON, tsConfigJSON, cwd); + const configs = postpublishUtils.generateConfig(packageJSON, tsConfigJSON, cwd); if (_.isUndefined(configs.docPublishConfigs.s3StagingBucketPath)) { utils.log('config.postpublish.docPublishConfigs.s3StagingBucketPath entry in package.json not found!'); return; @@ -84,10 +89,10 @@ export const postpublishUtils = { ); }, async publishReleaseNotesAsync(cwd: string, packageName: string, version: string, assets: string[]): Promise<void> { - const notes = this.getReleaseNotes(packageName, version); - const releaseName = this.getReleaseName(packageName, version); - const tag = this.getTag(packageName, version); - this.adjustAssetPaths(cwd, assets); + const notes = postpublishUtils.getReleaseNotes(packageName, version); + const releaseName = postpublishUtils.getReleaseName(packageName, version); + const tag = postpublishUtils.getTag(packageName, version); + postpublishUtils.adjustAssetPaths(cwd, assets); utils.log('POSTPUBLISH: Releasing ', releaseName, '...'); await publishReleaseAsync({ token: constants.githubPersonalAccessToken, @@ -165,7 +170,7 @@ export const postpublishUtils = { version: string, S3BucketPath: string, ): Promise<void> { - const fileIncludesAdjusted = this.adjustFileIncludePaths(fileIncludes, cwd); + const fileIncludesAdjusted = postpublishUtils.adjustFileIncludePaths(fileIncludes, cwd); const projectFiles = fileIncludesAdjusted.join(' '); const jsonFilePath = `${cwd}/${generatedDocsDirectoryName}/index.json`; const result = await execAsync( diff --git a/packages/monorepo-scripts/src/utils/changelog_utils.ts b/packages/monorepo-scripts/src/utils/changelog_utils.ts index dbafb6f16..4781b3b7d 100644 --- a/packages/monorepo-scripts/src/utils/changelog_utils.ts +++ b/packages/monorepo-scripts/src/utils/changelog_utils.ts @@ -10,7 +10,7 @@ import { Change, Changelog, VersionChangelog } from '../types'; const CHANGELOG_MD_HEADER = ` <!-- -This file is auto-generated using the monorepo-scripts package. Don't edit directly. +changelogUtils.file is auto-generated using the monorepo-scripts package. Don't edit directly. Edit the package's CHANGELOG.json file only. --> @@ -74,7 +74,7 @@ export const changelogUtils = { }, getChangelogOrCreateIfMissing(packageName: string, packageLocation: string): Changelog { const changelogJSONPath = path.join(packageLocation, 'CHANGELOG.json'); - let changelogJsonIfExists = this.getChangelogJSONIfExists(changelogJSONPath); + let changelogJsonIfExists = changelogUtils.getChangelogJSONIfExists(changelogJSONPath); if (_.isUndefined(changelogJsonIfExists)) { // If none exists, create new, empty one. changelogJsonIfExists = '[]'; @@ -91,12 +91,12 @@ export const changelogUtils = { async writeChangelogJsonFileAsync(packageLocation: string, changelog: Changelog): Promise<void> { const changelogJSONPath = path.join(packageLocation, 'CHANGELOG.json'); fs.writeFileSync(changelogJSONPath, JSON.stringify(changelog, null, '\t')); - await this.prettifyAsync(changelogJSONPath, constants.monorepoRootPath); + await changelogUtils.prettifyAsync(changelogJSONPath, constants.monorepoRootPath); }, async writeChangelogMdFileAsync(packageLocation: string, changelogMdString: string): Promise<void> { const changelogMarkdownPath = path.join(packageLocation, 'CHANGELOG.md'); fs.writeFileSync(changelogMarkdownPath, changelogMdString); - await this.prettifyAsync(changelogMarkdownPath, constants.monorepoRootPath); + await changelogUtils.prettifyAsync(changelogMarkdownPath, constants.monorepoRootPath); }, async prettifyAsync(filePath: string, cwd: string): Promise<void> { await execAsync(`prettier --write ${filePath} --config .prettierrc`, { diff --git a/packages/monorepo-scripts/src/utils/utils.ts b/packages/monorepo-scripts/src/utils/utils.ts index f819ab6f1..be3ad950f 100644 --- a/packages/monorepo-scripts/src/utils/utils.ts +++ b/packages/monorepo-scripts/src/utils/utils.ts @@ -13,7 +13,7 @@ export const utils = { console.log(...args); // tslint:disable-line:no-console }, async getUpdatedLernaPackagesAsync(shouldIncludePrivate: boolean): Promise<LernaPackage[]> { - const updatedPublicPackages = await this.getLernaUpdatedPackagesAsync(shouldIncludePrivate); + const updatedPublicPackages = await utils.getLernaUpdatedPackagesAsync(shouldIncludePrivate); const updatedPackageNames = _.map(updatedPublicPackages, pkg => pkg.name); const allLernaPackages = lernaGetPackages(constants.monorepoRootPath); @@ -110,7 +110,7 @@ export const utils = { } catch (err) { throw new Error(`Failed to delete local git tag. Got err: ${err}`); } - this.log(`Removed local tag: ${tagName}`); + utils.log(`Removed local tag: ${tagName}`); }, async removeRemoteTagAsync(tagName: string): Promise<void> { try { @@ -120,6 +120,6 @@ export const utils = { } catch (err) { throw new Error(`Failed to delete remote git tag. Got err: ${err}`); } - this.log(`Removed remote tag: ${tagName}`); + utils.log(`Removed remote tag: ${tagName}`); }, }; diff --git a/packages/order-utils/package.json b/packages/order-utils/package.json index 20f050cb4..a8205f848 100644 --- a/packages/order-utils/package.json +++ b/packages/order-utils/package.json @@ -67,7 +67,7 @@ "npm-run-all": "^4.1.2", "shx": "^0.2.2", "sinon": "^4.0.0", - "tslint": "5.10.0", + "tslint": "5.11.0", "typedoc": "0xProject/typedoc", "typescript": "2.7.1" }, diff --git a/packages/order-utils/src/exchange_transfer_simulator.ts b/packages/order-utils/src/exchange_transfer_simulator.ts index 72ed85406..c3a4f9c2a 100644 --- a/packages/order-utils/src/exchange_transfer_simulator.ts +++ b/packages/order-utils/src/exchange_transfer_simulator.ts @@ -34,7 +34,7 @@ const ERR_MSG_MAPPING = { }; export class ExchangeTransferSimulator { - private _store: AbstractBalanceAndProxyAllowanceLazyStore; + private readonly _store: AbstractBalanceAndProxyAllowanceLazyStore; private static _throwValidationError( failureReason: FailureReason, tradeSide: TradeSide, diff --git a/packages/order-utils/src/order_state_utils.ts b/packages/order-utils/src/order_state_utils.ts index dd45a1298..189bf4180 100644 --- a/packages/order-utils/src/order_state_utils.ts +++ b/packages/order-utils/src/order_state_utils.ts @@ -27,8 +27,8 @@ interface SidedOrderRelevantState { const ACCEPTABLE_RELATIVE_ROUNDING_ERROR = 0.0001; export class OrderStateUtils { - private _balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher; - private _orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher; + private readonly _balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher; + private readonly _orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher; private static _validateIfOrderIsValid( signedOrder: SignedOrder, sidedOrderRelevantState: SidedOrderRelevantState, diff --git a/packages/order-utils/src/order_validation_utils.ts b/packages/order-utils/src/order_validation_utils.ts index 94df3ef82..67d747081 100644 --- a/packages/order-utils/src/order_validation_utils.ts +++ b/packages/order-utils/src/order_validation_utils.ts @@ -13,7 +13,7 @@ import { isValidSignatureAsync } from './signature_utils'; import { utils } from './utils'; export class OrderValidationUtils { - private _orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher; + private readonly _orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher; public static isRoundingError(numerator: BigNumber, denominator: BigNumber, target: BigNumber): boolean { // Solidity's mulmod() in JS // Source: https://solidity.readthedocs.io/en/latest/units-and-global-variables.html#mathematical-and-cryptographic-functions diff --git a/packages/order-utils/src/remaining_fillable_calculator.ts b/packages/order-utils/src/remaining_fillable_calculator.ts index 29e19e5ab..7022aa979 100644 --- a/packages/order-utils/src/remaining_fillable_calculator.ts +++ b/packages/order-utils/src/remaining_fillable_calculator.ts @@ -1,14 +1,14 @@ import { BigNumber } from '@0xproject/utils'; export class RemainingFillableCalculator { - private _isTraderAssetZRX: boolean; + private readonly _isTraderAssetZRX: boolean; // Transferrable Amount is the minimum of Approval and Balance - private _transferrableAssetAmount: BigNumber; - private _transferrableFeeAmount: BigNumber; - private _remainingOrderAssetAmount: BigNumber; - private _remainingOrderFeeAmount: BigNumber; - private _orderFee: BigNumber; - private _orderAssetAmount: BigNumber; + private readonly _transferrableAssetAmount: BigNumber; + private readonly _transferrableFeeAmount: BigNumber; + private readonly _remainingOrderAssetAmount: BigNumber; + private readonly _remainingOrderFeeAmount: BigNumber; + private readonly _orderFee: BigNumber; + private readonly _orderAssetAmount: BigNumber; constructor( orderFee: BigNumber, orderAssetAmount: BigNumber, diff --git a/packages/order-utils/src/store/balance_and_proxy_allowance_lazy_store.ts b/packages/order-utils/src/store/balance_and_proxy_allowance_lazy_store.ts index 8235725ed..0f9526662 100644 --- a/packages/order-utils/src/store/balance_and_proxy_allowance_lazy_store.ts +++ b/packages/order-utils/src/store/balance_and_proxy_allowance_lazy_store.ts @@ -10,7 +10,7 @@ import { assetProxyUtils } from '../asset_proxy_utils'; * Copy on read store for balances/proxyAllowances of tokens/accounts */ export class BalanceAndProxyAllowanceLazyStore implements AbstractBalanceAndProxyAllowanceLazyStore { - private _balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher; + private readonly _balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher; private _balance: { [assetData: string]: { [userAddress: string]: BigNumber; diff --git a/packages/order-utils/test/exchange_transfer_simulator_test.ts b/packages/order-utils/test/exchange_transfer_simulator_test.ts index 37b2bd712..f86b05e20 100644 --- a/packages/order-utils/test/exchange_transfer_simulator_test.ts +++ b/packages/order-utils/test/exchange_transfer_simulator_test.ts @@ -34,7 +34,7 @@ describe('ExchangeTransferSimulator', async () => { let erc20ProxyAddress: string; before(async function(): Promise<void> { const mochaTestTimeoutMs = 20000; - this.timeout(mochaTestTimeoutMs); + this.timeout(mochaTestTimeoutMs); // tslint:disable-line:no-invalid-this userAddresses = await web3Wrapper.getAvailableAddressesAsync(); [coinbase, sender, recipient] = userAddresses; @@ -77,8 +77,7 @@ describe('ExchangeTransferSimulator', async () => { describe('#transferFromAsync', function(): void { // HACK: For some reason these tests need a slightly longer timeout const mochaTestTimeoutMs = 3000; - this.timeout(mochaTestTimeoutMs); - + this.timeout(mochaTestTimeoutMs); // tslint:disable-line:no-invalid-this beforeEach(() => { const simpleERC20BalanceAndProxyAllowanceFetcher = new SimpleERC20BalanceAndProxyAllowanceFetcher( (dummyERC20Token as any) as ERC20TokenContract, 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 68f6a164c..279a5c0db 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 @@ -5,8 +5,8 @@ import { AbstractBalanceAndProxyAllowanceFetcher } from '../../src/abstract/abst import { ERC20TokenContract } from '../../src/generated_contract_wrappers/erc20_token'; export class SimpleERC20BalanceAndProxyAllowanceFetcher implements AbstractBalanceAndProxyAllowanceFetcher { - private _erc20TokenContract: ERC20TokenContract; - private _erc20ProxyAddress: string; + private readonly _erc20TokenContract: ERC20TokenContract; + private readonly _erc20ProxyAddress: string; constructor(erc20TokenWrapper: ERC20TokenContract, erc20ProxyAddress: string) { this._erc20TokenContract = erc20TokenWrapper; this._erc20ProxyAddress = erc20ProxyAddress; diff --git a/packages/order-watcher/CHANGELOG.json b/packages/order-watcher/CHANGELOG.json index a66db6eec..e747a2129 100644 --- a/packages/order-watcher/CHANGELOG.json +++ b/packages/order-watcher/CHANGELOG.json @@ -9,6 +9,14 @@ { "note": "Do not stop subscription if error is encountered", "pr": 825 + }, + { + "note": "Fixed a bug that caused the incorrect block to be fetched via JSON-RPC within Blockstream", + "pr": 875 + }, + { + "note": "Remove stateLayer config from OrderWatcher. It now always operates on the latest block", + "pr": 875 } ], "timestamp": 1531149657 diff --git a/packages/order-watcher/package.json b/packages/order-watcher/package.json index cda99f6b9..cafa38946 100644 --- a/packages/order-watcher/package.json +++ b/packages/order-watcher/package.json @@ -73,7 +73,7 @@ "shx": "^0.2.2", "sinon": "^4.0.0", "source-map-support": "^0.5.0", - "tslint": "5.10.0", + "tslint": "5.11.0", "typescript": "2.7.1" }, "dependencies": { diff --git a/packages/order-watcher/src/order_watcher/event_watcher.ts b/packages/order-watcher/src/order_watcher/event_watcher.ts index 68c043dfe..9509c75de 100644 --- a/packages/order-watcher/src/order_watcher/event_watcher.ts +++ b/packages/order-watcher/src/order_watcher/event_watcher.ts @@ -20,17 +20,17 @@ enum LogEventState { */ export class EventWatcher { private readonly _web3Wrapper: Web3Wrapper; - private readonly _pollingIntervalMs: number; private readonly _stateLayer: BlockParamLiteral; private readonly _isVerbose: boolean; private _blockAndLogStreamerIfExists: BlockAndLogStreamer<Block, Log> | undefined; private _blockAndLogStreamIntervalIfExists?: NodeJS.Timer; private _onLogAddedSubscriptionToken: string | undefined; private _onLogRemovedSubscriptionToken: string | undefined; + private readonly _pollingIntervalMs: number; constructor( provider: Provider, pollingIntervalIfExistsMs: undefined | number, - stateLayer: BlockParamLiteral = BlockParamLiteral.Latest, + stateLayer: BlockParamLiteral, isVerbose: boolean, ) { this._isVerbose = isVerbose; @@ -61,13 +61,9 @@ export class EventWatcher { if (!_.isUndefined(this._blockAndLogStreamerIfExists)) { throw new Error(OrderWatcherError.SubscriptionAlreadyPresent); } - const eventFilter = { - fromBlock: this._stateLayer, - toBlock: this._stateLayer, - }; this._blockAndLogStreamerIfExists = new BlockAndLogStreamer( - this._web3Wrapper.getBlockAsync.bind(this._web3Wrapper, this._stateLayer), - this._web3Wrapper.getLogsAsync.bind(this._web3Wrapper, eventFilter), + this._web3Wrapper.getBlockAsync.bind(this._web3Wrapper), + this._web3Wrapper.getLogsAsync.bind(this._web3Wrapper), this._onBlockAndLogStreamerError.bind(this), ); const catchAllLogFilter = {}; @@ -104,7 +100,7 @@ export class EventWatcher { await this._emitDifferencesAsync(log, isRemoved ? LogEventState.Removed : LogEventState.Added, callback); } private async _reconcileBlockAsync(): Promise<void> { - const latestBlock = await this._web3Wrapper.getBlockAsync(BlockParamLiteral.Latest); + const latestBlock = await this._web3Wrapper.getBlockAsync(this._stateLayer); // We need to coerce to Block type cause Web3.Block includes types for mempool blocks if (!_.isUndefined(this._blockAndLogStreamerIfExists)) { // If we clear the interval while fetching the block - this._blockAndLogStreamer will be undefined diff --git a/packages/order-watcher/src/order_watcher/expiration_watcher.ts b/packages/order-watcher/src/order_watcher/expiration_watcher.ts index c4c94a015..6eadf14c7 100644 --- a/packages/order-watcher/src/order_watcher/expiration_watcher.ts +++ b/packages/order-watcher/src/order_watcher/expiration_watcher.ts @@ -44,7 +44,7 @@ export class ExpirationWatcher { this._orderExpirationCheckingIntervalIdIfExists = intervalUtils.setInterval( this._pruneExpiredOrders.bind(this, callback), this._orderExpirationCheckingIntervalMs, - _.noop, // _pruneExpiredOrders never throws + _.noop.bind(_), // _pruneExpiredOrders never throws ); } public unsubscribe(): void { diff --git a/packages/order-watcher/src/order_watcher/order_watcher.ts b/packages/order-watcher/src/order_watcher/order_watcher.ts index af479f32d..0ad3267d8 100644 --- a/packages/order-watcher/src/order_watcher/order_watcher.ts +++ b/packages/order-watcher/src/order_watcher/order_watcher.ts @@ -58,7 +58,6 @@ interface OrderStateByOrderHash { } const DEFAULT_ORDER_WATCHER_CONFIG: OrderWatcherConfig = { - stateLayer: BlockParamLiteral.Latest, orderExpirationCheckingIntervalMs: 50, eventPollingIntervalMs: 200, expirationMarginMs: 0, @@ -66,6 +65,7 @@ const DEFAULT_ORDER_WATCHER_CONFIG: OrderWatcherConfig = { cleanupJobIntervalMs: 1000 * 60 * 60, // 1h isVerbose: true, }; +const STATE_LAYER = BlockParamLiteral.Latest; /** * This class includes all the functionality related to watching a set of orders @@ -107,24 +107,16 @@ export class OrderWatcher { [artifacts.EtherToken.abi, artifacts.Exchange.abi], ); const contractWrappers = new ContractWrappers(provider, { networkId }); - this._eventWatcher = new EventWatcher( - provider, - config.eventPollingIntervalMs, - config.stateLayer, - config.isVerbose, - ); + this._eventWatcher = new EventWatcher(provider, config.eventPollingIntervalMs, STATE_LAYER, config.isVerbose); const balanceAndProxyAllowanceFetcher = new AssetBalanceAndProxyAllowanceFetcher( contractWrappers.erc20Token, contractWrappers.erc721Token, - config.stateLayer, + STATE_LAYER, ); this._balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore( balanceAndProxyAllowanceFetcher, ); - const orderFilledCancelledFetcher = new OrderFilledCancelledFetcher( - contractWrappers.exchange, - config.stateLayer, - ); + const orderFilledCancelledFetcher = new OrderFilledCancelledFetcher(contractWrappers.exchange, STATE_LAYER); this._orderFilledCancelledLazyStore = new OrderFilledCancelledLazyStore(orderFilledCancelledFetcher); this._orderStateUtils = new OrderStateUtils(balanceAndProxyAllowanceFetcher, orderFilledCancelledFetcher); const expirationMarginIfExistsMs = _.isUndefined(config) ? undefined : config.expirationMarginMs; diff --git a/packages/order-watcher/src/types.ts b/packages/order-watcher/src/types.ts index 7991df58c..27d892985 100644 --- a/packages/order-watcher/src/types.ts +++ b/packages/order-watcher/src/types.ts @@ -1,5 +1,5 @@ import { OrderState } from '@0xproject/types'; -import { BlockParamLiteral, LogEntryEvent } from 'ethereum-types'; +import { LogEntryEvent } from 'ethereum-types'; export enum OrderWatcherError { SubscriptionAlreadyPresent = 'SUBSCRIPTION_ALREADY_PRESENT', @@ -9,7 +9,6 @@ export enum OrderWatcherError { export type EventWatcherCallback = (err: null | Error, log?: LogEntryEvent) => void; /** - * stateLayer: Optional blockchain state layer OrderWatcher will monitor for new events. Default=latest. * orderExpirationCheckingIntervalMs: How often to check for expired orders. Default=50. * eventPollingIntervalMs: How often to poll the Ethereum node for new events. Default=200. * expirationMarginMs: Amount of time before order expiry that you'd like to be notified @@ -18,7 +17,6 @@ export type EventWatcherCallback = (err: null | Error, log?: LogEntryEvent) => v * isVerbose: Weather the order watcher should be verbose. Default=true. */ export interface OrderWatcherConfig { - stateLayer: BlockParamLiteral; orderExpirationCheckingIntervalMs: number; eventPollingIntervalMs: number; expirationMarginMs: number; diff --git a/packages/order-watcher/src/utils/assert.ts b/packages/order-watcher/src/utils/assert.ts index fa22617c7..a891a60d2 100644 --- a/packages/order-watcher/src/utils/assert.ts +++ b/packages/order-watcher/src/utils/assert.ts @@ -18,6 +18,6 @@ export const assert = { signerAddress: string, ): Promise<void> { const isValid = await isValidSignatureAsync(provider, orderHash, signature, signerAddress); - this.assert(isValid, `Expected order with hash '${orderHash}' to have a valid signature`); + assert.assert(isValid, `Expected order with hash '${orderHash}' to have a valid signature`); }, }; diff --git a/packages/order-watcher/test/global_hooks.ts b/packages/order-watcher/test/global_hooks.ts index 4552e01b0..f64f1df78 100644 --- a/packages/order-watcher/test/global_hooks.ts +++ b/packages/order-watcher/test/global_hooks.ts @@ -7,7 +7,7 @@ before('migrate contracts', async function(): Promise<void> { // HACK: Since the migrations take longer then our global mocha timeout limit // we manually increase it for this before hook. const mochaTestTimeoutMs = 25000; - this.timeout(mochaTestTimeoutMs); + this.timeout(mochaTestTimeoutMs); // tslint:disable-line:no-invalid-this const txDefaults = { gas: devConstants.GAS_LIMIT, from: devConstants.TESTRPC_FIRST_ADDRESS, diff --git a/packages/order-watcher/test/order_watcher_test.ts b/packages/order-watcher/test/order_watcher_test.ts index 6339505ce..1281d11c2 100644 --- a/packages/order-watcher/test/order_watcher_test.ts +++ b/packages/order-watcher/test/order_watcher_test.ts @@ -136,8 +136,8 @@ describe('OrderWatcher', () => { orderWatcher.unsubscribe(); }); it('should fail when trying to subscribe twice', async () => { - orderWatcher.subscribe(_.noop); - expect(() => orderWatcher.subscribe(_.noop)).to.throw(OrderWatcherError.SubscriptionAlreadyPresent); + orderWatcher.subscribe(_.noop.bind(_)); + expect(() => orderWatcher.subscribe(_.noop.bind(_))).to.throw(OrderWatcherError.SubscriptionAlreadyPresent); }); }); describe('tests with cleanup', async () => { diff --git a/packages/order-watcher/test/utils/token_utils.ts b/packages/order-watcher/test/utils/token_utils.ts new file mode 100644 index 000000000..f91b3797f --- /dev/null +++ b/packages/order-watcher/test/utils/token_utils.ts @@ -0,0 +1,34 @@ +import { Token } from '@0xproject/types'; +import * as _ from 'lodash'; + +import { InternalOrderWatcherError } from '../../src/types'; + +const PROTOCOL_TOKEN_SYMBOL = 'ZRX'; +const WETH_TOKEN_SYMBOL = 'WETH'; + +export class TokenUtils { + private readonly _tokens: Token[]; + constructor(tokens: Token[]) { + this._tokens = tokens; + } + public getProtocolTokenOrThrow(): Token { + const zrxToken = _.find(this._tokens, { symbol: PROTOCOL_TOKEN_SYMBOL }); + if (_.isUndefined(zrxToken)) { + throw new Error(InternalOrderWatcherError.ZrxNotInTokenRegistry); + } + return zrxToken; + } + public getWethTokenOrThrow(): Token { + const wethToken = _.find(this._tokens, { symbol: WETH_TOKEN_SYMBOL }); + if (_.isUndefined(wethToken)) { + throw new Error(InternalOrderWatcherError.WethNotInTokenRegistry); + } + return wethToken; + } + public getDummyTokens(): Token[] { + const dummyTokens = _.filter(this._tokens, token => { + return !_.includes([PROTOCOL_TOKEN_SYMBOL, WETH_TOKEN_SYMBOL], token.symbol); + }); + return dummyTokens; + } +} diff --git a/packages/react-docs/src/docs_info.ts b/packages/react-docs/src/docs_info.ts index 6f4f39f00..5d46dbda6 100644 --- a/packages/react-docs/src/docs_info.ts +++ b/packages/react-docs/src/docs_info.ts @@ -27,7 +27,7 @@ export class DocsInfo { public sectionNameToMarkdown: { [sectionName: string]: string }; public contractsByVersionByNetworkId?: ContractsByVersionByNetworkId; public typeConfigs: DocsInfoTypeConfigs; - private _docsInfo: DocsInfoConfig; + private readonly _docsInfo: DocsInfoConfig; constructor(config: DocsInfoConfig) { this.id = config.id; this.type = config.type; diff --git a/packages/react-docs/src/utils/doxity_utils.ts b/packages/react-docs/src/utils/doxity_utils.ts index 374ee07dd..6815daa0c 100644 --- a/packages/react-docs/src/utils/doxity_utils.ts +++ b/packages/react-docs/src/utils/doxity_utils.ts @@ -31,8 +31,8 @@ export const doxityUtils = { comment: doxityConstructor.details, returnComment: doxityConstructor.return, callPath: '', - parameters: this._convertParameters(doxityConstructor.inputs), - returnType: this._convertType(doxityContractObj.name), + parameters: doxityUtils._convertParameters(doxityConstructor.inputs), + returnType: doxityUtils._convertType(doxityContractObj.name), }; constructors.push(constructor); } @@ -40,7 +40,7 @@ export const doxityUtils = { const doxityMethods: DoxityAbiDoc[] = _.filter<DoxityAbiDoc>( doxityContractObj.abiDocs, (abiDoc: DoxityAbiDoc) => { - return this._isMethod(abiDoc); + return doxityUtils._isMethod(abiDoc); }, ); const methods: SolidityMethod[] = _.map<DoxityAbiDoc, SolidityMethod>( @@ -52,10 +52,10 @@ export const doxityUtils = { // no-op. It's already undefined } else if (outputs.length === 1) { const outputsType = outputs[0].type; - returnTypeIfExists = this._convertType(outputsType); + returnTypeIfExists = doxityUtils._convertType(outputsType); } else { const outputsType = `[${_.map(outputs, output => output.type).join(', ')}]`; - returnTypeIfExists = this._convertType(outputsType); + returnTypeIfExists = doxityUtils._convertType(outputsType); } // For ZRXToken, we want to convert it to zrxToken, rather then simply zRXToken const callPath = @@ -70,7 +70,7 @@ export const doxityUtils = { comment: doxityMethod.details, returnComment: doxityMethod.return, callPath, - parameters: this._convertParameters(doxityMethod.inputs), + parameters: doxityUtils._convertParameters(doxityMethod.inputs), returnType: returnTypeIfExists, }; return method; @@ -80,7 +80,7 @@ export const doxityUtils = { const doxityProperties: DoxityAbiDoc[] = _.filter<DoxityAbiDoc>( doxityContractObj.abiDocs, (abiDoc: DoxityAbiDoc) => { - return this._isProperty(abiDoc); + return doxityUtils._isProperty(abiDoc); }, ); const properties = _.map<DoxityAbiDoc, Property>(doxityProperties, (doxityProperty: DoxityAbiDoc) => { @@ -92,7 +92,7 @@ export const doxityUtils = { } const property = { name: doxityProperty.name, - type: this._convertType(typeName), + type: doxityUtils._convertType(typeName), comment: doxityProperty.details, }; return property; @@ -105,7 +105,7 @@ export const doxityUtils = { const events = _.map(doxityEvents, doxityEvent => { const event = { name: doxityEvent.name, - eventArgs: this._convertEventArgs(doxityEvent.inputs), + eventArgs: doxityUtils._convertEventArgs(doxityEvent.inputs), }; return event; }); @@ -129,7 +129,7 @@ export const doxityUtils = { name: input.name, comment: input.description, isOptional: false, - type: this._convertType(input.type), + type: doxityUtils._convertType(input.type), }; return parameter; }); @@ -167,7 +167,7 @@ export const doxityUtils = { const eventArg = { isIndexed: input.indexed, name: input.name, - type: this._convertType(input.type), + type: doxityUtils._convertType(input.type), }; return eventArg; }); diff --git a/packages/react-docs/src/utils/typedoc_utils.ts b/packages/react-docs/src/utils/typedoc_utils.ts index 5633d9040..a6d938e94 100644 --- a/packages/react-docs/src/utils/typedoc_utils.ts +++ b/packages/react-docs/src/utils/typedoc_utils.ts @@ -235,7 +235,7 @@ export const typeDocUtils = { childTypeIfExists = { name: child.name, typeDocType: TypeDocTypes.Reflection, - method: this._convertMethod(child, isConstructor, sections, sectionName, docId), + method: typeDocUtils._convertMethod(child, isConstructor, sections, sectionName, docId), }; } const c: CustomTypeChild = { diff --git a/packages/react-shared/src/components/nested_sidebar_menu.tsx b/packages/react-shared/src/components/nested_sidebar_menu.tsx index 9b08e3c53..aa00d5985 100644 --- a/packages/react-shared/src/components/nested_sidebar_menu.tsx +++ b/packages/react-shared/src/components/nested_sidebar_menu.tsx @@ -41,7 +41,7 @@ const styles: Styles = { export class NestedSidebarMenu extends React.Component<NestedSidebarMenuProps, NestedSidebarMenuState> { public static defaultProps: Partial<NestedSidebarMenuProps> = { shouldDisplaySectionHeaders: true, - onMenuItemClick: _.noop, + onMenuItemClick: _.noop.bind(_), }; public render(): React.ReactNode { const navigation = _.map(this.props.topLevelMenu, (menuItems: string[], sectionName: string) => { diff --git a/packages/sol-compiler/package.json b/packages/sol-compiler/package.json index 892332d8d..99e00cdc2 100644 --- a/packages/sol-compiler/package.json +++ b/packages/sol-compiler/package.json @@ -68,7 +68,7 @@ "npm-run-all": "^4.1.2", "nyc": "^11.0.1", "shx": "^0.2.2", - "tslint": "5.10.0", + "tslint": "5.11.0", "typedoc": "0xProject/typedoc", "types-bn": "^0.0.1", "typescript": "2.7.1", diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index e61c606be..3620a3ec1 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -58,13 +58,13 @@ const CONFIG_FILE = 'compiler.json'; * to artifact files. */ export class Compiler { - private _resolver: Resolver; - private _nameResolver: NameResolver; - private _contractsDir: string; - private _compilerSettings: solc.CompilerSettings; - private _artifactsDir: string; - private _solcVersionIfExists: string | undefined; - private _specifiedContracts: string[] | TYPE_ALL_FILES_IDENTIFIER; + private readonly _resolver: Resolver; + private readonly _nameResolver: NameResolver; + private readonly _contractsDir: string; + private readonly _compilerSettings: solc.CompilerSettings; + private readonly _artifactsDir: string; + private readonly _solcVersionIfExists: string | undefined; + private readonly _specifiedContracts: string[] | TYPE_ALL_FILES_IDENTIFIER; /** * Instantiates a new instance of the Compiler class. * @return An instance of the Compiler class. diff --git a/packages/sol-compiler/test/compiler_test.ts b/packages/sol-compiler/test/compiler_test.ts index ce359dceb..c9e141ee9 100644 --- a/packages/sol-compiler/test/compiler_test.ts +++ b/packages/sol-compiler/test/compiler_test.ts @@ -12,7 +12,7 @@ import { constants } from './util/constants'; const expect = chai.expect; describe('#Compiler', function(): void { - this.timeout(constants.timeoutMs); + this.timeout(constants.timeoutMs); // tslint:disable-line:no-invalid-this const artifactsDir = `${__dirname}/fixtures/artifacts`; const contractsDir = `${__dirname}/fixtures/contracts`; const exchangeArtifactPath = `${artifactsDir}/Exchange.json`; diff --git a/packages/sol-cov/package.json b/packages/sol-cov/package.json index 32755fbb6..cfdc14123 100644 --- a/packages/sol-cov/package.json +++ b/packages/sol-cov/package.json @@ -86,7 +86,7 @@ "nyc": "^11.0.1", "shx": "^0.2.2", "sinon": "^4.0.0", - "tslint": "5.10.0", + "tslint": "5.11.0", "typedoc": "0xProject/typedoc", "typescript": "2.7.1" }, diff --git a/packages/sol-cov/src/artifact_adapters/sol_compiler_artifact_adapter.ts b/packages/sol-cov/src/artifact_adapters/sol_compiler_artifact_adapter.ts index 220a9f98c..8e03bf7fd 100644 --- a/packages/sol-cov/src/artifact_adapters/sol_compiler_artifact_adapter.ts +++ b/packages/sol-cov/src/artifact_adapters/sol_compiler_artifact_adapter.ts @@ -12,8 +12,8 @@ import { AbstractArtifactAdapter } from './abstract_artifact_adapter'; const CONFIG_FILE = 'compiler.json'; export class SolCompilerArtifactAdapter extends AbstractArtifactAdapter { - private _artifactsPath: string; - private _sourcesPath: string; + private readonly _artifactsPath: string; + private readonly _sourcesPath: string; constructor(artifactsPath?: string, sourcesPath?: string) { super(); const config: CompilerOptions = fs.existsSync(CONFIG_FILE) diff --git a/packages/sol-cov/src/artifact_adapters/truffle_artifact_adapter.ts b/packages/sol-cov/src/artifact_adapters/truffle_artifact_adapter.ts index 53449e5e1..53b77aed5 100644 --- a/packages/sol-cov/src/artifact_adapters/truffle_artifact_adapter.ts +++ b/packages/sol-cov/src/artifact_adapters/truffle_artifact_adapter.ts @@ -7,8 +7,8 @@ import { AbstractArtifactAdapter } from './abstract_artifact_adapter'; import { SolCompilerArtifactAdapter } from './sol_compiler_artifact_adapter'; export class TruffleArtifactAdapter extends AbstractArtifactAdapter { - private _solcVersion: string; - private _sourcesPath: string; + private readonly _solcVersion: string; + private readonly _sourcesPath: string; constructor(sourcesPath: string, solcVersion: string) { super(); this._solcVersion = solcVersion; diff --git a/packages/sol-cov/src/ast_visitor.ts b/packages/sol-cov/src/ast_visitor.ts index a6bca4704..e55cdf6ec 100644 --- a/packages/sol-cov/src/ast_visitor.ts +++ b/packages/sol-cov/src/ast_visitor.ts @@ -18,15 +18,15 @@ enum BranchType { export class ASTVisitor { private _entryId = 0; - private _fnMap: FnMap = {}; - private _branchMap: BranchMap = {}; - private _modifiersStatementIds: number[] = []; - private _statementMap: StatementMap = {}; - private _locationByOffset: LocationByOffset; - private _ignoreRangesBeginningAt: number[]; + private readonly _fnMap: FnMap = {}; + private readonly _branchMap: BranchMap = {}; + private readonly _modifiersStatementIds: number[] = []; + private readonly _statementMap: StatementMap = {}; + private readonly _locationByOffset: LocationByOffset; + private readonly _ignoreRangesBeginningAt: number[]; // keep track of contract/function ranges that are to be ignored // so we can also ignore any children nodes within the contract/function - private _ignoreRangesWithin: Array<[number, number]> = []; + private readonly _ignoreRangesWithin: Array<[number, number]> = []; constructor(locationByOffset: LocationByOffset, ignoreRangesBeginningAt: number[] = []) { this._locationByOffset = locationByOffset; this._ignoreRangesBeginningAt = ignoreRangesBeginningAt; diff --git a/packages/sol-cov/src/coverage_subprovider.ts b/packages/sol-cov/src/coverage_subprovider.ts index 45843bc96..9667e891c 100644 --- a/packages/sol-cov/src/coverage_subprovider.ts +++ b/packages/sol-cov/src/coverage_subprovider.ts @@ -23,7 +23,7 @@ import { utils } from './utils'; * It's used to compute your code coverage while running solidity tests. */ export class CoverageSubprovider extends TraceInfoSubprovider { - private _coverageCollector: TraceCollector; + private readonly _coverageCollector: TraceCollector; /** * Instantiates a CoverageSubprovider instance * @param artifactAdapter Adapter for used artifacts format (0x, truffle, giveth, etc.) diff --git a/packages/sol-cov/src/get_source_range_snippet.ts b/packages/sol-cov/src/get_source_range_snippet.ts index 30d6ec802..bea17beae 100644 --- a/packages/sol-cov/src/get_source_range_snippet.ts +++ b/packages/sol-cov/src/get_source_range_snippet.ts @@ -38,7 +38,7 @@ export function getSourceRangeSnippet(sourceRange: SourceRange, sourceCode: stri // A visitor which collects ASTInfo for most nodes in the AST. class ASTInfoVisitor { - private _astInfos: ASTInfo[] = []; + private readonly _astInfos: ASTInfo[] = []; public getASTInfoForRange(sourceRange: SourceRange): ASTInfo | null { // HACK(albrow): Sometimes the source range doesn't exactly match that // of astInfo. To work around that we try with a +/-1 offset on diff --git a/packages/sol-cov/src/profiler_subprovider.ts b/packages/sol-cov/src/profiler_subprovider.ts index 9f98da524..ae9351f17 100644 --- a/packages/sol-cov/src/profiler_subprovider.ts +++ b/packages/sol-cov/src/profiler_subprovider.ts @@ -12,7 +12,7 @@ import { utils } from './utils'; * ProfilerSubprovider is used to profile Solidity code while running tests. */ export class ProfilerSubprovider extends TraceInfoSubprovider { - private _profilerCollector: TraceCollector; + private readonly _profilerCollector: TraceCollector; /** * Instantiates a ProfilerSubprovider instance * @param artifactAdapter Adapter for used artifacts format (0x, truffle, giveth, etc.) diff --git a/packages/sol-cov/src/revert_trace_subprovider.ts b/packages/sol-cov/src/revert_trace_subprovider.ts index fed305bd3..6ccf59653 100644 --- a/packages/sol-cov/src/revert_trace_subprovider.ts +++ b/packages/sol-cov/src/revert_trace_subprovider.ts @@ -18,8 +18,8 @@ import { utils } from './utils'; export class RevertTraceSubprovider extends TraceCollectionSubprovider { // Lock is used to not accept normal transactions while doing call/snapshot magic because they'll be reverted later otherwise private _contractsData!: ContractData[]; - private _artifactAdapter: AbstractArtifactAdapter; - private _logger: Logger; + private readonly _artifactAdapter: AbstractArtifactAdapter; + private readonly _logger: Logger; /** * Instantiates a RevertTraceSubprovider instance diff --git a/packages/sol-cov/src/trace_collection_subprovider.ts b/packages/sol-cov/src/trace_collection_subprovider.ts index 9866472b9..b530b59db 100644 --- a/packages/sol-cov/src/trace_collection_subprovider.ts +++ b/packages/sol-cov/src/trace_collection_subprovider.ts @@ -32,10 +32,10 @@ export interface TraceCollectionSubproviderConfig { export abstract class TraceCollectionSubprovider extends Subprovider { protected _web3Wrapper!: Web3Wrapper; // Lock is used to not accept normal transactions while doing call/snapshot magic because they'll be reverted later otherwise - private _lock = new Lock(); - private _defaultFromAddress: string; + private readonly _lock = new Lock(); + private readonly _defaultFromAddress: string; private _isEnabled = true; - private _config: TraceCollectionSubproviderConfig; + private readonly _config: TraceCollectionSubproviderConfig; /** * Instantiates a TraceCollectionSubprovider instance * @param defaultFromAddress default from address to use when sending transactions diff --git a/packages/sol-cov/src/trace_collector.ts b/packages/sol-cov/src/trace_collector.ts index 1b458edec..3e2ae3516 100644 --- a/packages/sol-cov/src/trace_collector.ts +++ b/packages/sol-cov/src/trace_collector.ts @@ -33,11 +33,11 @@ export type SingleFileSubtraceHandler = ( * TraceCollector is used by CoverageSubprovider to compute code coverage based on collected trace data. */ export class TraceCollector { - private _artifactAdapter: AbstractArtifactAdapter; - private _logger: Logger; + private readonly _artifactAdapter: AbstractArtifactAdapter; + private readonly _logger: Logger; private _contractsData!: ContractData[]; - private _collector = new Collector(); - private _singleFileSubtraceHandler: SingleFileSubtraceHandler; + private readonly _collector = new Collector(); + private readonly _singleFileSubtraceHandler: SingleFileSubtraceHandler; /** * Instantiates a TraceCollector instance diff --git a/packages/sol-resolver/package.json b/packages/sol-resolver/package.json index bef38b40c..f3fd62a2e 100644 --- a/packages/sol-resolver/package.json +++ b/packages/sol-resolver/package.json @@ -29,7 +29,7 @@ "copyfiles": "^1.2.0", "make-promises-safe": "^1.1.0", "shx": "^0.2.2", - "tslint": "5.10.0", + "tslint": "5.11.0", "typescript": "2.7.1" }, "dependencies": { diff --git a/packages/sol-resolver/src/resolvers/fallthrough_resolver.ts b/packages/sol-resolver/src/resolvers/fallthrough_resolver.ts index 8f6af9be0..338f334f4 100644 --- a/packages/sol-resolver/src/resolvers/fallthrough_resolver.ts +++ b/packages/sol-resolver/src/resolvers/fallthrough_resolver.ts @@ -5,7 +5,7 @@ import { ContractSource } from '../types'; import { Resolver } from './resolver'; export class FallthroughResolver extends Resolver { - private _resolvers: Resolver[] = []; + private readonly _resolvers: Resolver[] = []; public appendResolver(resolver: Resolver): void { this._resolvers.push(resolver); } diff --git a/packages/sol-resolver/src/resolvers/name_resolver.ts b/packages/sol-resolver/src/resolvers/name_resolver.ts index bcd98615f..d6ac6a499 100644 --- a/packages/sol-resolver/src/resolvers/name_resolver.ts +++ b/packages/sol-resolver/src/resolvers/name_resolver.ts @@ -8,7 +8,7 @@ import { EnumerableResolver } from './enumerable_resolver'; const SOLIDITY_FILE_EXTENSION = '.sol'; export class NameResolver extends EnumerableResolver { - private _contractsDir: string; + private readonly _contractsDir: string; constructor(contractsDir: string) { super(); this._contractsDir = contractsDir; diff --git a/packages/sol-resolver/src/resolvers/npm_resolver.ts b/packages/sol-resolver/src/resolvers/npm_resolver.ts index 2c0a44aad..9f8617145 100644 --- a/packages/sol-resolver/src/resolvers/npm_resolver.ts +++ b/packages/sol-resolver/src/resolvers/npm_resolver.ts @@ -6,7 +6,7 @@ import { ContractSource } from '../types'; import { Resolver } from './resolver'; export class NPMResolver extends Resolver { - private _packagePath: string; + private readonly _packagePath: string; constructor(packagePath: string) { super(); this._packagePath = packagePath; diff --git a/packages/sol-resolver/src/resolvers/relative_fs_resolver.ts b/packages/sol-resolver/src/resolvers/relative_fs_resolver.ts index 2317ede83..77103b8c1 100644 --- a/packages/sol-resolver/src/resolvers/relative_fs_resolver.ts +++ b/packages/sol-resolver/src/resolvers/relative_fs_resolver.ts @@ -6,7 +6,7 @@ import { ContractSource } from '../types'; import { Resolver } from './resolver'; export class RelativeFSResolver extends Resolver { - private _contractsDir: string; + private readonly _contractsDir: string; constructor(contractsDir: string) { super(); this._contractsDir = contractsDir; diff --git a/packages/sra-report/package.json b/packages/sra-report/package.json index 8d2f25a6c..9974111e6 100644 --- a/packages/sra-report/package.json +++ b/packages/sra-report/package.json @@ -65,7 +65,7 @@ "npm-run-all": "^4.1.2", "nyc": "^11.0.1", "shx": "^0.2.2", - "tslint": "5.10.0", + "tslint": "5.11.0", "typescript": "2.7.1" }, "publishConfig": { diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json index 3e52e4823..02e51a614 100644 --- a/packages/subproviders/package.json +++ b/packages/subproviders/package.json @@ -82,7 +82,7 @@ "nyc": "^11.0.1", "shx": "^0.2.2", "sinon": "^4.0.0", - "tslint": "5.10.0", + "tslint": "5.11.0", "typedoc": "0xProject/typedoc", "typescript": "2.7.1", "webpack": "^3.1.0" diff --git a/packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts b/packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts index a9ebbb790..454dae58e 100644 --- a/packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts +++ b/packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts @@ -12,8 +12,8 @@ import { PrivateKeyWalletSubprovider } from './private_key_wallet'; * Source: https://github.com/MetaMask/provider-engine/blob/master/subproviders/subprovider.js */ export class EthLightwalletSubprovider extends BaseWalletSubprovider { - private _keystore: lightwallet.keystore; - private _pwDerivedKey: Uint8Array; + private readonly _keystore: lightwallet.keystore; + private readonly _pwDerivedKey: Uint8Array; constructor(keystore: lightwallet.keystore, pwDerivedKey: Uint8Array) { super(); this._keystore = keystore; diff --git a/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts b/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts index d750505e7..bc1b34aba 100644 --- a/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts +++ b/packages/subproviders/src/subproviders/fake_gas_estimate_subprovider.ts @@ -14,7 +14,7 @@ import { Subprovider } from './subprovider'; * It intercepts the `eth_estimateGas` JSON RPC call and always returns a constant gas amount when queried. */ export class FakeGasEstimateSubprovider extends Subprovider { - private _constantGasAmount: number; + private readonly _constantGasAmount: number; /** * Instantiates an instance of the FakeGasEstimateSubprovider * @param constantGasAmount The constant gas amount you want returned diff --git a/packages/subproviders/src/subproviders/ganache.ts b/packages/subproviders/src/subproviders/ganache.ts index 79c43bc68..986094dba 100644 --- a/packages/subproviders/src/subproviders/ganache.ts +++ b/packages/subproviders/src/subproviders/ganache.ts @@ -10,7 +10,7 @@ import { Subprovider } from './subprovider'; * It intercepts all JSON RPC requests and relays them to an in-process ganache instance. */ export class GanacheSubprovider extends Subprovider { - private _ganacheProvider: Provider; + private readonly _ganacheProvider: Provider; /** * Instantiates a GanacheSubprovider * @param opts The desired opts with which to instantiate the Ganache provider diff --git a/packages/subproviders/src/subproviders/ledger.ts b/packages/subproviders/src/subproviders/ledger.ts index 8345be33c..6ad5de2e2 100644 --- a/packages/subproviders/src/subproviders/ledger.ts +++ b/packages/subproviders/src/subproviders/ledger.ts @@ -32,14 +32,14 @@ const DEFAULT_ADDRESS_SEARCH_LIMIT = 1000; */ export class LedgerSubprovider extends BaseWalletSubprovider { // tslint:disable-next-line:no-unused-variable - private _nonceLock = new Lock(); - private _connectionLock = new Lock(); - private _networkId: number; + private readonly _nonceLock = new Lock(); + private readonly _connectionLock = new Lock(); + private readonly _networkId: number; private _baseDerivationPath: string; - private _ledgerEthereumClientFactoryAsync: LedgerEthereumClientFactoryAsync; + private readonly _ledgerEthereumClientFactoryAsync: LedgerEthereumClientFactoryAsync; private _ledgerClientIfExists?: LedgerEthereumClient; - private _shouldAlwaysAskForConfirmation: boolean; - private _addressSearchLimit: number; + private readonly _shouldAlwaysAskForConfirmation: boolean; + private readonly _addressSearchLimit: number; /** * Instantiates a LedgerSubprovider. Defaults to derivationPath set to `44'/60'/0'`. * TestRPC/Ganache defaults to `m/44'/60'/0'/0`, so set this in the configs if desired. diff --git a/packages/subproviders/src/subproviders/mnemonic_wallet.ts b/packages/subproviders/src/subproviders/mnemonic_wallet.ts index 596300425..1495112b6 100644 --- a/packages/subproviders/src/subproviders/mnemonic_wallet.ts +++ b/packages/subproviders/src/subproviders/mnemonic_wallet.ts @@ -20,10 +20,10 @@ const DEFAULT_ADDRESS_SEARCH_LIMIT = 1000; * all requests with accounts derived from the supplied mnemonic. */ export class MnemonicWalletSubprovider extends BaseWalletSubprovider { - private _addressSearchLimit: number; + private readonly _addressSearchLimit: number; private _baseDerivationPath: string; private _derivedKeyInfo: DerivedHDKeyInfo; - private _mnemonic: string; + private readonly _mnemonic: string; /** * Instantiates a MnemonicWalletSubprovider. Defaults to baseDerivationPath set to `44'/60'/0'/0`. diff --git a/packages/subproviders/src/subproviders/nonce_tracker.ts b/packages/subproviders/src/subproviders/nonce_tracker.ts index dcc421574..eea722aee 100644 --- a/packages/subproviders/src/subproviders/nonce_tracker.ts +++ b/packages/subproviders/src/subproviders/nonce_tracker.ts @@ -17,7 +17,7 @@ const NONCE_TOO_LOW_ERROR_MESSAGE = 'Transaction nonce is too low'; * We added the additional feature of clearing the cached nonce value when a `nonce value too low` error occurs. */ export class NonceTrackerSubprovider extends Subprovider { - private _nonceCache: { [address: string]: string } = {}; + private readonly _nonceCache: { [address: string]: string } = {}; private static _reconstructTransaction(payload: JSONRPCRequestPayload): EthereumTx { const raw = payload.params[0]; if (_.isUndefined(raw)) { diff --git a/packages/subproviders/src/subproviders/private_key_wallet.ts b/packages/subproviders/src/subproviders/private_key_wallet.ts index b3f48fd90..9d6fc487e 100644 --- a/packages/subproviders/src/subproviders/private_key_wallet.ts +++ b/packages/subproviders/src/subproviders/private_key_wallet.ts @@ -13,8 +13,8 @@ import { BaseWalletSubprovider } from './base_wallet_subprovider'; * all requests with the supplied Ethereum private key. */ export class PrivateKeyWalletSubprovider extends BaseWalletSubprovider { - private _address: string; - private _privateKeyBuffer: Buffer; + private readonly _address: string; + private readonly _privateKeyBuffer: Buffer; /** * Instantiates a PrivateKeyWalletSubprovider. * @param privateKey The corresponding private key to an Ethereum address diff --git a/packages/subproviders/src/subproviders/redundant_subprovider.ts b/packages/subproviders/src/subproviders/redundant_subprovider.ts index a60d6706e..7aa6226d5 100644 --- a/packages/subproviders/src/subproviders/redundant_subprovider.ts +++ b/packages/subproviders/src/subproviders/redundant_subprovider.ts @@ -12,7 +12,7 @@ import { Subprovider } from './subprovider'; * set of JSON RPC endpoints. */ export class RedundantSubprovider extends Subprovider { - private _subproviders: Subprovider[]; + private readonly _subproviders: Subprovider[]; private static async _firstSuccessAsync( subproviders: Subprovider[], payload: JSONRPCRequestPayload, diff --git a/packages/subproviders/src/subproviders/rpc_subprovider.ts b/packages/subproviders/src/subproviders/rpc_subprovider.ts index 3ad0e5325..d874c6f05 100644 --- a/packages/subproviders/src/subproviders/rpc_subprovider.ts +++ b/packages/subproviders/src/subproviders/rpc_subprovider.ts @@ -13,8 +13,8 @@ import { Subprovider } from './subprovider'; * It forwards on JSON RPC requests to the supplied `rpcUrl` endpoint */ export class RPCSubprovider extends Subprovider { - private _rpcUrl: string; - private _requestTimeoutMs: number; + private readonly _rpcUrl: string; + private readonly _requestTimeoutMs: number; constructor(rpcUrl: string, requestTimeoutMs: number = 20000) { super(); assert.isString('rpcUrl', rpcUrl); diff --git a/packages/subproviders/src/subproviders/signer.ts b/packages/subproviders/src/subproviders/signer.ts index f7329e00c..d5fd86897 100644 --- a/packages/subproviders/src/subproviders/signer.ts +++ b/packages/subproviders/src/subproviders/signer.ts @@ -12,7 +12,7 @@ import { Subprovider } from './subprovider'; * are passed onwards for subsequent subproviders to handle. */ export class SignerSubprovider extends Subprovider { - private _web3Wrapper: Web3Wrapper; + private readonly _web3Wrapper: Web3Wrapper; /** * Instantiates a new SignerSubprovider * @param provider Web3 provider that should handle all user account related requests diff --git a/packages/subproviders/src/utils/wallet_utils.ts b/packages/subproviders/src/utils/wallet_utils.ts index 3748077ef..4c233645b 100644 --- a/packages/subproviders/src/utils/wallet_utils.ts +++ b/packages/subproviders/src/utils/wallet_utils.ts @@ -6,8 +6,8 @@ import { DerivedHDKeyInfo } from '../types'; const DEFAULT_ADDRESS_SEARCH_LIMIT = 1000; class DerivedHDKeyInfoIterator implements IterableIterator<DerivedHDKeyInfo> { - private _parentDerivedKeyInfo: DerivedHDKeyInfo; - private _searchLimit: number; + private readonly _parentDerivedKeyInfo: DerivedHDKeyInfo; + private readonly _searchLimit: number; private _index: number; constructor(initialDerivedKey: DerivedHDKeyInfo, searchLimit: number = DEFAULT_ADDRESS_SEARCH_LIMIT) { diff --git a/packages/subproviders/test/integration/ledger_subprovider_test.ts b/packages/subproviders/test/integration/ledger_subprovider_test.ts index 103e8f952..527ee5b22 100644 --- a/packages/subproviders/test/integration/ledger_subprovider_test.ts +++ b/packages/subproviders/test/integration/ledger_subprovider_test.ts @@ -176,7 +176,7 @@ describe('LedgerSubprovider', () => { params: [tx], id: 1, }; - await promisify(defaultProvider.sendAsync, defaultProvider)(payload); + await promisify(defaultProvider.sendAsync.bind(defaultProvider))(payload); // Send transaction from Ledger tx = { diff --git a/packages/subproviders/test/unit/ledger_subprovider_test.ts b/packages/subproviders/test/unit/ledger_subprovider_test.ts index edff5144e..a1d146dbc 100644 --- a/packages/subproviders/test/unit/ledger_subprovider_test.ts +++ b/packages/subproviders/test/unit/ledger_subprovider_test.ts @@ -55,7 +55,7 @@ describe('LedgerSubprovider', () => { return ecSignature; }, transport: { - close: _.noop, + close: _.noop.bind(_), } as LedgerCommunicationClient, }; // tslint:enable:no-object-literal-type-assertion diff --git a/packages/subproviders/test/unit/nonce_tracker_subprovider_test.ts b/packages/subproviders/test/unit/nonce_tracker_subprovider_test.ts index c437d0815..05f213cf5 100644 --- a/packages/subproviders/test/unit/nonce_tracker_subprovider_test.ts +++ b/packages/subproviders/test/unit/nonce_tracker_subprovider_test.ts @@ -60,9 +60,9 @@ describe('NonceTrackerSubprovider', () => { const payload = { ...getTransactionCountPayload, params: ['0x0', 'pending'] }; - const response = await promisify<any>(provider.sendAsync, provider)(payload); + const response = await promisify<any>(provider.sendAsync.bind(provider))(payload); expect(response.result).to.be.eq('0x00'); - const secondResponse = await promisify<any>(provider.sendAsync, provider)(payload); + const secondResponse = await promisify<any>(provider.sendAsync.bind(provider))(payload); expect(secondResponse.result).to.be.eq('0x00'); }); it('does not cache the result for latest transaction count', async () => { @@ -74,9 +74,9 @@ describe('NonceTrackerSubprovider', () => { const payload = { ...getTransactionCountPayload, params: ['0x0', 'latest'] }; - const response = await promisify<any>(provider.sendAsync, provider)(payload); + const response = await promisify<any>(provider.sendAsync.bind(provider))(payload); expect(response.result).to.be.eq('0x00'); - const secondResponse = await promisify<any>(provider.sendAsync, provider)(payload); + const secondResponse = await promisify<any>(provider.sendAsync.bind(provider))(payload); expect(secondResponse.result).to.be.eq('0x99'); }); it('clears the cache on a Nonce Too Low Error', async () => { @@ -103,14 +103,14 @@ describe('NonceTrackerSubprovider', () => { params: [transaction.serialize()], }; - const response = await promisify<any>(provider.sendAsync, provider)(noncePayload); + const response = await promisify<any>(provider.sendAsync.bind(provider))(noncePayload); expect(response.result).to.be.eq('0x00'); - const secondResponse = await promisify<any>(provider.sendAsync, provider)(noncePayload); + const secondResponse = await promisify<any>(provider.sendAsync.bind(provider))(noncePayload); expect(secondResponse.result).to.be.eq('0x00'); try { - await promisify(provider.sendAsync, provider)(txPayload); + await promisify(provider.sendAsync.bind(provider))(txPayload); } catch (err) { - const thirdResponse = await promisify<any>(provider.sendAsync, provider)(noncePayload); + const thirdResponse = await promisify<any>(provider.sendAsync.bind(provider))(noncePayload); expect(thirdResponse.result).to.be.eq('0x99'); } }); @@ -138,12 +138,12 @@ describe('NonceTrackerSubprovider', () => { params: [transaction.serialize()], }; - const response = await promisify<any>(provider.sendAsync, provider)(noncePayload); + const response = await promisify<any>(provider.sendAsync.bind(provider))(noncePayload); expect(response.result).to.be.eq('0x00'); - const secondResponse = await promisify<any>(provider.sendAsync, provider)(noncePayload); + const secondResponse = await promisify<any>(provider.sendAsync.bind(provider))(noncePayload); expect(secondResponse.result).to.be.eq('0x00'); - await promisify(provider.sendAsync, provider)(txPayload); - const thirdResponse = await promisify<any>(provider.sendAsync, provider)(noncePayload); + await promisify(provider.sendAsync.bind(provider))(txPayload); + const thirdResponse = await promisify<any>(provider.sendAsync.bind(provider))(noncePayload); expect(thirdResponse.result).to.be.eq('0x01'); }); }); diff --git a/packages/testnet-faucets/package.json b/packages/testnet-faucets/package.json index d3c9cff34..6711817f0 100644 --- a/packages/testnet-faucets/package.json +++ b/packages/testnet-faucets/package.json @@ -42,7 +42,7 @@ "nodemon": "^1.11.0", "shx": "^0.2.2", "source-map-loader": "^0.1.6", - "tslint": "5.10.0", + "tslint": "5.11.0", "typescript": "2.7.1", "webpack": "^3.1.0", "webpack-node-externals": "^1.6.0" diff --git a/packages/testnet-faucets/src/ts/dispatch_queue.ts b/packages/testnet-faucets/src/ts/dispatch_queue.ts index b1996a0c2..0a13df7c9 100644 --- a/packages/testnet-faucets/src/ts/dispatch_queue.ts +++ b/packages/testnet-faucets/src/ts/dispatch_queue.ts @@ -7,8 +7,8 @@ const MAX_QUEUE_SIZE = 500; const DEFAULT_QUEUE_INTERVAL_MS = 1000; export class DispatchQueue { - private _queueIntervalMs: number; - private _queue: Array<() => Promise<void>>; + private readonly _queueIntervalMs: number; + private readonly _queue: Array<() => Promise<void>>; private _queueIntervalIdIfExists?: NodeJS.Timer; constructor() { this._queueIntervalMs = DEFAULT_QUEUE_INTERVAL_MS; diff --git a/packages/testnet-faucets/src/ts/error_reporter.ts b/packages/testnet-faucets/src/ts/error_reporter.ts index a0abcc07b..49c37b6eb 100644 --- a/packages/testnet-faucets/src/ts/error_reporter.ts +++ b/packages/testnet-faucets/src/ts/error_reporter.ts @@ -12,7 +12,7 @@ export const errorReporter = { rollbar.handleUncaughtExceptions(configs.ROLLBAR_ACCESS_KEY); process.on('unhandledRejection', async (err: Error) => { logUtils.log(`Uncaught exception ${err}. Stack: ${err.stack}`); - await this.reportAsync(err); + await errorReporter.reportAsync(err); process.exit(1); }); }, @@ -20,7 +20,7 @@ export const errorReporter = { if (configs.ENVIRONMENT === 'development') { return; // Do not log development environment errors } - return new Promise((resolve, reject) => { + return new Promise<any>((resolve, reject) => { rollbar.handleError(err, req, (rollbarErr: Error) => { if (rollbarErr) { logUtils.log(`Error reporting to rollbar, ignoring: ${rollbarErr}`); diff --git a/packages/testnet-faucets/src/ts/handler.ts b/packages/testnet-faucets/src/ts/handler.ts index 0f61159fa..3749bc70b 100644 --- a/packages/testnet-faucets/src/ts/handler.ts +++ b/packages/testnet-faucets/src/ts/handler.ts @@ -37,7 +37,7 @@ enum RequestedAssetType { const FIVE_DAYS_IN_MS = 4.32e8; // TODO: make this configurable export class Handler { - private _networkConfigByNetworkId: ItemByNetworkId<NetworkConfig> = {}; + private readonly _networkConfigByNetworkId: ItemByNetworkId<NetworkConfig> = {}; private static _createProviderEngine(rpcUrl: string): Provider { if (_.isUndefined(configs.DISPENSER_PRIVATE_KEY)) { throw new Error('Dispenser Private key not found'); diff --git a/packages/testnet-faucets/src/ts/server.ts b/packages/testnet-faucets/src/ts/server.ts index 5416cdcc3..f00562000 100644 --- a/packages/testnet-faucets/src/ts/server.ts +++ b/packages/testnet-faucets/src/ts/server.ts @@ -24,10 +24,26 @@ app.get('/ping', (req: express.Request, res: express.Response) => { res.status(constants.SUCCESS_STATUS).send('pong'); }); app.get('/info', handler.getQueueInfo.bind(handler)); -app.get('/ether/:recipient', parameterTransformer.transform, handler.dispenseEther.bind(handler)); -app.get('/zrx/:recipient', parameterTransformer.transform, handler.dispenseZRX.bind(handler)); -app.get('/order/weth/:recipient', parameterTransformer.transform, handler.dispenseWETHOrderAsync.bind(handler)); -app.get('/order/zrx/:recipient', parameterTransformer.transform, handler.dispenseZRXOrderAsync.bind(handler)); +app.get( + '/ether/:recipient', + parameterTransformer.transform.bind(parameterTransformer), + handler.dispenseEther.bind(handler), +); +app.get( + '/zrx/:recipient', + parameterTransformer.transform.bind(parameterTransformer), + handler.dispenseZRX.bind(handler), +); +app.get( + '/order/weth/:recipient', + parameterTransformer.transform.bind(parameterTransformer), + handler.dispenseWETHOrderAsync.bind(handler), +); +app.get( + '/order/zrx/:recipient', + parameterTransformer.transform.bind(parameterTransformer), + handler.dispenseZRXOrderAsync.bind(handler), +); // Log to rollbar any errors unhandled by handlers app.use(errorReporter.errorHandler()); diff --git a/packages/tslint-config/package.json b/packages/tslint-config/package.json index ec8686262..b136b7e4a 100644 --- a/packages/tslint-config/package.json +++ b/packages/tslint-config/package.json @@ -43,7 +43,7 @@ }, "dependencies": { "lodash": "^4.17.4", - "tslint": "5.10.0", + "tslint": "5.11.0", "tslint-eslint-rules": "^4.1.1", "tslint-react": "^3.2.0", "tsutils": "2.22.2" diff --git a/packages/tslint-config/rules/customNoMagicNumbersRule.ts b/packages/tslint-config/rules/customNoMagicNumbersRule.ts index 0a565b2e6..cb124f738 100644 --- a/packages/tslint-config/rules/customNoMagicNumbersRule.ts +++ b/packages/tslint-config/rules/customNoMagicNumbersRule.ts @@ -29,6 +29,7 @@ export class Rule extends Lint.Rules.AbstractRule { public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { const allowedNumbers = this.ruleArguments.length > 0 ? this.ruleArguments : Rule.DEFAULT_ALLOWED; return this.applyWithWalker( + // tslint:disable-next-line:no-inferred-empty-object-type new CustomNoMagicNumbersWalker(sourceFile, this.ruleName, new Set(allowedNumbers.map(String))), ); } diff --git a/packages/tslint-config/tslint.json b/packages/tslint-config/tslint.json index fbc71e140..30aaf6538 100644 --- a/packages/tslint-config/tslint.json +++ b/packages/tslint-config/tslint.json @@ -1,61 +1,132 @@ { - "extends": ["tslint:latest", "tslint-react", "tslint-eslint-rules"], + "extends": [ + "tslint:latest", + "tslint-react", + "tslint-eslint-rules" + ], "rules": { "adjacent-overload-signatures": true, - "arrow-parens": [true, "ban-single-arg-parens"], + "arrow-parens": [ + true, + "ban-single-arg-parens" + ], "arrow-return-shorthand": true, "async-suffix": true, - "boolean-naming": true, - "no-switch-case-fall-through": true, - "switch-default": true, "await-promise": true, - "custom-no-magic-numbers": [true, 0, 1, 2, 3, -1], "binary-expression-operand-order": true, + "boolean-naming": true, "callable-types": true, "class-name": true, "completed-docs": [ true, { - "functions": { "visibilities": ["exported"] }, - "methods": { "locations": "instance", "privacies": ["public", "protected"] } + "functions": { + "visibilities": [ + "exported" + ] + }, + "methods": { + "locations": "instance", + "privacies": [ + "public", + "protected" + ] + } } ], "curly": true, - "eofline": true, - "typedef": [true, "call-signature", "parameter", "property-declaration"], + "custom-no-magic-numbers": [ + true, + 0, + 1, + 2, + 3, + -1 + ], "encoding": true, + "eofline": true, "import-spacing": true, - "indent": [true, "spaces", 4], + "indent": [ + true, + "spaces", + 4 + ], "interface-name": false, "interface-over-type-literal": true, - "linebreak-style": [true, "LF"], - "max-classes-per-file": [true, 1], + "jsx-alignment": true, + "jsx-boolean-value": true, + "jsx-curly-spacing": [ + true, + "never" + ], + "jsx-no-bind": false, + "jsx-no-lambda": true, + "jsx-no-multiline-js": false, + "jsx-no-string-ref": true, + "jsx-self-close": true, + "jsx-wrap-multiline": false, + "linebreak-style": [ + true, + "LF" + ], + "max-classes-per-file": [ + true, + 1 + ], + "max-file-line-count": [ + true, + 500 + ], "max-line-length": false, - "max-file-line-count": [true, 500], "member-access": true, - "member-ordering": [true, "public-before-private", "static-before-instance", "variables-before-functions"], - "newline-before-return": false, + "member-ordering": [ + true, + "public-before-private", + "static-before-instance", + "variables-before-functions" + ], "new-parens": true, + "newline-before-return": false, "no-angle-bracket-type-assertion": true, "no-boolean-literal-compare": true, + "no-debugger": true, "no-default-export": true, - "no-return-await": true, + "no-duplicate-super": true, "no-duplicate-switch-case": true, - "no-implicit-dependencies": true, + "no-duplicate-variable": true, "no-empty-interface": false, + "no-eval": true, "no-floating-promises": true, + "no-implicit-dependencies": [ + true, + "dev" + ], + "no-inferred-empty-object-type": true, + "no-invalid-template-strings": true, + "no-invalid-this": true, + "no-misused-new": true, "no-non-null-assertion": true, "no-parameter-reassignment": true, "no-redundant-jsdoc": true, "no-return-await": true, - "no-unused-variable": [true, "check-parameters"], + "no-shadowed-variable": true, + "no-sparse-arrays": true, + "no-string-literal": true, "no-string-throw": true, "no-submodule-imports": false, + "no-switch-case-fall-through": true, + "no-this-assignment": false, + "no-unbound-method": true, + "no-unnecessary-class": true, "no-unnecessary-type-assertion": true, - "no-implicit-dependencies": [true, "dev"], + "no-unsafe-finally": true, + "no-unused-variable": [ + true, + "check-parameters" + ], "number-literal-format": true, - "object-literal-sort-keys": false, "object-literal-key-quotes": false, + "object-literal-sort-keys": false, "ordered-imports": [ true, { @@ -65,24 +136,45 @@ "prefer-const": true, "prefer-for-of": true, "prefer-function-over-method": true, + "prefer-object-spread": true, + "prefer-readonly": true, "promise-function-async": true, - "quotemark": [true, "single", "avoid-escape", "jsx-double"], + "quotemark": [ + true, + "single", + "avoid-escape", + "jsx-double" + ], "restrict-plus-operands": true, - "semicolon": [true, "always"], + "semicolon": [ + true, + "always" + ], "space-before-function-paren": [ true, { "anonymous": "never", - "named": "never", - "method": "never", + "asyncArrow": "always", "constructor": "never", - "asyncArrow": "always" + "method": "never", + "named": "never" } ], "space-within-parens": false, + "switch-default": true, "type-literal-delimiter": true, + "typedef": [ + true, + "call-signature", + "parameter", + "property-declaration" + ], "underscore-private-and-protected": true, - "variable-name": [true, "ban-keywords", "allow-pascal-case"], + "variable-name": [ + true, + "ban-keywords", + "allow-pascal-case" + ], "whitespace": [ true, "check-branch", @@ -93,16 +185,7 @@ "check-type", "check-typecast", "check-preblock" - ], - "jsx-alignment": true, - "jsx-boolean-value": true, - "jsx-curly-spacing": [true, "never"], - "jsx-no-lambda": true, - "jsx-no-multiline-js": false, - "jsx-no-string-ref": true, - "jsx-self-close": true, - "jsx-wrap-multiline": false, - "jsx-no-bind": false + ] }, "rulesDirectory": "lib/rules" -} +}
\ No newline at end of file diff --git a/packages/types/package.json b/packages/types/package.json index ca02ae323..fee9d847f 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -29,7 +29,7 @@ "copyfiles": "^1.2.0", "make-promises-safe": "^1.1.0", "shx": "^0.2.2", - "tslint": "5.10.0", + "tslint": "5.11.0", "typescript": "2.7.1" }, "dependencies": { diff --git a/packages/utils/package.json b/packages/utils/package.json index ebecd3a3b..b2658f491 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -31,7 +31,7 @@ "make-promises-safe": "^1.1.0", "npm-run-all": "^4.1.2", "shx": "^0.2.2", - "tslint": "5.10.0", + "tslint": "5.11.0", "typescript": "2.7.1" }, "dependencies": { diff --git a/packages/utils/src/abi_decoder.ts b/packages/utils/src/abi_decoder.ts index b75387e3e..7f93e746e 100644 --- a/packages/utils/src/abi_decoder.ts +++ b/packages/utils/src/abi_decoder.ts @@ -16,7 +16,7 @@ import { addressUtils } from './address_utils'; import { BigNumber } from './configured_bignumber'; export class AbiDecoder { - private _methodIds: { [signatureHash: string]: EventAbi } = {}; + private readonly _methodIds: { [signatureHash: string]: EventAbi } = {}; constructor(abiArrays: AbiDefinition[][]) { _.forEach(abiArrays, this.addABI.bind(this)); } diff --git a/packages/utils/src/abi_utils.ts b/packages/utils/src/abi_utils.ts index 413c2f481..421dd405c 100644 --- a/packages/utils/src/abi_utils.ts +++ b/packages/utils/src/abi_utils.ts @@ -6,7 +6,7 @@ export const abiUtils = { if (param.type === 'tuple') { // Parse out tuple types into {type_1, type_2, ..., type_N} const tupleComponents = param.components; - const paramString = _.map(tupleComponents, component => this.parseFunctionParam(component)); + const paramString = _.map(tupleComponents, component => abiUtils.parseFunctionParam(component)); const tupleParamString = `{${paramString}}`; return tupleParamString; } @@ -14,7 +14,7 @@ export const abiUtils = { }, getFunctionSignature(methodAbi: MethodAbi): string { const functionName = methodAbi.name; - const parameterTypeList = _.map(methodAbi.inputs, (param: DataItem) => this.parseFunctionParam(param)); + const parameterTypeList = _.map(methodAbi.inputs, (param: DataItem) => abiUtils.parseFunctionParam(param)); const functionSignature = `${functionName}(${parameterTypeList})`; return functionSignature; }, @@ -37,7 +37,7 @@ export const abiUtils = { // Sort method Abis into alphabetical order, by function signature const methodAbisOrdered = _.sortBy(methodAbis, [ (methodAbi: MethodAbi) => { - const functionSignature = this.getFunctionSignature(methodAbi); + const functionSignature = abiUtils.getFunctionSignature(methodAbi); return functionSignature; }, ]); diff --git a/packages/web3-wrapper/package.json b/packages/web3-wrapper/package.json index 5d4a2720b..1f4854baa 100644 --- a/packages/web3-wrapper/package.json +++ b/packages/web3-wrapper/package.json @@ -59,7 +59,7 @@ "npm-run-all": "^4.1.2", "nyc": "^11.0.1", "shx": "^0.2.2", - "tslint": "5.10.0", + "tslint": "5.11.0", "typedoc": "0xProject/typedoc", "typescript": "2.7.1" }, diff --git a/packages/web3-wrapper/src/marshaller.ts b/packages/web3-wrapper/src/marshaller.ts index 15384417e..fed197822 100644 --- a/packages/web3-wrapper/src/marshaller.ts +++ b/packages/web3-wrapper/src/marshaller.ts @@ -54,7 +54,7 @@ export const marshaller = { transactions: [] as Transaction[], }; block.transactions = _.map(blockWithHexValues.transactions, (tx: TransactionRPC) => { - const transaction = this.unmarshalTransaction(tx); + const transaction = marshaller.unmarshalTransaction(tx); return transaction; }); return block; @@ -94,10 +94,10 @@ export const marshaller = { ...txData, }; delete callTxDataBase.from; - const callTxDataBaseRPC = this._marshalCallTxDataBase(callTxDataBase); + const callTxDataBaseRPC = marshaller._marshalCallTxDataBase(callTxDataBase); const txDataRPC = { ...callTxDataBaseRPC, - from: this.marshalAddress(txData.from), + from: marshaller.marshalAddress(txData.from), }; const prunableIfUndefined = ['gasPrice', 'gas', 'value', 'nonce']; _.each(txDataRPC, (value: any, key: string) => { @@ -112,10 +112,10 @@ export const marshaller = { ...callData, }; delete callTxDataBase.from; - const callTxDataBaseRPC = this._marshalCallTxDataBase(callTxDataBase); + const callTxDataBaseRPC = marshaller._marshalCallTxDataBase(callTxDataBase); const callDataRPC = { ...callTxDataBaseRPC, - from: _.isUndefined(callData.from) ? undefined : this.marshalAddress(callData.from), + from: _.isUndefined(callData.from) ? undefined : marshaller.marshalAddress(callData.from), }; return callDataRPC; }, @@ -144,7 +144,7 @@ export const marshaller = { _marshalCallTxDataBase(callTxDataBase: Partial<CallTxDataBase>): Partial<CallTxDataBaseRPC> { const callTxDataBaseRPC = { ...callTxDataBase, - to: _.isUndefined(callTxDataBase.to) ? undefined : this.marshalAddress(callTxDataBase.to), + to: _.isUndefined(callTxDataBase.to) ? undefined : marshaller.marshalAddress(callTxDataBase.to), gasPrice: _.isUndefined(callTxDataBase.gasPrice) ? undefined : utils.encodeAmountAsHexString(callTxDataBase.gasPrice), diff --git a/packages/web3-wrapper/src/utils.ts b/packages/web3-wrapper/src/utils.ts index d13eb9404..01605dc9a 100644 --- a/packages/web3-wrapper/src/utils.ts +++ b/packages/web3-wrapper/src/utils.ts @@ -15,7 +15,7 @@ export const utils = { if (_.isNull(hex)) { return null; } - const decimal = this.convertHexToNumber(hex); + const decimal = utils.convertHexToNumber(hex); return decimal; }, convertAmountToBigNumber(value: string | number | BigNumber): BigNumber { @@ -40,7 +40,7 @@ export const utils = { return valueBigNumber.lessThan(0) ? '-0x' + valueHex.substr(1) : '0x' + valueHex; }, numberToHex(value: number): string { - if (!isFinite(value) && !this.isHexStrict(value)) { + if (!isFinite(value) && !utils.isHexStrict(value)) { throw new Error(`Given input ${value} is not a number.`); } diff --git a/packages/web3-wrapper/src/web3_wrapper.ts b/packages/web3-wrapper/src/web3_wrapper.ts index 495523e44..e828708f0 100644 --- a/packages/web3-wrapper/src/web3_wrapper.ts +++ b/packages/web3-wrapper/src/web3_wrapper.ts @@ -50,7 +50,7 @@ export class Web3Wrapper { public isZeroExWeb3Wrapper = true; public abiDecoder: AbiDecoder; private _provider: Provider; - private _txDefaults: Partial<TxData>; + private readonly _txDefaults: Partial<TxData>; private _jsonRpcRequestId: number; /** * Check if an address is a valid Ethereum address diff --git a/packages/website/package.json b/packages/website/package.json index e675273b7..80e49cd70 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -97,7 +97,7 @@ "shx": "^0.2.2", "source-map-loader": "^0.1.6", "style-loader": "0.13.x", - "tslint": "5.10.0", + "tslint": "5.11.0", "tslint-config-0xproject": "^0.0.2", "typescript": "2.7.1", "uglifyjs-webpack-plugin": "^1.2.5", diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index e8168d975..88461f8a9 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -83,11 +83,11 @@ export class Blockchain { public networkId: number; public nodeVersion: string; private _contractWrappers: ContractWrappers; - private _dispatcher: Dispatcher; + private readonly _dispatcher: Dispatcher; private _web3Wrapper?: Web3Wrapper; private _blockchainWatcher?: BlockchainWatcher; private _injectedProviderObservable?: InjectedProviderObservable; - private _injectedProviderUpdateHandler: (update: InjectedProviderUpdate) => Promise<void>; + private readonly _injectedProviderUpdateHandler: (update: InjectedProviderUpdate) => Promise<void>; private _userAddressIfExists: string; private _ledgerSubprovider: LedgerSubprovider; private _defaultGasPrice: BigNumber; @@ -125,7 +125,11 @@ export class Blockchain { let networkIdIfExists: number; if (!_.isUndefined(injectedWeb3IfExists)) { try { - networkIdIfExists = _.parseInt(await promisify<string>(injectedWeb3IfExists.version.getNetwork)()); + networkIdIfExists = _.parseInt( + await promisify<string>( + injectedWeb3IfExists.version.getNetwork.bind(injectedWeb3IfExists.version), + )(), + ); } catch (err) { // Ignore error and proceed with networkId undefined } diff --git a/packages/website/ts/blockchain_watcher.ts b/packages/website/ts/blockchain_watcher.ts index 4b23aa98a..39ed8b08b 100644 --- a/packages/website/ts/blockchain_watcher.ts +++ b/packages/website/ts/blockchain_watcher.ts @@ -4,9 +4,9 @@ import * as _ from 'lodash'; import { Dispatcher } from 'ts/redux/dispatcher'; export class BlockchainWatcher { - private _dispatcher: Dispatcher; - private _web3Wrapper: Web3Wrapper; - private _shouldPollUserAddress: boolean; + private readonly _dispatcher: Dispatcher; + private readonly _web3Wrapper: Web3Wrapper; + private readonly _shouldPollUserAddress: boolean; private _watchBalanceIntervalId: NodeJS.Timer; private _prevUserEtherBalanceInWei?: BigNumber; private _prevUserAddressIfExists: string; diff --git a/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx b/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx index ce86df856..3ebab03ef 100644 --- a/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx +++ b/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx @@ -14,9 +14,9 @@ export const U2fNotSupportedDialog = (props: U2fNotSupportedDialogProps) => { <Dialog title="U2F Not Supported" titleStyle={{ fontWeight: 100 }} - actions={[<FlatButton key="u2fNo" label="Ok" onTouchTap={props.onToggleDialog.bind(this)} />]} + actions={[<FlatButton key="u2fNo" label="Ok" onTouchTap={props.onToggleDialog} />]} open={props.isOpen} - onRequestClose={props.onToggleDialog.bind(this)} + onRequestClose={props.onToggleDialog} autoScrollBodyContent={true} > <div className="pt2" style={{ color: colors.grey700 }}> diff --git a/packages/website/ts/components/eth_weth_conversion_button.tsx b/packages/website/ts/components/eth_weth_conversion_button.tsx index d547a4e6a..b0091a1c1 100644 --- a/packages/website/ts/components/eth_weth_conversion_button.tsx +++ b/packages/website/ts/components/eth_weth_conversion_button.tsx @@ -37,7 +37,7 @@ export class EthWethConversionButton extends React.Component< > { public static defaultProps: Partial<EthWethConversionButtonProps> = { isDisabled: false, - onConversionSuccessful: _.noop, + onConversionSuccessful: _.noop.bind(_), }; public constructor(props: EthWethConversionButtonProps) { super(props); diff --git a/packages/website/ts/components/fill_warning_dialog.tsx b/packages/website/ts/components/fill_warning_dialog.tsx index 83095b1d3..45c492221 100644 --- a/packages/website/ts/components/fill_warning_dialog.tsx +++ b/packages/website/ts/components/fill_warning_dialog.tsx @@ -18,16 +18,16 @@ export const FillWarningDialog = (props: FillWarningDialogProps) => { <FlatButton key="fillWarningCancel" label="Cancel" - onTouchTap={props.onToggleDialog.bind(this, didCancel)} + onTouchTap={() => props.onToggleDialog(didCancel)} // tslint:disable-line:jsx-no-lambda />, <FlatButton key="fillWarningContinue" label="Fill Order" - onTouchTap={props.onToggleDialog.bind(this, !didCancel)} + onTouchTap={() => props.onToggleDialog(!didCancel)} // tslint:disable-line:jsx-no-lambda />, ]} open={props.isOpen} - onRequestClose={props.onToggleDialog.bind(this)} + onRequestClose={() => props.onToggleDialog(didCancel)} // tslint:disable-line:jsx-no-lambda autoScrollBodyContent={true} modal={true} > diff --git a/packages/website/ts/components/generate_order/asset_picker.tsx b/packages/website/ts/components/generate_order/asset_picker.tsx index 5eada37b6..2dca3483f 100644 --- a/packages/website/ts/components/generate_order/asset_picker.tsx +++ b/packages/website/ts/components/generate_order/asset_picker.tsx @@ -46,7 +46,7 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt public static defaultProps: Partial<AssetPickerProps> = { tokenVisibility: TokenVisibility.ALL, }; - private _dialogConfigsByAssetView: { [assetView: string]: DialogConfigs }; + private readonly _dialogConfigsByAssetView: { [assetView: string]: DialogConfigs }; constructor(props: AssetPickerProps) { super(props); this.state = { diff --git a/packages/website/ts/components/inputs/allowance_toggle.tsx b/packages/website/ts/components/inputs/allowance_toggle.tsx index 297617bef..05dce134a 100644 --- a/packages/website/ts/components/inputs/allowance_toggle.tsx +++ b/packages/website/ts/components/inputs/allowance_toggle.tsx @@ -57,7 +57,7 @@ const styles: Styles = { export class AllowanceToggle extends React.Component<AllowanceToggleProps, AllowanceToggleState> { public static defaultProps = { - onErrorOccurred: _.noop, + onErrorOccurred: _.noop.bind(_), isDisabled: false, }; constructor(props: AllowanceToggleProps) { diff --git a/packages/website/ts/components/inputs/balance_bounded_input.tsx b/packages/website/ts/components/inputs/balance_bounded_input.tsx index f23beb436..eb01e3ea6 100644 --- a/packages/website/ts/components/inputs/balance_bounded_input.tsx +++ b/packages/website/ts/components/inputs/balance_bounded_input.tsx @@ -35,7 +35,7 @@ export class BalanceBoundedInput extends React.Component<BalanceBoundedInputProp isDisabled: false, shouldShowErrs: true, hintText: 'amount', - onErrorMsgChange: _.noop, + onErrorMsgChange: _.noop.bind(_), shouldShowUnderline: true, }; constructor(props: BalanceBoundedInputProps) { @@ -125,7 +125,7 @@ export class BalanceBoundedInput extends React.Component<BalanceBoundedInputProp const errMsg = _.isUndefined(this.props.validate) ? undefined : this.props.validate(amount); return errMsg; } - private _setAmountState(amount: string, balance: BigNumber, callback: () => void = _.noop): void { + private _setAmountState(amount: string, balance: BigNumber, callback: () => void = _.noop.bind(_)): void { const errorMsg = this._validate(amount, balance); this.props.onErrorMsgChange(errorMsg); this.setState( diff --git a/packages/website/ts/components/inputs/expiration_input.tsx b/packages/website/ts/components/inputs/expiration_input.tsx index 79dd2f568..5417ce715 100644 --- a/packages/website/ts/components/inputs/expiration_input.tsx +++ b/packages/website/ts/components/inputs/expiration_input.tsx @@ -17,7 +17,7 @@ interface ExpirationInputState { } export class ExpirationInput extends React.Component<ExpirationInputProps, ExpirationInputState> { - private _earliestPickableMoment: moment.Moment; + private readonly _earliestPickableMoment: moment.Moment; constructor(props: ExpirationInputProps) { super(props); // Set the earliest pickable date to today at 00:00, so users can only pick the current or later dates diff --git a/packages/website/ts/components/order_json.tsx b/packages/website/ts/components/order_json.tsx index c2606bd56..cf06f10c8 100644 --- a/packages/website/ts/components/order_json.tsx +++ b/packages/website/ts/components/order_json.tsx @@ -127,7 +127,7 @@ export class OrderJSON extends React.Component<OrderJSONProps, OrderJSONState> { href: this.state.shareLink, method: 'share', }, - _.noop, + _.noop.bind(_), ); } private _shareViaEmailAsync(): void { diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index ea821d038..1790a9678 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -110,8 +110,8 @@ const SIDE_PADDING = 20; export class Portal extends React.Component<PortalProps, PortalState> { private _blockchain: Blockchain; - private _sharedOrderIfExists: Order; - private _throttledScreenWidthUpdate: () => void; + private readonly _sharedOrderIfExists: Order; + private readonly _throttledScreenWidthUpdate: () => void; constructor(props: PortalProps) { super(props); this._sharedOrderIfExists = orderParser.parse(window.location.search); diff --git a/packages/website/ts/components/ui/menu_item.tsx b/packages/website/ts/components/ui/menu_item.tsx index 64c0dc49d..0cb4b387c 100644 --- a/packages/website/ts/components/ui/menu_item.tsx +++ b/packages/website/ts/components/ui/menu_item.tsx @@ -15,7 +15,7 @@ interface MenuItemState { export class MenuItem extends React.Component<MenuItemProps, MenuItemState> { public static defaultProps: Partial<MenuItemProps> = { - onClick: _.noop, + onClick: _.noop.bind(_), className: '', }; public constructor(props: MenuItemProps) { diff --git a/packages/website/ts/components/ui/overlay.tsx b/packages/website/ts/components/ui/overlay.tsx index da26317de..fc7507475 100644 --- a/packages/website/ts/components/ui/overlay.tsx +++ b/packages/website/ts/components/ui/overlay.tsx @@ -26,7 +26,7 @@ export const Overlay: React.StatelessComponent<OverlayProps> = props => ( Overlay.defaultProps = { style: {}, - onClick: _.noop, + onClick: _.noop.bind(_), }; Overlay.displayName = 'Overlay'; diff --git a/packages/website/ts/components/ui/simple_menu.tsx b/packages/website/ts/components/ui/simple_menu.tsx index dcbc6946b..8a9349c6d 100644 --- a/packages/website/ts/components/ui/simple_menu.tsx +++ b/packages/website/ts/components/ui/simple_menu.tsx @@ -41,7 +41,7 @@ export const SimpleMenuItem: React.StatelessComponent<SimpleMenuItemProps> = ({ <Text fontSize="14px" fontColor={colors.darkGrey} - onClick={onClick || _.noop} + onClick={onClick || _.noop.bind(_)} hoverColor={colors.mediumBlue} > {displayText} diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index e462ab3e0..40a8a23ea 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -204,7 +204,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> { <AccountConnection accountState={accountState} injectedProviderName={this.props.injectedProviderName} /> </div> ); - const onClick = _.noop; + const onClick = _.noop.bind(_); const accessory = ( <DropDown activeNode={ diff --git a/packages/website/ts/local_storage/local_storage.ts b/packages/website/ts/local_storage/local_storage.ts index 1e3258ce0..13d9ca401 100644 --- a/packages/website/ts/local_storage/local_storage.ts +++ b/packages/website/ts/local_storage/local_storage.ts @@ -5,7 +5,7 @@ export const localStorage = { return !!window.localStorage; }, getItemIfExists(key: string): string { - if (!this.doesExist) { + if (!localStorage.doesExist) { return undefined; } const item = window.localStorage.getItem(key); @@ -15,13 +15,13 @@ export const localStorage = { return item; }, setItem(key: string, value: string): void { - if (!this.doesExist || _.isUndefined(value)) { + if (!localStorage.doesExist || _.isUndefined(value)) { return; } window.localStorage.setItem(key, value); }, removeItem(key: string): void { - if (!this.doesExist) { + if (!localStorage.doesExist) { return; } window.localStorage.removeItem(key); @@ -37,7 +37,7 @@ export const localStorage = { localStorage.setItem(key, JSON.stringify(value)); }, getAllKeys(): string[] { - if (!this.doesExist) { + if (!localStorage.doesExist) { return []; } return _.keys(window.localStorage); diff --git a/packages/website/ts/local_storage/tracked_token_storage.ts b/packages/website/ts/local_storage/tracked_token_storage.ts index f865f8109..b1b579aef 100644 --- a/packages/website/ts/local_storage/tracked_token_storage.ts +++ b/packages/website/ts/local_storage/tracked_token_storage.ts @@ -17,7 +17,7 @@ export const trackedTokenStorage = { localStorage.setItem(TRACKED_TOKENS_CLEAR_KEY, configs.LAST_LOCAL_STORAGE_TRACKED_TOKEN_CLEARANCE_DATE); }, addTrackedTokenToUser(userAddress: string, networkId: number, token: Token): void { - const trackedTokensByUserAddress = this.getTrackedTokensByUserAddress(); + const trackedTokensByUserAddress = trackedTokenStorage.getTrackedTokensByUserAddress(); let trackedTokensByNetworkId = trackedTokensByUserAddress[userAddress]; if (_.isUndefined(trackedTokensByNetworkId)) { trackedTokensByNetworkId = {}; @@ -57,7 +57,7 @@ export const trackedTokenStorage = { return trackedTokensByAddress; }, removeTrackedToken(userAddress: string, networkId: number, tokenAddress: string): void { - const trackedTokensByUserAddress = this.getTrackedTokensByUserAddress(); + const trackedTokensByUserAddress = trackedTokenStorage.getTrackedTokensByUserAddress(); const trackedTokensByNetworkId = trackedTokensByUserAddress[userAddress]; const trackedTokens = trackedTokensByNetworkId[networkId]; const remainingTrackedTokens = _.filter(trackedTokens, (token: Token) => { diff --git a/packages/website/ts/local_storage/trade_history_storage.tsx b/packages/website/ts/local_storage/trade_history_storage.tsx index 2e2f4e64e..a9b042820 100644 --- a/packages/website/ts/local_storage/trade_history_storage.tsx +++ b/packages/website/ts/local_storage/trade_history_storage.tsx @@ -27,31 +27,31 @@ export const tradeHistoryStorage = { localStorage.setItem(FILL_CLEAR_KEY, configs.LAST_LOCAL_STORAGE_FILL_CLEARANCE_DATE); }, addFillToUser(userAddress: string, networkId: number, fill: Fill): void { - const fillsByHash = this.getUserFillsByHash(userAddress, networkId); - const fillHash = this._getFillHash(fill); + const fillsByHash = tradeHistoryStorage.getUserFillsByHash(userAddress, networkId); + const fillHash = tradeHistoryStorage._getFillHash(fill); const doesFillExist = !_.isUndefined(fillsByHash[fillHash]); if (doesFillExist) { return; // noop } fillsByHash[fillHash] = fill; const userFillsJSONString = JSON.stringify(fillsByHash); - const userFillsKey = this._getUserFillsKey(userAddress, networkId); + const userFillsKey = tradeHistoryStorage._getUserFillsKey(userAddress, networkId); localStorage.setItem(userFillsKey, userFillsJSONString); }, removeFillFromUser(userAddress: string, networkId: number, fill: Fill): void { - const fillsByHash = this.getUserFillsByHash(userAddress, networkId); - const fillHash = this._getFillHash(fill); + const fillsByHash = tradeHistoryStorage.getUserFillsByHash(userAddress, networkId); + const fillHash = tradeHistoryStorage._getFillHash(fill); const doesFillExist = !_.isUndefined(fillsByHash[fillHash]); if (!doesFillExist) { return; // noop } delete fillsByHash[fillHash]; const userFillsJSONString = JSON.stringify(fillsByHash); - const userFillsKey = this._getUserFillsKey(userAddress, networkId); + const userFillsKey = tradeHistoryStorage._getUserFillsKey(userAddress, networkId); localStorage.setItem(userFillsKey, userFillsJSONString); }, getUserFillsByHash(userAddress: string, networkId: number): { [fillHash: string]: Fill } { - const userFillsKey = this._getUserFillsKey(userAddress, networkId); + const userFillsKey = tradeHistoryStorage._getUserFillsKey(userAddress, networkId); const userFillsJSONString = localStorage.getItemIfExists(userFillsKey); if (_.isEmpty(userFillsJSONString)) { return {}; @@ -66,7 +66,7 @@ export const tradeHistoryStorage = { return userFillsByHash; }, getFillsLatestBlock(userAddress: string, networkId: number): number { - const userFillsLatestBlockKey = this._getFillsLatestBlockKey(userAddress, networkId); + const userFillsLatestBlockKey = tradeHistoryStorage._getFillsLatestBlockKey(userAddress, networkId); const blockNumberStr = localStorage.getItemIfExists(userFillsLatestBlockKey); if (_.isEmpty(blockNumberStr)) { return constants.GENESIS_ORDER_BLOCK_BY_NETWORK_ID[networkId]; @@ -75,7 +75,7 @@ export const tradeHistoryStorage = { return blockNumber; }, setFillsLatestBlock(userAddress: string, networkId: number, blockNumber: number): void { - const userFillsLatestBlockKey = this._getFillsLatestBlockKey(userAddress, networkId); + const userFillsLatestBlockKey = tradeHistoryStorage._getFillsLatestBlockKey(userAddress, networkId); localStorage.setItem(userFillsLatestBlockKey, `${blockNumber}`); }, _getUserFillsKey(userAddress: string, networkId: number): string { diff --git a/packages/website/ts/pages/about/about.tsx b/packages/website/ts/pages/about/about.tsx index be4a67cb3..33581c938 100644 --- a/packages/website/ts/pages/about/about.tsx +++ b/packages/website/ts/pages/about/about.tsx @@ -181,14 +181,14 @@ const teamRow6: ProfileInfo[] = [ image: 'images/team/peter.jpg', linkedIn: 'https://www.linkedin.com/in/peter-z-7b9595163/', }, - // { - // name: 'Chris Kalani', - // title: 'Director of Design', - // description: `Previously founded Wake (acquired by InVision). Early Facebook product designer.`, - // image: 'images/team/chris.png', - // linkedIn: 'https://www.linkedin.com/in/chriskalani/', - // github: 'https://github.com/chriskalani', - // }, + { + name: 'Chris Kalani', + title: 'Director of Design', + description: `Previously founded Wake (acquired by InVision). Early Facebook product designer.`, + image: 'images/team/chris.png', + linkedIn: 'https://www.linkedin.com/in/chriskalani/', + github: 'https://github.com/chriskalani', + }, ]; const advisors: ProfileInfo[] = [ diff --git a/packages/website/ts/pages/jobs/jobs.tsx b/packages/website/ts/pages/jobs/jobs.tsx index 314669ee9..38cefa832 100644 --- a/packages/website/ts/pages/jobs/jobs.tsx +++ b/packages/website/ts/pages/jobs/jobs.tsx @@ -33,7 +33,7 @@ export interface JobsState {} export class Jobs extends React.Component<JobsProps, JobsState> { // TODO: consolidate this small screen scaffolding into one place (its being used in portal and docs as well) - private _throttledScreenWidthUpdate: () => void; + private readonly _throttledScreenWidthUpdate: () => void; public constructor(props: JobsProps) { super(props); this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT); diff --git a/packages/website/ts/pages/landing/landing.tsx b/packages/website/ts/pages/landing/landing.tsx index b2cf4d979..2a51ee3c0 100644 --- a/packages/website/ts/pages/landing/landing.tsx +++ b/packages/website/ts/pages/landing/landing.tsx @@ -171,7 +171,7 @@ interface LandingState { } export class Landing extends React.Component<LandingProps, LandingState> { - private _throttledScreenWidthUpdate: () => void; + private readonly _throttledScreenWidthUpdate: () => void; constructor(props: LandingProps) { super(props); this.state = { diff --git a/packages/website/ts/redux/dispatcher.ts b/packages/website/ts/redux/dispatcher.ts index e0ce43ae5..db008d319 100644 --- a/packages/website/ts/redux/dispatcher.ts +++ b/packages/website/ts/redux/dispatcher.ts @@ -17,7 +17,7 @@ import { } from 'ts/types'; export class Dispatcher { - private _dispatch: Dispatch<State>; + private readonly _dispatch: Dispatch<State>; constructor(dispatch: Dispatch<State>) { this._dispatch = dispatch; } diff --git a/packages/website/ts/utils/constants.ts b/packages/website/ts/utils/constants.ts index e43f541bf..20441cd75 100644 --- a/packages/website/ts/utils/constants.ts +++ b/packages/website/ts/utils/constants.ts @@ -58,7 +58,7 @@ export const constants = { PROJECT_URL_MAKER: 'https://makerdao.com', PROJECT_URL_ARAGON: 'https://aragon.one', PROJECT_URL_BLOCKNET: 'https://blocknet.co', - PROJECT_URL_0CEAN: 'http://the0cean.com', + PROJECT_URL_0CEAN: 'https://theocean.trade', PROJECT_URL_IMTOKEN: 'https://tokenlon.token.im/', PROJECT_URL_AUGUR: 'https://augur.net', PROJECT_URL_AUCTUS: 'https://auctus.org', diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index 739bb7b66..e656d5963 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -59,7 +59,7 @@ export const utils = { return moment.unix(unixTimestampSec.toNumber()); }, convertToReadableDateTimeFromUnixTimestamp(unixTimestampSec: BigNumber): string { - const m = this.convertToMomentFromUnixTimestamp(unixTimestampSec); + const m = utils.convertToMomentFromUnixTimestamp(unixTimestampSec); const formattedDate: string = m.format('h:MMa MMMM D YYYY'); return formattedDate; }, @@ -299,12 +299,12 @@ export const utils = { const baseUrl = `https://${window.location.hostname}${hasPort ? `:${port}` : ''}`; return baseUrl; }, - onPageLoadPromise: new Promise((resolve, _reject) => { + onPageLoadPromise: new Promise<void>((resolve, _reject) => { if (document.readyState === 'complete') { resolve(); return; } - window.onload = resolve; + window.onload = () => resolve(); }), getProviderType(provider: Provider): Providers | string { const constructorName = provider.constructor.name; @@ -364,7 +364,7 @@ export const utils = { return Environments.UNKNOWN; }, shouldShowJobsPage(): boolean { - return this.isDevelopment() || this.isStaging() || this.isDogfood(); + return utils.isDevelopment() || utils.isStaging() || utils.isDogfood(); }, getEthToken(tokenByAddress: TokenByAddress): Token { return utils.getTokenBySymbol(constants.ETHER_TOKEN_SYMBOL, tokenByAddress); @@ -379,7 +379,7 @@ export const utils = { }, getTrackedTokens(tokenByAddress: TokenByAddress): Token[] { const allTokens = _.values(tokenByAddress); - const trackedTokens = _.filter(allTokens, t => this.isTokenTracked(t)); + const trackedTokens = _.filter(allTokens, t => utils.isTokenTracked(t)); return trackedTokens; }, getFormattedAmountFromToken(token: Token, tokenState: TokenState): string { |