diff options
59 files changed, 418 insertions, 124 deletions
diff --git a/packages/0x.js/src/schemas/zero_ex_public_network_config_schema.ts b/packages/0x.js/src/schemas/zero_ex_public_network_config_schema.ts index 9da31481a..f7f6727f0 100644 --- a/packages/0x.js/src/schemas/zero_ex_public_network_config_schema.ts +++ b/packages/0x.js/src/schemas/zero_ex_public_network_config_schema.ts @@ -1,9 +1,23 @@ +const networkNameToId: { [networkName: string]: number } = { + mainnet: 1, + ropsten: 3, + rinkeby: 4, + kovan: 42, + ganache: 50, +}; + export const zeroExPublicNetworkConfigSchema = { id: '/ZeroExPublicNetworkConfig', properties: { networkId: { type: 'number', - enum: [1, 3, 4, 42, 50], + enum: [ + networkNameToId.mainnet, + networkNameToId.ropsten, + networkNameToId.rinkeby, + networkNameToId.kovan, + networkNameToId.ganache, + ], }, gasPrice: { $ref: '/Number' }, zrxContractAddress: { $ref: '/Address' }, diff --git a/packages/0x.js/test/global_hooks.ts b/packages/0x.js/test/global_hooks.ts index 53b3ef545..fa1dfae38 100644 --- a/packages/0x.js/test/global_hooks.ts +++ b/packages/0x.js/test/global_hooks.ts @@ -8,7 +8,8 @@ import { provider } from './utils/web3_wrapper'; 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. - this.timeout(20000); + const mochaTestTimeoutMs = 20000; + this.timeout(mochaTestTimeoutMs); const txDefaults = { gas: devConstants.GAS_ESTIMATE, from: devConstants.TESTRPC_FIRST_ADDRESS, diff --git a/packages/assert/test/assert_test.ts b/packages/assert/test/assert_test.ts index 58d3e53b5..e61ec93e0 100644 --- a/packages/assert/test/assert_test.ts +++ b/packages/assert/test/assert_test.ts @@ -11,6 +11,7 @@ chai.config.includeStack = true; chai.use(dirtyChai); const expect = chai.expect; +// tslint:disable:custom-no-magic-numbers describe('Assertions', () => { const variableName = 'variable'; describe('#isBigNumber', () => { @@ -252,3 +253,4 @@ describe('Assertions', () => { }); }); }); +// tslint:enable:custom-no-magic-numbers diff --git a/packages/contract-wrappers/src/schemas/contract_wrappers_public_network_config_schema.ts b/packages/contract-wrappers/src/schemas/contract_wrappers_public_network_config_schema.ts index bf1000afa..304cd100b 100644 --- a/packages/contract-wrappers/src/schemas/contract_wrappers_public_network_config_schema.ts +++ b/packages/contract-wrappers/src/schemas/contract_wrappers_public_network_config_schema.ts @@ -1,9 +1,23 @@ +const networkNameToId: { [networkName: string]: number } = { + mainnet: 1, + ropsten: 3, + rinkeby: 4, + kovan: 42, + ganache: 50, +}; + export const contractWrappersPublicNetworkConfigSchema = { id: '/ZeroExContractPublicNetworkConfig', properties: { networkId: { type: 'number', - enum: [1, 3, 4, 42, 50], + enum: [ + networkNameToId.mainnet, + networkNameToId.kovan, + networkNameToId.ropsten, + networkNameToId.rinkeby, + networkNameToId.ganache, + ], }, gasPrice: { $ref: '/Number' }, zrxContractAddress: { $ref: '/Address' }, diff --git a/packages/contract-wrappers/src/utils/constants.ts b/packages/contract-wrappers/src/utils/constants.ts index 07da6745d..76d805cac 100644 --- a/packages/contract-wrappers/src/utils/constants.ts +++ b/packages/contract-wrappers/src/utils/constants.ts @@ -6,6 +6,7 @@ export const constants = { INVALID_JUMP_PATTERN: 'invalid JUMP at', OUT_OF_GAS_PATTERN: 'out of gas', INVALID_TAKER_FORMAT: 'instance.taker is not of a type(s) string', + // tslint:disable-next-line:custom-no-magic-numbers UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1), DEFAULT_BLOCK_POLLING_INTERVAL: 1000, }; diff --git a/packages/contract-wrappers/src/utils/filter_utils.ts b/packages/contract-wrappers/src/utils/filter_utils.ts index c5df7321e..4ec9e256b 100644 --- a/packages/contract-wrappers/src/utils/filter_utils.ts +++ b/packages/contract-wrappers/src/utils/filter_utils.ts @@ -73,14 +73,14 @@ export const filterUtils = { return false; } if (!_.isUndefined(filter.topics)) { - return filterUtils.matchesTopics(log.topics, filter.topics); + return filterUtils.doesMatchTopics(log.topics, filter.topics); } return true; }, - matchesTopics(logTopics: string[], filterTopics: Array<string[] | string | null>): boolean { + doesMatchTopics(logTopics: string[], filterTopics: Array<string[] | string | null>): boolean { const matchesTopic = _.zipWith(logTopics, filterTopics, filterUtils.matchesTopic.bind(filterUtils)); - const matchesTopics = _.every(matchesTopic); - return matchesTopics; + const doesMatchTopics = _.every(matchesTopic); + return doesMatchTopics; }, matchesTopic(logTopic: string, filterTopic: string[] | string | null): boolean { if (_.isArray(filterTopic)) { diff --git a/packages/contract-wrappers/src/utils/utils.ts b/packages/contract-wrappers/src/utils/utils.ts index af1125632..7cf9450a0 100644 --- a/packages/contract-wrappers/src/utils/utils.ts +++ b/packages/contract-wrappers/src/utils/utils.ts @@ -5,7 +5,8 @@ export const utils = { return new Error(`Unexpected switch value: ${value} encountered for ${name}`); }, getCurrentUnixTimestampSec(): BigNumber { - return new BigNumber(Date.now() / 1000).round(); + const milisecondsInSecond = 1000; + return new BigNumber(Date.now() / milisecondsInSecond).round(); }, getCurrentUnixTimestampMs(): BigNumber { return new BigNumber(Date.now()); diff --git a/packages/contract-wrappers/test/ether_token_wrapper_test.ts b/packages/contract-wrappers/test/ether_token_wrapper_test.ts index 974db34b1..e06fe96e5 100644 --- a/packages/contract-wrappers/test/ether_token_wrapper_test.ts +++ b/packages/contract-wrappers/test/ether_token_wrapper_test.ts @@ -42,7 +42,7 @@ describe('EtherTokenWrapper', () => { let addressWithETH: string; let wethContractAddress: string; let depositWeiAmount: BigNumber; - let decimalPlaces: number; + const decimalPlaces = 7; let addressWithoutFunds: string; const gasPrice = new BigNumber(1); const zeroExConfig = { @@ -60,7 +60,6 @@ describe('EtherTokenWrapper', () => { addressWithETH = userAddresses[0]; wethContractAddress = contractWrappers.etherToken.getContractAddressIfExists() as string; depositWeiAmount = Web3Wrapper.toWei(new BigNumber(5)); - decimalPlaces = 7; addressWithoutFunds = userAddresses[1]; }); beforeEach(async () => { @@ -155,6 +154,7 @@ describe('EtherTokenWrapper', () => { const preWETHBalance = await contractWrappers.token.getBalanceAsync(wethContractAddress, addressWithETH); expect(preWETHBalance).to.be.bignumber.equal(0); + // tslint:disable-next-line:custom-no-magic-numbers const overWETHBalance = preWETHBalance.add(999999999); return expect( diff --git a/packages/contract-wrappers/test/global_hooks.ts b/packages/contract-wrappers/test/global_hooks.ts index 53b3ef545..fa1dfae38 100644 --- a/packages/contract-wrappers/test/global_hooks.ts +++ b/packages/contract-wrappers/test/global_hooks.ts @@ -8,7 +8,8 @@ import { provider } from './utils/web3_wrapper'; 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. - this.timeout(20000); + const mochaTestTimeoutMs = 20000; + this.timeout(mochaTestTimeoutMs); const txDefaults = { gas: devConstants.GAS_ESTIMATE, from: devConstants.TESTRPC_FIRST_ADDRESS, diff --git a/packages/contract-wrappers/test/order_validation_test.ts b/packages/contract-wrappers/test/order_validation_test.ts index 2acdece3e..a14dc24b6 100644 --- a/packages/contract-wrappers/test/order_validation_test.ts +++ b/packages/contract-wrappers/test/order_validation_test.ts @@ -106,6 +106,7 @@ describe('OrderValidation', () => { }); it('should succeed if the order is asymmetric and fillable', async () => { const makerFillableAmount = fillableAmount; + // tslint:disable-next-line:custom-no-magic-numbers const takerFillableAmount = fillableAmount.minus(4); const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync( makerTokenAddress, @@ -172,6 +173,7 @@ describe('OrderValidation', () => { fillableAmount, ); // 27 <--> 28 + // tslint:disable-next-line:custom-no-magic-numbers signedOrder.ecSignature.v = 28 - signedOrder.ecSignature.v + 27; return expect( contractWrappers.exchange.validateFillOrderThrowIfInvalidAsync( @@ -206,6 +208,7 @@ describe('OrderValidation', () => { takerAddress, fillableAmount, ); + // tslint:disable-next-line:custom-no-magic-numbers const nonTakerAddress = userAddresses[6]; return expect( contractWrappers.exchange.validateFillOrderThrowIfInvalidAsync( @@ -353,6 +356,7 @@ describe('OrderValidation', () => { takerAddress, zrxTokenAddress, ); + // tslint:disable-next-line:custom-no-magic-numbers expect(transferFromAsync.callCount).to.be.equal(4); expect( transferFromAsync @@ -423,6 +427,7 @@ describe('OrderValidation', () => { takerAddress, zrxTokenAddress, ); + // tslint:disable-next-line:custom-no-magic-numbers expect(transferFromAsync.callCount).to.be.equal(4); expect( transferFromAsync @@ -491,6 +496,7 @@ describe('OrderValidation', () => { takerAddress, zrxTokenAddress, ); + // tslint:disable-next-line:custom-no-magic-numbers expect(transferFromAsync.callCount).to.be.equal(4); const makerFillAmount = transferFromAsync.getCall(0).args[3]; expect(makerFillAmount).to.be.bignumber.equal(makerTokenAmount); @@ -518,6 +524,7 @@ describe('OrderValidation', () => { ); const makerPartialFee = makerFee.div(2); const takerPartialFee = takerFee.div(2); + // tslint:disable-next-line:custom-no-magic-numbers expect(transferFromAsync.callCount).to.be.equal(4); const partialMakerFee = transferFromAsync.getCall(2).args[3]; expect(partialMakerFee).to.be.bignumber.equal(makerPartialFee); diff --git a/packages/contracts/test/unlimited_allowance_token.ts b/packages/contracts/test/unlimited_allowance_token.ts index 8851a04ef..5ad9321e8 100644 --- a/packages/contracts/test/unlimited_allowance_token.ts +++ b/packages/contracts/test/unlimited_allowance_token.ts @@ -97,8 +97,8 @@ describe('UnlimitedAllowanceToken', () => { const amountToTransfer = ownerBalance; const spenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); - const spenderAllowanceIsInsufficient = spenderAllowance.cmp(amountToTransfer) < 0; - expect(spenderAllowanceIsInsufficient).to.be.true(); + const isSpenderAllowanceInsufficient = spenderAllowance.cmp(amountToTransfer) < 0; + expect(isSpenderAllowanceInsufficient).to.be.true(); return expect( token.transferFrom.callAsync(owner, spender, amountToTransfer, { diff --git a/packages/contracts/test/zrx_token.ts b/packages/contracts/test/zrx_token.ts index 7a72f85dc..48b8f6e36 100644 --- a/packages/contracts/test/zrx_token.ts +++ b/packages/contracts/test/zrx_token.ts @@ -118,8 +118,8 @@ describe('ZRXToken', () => { const amountToTransfer = ownerBalance; const spenderAllowance = await zeroEx.token.getAllowanceAsync(zrxAddress, owner, spender); - const spenderAllowanceIsInsufficient = spenderAllowance.cmp(amountToTransfer) < 0; - expect(spenderAllowanceIsInsufficient).to.be.true(); + const isSpenderAllowanceInsufficient = spenderAllowance.cmp(amountToTransfer) < 0; + expect(isSpenderAllowanceInsufficient).to.be.true(); const didReturnTrue = await zrxToken.transferFrom.callAsync(owner, spender, amountToTransfer, { from: spender, diff --git a/packages/contracts/tslint.json b/packages/contracts/tslint.json index ffaefe83a..1ab924e47 100644 --- a/packages/contracts/tslint.json +++ b/packages/contracts/tslint.json @@ -1,3 +1,6 @@ { - "extends": ["@0xproject/tslint-config"] + "extends": ["@0xproject/tslint-config"], + "rules": { + "custom-no-magic-numbers": false + } } diff --git a/packages/json-schemas/test/schema_test.ts b/packages/json-schemas/test/schema_test.ts index ac6a68b59..b9574a0c9 100644 --- a/packages/json-schemas/test/schema_test.ts +++ b/packages/json-schemas/test/schema_test.ts @@ -149,7 +149,8 @@ describe('Schema', () => { }); describe('#blockParamSchema', () => { it('should validate valid block param', () => { - const testCases = [42, 'latest', 'pending', 'earliest']; + const blockNumber = 42; + const testCases = [blockNumber, 'latest', 'pending', 'earliest']; validateAgainstSchema(testCases, blockParamSchema); }); it('should fail for invalid block param', () => { @@ -182,6 +183,7 @@ describe('Schema', () => { validateAgainstSchema(testCases, tokenSchema); }); it('should fail for invalid token', () => { + const num = 4; const testCases = [ { ...token, @@ -192,7 +194,7 @@ describe('Schema', () => { decimals: undefined, }, [], - 4, + num, ]; const shouldFail = true; validateAgainstSchema(testCases, tokenSchema, shouldFail); @@ -871,10 +873,12 @@ describe('Schema', () => { }); describe('#jsNumberSchema', () => { it('should validate valid js number', () => { + // tslint:disable-next-line:custom-no-magic-numbers const testCases = [1, 42]; validateAgainstSchema(testCases, jsNumber); }); it('should fail for invalid js number', () => { + // tslint:disable-next-line:custom-no-magic-numbers const testCases = [NaN, -1, new BigNumber(1)]; const shouldFail = true; validateAgainstSchema(testCases, jsNumber, shouldFail); @@ -882,13 +886,14 @@ describe('Schema', () => { }); describe('#txDataSchema', () => { it('should validate valid txData', () => { + const bigNumGasAmount = new BigNumber(42); const testCases = [ { from: NULL_ADDRESS, }, { from: NULL_ADDRESS, - gas: new BigNumber(42), + gas: bigNumGasAmount, }, { from: NULL_ADDRESS, diff --git a/packages/migrations/package.json b/packages/migrations/package.json index ab5204d86..d9e68caaf 100644 --- a/packages/migrations/package.json +++ b/packages/migrations/package.json @@ -12,7 +12,7 @@ "prebuild": "run-s clean compile copy_artifacts generate_contract_wrappers", "copy_artifacts": "copyfiles 'artifacts/1.0.0/**/*' ./lib", "build": "tsc", - "clean": "shx rm -rf lib", + "clean": "shx rm -rf lib src/contract_wrappers", "lint": "tslint --project .", "migrate": "run-s build compile script:migrate", "script:migrate": "node ./lib/migrate.js", diff --git a/packages/migrations/src/migration.ts b/packages/migrations/src/migration.ts index 57ac311d7..e29414a57 100644 --- a/packages/migrations/src/migration.ts +++ b/packages/migrations/src/migration.ts @@ -80,11 +80,12 @@ export const runMigrationsAsync = async (provider: Provider, artifactsDir: strin tokenInfo[0].swarmHash, { from: owner }, ); + const decimals = 18; await tokenReg.addToken.sendTransactionAsync( zrxToken.address, '0x Protocol Token', 'ZRX', - 18, + decimals, NULL_BYTES, NULL_BYTES, { @@ -96,7 +97,7 @@ export const runMigrationsAsync = async (provider: Provider, artifactsDir: strin etherToken.address, 'Ether Token', 'WETH', - 18, + decimals, NULL_BYTES, NULL_BYTES, { diff --git a/packages/monorepo-scripts/src/postpublish_utils.ts b/packages/monorepo-scripts/src/postpublish_utils.ts index 22614f01b..f5785343d 100644 --- a/packages/monorepo-scripts/src/postpublish_utils.ts +++ b/packages/monorepo-scripts/src/postpublish_utils.ts @@ -158,6 +158,7 @@ export const postpublishUtils = { // HACK: tsconfig.json needs wildcard directory endings as `/**/*` // but TypeDoc needs it as `/**` in order to pick up files at the root if (_.endsWith(includePath, '/**/*')) { + // tslint:disable-next-line:custom-no-magic-numbers includePath = includePath.slice(0, -2); } return includePath; diff --git a/packages/monorepo-scripts/src/publish.ts b/packages/monorepo-scripts/src/publish.ts index 5c26475c9..73106821a 100644 --- a/packages/monorepo-scripts/src/publish.ts +++ b/packages/monorepo-scripts/src/publish.ts @@ -285,8 +285,8 @@ function shouldAddNewChangelogEntry(currentVersion: string, changelogs: Changelo return true; } const lastEntry = changelogs[0]; - const lastEntryCurrentVersion = lastEntry.version === currentVersion; - return lastEntryCurrentVersion; + const isLastEntryCurrentVersion = lastEntry.version === currentVersion; + return isLastEntryCurrentVersion; } function generateChangelogMd(changelogs: Changelog[]): string { diff --git a/packages/order-utils/src/order_hash.ts b/packages/order-utils/src/order_hash.ts index 1cde72a73..108344a04 100644 --- a/packages/order-utils/src/order_hash.ts +++ b/packages/order-utils/src/order_hash.ts @@ -17,7 +17,8 @@ const INVALID_TAKER_FORMAT = 'instance.taker is not of a type(s) string'; * We do not use BN anywhere else in the codebase. */ function bigNumberToBN(value: BigNumber): BN { - return new BN(value.toString(), 10); + const base = 10; + return new BN(value.toString(), base); } /** diff --git a/packages/order-utils/src/signature_utils.ts b/packages/order-utils/src/signature_utils.ts index b511573a8..28a8e7241 100644 --- a/packages/order-utils/src/signature_utils.ts +++ b/packages/order-utils/src/signature_utils.ts @@ -72,6 +72,7 @@ export async function signOrderHashAsync( // v + r + s OR r + s + v, and different clients (even different versions of the same client) // return the signature params in different orders. In order to support all client implementations, // we parse the signature in both ways, and evaluate if either one is a valid signature. + // tslint:disable-next-line:custom-no-magic-numbers const validVParamValues = [27, 28]; const ecSignatureVRS = parseSignatureHexAsVRS(signature); if (_.includes(validVParamValues, ecSignatureVRS.v)) { @@ -95,11 +96,19 @@ export async function signOrderHashAsync( function parseSignatureHexAsVRS(signatureHex: string): ECSignature { const signatureBuffer = ethUtil.toBuffer(signatureHex); let v = signatureBuffer[0]; - if (v < 27) { - v += 27; + // HACK: Sometimes v is returned as [0, 1] and sometimes as [27, 28] + // If it is returned as [0, 1], add 27 to both so it becomes [27, 28] + const lowestValidV = 27; + const isProperlyFormattedV = v < lowestValidV; + if (!isProperlyFormattedV) { + v += lowestValidV; } - const r = signatureBuffer.slice(1, 33); - const s = signatureBuffer.slice(33, 65); + // signatureBuffer contains vrs + const vEndIndex = 1; + const rsIndex = 33; + const r = signatureBuffer.slice(vEndIndex, rsIndex); + const sEndIndex = 65; + const s = signatureBuffer.slice(rsIndex, sEndIndex); const ecSignature: ECSignature = { v, r: ethUtil.bufferToHex(r), diff --git a/packages/order-utils/test/signature_utils_test.ts b/packages/order-utils/test/signature_utils_test.ts index 4b4de9217..e24fa0ce5 100644 --- a/packages/order-utils/test/signature_utils_test.ts +++ b/packages/order-utils/test/signature_utils_test.ts @@ -47,12 +47,13 @@ describe('Signature utils', () => { }); describe('#generateSalt', () => { it('generates different salts', () => { - const equal = generatePseudoRandomSalt().eq(generatePseudoRandomSalt()); - expect(equal).to.be.false(); + const isEqual = generatePseudoRandomSalt().eq(generatePseudoRandomSalt()); + expect(isEqual).to.be.false(); }); it('generates salt in range [0..2^256)', () => { const salt = generatePseudoRandomSalt(); expect(salt.greaterThanOrEqualTo(0)).to.be.true(); + // tslint:disable-next-line:custom-no-magic-numbers const twoPow256 = new BigNumber(2).pow(256); expect(salt.lessThan(twoPow256)).to.be.true(); }); @@ -67,7 +68,8 @@ describe('Signature utils', () => { expect(isValid).to.be.false(); }); it('returns true if order hash is correct', () => { - const isValid = isValidOrderHash('0x' + Array(65).join('0')); + const orderHashLength = 65; + const isValid = isValidOrderHash('0x' + Array(orderHashLength).join('0')); expect(isValid).to.be.true(); }); }); @@ -111,10 +113,12 @@ describe('Signature utils', () => { if (payload.method === 'eth_sign') { const [address, message] = payload.params; const signature = await web3Wrapper.signMessageAsync(address, message); + // tslint:disable-next-line:custom-no-magic-numbers + const rsvHex = `0x${signature.substr(130)}${signature.substr(2, 128)}`; callback(null, { id: 42, jsonrpc: '2.0', - result: `0x${signature.substr(130)}${signature.substr(2, 128)}`, + result: rsvHex, }); } else { callback(null, { id: 42, jsonrpc: '2.0', result: [makerAddress] }); diff --git a/packages/order-watcher/src/order_watcher/order_watcher.ts b/packages/order-watcher/src/order_watcher/order_watcher.ts index 3c93d6293..29936a066 100644 --- a/packages/order-watcher/src/order_watcher/order_watcher.ts +++ b/packages/order-watcher/src/order_watcher/order_watcher.ts @@ -60,6 +60,7 @@ interface OrderStateByOrderHash { [orderHash: string]: OrderState; } +// tslint:disable-next-line:custom-no-magic-numbers const DEFAULT_CLEANUP_JOB_INTERVAL_MS = 1000 * 60 * 60; // 1h /** @@ -130,7 +131,8 @@ export class OrderWatcher { assert.isValidSignature(orderHash, signedOrder.ecSignature, signedOrder.maker); this._orderByOrderHash[orderHash] = signedOrder; this._addToDependentOrderHashes(signedOrder, orderHash); - const expirationUnixTimestampMs = signedOrder.expirationUnixTimestampSec.times(1000); + const milisecondsInASecond = 1000; + const expirationUnixTimestampMs = signedOrder.expirationUnixTimestampSec.times(milisecondsInASecond); this._expirationWatcher.addOrder(orderHash, expirationUnixTimestampMs); } /** diff --git a/packages/order-watcher/src/utils/utils.ts b/packages/order-watcher/src/utils/utils.ts index af1125632..d34f6b99f 100644 --- a/packages/order-watcher/src/utils/utils.ts +++ b/packages/order-watcher/src/utils/utils.ts @@ -5,7 +5,8 @@ export const utils = { return new Error(`Unexpected switch value: ${value} encountered for ${name}`); }, getCurrentUnixTimestampSec(): BigNumber { - return new BigNumber(Date.now() / 1000).round(); + const milisecondsInASecond = 1000; + return new BigNumber(Date.now() / milisecondsInASecond).round(); }, getCurrentUnixTimestampMs(): BigNumber { return new BigNumber(Date.now()); diff --git a/packages/order-watcher/test/expiration_watcher_test.ts b/packages/order-watcher/test/expiration_watcher_test.ts index 8b006f58a..ef15bf006 100644 --- a/packages/order-watcher/test/expiration_watcher_test.ts +++ b/packages/order-watcher/test/expiration_watcher_test.ts @@ -22,6 +22,7 @@ import { provider, web3Wrapper } from './utils/web3_wrapper'; chaiSetup.configure(); const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); +const MILISECONDS_IN_SECOND = 1000; describe('ExpirationWatcher', () => { let contractWrappers: ContractWrappers; @@ -84,13 +85,13 @@ describe('ExpirationWatcher', () => { expirationUnixTimestampSec, ); const orderHash = getOrderHashHex(signedOrder); - expirationWatcher.addOrder(orderHash, signedOrder.expirationUnixTimestampSec.times(1000)); + expirationWatcher.addOrder(orderHash, signedOrder.expirationUnixTimestampSec.times(MILISECONDS_IN_SECOND)); const callbackAsync = callbackErrorReporter.reportNoErrorCallbackErrors(done)((hash: string) => { expect(hash).to.be.equal(orderHash); expect(utils.getCurrentUnixTimestampSec()).to.be.bignumber.gte(expirationUnixTimestampSec); }); expirationWatcher.subscribe(callbackAsync); - timer.tick(orderLifetimeSec * 1000); + timer.tick(orderLifetimeSec * MILISECONDS_IN_SECOND); })().catch(done); }); it("doesn't emit events before order expires", (done: DoneCallback) => { @@ -106,13 +107,13 @@ describe('ExpirationWatcher', () => { expirationUnixTimestampSec, ); const orderHash = getOrderHashHex(signedOrder); - expirationWatcher.addOrder(orderHash, signedOrder.expirationUnixTimestampSec.times(1000)); + expirationWatcher.addOrder(orderHash, signedOrder.expirationUnixTimestampSec.times(MILISECONDS_IN_SECOND)); const callbackAsync = callbackErrorReporter.reportNoErrorCallbackErrors(done)(async (hash: string) => { done(new Error('Emitted expiration went before the order actually expired')); }); expirationWatcher.subscribe(callbackAsync); const notEnoughTime = orderLifetimeSec - 1; - timer.tick(notEnoughTime * 1000); + timer.tick(notEnoughTime * MILISECONDS_IN_SECOND); done(); })().catch(done); }); @@ -140,8 +141,14 @@ describe('ExpirationWatcher', () => { ); const orderHash1 = getOrderHashHex(signedOrder1); const orderHash2 = getOrderHashHex(signedOrder2); - expirationWatcher.addOrder(orderHash2, signedOrder2.expirationUnixTimestampSec.times(1000)); - expirationWatcher.addOrder(orderHash1, signedOrder1.expirationUnixTimestampSec.times(1000)); + expirationWatcher.addOrder( + orderHash2, + signedOrder2.expirationUnixTimestampSec.times(MILISECONDS_IN_SECOND), + ); + expirationWatcher.addOrder( + orderHash1, + signedOrder1.expirationUnixTimestampSec.times(MILISECONDS_IN_SECOND), + ); const expirationOrder = [orderHash1, orderHash2]; const expectToBeCalledOnce = false; const callbackAsync = callbackErrorReporter.reportNoErrorCallbackErrors(done, expectToBeCalledOnce)( @@ -154,7 +161,7 @@ describe('ExpirationWatcher', () => { }, ); expirationWatcher.subscribe(callbackAsync); - timer.tick(order2Lifetime * 1000); + timer.tick(order2Lifetime * MILISECONDS_IN_SECOND); })().catch(done); }); it('emits events in correct order when expirations are equal', (done: DoneCallback) => { @@ -181,8 +188,14 @@ describe('ExpirationWatcher', () => { ); const orderHash1 = getOrderHashHex(signedOrder1); const orderHash2 = getOrderHashHex(signedOrder2); - expirationWatcher.addOrder(orderHash1, signedOrder1.expirationUnixTimestampSec.times(1000)); - expirationWatcher.addOrder(orderHash2, signedOrder2.expirationUnixTimestampSec.times(1000)); + expirationWatcher.addOrder( + orderHash1, + signedOrder1.expirationUnixTimestampSec.times(MILISECONDS_IN_SECOND), + ); + expirationWatcher.addOrder( + orderHash2, + signedOrder2.expirationUnixTimestampSec.times(MILISECONDS_IN_SECOND), + ); const expirationOrder = orderHash1 < orderHash2 ? [orderHash1, orderHash2] : [orderHash2, orderHash1]; const expectToBeCalledOnce = false; const callbackAsync = callbackErrorReporter.reportNoErrorCallbackErrors(done, expectToBeCalledOnce)( @@ -195,7 +208,7 @@ describe('ExpirationWatcher', () => { }, ); expirationWatcher.subscribe(callbackAsync); - timer.tick(order2Lifetime * 1000); + timer.tick(order2Lifetime * MILISECONDS_IN_SECOND); })().catch(done); }); }); diff --git a/packages/order-watcher/test/global_hooks.ts b/packages/order-watcher/test/global_hooks.ts index 03eab0e13..d4d033dd4 100644 --- a/packages/order-watcher/test/global_hooks.ts +++ b/packages/order-watcher/test/global_hooks.ts @@ -9,7 +9,8 @@ import { provider } from './utils/web3_wrapper'; 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. - this.timeout(20000); + const mochaTestTimeoutMs = 20000; + this.timeout(mochaTestTimeoutMs); const txDefaults = { gas: devConstants.GAS_ESTIMATE, 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 dc8e544b1..0d33e7ea2 100644 --- a/packages/order-watcher/test/order_watcher_test.ts +++ b/packages/order-watcher/test/order_watcher_test.ts @@ -269,8 +269,8 @@ describe('OrderWatcher', () => { }); it('should trigger the callback when orders backing ZRX allowance changes', (done: DoneCallback) => { (async () => { - const makerFee = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18); - const takerFee = Web3Wrapper.toBaseUnitAmount(new BigNumber(0), 18); + const makerFee = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), decimals); + const takerFee = Web3Wrapper.toBaseUnitAmount(new BigNumber(0), decimals); signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync( makerToken.address, takerToken.address, diff --git a/packages/react-docs/src/docs_info.ts b/packages/react-docs/src/docs_info.ts index e9c84b7c9..6f4f39f00 100644 --- a/packages/react-docs/src/docs_info.ts +++ b/packages/react-docs/src/docs_info.ts @@ -64,8 +64,8 @@ export class DocsInfo { finalMenu.contracts = _.filter(finalMenu.contracts, (contractName: string) => { const versionIntroducedIfExists = this._docsInfo.menuSubsectionToVersionWhenIntroduced[contractName]; if (!_.isUndefined(versionIntroducedIfExists)) { - const existsInSelectedVersion = compareVersions(selectedVersion, versionIntroducedIfExists) >= 0; - return existsInSelectedVersion; + const doesExistInSelectedVersion = compareVersions(selectedVersion, versionIntroducedIfExists) >= 0; + return doesExistInSelectedVersion; } else { return true; } diff --git a/packages/react-docs/tslint.json b/packages/react-docs/tslint.json index ee918e360..c78434416 100644 --- a/packages/react-docs/tslint.json +++ b/packages/react-docs/tslint.json @@ -3,6 +3,7 @@ "rules": { "no-object-literal-type-assertion": false, "completed-docs": false, - "prefer-function-over-method": false + "prefer-function-over-method": false, + "custom-no-magic-numbers": false } } diff --git a/packages/react-shared/tslint.json b/packages/react-shared/tslint.json index ee918e360..c78434416 100644 --- a/packages/react-shared/tslint.json +++ b/packages/react-shared/tslint.json @@ -3,6 +3,7 @@ "rules": { "no-object-literal-type-assertion": false, "completed-docs": false, - "prefer-function-over-method": false + "prefer-function-over-method": false, + "custom-no-magic-numbers": false } } diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index efb30091b..c17616246 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -152,7 +152,8 @@ export class Compiler { logUtils.log(`Downloading ${fullSolcVersion}...`); const url = `${constants.BASE_COMPILER_URL}${fullSolcVersion}`; const response = await fetch(url); - if (response.status !== 200) { + const SUCCESS_STATUS = 200; + if (response.status !== SUCCESS_STATUS) { throw new Error(`Failed to load ${fullSolcVersion}`); } solcjs = await response.text(); diff --git a/packages/sol-compiler/test/compiler_test.ts b/packages/sol-compiler/test/compiler_test.ts index dc8eb1c4e..991965caa 100644 --- a/packages/sol-compiler/test/compiler_test.ts +++ b/packages/sol-compiler/test/compiler_test.ts @@ -39,8 +39,13 @@ describe('#Compiler', function(): void { const exchangeArtifactString = await fsWrapper.readFileAsync(exchangeArtifactPath, opts); const exchangeArtifact: ContractArtifact = JSON.parse(exchangeArtifactString); // The last 43 bytes of the binaries are metadata which may not be equivalent - const unlinkedBinaryWithoutMetadata = exchangeArtifact.compilerOutput.evm.bytecode.object.slice(2, -86); - const exchangeBinaryWithoutMetadata = exchange_binary.slice(0, -86); + const metadataByteLength = 43; + const metadataHexLength = metadataByteLength * 2; + const unlinkedBinaryWithoutMetadata = exchangeArtifact.compilerOutput.evm.bytecode.object.slice( + 2, + -metadataHexLength, + ); + const exchangeBinaryWithoutMetadata = exchange_binary.slice(0, -metadataHexLength); expect(unlinkedBinaryWithoutMetadata).to.equal(exchangeBinaryWithoutMetadata); }); }); diff --git a/packages/sol-cov/test/collect_coverage_entries_test.ts b/packages/sol-cov/test/collect_coverage_entries_test.ts index 82012edfa..a03be19cd 100644 --- a/packages/sol-cov/test/collect_coverage_entries_test.ts +++ b/packages/sol-cov/test/collect_coverage_entries_test.ts @@ -40,12 +40,14 @@ describe('Collect coverage entries', () => { const coverageEntries = collectCoverageEntries(simpleStorageContract); const fnIds = _.keys(coverageEntries.fnMap); expect(coverageEntries.fnMap[fnIds[0]].name).to.be.equal('set'); + // tslint:disable-next-line:custom-no-magic-numbers expect(coverageEntries.fnMap[fnIds[0]].line).to.be.equal(5); const setFunction = `function set(uint x) { storedData = x; }`; expect(getRange(simpleStorageContract, coverageEntries.fnMap[fnIds[0]].loc)).to.be.equal(setFunction); expect(coverageEntries.fnMap[fnIds[1]].name).to.be.equal('get'); + // tslint:disable-next-line:custom-no-magic-numbers expect(coverageEntries.fnMap[fnIds[1]].line).to.be.equal(8); const getFunction = `function get() constant returns (uint retVal) { return storedData; @@ -122,6 +124,7 @@ describe('Collect coverage entries', () => { const branchDescriptions = _.values(coverageEntries.branchMap); const branchLines = _.map(branchDescriptions, branchDescription => branchDescription.line); + // tslint:disable-next-line:custom-no-magic-numbers expect(branchLines).to.be.deep.equal([94, 115, 119, 130, 151, 187]); const branchTypes = _.map(branchDescriptions, branchDescription => branchDescription.type); expect(branchTypes).to.be.deep.equal(['if', 'if', 'if', 'if', 'binary-expr', 'if']); diff --git a/packages/sol-cov/test/instructions_test.ts b/packages/sol-cov/test/instructions_test.ts index f66612f5f..8012674f5 100644 --- a/packages/sol-cov/test/instructions_test.ts +++ b/packages/sol-cov/test/instructions_test.ts @@ -12,6 +12,7 @@ const expect = chai.expect; describe('instructions', () => { describe('#getPcToInstructionIndexMapping', () => { it('correctly maps pcs to instruction indexed', () => { + // tslint:disable-next-line:custom-no-magic-numbers const bytecode = new Uint8Array([constants.PUSH1, 42, constants.PUSH2, 1, 2, constants.TIMESTAMP]); const pcToInstruction = getPcToInstructionIndexMapping(bytecode); const expectedPcToInstruction = { '0': 0, '2': 1, '5': 2 }; diff --git a/packages/sra-report/src/index.ts b/packages/sra-report/src/index.ts index 9a203b654..3b72ad44e 100644 --- a/packages/sra-report/src/index.ts +++ b/packages/sra-report/src/index.ts @@ -13,7 +13,18 @@ import { postmanEnvironmentFactory } from './postman_environment_factory'; import { utils } from './utils'; const DEFAULT_NETWORK_ID = 1; -const SUPPORTED_NETWORK_IDS = [1, 3, 4, 42]; +const networkNameToId: { [networkName: string]: number } = { + mainnet: 1, + ropsten: 3, + rinkeby: 4, + kovan: 42, +}; +const SUPPORTED_NETWORK_IDS = [ + networkNameToId.mainnet, + networkNameToId.ropsten, + networkNameToId.rinkeby, + networkNameToId.kovan, +]; // extract command line arguments const args = yargs diff --git a/packages/sra-report/src/postman_environment_factory.ts b/packages/sra-report/src/postman_environment_factory.ts index 42389aea2..e899aaa79 100644 --- a/packages/sra-report/src/postman_environment_factory.ts +++ b/packages/sra-report/src/postman_environment_factory.ts @@ -11,6 +11,12 @@ import { addresses as rinkebyAddresses } from './contract_addresses/rinkeby_addr import { addresses as ropstenAddresses } from './contract_addresses/ropsten_addresses'; const ENVIRONMENT_NAME = 'SRA Report'; +const networkNameToId: { [networkName: string]: number } = { + mainnet: 1, + ropsten: 3, + rinkeby: 4, + kovan: 42, +}; export interface EnvironmentValue { key: string; @@ -107,13 +113,13 @@ async function createOrderEnvironmentValuesAsync(url: string): Promise<Environme } function getContractAddresses(networkId: number): Addresses { switch (networkId) { - case 1: + case networkNameToId.mainnet: return mainnetAddresses; - case 3: + case networkNameToId.ropsten: return ropstenAddresses; - case 4: + case networkNameToId.rinkeby: return rinkebyAddresses; - case 42: + case networkNameToId.kovan: return kovanAddresses; default: throw new Error('Unsupported network id'); diff --git a/packages/sra-report/test/test_runner.ts b/packages/sra-report/test/test_runner.ts index 5ea3cdc4d..fe238e98a 100644 --- a/packages/sra-report/test/test_runner.ts +++ b/packages/sra-report/test/test_runner.ts @@ -24,6 +24,7 @@ const expect = chai.expect; const CONTENT_TYPE_ASSERTION_NAME = 'Has Content-Type header with value application/json'; const SCHEMA_ASSERTION_NAME = 'Schema is valid'; +const SUCCESS_STATUS = 200; const baseNewmanRunOptions = { collection: sraReportCollectionJSON, environment: postmanEnvironmentJSON, @@ -46,7 +47,7 @@ export const testRunner = { }; describe(CONTENT_TYPE_ASSERTION_NAME, () => { it('fails when there are no headers', async () => { - nockInterceptor.reply(200, {}); + nockInterceptor.reply(SUCCESS_STATUS, {}); const summary = await utils.newmanRunAsync(newmanRunOptions); const error = findAssertionErrorIfExists( summary, @@ -61,7 +62,7 @@ export const testRunner = { const headers = { 'Content-Type': 'text/html', }; - nockInterceptor.reply(200, {}, headers); + nockInterceptor.reply(SUCCESS_STATUS, {}, headers); const summary = await utils.newmanRunAsync(newmanRunOptions); const error = findAssertionErrorIfExists( summary, @@ -76,7 +77,7 @@ export const testRunner = { const headers = { 'Content-Type': 'charset=utf-8; application/json', }; - nockInterceptor.reply(200, {}, headers); + nockInterceptor.reply(SUCCESS_STATUS, {}, headers); const summary = await utils.newmanRunAsync(newmanRunOptions); const error = findAssertionErrorIfExists( summary, @@ -100,7 +101,7 @@ export const testRunner = { }; describe(SCHEMA_ASSERTION_NAME, () => { it('fails when schema is invalid', async () => { - nockInterceptor.reply(200, malformedJson); + nockInterceptor.reply(SUCCESS_STATUS, malformedJson); const summary = await utils.newmanRunAsync(newmanRunOptions); const error = findAssertionErrorIfExists(summary, postmanCollectionRequestName, SCHEMA_ASSERTION_NAME); const errorMessage = _.get(error, 'message'); @@ -108,7 +109,7 @@ export const testRunner = { expect(errorMessage).to.equal('expected false to be true'); }); it('passes when schema is valid', async () => { - nockInterceptor.reply(200, correctJson); + nockInterceptor.reply(SUCCESS_STATUS, correctJson); const summary = await utils.newmanRunAsync(newmanRunOptions); const error = findAssertionErrorIfExists(summary, postmanCollectionRequestName, SCHEMA_ASSERTION_NAME); const errorMessage = _.get(error, 'message'); diff --git a/packages/subproviders/src/subproviders/ledger.ts b/packages/subproviders/src/subproviders/ledger.ts index 347eda55f..467299db0 100644 --- a/packages/subproviders/src/subproviders/ledger.ts +++ b/packages/subproviders/src/subproviders/ledger.ts @@ -113,9 +113,12 @@ export class LedgerSubprovider extends BaseWalletSubprovider { const tx = new EthereumTx(txParams); // Set the EIP155 bits - tx.raw[6] = Buffer.from([this._networkId]); // v - tx.raw[7] = Buffer.from([]); // r - tx.raw[8] = Buffer.from([]); // s + const vIndex = 6; + tx.raw[vIndex] = Buffer.from([this._networkId]); // v + const rIndex = 7; + tx.raw[rIndex] = Buffer.from([]); // r + const sIndex = 8; + tx.raw[sIndex] = Buffer.from([]); // s const txHex = tx.serialize().toString('hex'); try { @@ -127,7 +130,8 @@ export class LedgerSubprovider extends BaseWalletSubprovider { tx.v = Buffer.from(result.v, 'hex'); // EIP155: v should be chain_id * 2 + {35, 36} - const signedChainId = Math.floor((tx.v[0] - 35) / 2); + const eip55Constant = 35; + const signedChainId = Math.floor((tx.v[0] - eip55Constant) / 2); if (signedChainId !== this._networkId) { await this._destroyLedgerClientAsync(); const err = new Error(LedgerSubproviderErrors.TooOldLedgerFirmware); @@ -169,8 +173,10 @@ export class LedgerSubprovider extends BaseWalletSubprovider { fullDerivationPath, ethUtil.stripHexPrefix(data), ); - const v = result.v - 27; - let vHex = v.toString(16); + const lowestValidV = 27; + const v = result.v - lowestValidV; + const hexBase = 16; + let vHex = v.toString(hexBase); if (vHex.length < 2) { vHex = `0${v}`; } diff --git a/packages/subproviders/src/subproviders/nonce_tracker.ts b/packages/subproviders/src/subproviders/nonce_tracker.ts index 907330111..345e5e975 100644 --- a/packages/subproviders/src/subproviders/nonce_tracker.ts +++ b/packages/subproviders/src/subproviders/nonce_tracker.ts @@ -93,7 +93,8 @@ export class NonceTrackerSubprovider extends Subprovider { // Increment the nonce from the previous successfully submitted transaction let nonce = ethUtil.bufferToInt(transaction.nonce); nonce++; - let nextHexNonce = nonce.toString(16); + const hexBase = 16; + let nextHexNonce = nonce.toString(hexBase); if (nextHexNonce.length % 2) { nextHexNonce = `0${nextHexNonce}`; } diff --git a/packages/subproviders/src/subproviders/subprovider.ts b/packages/subproviders/src/subproviders/subprovider.ts index 56d2381a0..cb6dffc4a 100644 --- a/packages/subproviders/src/subproviders/subprovider.ts +++ b/packages/subproviders/src/subproviders/subprovider.ts @@ -13,10 +13,11 @@ export abstract class Subprovider { // Ported from: https://github.com/MetaMask/provider-engine/blob/master/util/random-id.js private static _getRandomId(): number { const extraDigits = 3; + const baseTen = 10; // 13 time digits - const datePart = new Date().getTime() * Math.pow(10, extraDigits); + const datePart = new Date().getTime() * Math.pow(baseTen, extraDigits); // 3 random digits - const extraPart = Math.floor(Math.random() * Math.pow(10, extraDigits)); + const extraPart = Math.floor(Math.random() * Math.pow(baseTen, extraDigits)); // 16 digits return datePart + extraPart; } diff --git a/packages/subproviders/src/utils/wallet_utils.ts b/packages/subproviders/src/utils/wallet_utils.ts index cd5cd9ba0..c36fdb9fc 100644 --- a/packages/subproviders/src/utils/wallet_utils.ts +++ b/packages/subproviders/src/utils/wallet_utils.ts @@ -30,10 +30,10 @@ class DerivedHDKeyInfoIterator implements IterableIterator<DerivedHDKeyInfo> { baseDerivationPath, derivationPath: fullDerivationPath, }; - const done = this._index === this._searchLimit; + const isDone = this._index === this._searchLimit; this._index++; return { - done, + done: isDone, value: derivedKey, }; } diff --git a/packages/subproviders/test/integration/ledger_subprovider_test.ts b/packages/subproviders/test/integration/ledger_subprovider_test.ts index 70fd2cfce..d3e9d0fde 100644 --- a/packages/subproviders/test/integration/ledger_subprovider_test.ts +++ b/packages/subproviders/test/integration/ledger_subprovider_test.ts @@ -20,6 +20,8 @@ import { reportCallbackErrors } from '../utils/report_callback_errors'; chaiSetup.configure(); const expect = chai.expect; +const DEFAULT_NUM_ACCOUNTS = 10; +const EXPECTED_SIGNATURE_LENGTH = 132; async function ledgerEthereumNodeJsClientFactoryAsync(): Promise<LedgerEthereumClient> { const ledgerConnection = await TransportNodeHid.create(); @@ -41,7 +43,7 @@ describe('LedgerSubprovider', () => { it('returns default number of accounts', async () => { const accounts = await ledgerSubprovider.getAccountsAsync(); expect(accounts[0]).to.not.be.an('undefined'); - expect(accounts.length).to.be.equal(10); + expect(accounts.length).to.be.equal(DEFAULT_NUM_ACCOUNTS); }); it('returns the expected accounts from a ledger set up with the test mnemonic', async () => { const accounts = await ledgerSubprovider.getAccountsAsync(); @@ -105,7 +107,7 @@ describe('LedgerSubprovider', () => { }; const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { expect(err).to.be.a('null'); - expect(response.result.length).to.be.equal(10); + expect(response.result.length).to.be.equal(DEFAULT_NUM_ACCOUNTS); done(); }); ledgerProvider.sendAsync(payload, callback); @@ -123,7 +125,7 @@ describe('LedgerSubprovider', () => { }; const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { expect(err).to.be.a('null'); - expect(response.result.length).to.be.equal(132); + expect(response.result.length).to.be.equal(EXPECTED_SIGNATURE_LENGTH); expect(response.result.substr(0, 2)).to.be.equal('0x'); done(); }); @@ -143,7 +145,7 @@ describe('LedgerSubprovider', () => { }; const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { expect(err).to.be.a('null'); - expect(response.result.length).to.be.equal(132); + expect(response.result.length).to.be.equal(EXPECTED_SIGNATURE_LENGTH); expect(response.result.substr(0, 2)).to.be.equal('0x'); done(); }); @@ -197,7 +199,8 @@ describe('LedgerSubprovider', () => { const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { expect(err).to.be.a('null'); const result = response.result; - expect(result.length).to.be.equal(66); + const signedTxLength = 66; + expect(result.length).to.be.equal(signedTxLength); expect(result.substr(0, 2)).to.be.equal('0x'); done(); }); diff --git a/packages/subproviders/test/unit/ledger_subprovider_test.ts b/packages/subproviders/test/unit/ledger_subprovider_test.ts index 6455454cb..8571f7d11 100644 --- a/packages/subproviders/test/unit/ledger_subprovider_test.ts +++ b/packages/subproviders/test/unit/ledger_subprovider_test.ts @@ -21,6 +21,7 @@ import { reportCallbackErrors } from '../utils/report_callback_errors'; chaiSetup.configure(); const expect = chai.expect; const FAKE_ADDRESS = '0xb088a3bc93f71b4de97b9de773e9647645983688'; +const DEFAULT_NUM_ACCOUNTS = 10; describe('LedgerSubprovider', () => { const networkId: number = 42; @@ -73,7 +74,7 @@ describe('LedgerSubprovider', () => { it('returns default number of accounts', async () => { const accounts = await ledgerSubprovider.getAccountsAsync(); expect(accounts[0]).to.be.equal(FAKE_ADDRESS); - expect(accounts.length).to.be.equal(10); + expect(accounts.length).to.be.equal(DEFAULT_NUM_ACCOUNTS); }); it('returns requested number of accounts', async () => { const numberOfAccounts = 20; @@ -119,7 +120,7 @@ describe('LedgerSubprovider', () => { }; const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { expect(err).to.be.a('null'); - expect(response.result.length).to.be.equal(10); + expect(response.result.length).to.be.equal(DEFAULT_NUM_ACCOUNTS); expect(response.result[0]).to.be.equal(FAKE_ADDRESS); done(); }); @@ -176,7 +177,8 @@ describe('LedgerSubprovider', () => { }; const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { expect(err).to.be.a('null'); - expect(response.result.raw.length).to.be.equal(192); + const rawTxLength = 192; + expect(response.result.raw.length).to.be.equal(rawTxLength); expect(response.result.raw.substr(0, 2)).to.be.equal('0x'); done(); }); diff --git a/packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts b/packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts index 52b636ac2..90565181e 100644 --- a/packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts +++ b/packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts @@ -18,6 +18,7 @@ import { reportCallbackErrors } from '../utils/report_callback_errors'; chaiSetup.configure(); const expect = chai.expect; +const DEFAULT_NUM_ACCOUNTS = 10; describe('MnemonicWalletSubprovider', () => { let subprovider: MnemonicWalletSubprovider; @@ -33,7 +34,7 @@ describe('MnemonicWalletSubprovider', () => { const accounts = await subprovider.getAccountsAsync(); expect(accounts[0]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_0); expect(accounts[1]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_1); - expect(accounts.length).to.be.equal(10); + expect(accounts.length).to.be.equal(DEFAULT_NUM_ACCOUNTS); }); it('signs a personal message', async () => { const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING)); @@ -90,7 +91,7 @@ describe('MnemonicWalletSubprovider', () => { const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { expect(err).to.be.a('null'); expect(response.result[0]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_0); - expect(response.result.length).to.be.equal(10); + expect(response.result.length).to.be.equal(DEFAULT_NUM_ACCOUNTS); done(); }); provider.sendAsync(payload, callback); diff --git a/packages/subproviders/test/unit/redundant_rpc_subprovider_test.ts b/packages/subproviders/test/unit/redundant_rpc_subprovider_test.ts index f9c47f141..fdbbb332c 100644 --- a/packages/subproviders/test/unit/redundant_rpc_subprovider_test.ts +++ b/packages/subproviders/test/unit/redundant_rpc_subprovider_test.ts @@ -14,6 +14,7 @@ import { reportCallbackErrors } from '../utils/report_callback_errors'; const expect = chai.expect; chaiSetup.configure(); +const DEFAULT_NUM_ACCOUNTS = 10; describe('RedundantSubprovider', () => { let provider: Web3ProviderEngine; @@ -32,7 +33,7 @@ describe('RedundantSubprovider', () => { }; const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { expect(err).to.be.a('null'); - expect(response.result.length).to.be.equal(10); + expect(response.result.length).to.be.equal(DEFAULT_NUM_ACCOUNTS); done(); }); provider.sendAsync(payload, callback); @@ -55,7 +56,7 @@ describe('RedundantSubprovider', () => { }; const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { expect(err).to.be.a('null'); - expect(response.result.length).to.be.equal(10); + expect(response.result.length).to.be.equal(DEFAULT_NUM_ACCOUNTS); done(); }); provider.sendAsync(payload, callback); diff --git a/packages/testnet-faucets/src/ts/constants.ts b/packages/testnet-faucets/src/ts/constants.ts new file mode 100644 index 000000000..c6370e3f6 --- /dev/null +++ b/packages/testnet-faucets/src/ts/constants.ts @@ -0,0 +1,5 @@ +export const constants = { + SUCCESS_STATUS: 200, + SERVICE_UNAVAILABLE_STATUS: 503, + BAD_REQUEST_STATUS: 400, +}; diff --git a/packages/testnet-faucets/src/ts/handler.ts b/packages/testnet-faucets/src/ts/handler.ts index 3858b5339..d5f0dc2f9 100644 --- a/packages/testnet-faucets/src/ts/handler.ts +++ b/packages/testnet-faucets/src/ts/handler.ts @@ -15,6 +15,7 @@ import ProviderEngine = require('web3-provider-engine'); import RpcSubprovider = require('web3-provider-engine/subproviders/rpc'); import { configs } from './configs'; +import { constants } from './constants'; import { DispatchQueue } from './dispatch_queue'; import { dispenseAssetTasks } from './dispense_asset_tasks'; import { rpcUrls } from './rpc_urls'; @@ -80,7 +81,7 @@ export class Handler { }; }); const payload = JSON.stringify(queueInfo); - res.status(200).send(payload); + res.status(constants.SUCCESS_STATUS).send(payload); } public dispenseEther(req: express.Request, res: express.Response): void { this._dispenseAsset(req, res, RequestedAssetType.ETH); @@ -120,11 +121,11 @@ export class Handler { } const didAddToQueue = networkConfig.dispatchQueue.add(dispenserTask); if (!didAddToQueue) { - res.status(503).send('QUEUE_IS_FULL'); + res.status(constants.SERVICE_UNAVAILABLE_STATUS).send('QUEUE_IS_FULL'); return; } logUtils.log(`Added ${recipient} to queue: ${requestedAssetType} networkId: ${networkId}`); - res.status(200).end(); + res.status(constants.SUCCESS_STATUS).end(); } private async _dispenseOrderAsync( req: express.Request, @@ -133,7 +134,7 @@ export class Handler { ): Promise<void> { const networkConfig = _.get(this._networkConfigByNetworkId, req.params.networkId); if (_.isUndefined(networkConfig)) { - res.status(400).send('UNSUPPORTED_NETWORK_ID'); + res.status(constants.BAD_REQUEST_STATUS).send('UNSUPPORTED_NETWORK_ID'); return; } const zeroEx = networkConfig.zeroEx; @@ -173,6 +174,6 @@ export class Handler { const signedOrderHash = ZeroEx.getOrderHashHex(signedOrder); const payload = JSON.stringify(signedOrder); logUtils.log(`Dispensed signed order: ${payload}`); - res.status(200).send(payload); + res.status(constants.SUCCESS_STATUS).send(payload); } } diff --git a/packages/testnet-faucets/src/ts/parameter_transformer.ts b/packages/testnet-faucets/src/ts/parameter_transformer.ts index 58bf154dc..b9929a0d9 100644 --- a/packages/testnet-faucets/src/ts/parameter_transformer.ts +++ b/packages/testnet-faucets/src/ts/parameter_transformer.ts @@ -3,6 +3,7 @@ import { NextFunction, Request, Response } from 'express'; import * as _ from 'lodash'; import { configs } from './configs'; +import { constants } from './constants'; import { rpcUrls } from './rpc_urls'; const DEFAULT_NETWORK_ID = 42; // kovan @@ -11,7 +12,7 @@ export const parameterTransformer = { transform(req: Request, res: Response, next: NextFunction): void { const recipientAddress = req.params.recipient; if (_.isUndefined(recipientAddress) || !addressUtils.isAddress(recipientAddress)) { - res.status(400).send('INVALID_RECIPIENT_ADDRESS'); + res.status(constants.BAD_REQUEST_STATUS).send('INVALID_RECIPIENT_ADDRESS'); return; } const lowerCaseRecipientAddress = recipientAddress.toLowerCase(); @@ -19,7 +20,7 @@ export const parameterTransformer = { const networkId = _.get(req.query, 'networkId', DEFAULT_NETWORK_ID); const rpcUrlIfExists = _.get(rpcUrls, networkId); if (_.isUndefined(rpcUrlIfExists)) { - res.status(400).send('UNSUPPORTED_NETWORK_ID'); + res.status(constants.BAD_REQUEST_STATUS).send('UNSUPPORTED_NETWORK_ID'); return; } req.params.networkId = networkId; diff --git a/packages/testnet-faucets/src/ts/server.ts b/packages/testnet-faucets/src/ts/server.ts index 198a5fdc9..55c1d55d8 100644 --- a/packages/testnet-faucets/src/ts/server.ts +++ b/packages/testnet-faucets/src/ts/server.ts @@ -1,6 +1,7 @@ import * as bodyParser from 'body-parser'; import * as express from 'express'; +import { constants } from './constants'; import { errorReporter } from './error_reporter'; import { Handler } from './handler'; import { parameterTransformer } from './parameter_transformer'; @@ -18,7 +19,7 @@ app.use((req, res, next) => { const handler = new Handler(); app.get('/ping', (req: express.Request, res: express.Response) => { - res.status(200).send('pong'); + res.status(constants.SUCCESS_STATUS).send('pong'); }); app.get('/info', handler.getQueueInfo.bind(handler)); app.get('/ether/:recipient', parameterTransformer.transform, handler.dispenseEther.bind(handler)); @@ -28,5 +29,6 @@ app.get('/order/zrx/:recipient', parameterTransformer.transform, handler.dispens // Log to rollbar any errors unhandled by handlers app.use(errorReporter.errorHandler()); -const port = process.env.PORT || 3000; +const DEFAULT_PORT = 3000; +const port = process.env.PORT || DEFAULT_PORT; app.listen(port); diff --git a/packages/tslint-config/package.json b/packages/tslint-config/package.json index 317ae4591..75cf03b05 100644 --- a/packages/tslint-config/package.json +++ b/packages/tslint-config/package.json @@ -45,7 +45,8 @@ "lodash": "^4.17.4", "tslint": "5.8.0", "tslint-eslint-rules": "^4.1.1", - "tslint-react": "^3.2.0" + "tslint-react": "^3.2.0", + "tsutils": "^2.12.1" }, "publishConfig": { "access": "public" diff --git a/packages/tslint-config/rules/booleanNamingRule.ts b/packages/tslint-config/rules/booleanNamingRule.ts new file mode 100644 index 000000000..f673afc6a --- /dev/null +++ b/packages/tslint-config/rules/booleanNamingRule.ts @@ -0,0 +1,68 @@ +import * as _ from 'lodash'; +import * as Lint from 'tslint'; +import * as ts from 'typescript'; + +const VALID_BOOLEAN_PREFIXES = ['is', 'does', 'should', 'was', 'has', 'can', 'did', 'would']; + +export class Rule extends Lint.Rules.TypedRule { + public static FAILURE_STRING = `Boolean variable names should begin with: ${VALID_BOOLEAN_PREFIXES.join(', ')}`; + + public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] { + return this.applyWithFunction(sourceFile, walk, undefined, program.getTypeChecker()); + } +} + +function walk(ctx: Lint.WalkContext<void>, tc: ts.TypeChecker): void { + traverse(ctx.sourceFile); + + function traverse(node: ts.Node): void { + checkNodeForViolations(ctx, node, tc); + return ts.forEachChild(node, traverse); + } +} + +function checkNodeForViolations(ctx: Lint.WalkContext<void>, node: ts.Node, tc: ts.TypeChecker): void { + switch (node.kind) { + // Handle: const { timestamp } = ... + case ts.SyntaxKind.BindingElement: { + const bindingElementNode = node as ts.BindingElement; + if (bindingElementNode.name.kind === ts.SyntaxKind.Identifier) { + handleBooleanNaming(bindingElementNode, tc, ctx); + } + break; + } + + // Handle regular assignments: const block = ... + case ts.SyntaxKind.VariableDeclaration: + const variableDeclarationNode = node as ts.VariableDeclaration; + if (variableDeclarationNode.name.kind === ts.SyntaxKind.Identifier) { + handleBooleanNaming(node as ts.VariableDeclaration, tc, ctx); + } + break; + + default: + _.noop(); + } +} + +function handleBooleanNaming( + node: ts.VariableDeclaration | ts.BindingElement, + tc: ts.TypeChecker, + ctx: Lint.WalkContext<void>, +): void { + const nodeName = node.name; + const variableName = nodeName.getText(); + const lowercasedName = _.toLower(variableName); + const typeNode = tc.getTypeAtLocation(node); + const typeName = (typeNode as any).intrinsicName; + if (typeName === 'boolean') { + const hasProperName = !_.isUndefined( + _.find(VALID_BOOLEAN_PREFIXES, prefix => { + return _.startsWith(lowercasedName, prefix); + }), + ); + if (!hasProperName) { + ctx.addFailureAtNode(node, Rule.FAILURE_STRING); + } + } +} diff --git a/packages/tslint-config/rules/customNoMagicNumbersRule.ts b/packages/tslint-config/rules/customNoMagicNumbersRule.ts new file mode 100644 index 000000000..e358221eb --- /dev/null +++ b/packages/tslint-config/rules/customNoMagicNumbersRule.ts @@ -0,0 +1,76 @@ +import * as Lint from 'tslint'; +import { isPrefixUnaryExpression } from 'tsutils'; +import * as ts from 'typescript'; + +/** + * A modified version of the no-magic-numbers rule that allows for magic numbers + * when instantiating a BigNumber instance. + * E.g We want to be able to write: + * const amount = new BigNumber(5); + * Original source: https://github.com/palantir/tslint/blob/42b058a6baa688f8be8558b277eb056c3ff79818/src/rules/noMagicNumbersRule.ts + */ +export class Rule extends Lint.Rules.AbstractRule { + public static ALLOWED_NODES = new Set<ts.SyntaxKind>([ + ts.SyntaxKind.ExportAssignment, + ts.SyntaxKind.FirstAssignment, + ts.SyntaxKind.LastAssignment, + ts.SyntaxKind.PropertyAssignment, + ts.SyntaxKind.ShorthandPropertyAssignment, + ts.SyntaxKind.VariableDeclaration, + ts.SyntaxKind.VariableDeclarationList, + ts.SyntaxKind.EnumMember, + ts.SyntaxKind.PropertyDeclaration, + ts.SyntaxKind.Parameter, + ]); + + public static DEFAULT_ALLOWED = [-1, 0, 1]; + + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { + const allowedNumbers = this.ruleArguments.length > 0 ? this.ruleArguments : Rule.DEFAULT_ALLOWED; + return this.applyWithWalker( + new CustomNoMagicNumbersWalker(sourceFile, this.ruleName, new Set(allowedNumbers.map(String))), + ); + } +} + +// tslint:disable-next-line:max-classes-per-file +class CustomNoMagicNumbersWalker extends Lint.AbstractWalker<Set<string>> { + public static FAILURE_STRING = "'magic numbers' are not allowed"; + private static _isNegativeNumberLiteral( + node: ts.Node, + ): node is ts.PrefixUnaryExpression & { operand: ts.NumericLiteral } { + return ( + isPrefixUnaryExpression(node) && + node.operator === ts.SyntaxKind.MinusToken && + node.operand.kind === ts.SyntaxKind.NumericLiteral + ); + } + public walk(sourceFile: ts.SourceFile): void { + const cb = (node: ts.Node): void => { + if (node.kind === ts.SyntaxKind.NumericLiteral) { + return this.checkNumericLiteral(node, (node as ts.NumericLiteral).text); + } + if (CustomNoMagicNumbersWalker._isNegativeNumberLiteral(node)) { + return this.checkNumericLiteral(node, `-${(node.operand as ts.NumericLiteral).text}`); + } + return ts.forEachChild(node, cb); + }; + return ts.forEachChild(sourceFile, cb); + } + + // tslint:disable:no-non-null-assertion + // tslint:disable-next-line:underscore-private-and-protected + private checkNumericLiteral(node: ts.Node, num: string): void { + if (!Rule.ALLOWED_NODES.has(node.parent!.kind) && !this.options.has(num)) { + if (node.parent!.kind === ts.SyntaxKind.NewExpression) { + const className = (node.parent! as any).expression.escapedText; + const BIG_NUMBER_NEW_EXPRESSION = 'BigNumber'; + if (className === BIG_NUMBER_NEW_EXPRESSION) { + return; // noop + } + } + this.addFailureAtNode(node, CustomNoMagicNumbersWalker.FAILURE_STRING); + } + } + // tslint:enable:no-non-null-assertion +} diff --git a/packages/tslint-config/tslint.json b/packages/tslint-config/tslint.json index 1d717430d..77a1f41cc 100644 --- a/packages/tslint-config/tslint.json +++ b/packages/tslint-config/tslint.json @@ -5,7 +5,10 @@ "arrow-parens": [true, "ban-single-arg-parens"], "arrow-return-shorthand": true, "async-suffix": true, + "boolean-naming": true, + "no-switch-case-fall-through": true, "await-promise": true, + "custom-no-magic-numbers": [true, 0, 1, 2, 3, -1], "binary-expression-operand-order": true, "callable-types": true, "class-name": true, diff --git a/packages/utils/src/abi_decoder.ts b/packages/utils/src/abi_decoder.ts index d329f917a..c78bfa343 100644 --- a/packages/utils/src/abi_decoder.ts +++ b/packages/utils/src/abi_decoder.ts @@ -23,7 +23,8 @@ export class AbiDecoder { formatted = formatted.slice(2); } - formatted = _.padStart(formatted, 40, '0'); + const addressLength = 40; + formatted = _.padStart(formatted, addressLength, '0'); return `0x${formatted}`; } constructor(abiArrays: AbiDefinition[][]) { @@ -45,16 +46,17 @@ export class AbiDecoder { const dataTypes = _.map(nonIndexedInputs, input => input.type); const decodedData = ethersInterface.events[event.name].parse(log.data); - let failedToDecode = false; + let didFailToDecode = false; _.forEach(event.inputs, (param: EventParameter, i: number) => { // Indexed parameters are stored in topics. Non-indexed ones in decodedData let value: BigNumber | string | number = param.indexed ? log.topics[topicsIndex++] : decodedData[i]; if (_.isUndefined(value)) { - failedToDecode = true; + didFailToDecode = true; return; } if (param.type === SolidityTypes.Address) { - value = AbiDecoder._padZeros(new BigNumber(value).toString(16)); + const baseHex = 16; + value = AbiDecoder._padZeros(new BigNumber(value).toString(baseHex)); } else if (param.type === SolidityTypes.Uint256 || param.type === SolidityTypes.Uint) { value = new BigNumber(value); } else if (param.type === SolidityTypes.Uint8) { @@ -63,7 +65,7 @@ export class AbiDecoder { decodedParams[param.name] = value; }); - if (failedToDecode) { + if (didFailToDecode) { return log; } else { return { diff --git a/packages/utils/src/address_utils.ts b/packages/utils/src/address_utils.ts index f94985441..e25bde249 100644 --- a/packages/utils/src/address_utils.ts +++ b/packages/utils/src/address_utils.ts @@ -9,11 +9,16 @@ export const addressUtils = { const unprefixedAddress = address.replace('0x', ''); const addressHash = jsSHA3.keccak256(unprefixedAddress.toLowerCase()); - for (let i = 0; i < 40; i++) { + const addressLength = 40; + for (let i = 0; i < addressLength; i++) { // The nth letter should be uppercase if the nth digit of casemap is 1 + const hexBase = 16; + const lowercaseRange = 7; if ( - (parseInt(addressHash[i], 16) > 7 && unprefixedAddress[i].toUpperCase() !== unprefixedAddress[i]) || - (parseInt(addressHash[i], 16) <= 7 && unprefixedAddress[i].toLowerCase() !== unprefixedAddress[i]) + (parseInt(addressHash[i], hexBase) > lowercaseRange && + unprefixedAddress[i].toUpperCase() !== unprefixedAddress[i]) || + (parseInt(addressHash[i], hexBase) <= lowercaseRange && + unprefixedAddress[i].toLowerCase() !== unprefixedAddress[i]) ) { return false; } diff --git a/packages/utils/src/interval_utils.ts b/packages/utils/src/interval_utils.ts index 6984bf42d..6784d5b35 100644 --- a/packages/utils/src/interval_utils.ts +++ b/packages/utils/src/interval_utils.ts @@ -6,18 +6,18 @@ export const intervalUtils = { intervalMs: number, onError: (err: Error) => void, ): NodeJS.Timer { - let locked = false; + let isLocked = false; const intervalId = setInterval(async () => { - if (locked) { + if (isLocked) { return; } else { - locked = true; + isLocked = true; try { await fn(); } catch (err) { onError(err); } - locked = false; + isLocked = false; } }, intervalMs); return intervalId; diff --git a/packages/web3-wrapper/src/web3_wrapper.ts b/packages/web3-wrapper/src/web3_wrapper.ts index c60d5fe33..91a1af870 100644 --- a/packages/web3-wrapper/src/web3_wrapper.ts +++ b/packages/web3-wrapper/src/web3_wrapper.ts @@ -19,6 +19,8 @@ import * as Web3 from 'web3'; import { Web3WrapperErrors } from './types'; +const BASE_TEN = 10; + /** * A wrapper around the Web3.js 0.x library that provides a consistent, clean promise-based interface. */ @@ -48,7 +50,7 @@ export class Web3Wrapper { * @return The amount in units. */ public static toUnitAmount(amount: BigNumber, decimals: number): BigNumber { - const aUnit = new BigNumber(10).pow(decimals); + const aUnit = new BigNumber(BASE_TEN).pow(decimals); const unit = amount.div(aUnit); return unit; } @@ -61,7 +63,7 @@ export class Web3Wrapper { * @return The amount in baseUnits. */ public static toBaseUnitAmount(amount: BigNumber, decimals: number): BigNumber { - const unit = new BigNumber(10).pow(decimals); + const unit = new BigNumber(BASE_TEN).pow(decimals); const baseUnitAmount = amount.times(unit); const hasDecimals = baseUnitAmount.decimalPlaces() !== 0; if (hasDecimals) { @@ -180,8 +182,8 @@ export class Web3Wrapper { public async doesContractExistAtAddressAsync(address: string): Promise<boolean> { const code = await promisify<string>(this._web3.eth.getCode)(address); // Regex matches 0x0, 0x00, 0x in order to accommodate poorly implemented clients - const codeIsEmpty = /^0x0{0,40}$/i.test(code); - return !codeIsEmpty; + const isCodeEmpty = /^0x0{0,40}$/i.test(code); + return !isCodeEmpty; } /** * Sign a message with a specific address's private key (`eth_sign`) @@ -336,16 +338,16 @@ export class Web3Wrapper { pollingIntervalMs: number = 1000, timeoutMs?: number, ): Promise<TransactionReceiptWithDecodedLogs> { - let timeoutExceeded = false; + let wasTimeoutExceeded = false; if (timeoutMs) { - setTimeout(() => (timeoutExceeded = true), timeoutMs); + setTimeout(() => (wasTimeoutExceeded = true), timeoutMs); } const txReceiptPromise = new Promise( (resolve: (receipt: TransactionReceiptWithDecodedLogs) => void, reject) => { const intervalId = intervalUtils.setAsyncExcludingInterval( async () => { - if (timeoutExceeded) { + if (wasTimeoutExceeded) { intervalUtils.clearAsyncExcludingInterval(intervalId); return reject(Web3WrapperErrors.TransactionMiningTimeout); } diff --git a/packages/website/ts/components/generate_order/new_token_form.tsx b/packages/website/ts/components/generate_order/new_token_form.tsx index 10f71b430..a9b8e9589 100644 --- a/packages/website/ts/components/generate_order/new_token_form.tsx +++ b/packages/website/ts/components/generate_order/new_token_form.tsx @@ -157,14 +157,14 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor const maxLength = 30; const tokens = _.values(this.props.tokenByAddress); const tokenWithNameIfExists = _.find(tokens, { name }); - const tokenWithNameExists = !_.isUndefined(tokenWithNameIfExists); + const doesTokenWithNameExists = !_.isUndefined(tokenWithNameIfExists); if (name === '') { nameErrText = 'Name is required'; } else if (!this._isValidName(name)) { nameErrText = 'Name should only contain letters, digits and spaces'; } else if (name.length > maxLength) { nameErrText = `Max length is ${maxLength}`; - } else if (tokenWithNameExists) { + } else if (doesTokenWithNameExists) { nameErrText = 'Token with this name already exists'; } @@ -177,14 +177,14 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor let symbolErrText = ''; const maxLength = 5; const tokens = _.values(this.props.tokenByAddress); - const tokenWithSymbolExists = !_.isUndefined(_.find(tokens, { symbol })); + const doesTokenWithSymbolExists = !_.isUndefined(_.find(tokens, { symbol })); if (symbol === '') { symbolErrText = 'Symbol is required'; } else if (!this._isAlphanumeric(symbol)) { symbolErrText = 'Can only include alphanumeric characters'; } else if (symbol.length > maxLength) { symbolErrText = `Max length is ${maxLength}`; - } else if (tokenWithSymbolExists) { + } else if (doesTokenWithSymbolExists) { symbolErrText = 'Token with symbol already exists'; } diff --git a/packages/website/ts/components/relayer_index/relayer_index.tsx b/packages/website/ts/components/relayer_index/relayer_index.tsx index 8da4e0e10..9ef6eaf59 100644 --- a/packages/website/ts/components/relayer_index/relayer_index.tsx +++ b/packages/website/ts/components/relayer_index/relayer_index.tsx @@ -60,8 +60,8 @@ export class RelayerIndex extends React.Component<RelayerIndexProps, RelayerInde this._isUnmounted = true; } public render(): React.ReactNode { - const readyToRender = _.isUndefined(this.state.error) && !_.isUndefined(this.state.relayerInfos); - if (!readyToRender) { + const isReadyToRender = _.isUndefined(this.state.error) && !_.isUndefined(this.state.relayerInfos); + if (!isReadyToRender) { return ( // TODO: consolidate this loading component with the one in portal <div className="center"> diff --git a/packages/website/tslint.json b/packages/website/tslint.json index d6a5f5031..b55ffe90f 100644 --- a/packages/website/tslint.json +++ b/packages/website/tslint.json @@ -4,6 +4,7 @@ "no-implicit-dependencies": false, "no-object-literal-type-assertion": false, "completed-docs": false, - "prefer-function-over-method": false + "prefer-function-over-method": false, + "custom-no-magic-numbers": false } } |