diff options
88 files changed, 977 insertions, 155 deletions
diff --git a/packages/0x.js/package.json b/packages/0x.js/package.json index 96e870851..3df2a0e06 100644 --- a/packages/0x.js/package.json +++ b/packages/0x.js/package.json @@ -21,7 +21,7 @@ "pre_build": "run-s generate_contract_wrappers copy_artifacts", "copy_artifacts": "copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts", "generate_contract_wrappers": "abi-gen --abis 'src/compact_artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers", - "lint": "tslint --project . --exclude **/src/generated_contract_wrapper/**/*", + "lint": "tslint --project . --exclude **/src/generated_contract_wrappers/**/*", "test:circleci": "run-s test:coverage", "test": "yarn run_mocha", "rebuild_and_test": "run-s build test", diff --git a/packages/base-contract/src/index.ts b/packages/base-contract/src/index.ts index a46d985f5..cb9042415 100644 --- a/packages/base-contract/src/index.ts +++ b/packages/base-contract/src/index.ts @@ -37,7 +37,7 @@ export class BaseContract { protected static _lowercaseAddress(type: string, value: string): string { return type === 'address' ? value.toLowerCase() : value; } - protected static _bigNumberToString(type: string, value: any): any { + protected static _bigNumberToString(_type: string, value: any): any { return _.isObject(value) && value.isBigNumber ? value.toString() : value; } protected static _lookupConstructorAbi(abi: ContractAbi): ConstructorAbi { @@ -60,7 +60,7 @@ export class BaseContract { return defaultConstructorAbi; } } - protected static _bnToBigNumber(type: string, value: any): any { + protected static _bnToBigNumber(_type: string, value: any): any { return _.isObject(value) && value._bn ? new BigNumber(value.toString()) : value; } protected static async _applyDefaultsToTxDataAsync<T extends Partial<TxData | TxDataPayable>>( diff --git a/packages/connect/src/http_client.ts b/packages/connect/src/http_client.ts index 5806f1d43..f6503835a 100644 --- a/packages/connect/src/http_client.ts +++ b/packages/connect/src/http_client.ts @@ -48,7 +48,7 @@ export class HttpClient implements Client { return ''; } // format params into a form the api expects - const formattedParams = _.mapKeys(params, (value: any, key: string) => { + const formattedParams = _.mapKeys(params, (_value: any, key: string) => { return _.get(OPTS_TO_QUERY_FIELD_MAP, key, key); }); // stringify the formatted object diff --git a/packages/connect/src/ws_orderbook_channel.ts b/packages/connect/src/ws_orderbook_channel.ts index 4a9d4058f..bdcc8a75d 100644 --- a/packages/connect/src/ws_orderbook_channel.ts +++ b/packages/connect/src/ws_orderbook_channel.ts @@ -78,7 +78,7 @@ export class WebSocketOrderbookChannel implements OrderbookChannel { connection.on(WebsocketConnectionEventType.Error, wsError => { handler.onError(this, subscriptionOpts, wsError); }); - connection.on(WebsocketConnectionEventType.Close, (code: number, desc: string) => { + connection.on(WebsocketConnectionEventType.Close, (_code: number, _desc: string) => { handler.onClose(this, subscriptionOpts); }); connection.on(WebsocketConnectionEventType.Message, message => { diff --git a/packages/contract-wrappers/src/abstract/abstract_balance_and_proxy_allowance_lazy_store.ts b/packages/contract-wrappers/src/abstract/abstract_balance_and_proxy_allowance_lazy_store.ts new file mode 100644 index 000000000..1f139f1ef --- /dev/null +++ b/packages/contract-wrappers/src/abstract/abstract_balance_and_proxy_allowance_lazy_store.ts @@ -0,0 +1,11 @@ +import { BigNumber } from '@0xproject/utils'; + +export abstract class AbstractBalanceAndProxyAllowanceLazyStore { + public abstract async getBalanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber>; + public abstract async getProxyAllowanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber>; + public abstract setBalance(tokenAddress: string, userAddress: string, balance: BigNumber): void; + public abstract deleteBalance(tokenAddress: string, userAddress: string): void; + public abstract setProxyAllowance(tokenAddress: string, userAddress: string, proxyAllowance: BigNumber): void; + public abstract deleteProxyAllowance(tokenAddress: string, userAddress: string): void; + public abstract deleteAll(): void; +} diff --git a/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts index 2d5261900..430ce9c5e 100644 --- a/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts @@ -18,6 +18,7 @@ import * as _ from 'lodash'; import { artifacts } from '../artifacts'; import { SimpleBalanceAndProxyAllowanceFetcher } from '../fetchers/simple_balance_and_proxy_allowance_fetcher'; import { SimpleOrderFilledCancelledFetcher } from '../fetchers/simple_order_filled_cancelled_fetcher'; +import { BalanceAndProxyAllowanceLazyStore } from '../stores/balance_proxy_allowance_lazy_store'; import { BlockRange, EventCallback, @@ -54,7 +55,7 @@ interface ExchangeContractErrCodesToMsgs { */ export class ExchangeWrapper extends ContractWrapper { private _exchangeContractIfExists?: ExchangeContract; - private _orderValidationUtils: OrderValidationUtils; + private _orderValidationUtilsIfExists?: OrderValidationUtils; private _tokenWrapper: TokenWrapper; private _exchangeContractErrCodesToMsg: ExchangeContractErrCodesToMsgs = { [ExchangeContractErrCodes.ERROR_FILL_EXPIRED]: ExchangeContractErrs.OrderFillExpired, @@ -75,7 +76,6 @@ export class ExchangeWrapper extends ContractWrapper { ) { super(web3Wrapper, networkId); this._tokenWrapper = tokenWrapper; - this._orderValidationUtils = new OrderValidationUtils(this); this._contractAddressIfExists = contractAddressIfExists; this._zrxContractAddressIfExists = zrxContractAddressIfExists; } @@ -177,8 +177,13 @@ export class ExchangeWrapper extends ContractWrapper { : orderTransactionOpts.shouldValidate; if (shouldValidate) { const zrxTokenAddress = this.getZRXTokenAddress(); - const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); - await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync( + const balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore( + this._tokenWrapper, + BlockParamLiteral.Latest, + ); + const exchangeTradeEmulator = new ExchangeTransferSimulator(balanceAndProxyAllowanceLazyStore); + const orderValidationUtils = await this._getOrderValidationUtilsAsync(); + await orderValidationUtils.validateFillOrderThrowIfInvalidAsync( exchangeTradeEmulator, signedOrder, fillTakerTokenAmount, @@ -252,9 +257,14 @@ export class ExchangeWrapper extends ContractWrapper { if (shouldValidate) { let filledTakerTokenAmount = new BigNumber(0); const zrxTokenAddress = this.getZRXTokenAddress(); - const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); + const balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore( + this._tokenWrapper, + BlockParamLiteral.Latest, + ); + const exchangeTradeEmulator = new ExchangeTransferSimulator(balanceAndProxyAllowanceLazyStore); + const orderValidationUtils = await this._getOrderValidationUtilsAsync(); for (const signedOrder of signedOrders) { - const singleFilledTakerTokenAmount = await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync( + const singleFilledTakerTokenAmount = await orderValidationUtils.validateFillOrderThrowIfInvalidAsync( exchangeTradeEmulator, signedOrder, fillTakerTokenAmount.minus(filledTakerTokenAmount), @@ -345,9 +355,14 @@ export class ExchangeWrapper extends ContractWrapper { : orderTransactionOpts.shouldValidate; if (shouldValidate) { const zrxTokenAddress = this.getZRXTokenAddress(); - const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); + const balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore( + this._tokenWrapper, + BlockParamLiteral.Latest, + ); + const exchangeTradeEmulator = new ExchangeTransferSimulator(balanceAndProxyAllowanceLazyStore); + const orderValidationUtils = await this._getOrderValidationUtilsAsync(); for (const orderFillRequest of orderFillRequests) { - await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync( + await orderValidationUtils.validateFillOrderThrowIfInvalidAsync( exchangeTradeEmulator, orderFillRequest.signedOrder, orderFillRequest.takerTokenFillAmount, @@ -421,8 +436,13 @@ export class ExchangeWrapper extends ContractWrapper { : orderTransactionOpts.shouldValidate; if (shouldValidate) { const zrxTokenAddress = this.getZRXTokenAddress(); - const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); - await this._orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync( + const balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore( + this._tokenWrapper, + BlockParamLiteral.Latest, + ); + const exchangeTradeEmulator = new ExchangeTransferSimulator(balanceAndProxyAllowanceLazyStore); + const orderValidationUtils = await this._getOrderValidationUtilsAsync(); + await orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync( exchangeTradeEmulator, signedOrder, fillTakerTokenAmount, @@ -483,9 +503,14 @@ export class ExchangeWrapper extends ContractWrapper { : orderTransactionOpts.shouldValidate; if (shouldValidate) { const zrxTokenAddress = this.getZRXTokenAddress(); - const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); + const balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore( + this._tokenWrapper, + BlockParamLiteral.Latest, + ); + const exchangeTradeEmulator = new ExchangeTransferSimulator(balanceAndProxyAllowanceLazyStore); + const orderValidationUtils = await this._getOrderValidationUtilsAsync(); for (const orderFillRequest of orderFillRequests) { - await this._orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync( + await orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync( exchangeTradeEmulator, orderFillRequest.signedOrder, orderFillRequest.takerTokenFillAmount, @@ -733,8 +758,13 @@ export class ExchangeWrapper extends ContractWrapper { assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); const zrxTokenAddress = this.getZRXTokenAddress(); const expectedFillTakerTokenAmount = !_.isUndefined(opts) ? opts.expectedFillTakerTokenAmount : undefined; - const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); - await this._orderValidationUtils.validateOrderFillableOrThrowAsync( + const balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore( + this._tokenWrapper, + BlockParamLiteral.Latest, + ); + const exchangeTradeEmulator = new ExchangeTransferSimulator(balanceAndProxyAllowanceLazyStore); + const orderValidationUtils = await this._getOrderValidationUtilsAsync(); + await orderValidationUtils.validateOrderFillableOrThrowAsync( exchangeTradeEmulator, signedOrder, zrxTokenAddress, @@ -759,8 +789,13 @@ export class ExchangeWrapper extends ContractWrapper { await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); const normalizedTakerAddress = takerAddress.toLowerCase(); const zrxTokenAddress = this.getZRXTokenAddress(); - const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); - await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync( + const balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore( + this._tokenWrapper, + BlockParamLiteral.Latest, + ); + const exchangeTradeEmulator = new ExchangeTransferSimulator(balanceAndProxyAllowanceLazyStore); + const orderValidationUtils = await this._getOrderValidationUtilsAsync(); + await orderValidationUtils.validateFillOrderThrowIfInvalidAsync( exchangeTradeEmulator, signedOrder, fillTakerTokenAmount, @@ -806,8 +841,13 @@ export class ExchangeWrapper extends ContractWrapper { await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); const normalizedTakerAddress = takerAddress.toLowerCase(); const zrxTokenAddress = this.getZRXTokenAddress(); - const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); - await this._orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync( + const balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore( + this._tokenWrapper, + BlockParamLiteral.Latest, + ); + const exchangeTradeEmulator = new ExchangeTransferSimulator(balanceAndProxyAllowanceLazyStore); + const orderValidationUtils = await this._getOrderValidationUtilsAsync(); + await orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync( exchangeTradeEmulator, signedOrder, fillTakerTokenAmount, @@ -917,6 +957,14 @@ export class ExchangeWrapper extends ContractWrapper { const orderHashHex = await exchangeInstance.getOrderHash.callAsync(orderAddresses, orderValues); return orderHashHex; } + private async _getOrderValidationUtilsAsync(): Promise<OrderValidationUtils> { + if (!_.isUndefined(this._orderValidationUtilsIfExists)) { + return this._orderValidationUtilsIfExists; + } + const exchangeContract = await this._getExchangeContractAsync(); + this._orderValidationUtilsIfExists = new OrderValidationUtils(exchangeContract); + return this._orderValidationUtilsIfExists; + } // tslint:enable:no-unused-variable private async _getExchangeContractAsync(): Promise<ExchangeContract> { if (!_.isUndefined(this._exchangeContractIfExists)) { diff --git a/packages/contract-wrappers/src/stores/balance_proxy_allowance_lazy_store.ts b/packages/contract-wrappers/src/stores/balance_proxy_allowance_lazy_store.ts index 614195157..c0250ce7c 100644 --- a/packages/contract-wrappers/src/stores/balance_proxy_allowance_lazy_store.ts +++ b/packages/contract-wrappers/src/stores/balance_proxy_allowance_lazy_store.ts @@ -1,14 +1,14 @@ -import { AbstractBalanceAndProxyAllowanceFetcher } from '@0xproject/order-utils'; import { BlockParamLiteral } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; +import { AbstractBalanceAndProxyAllowanceLazyStore } from '../abstract/abstract_balance_and_proxy_allowance_lazy_store'; import { TokenWrapper } from '../contract_wrappers/token_wrapper'; /** * Copy on read store for balances/proxyAllowances of tokens/accounts */ -export class BalanceAndProxyAllowanceLazyStore implements AbstractBalanceAndProxyAllowanceFetcher { +export class BalanceAndProxyAllowanceLazyStore implements AbstractBalanceAndProxyAllowanceLazyStore { private _tokenWrapper: TokenWrapper; private _defaultBlock: BlockParamLiteral; private _balance: { diff --git a/packages/contract-wrappers/src/utils/exchange_transfer_simulator.ts b/packages/contract-wrappers/src/utils/exchange_transfer_simulator.ts index 395945fe3..527b8575d 100644 --- a/packages/contract-wrappers/src/utils/exchange_transfer_simulator.ts +++ b/packages/contract-wrappers/src/utils/exchange_transfer_simulator.ts @@ -1,8 +1,8 @@ import { BlockParamLiteral, ExchangeContractErrs } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; +import { AbstractBalanceAndProxyAllowanceLazyStore } from '../abstract/abstract_balance_and_proxy_allowance_lazy_store'; import { TokenWrapper } from '../contract_wrappers/token_wrapper'; -import { BalanceAndProxyAllowanceLazyStore } from '../stores/balance_proxy_allowance_lazy_store'; import { TradeSide, TransferType } from '../types'; import { constants } from '../utils/constants'; @@ -35,8 +35,7 @@ const ERR_MSG_MAPPING = { }; export class ExchangeTransferSimulator { - private _store: BalanceAndProxyAllowanceLazyStore; - private _UNLIMITED_ALLOWANCE_IN_BASE_UNITS: BigNumber; + private _store: AbstractBalanceAndProxyAllowanceLazyStore; private static _throwValidationError( failureReason: FailureReason, tradeSide: TradeSide, @@ -45,9 +44,8 @@ export class ExchangeTransferSimulator { const errMsg = ERR_MSG_MAPPING[failureReason][tradeSide][transferType]; throw new Error(errMsg); } - constructor(token: TokenWrapper, defaultBlock: BlockParamLiteral) { - this._store = new BalanceAndProxyAllowanceLazyStore(token, defaultBlock); - this._UNLIMITED_ALLOWANCE_IN_BASE_UNITS = token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; + constructor(store: AbstractBalanceAndProxyAllowanceLazyStore) { + this._store = store; } /** * Simulates transferFrom call performed by a proxy @@ -91,7 +89,7 @@ export class ExchangeTransferSimulator { amountInBaseUnits: BigNumber, ): Promise<void> { const proxyAllowance = await this._store.getProxyAllowanceAsync(tokenAddress, userAddress); - if (!proxyAllowance.eq(this._UNLIMITED_ALLOWANCE_IN_BASE_UNITS)) { + if (!proxyAllowance.eq(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS)) { this._store.setProxyAllowance(tokenAddress, userAddress, proxyAllowance.minus(amountInBaseUnits)); } } diff --git a/packages/contract-wrappers/src/utils/order_validation_utils.ts b/packages/contract-wrappers/src/utils/order_validation_utils.ts index b6b3334a6..c6ef26275 100644 --- a/packages/contract-wrappers/src/utils/order_validation_utils.ts +++ b/packages/contract-wrappers/src/utils/order_validation_utils.ts @@ -3,7 +3,7 @@ import { ExchangeContractErrs, Order, SignedOrder } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; -import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper'; +import { ExchangeContract } from '../contract_wrappers/generated/exchange'; import { TradeSide, TransferType } from '../types'; import { constants } from '../utils/constants'; import { utils } from '../utils/utils'; @@ -11,7 +11,7 @@ import { utils } from '../utils/utils'; import { ExchangeTransferSimulator } from './exchange_transfer_simulator'; export class OrderValidationUtils { - private _exchangeWrapper: ExchangeWrapper; + private _exchangeContract: ExchangeContract; public static validateCancelOrderThrowIfInvalid( order: Order, cancelTakerTokenAmount: BigNumber, @@ -104,8 +104,8 @@ export class OrderValidationUtils { .round(0); return fillMakerTokenAmount; } - constructor(exchangeWrapper: ExchangeWrapper) { - this._exchangeWrapper = exchangeWrapper; + constructor(exchangeContract: ExchangeContract) { + this._exchangeContract = exchangeContract; } public async validateOrderFillableOrThrowAsync( exchangeTradeEmulator: ExchangeTransferSimulator, @@ -114,7 +114,9 @@ export class OrderValidationUtils { expectedFillTakerTokenAmount?: BigNumber, ): Promise<void> { const orderHash = getOrderHashHex(signedOrder); - const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash); + const unavailableTakerTokenAmount = await this._exchangeContract.getUnavailableTakerTokenAmount.callAsync( + orderHash, + ); OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow( signedOrder.takerTokenAmount, unavailableTakerTokenAmount, @@ -146,7 +148,9 @@ export class OrderValidationUtils { if (!isValidSignature(orderHash, signedOrder.ecSignature, signedOrder.maker)) { throw new Error(OrderError.InvalidSignature); } - const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash); + const unavailableTakerTokenAmount = await this._exchangeContract.getUnavailableTakerTokenAmount.callAsync( + orderHash, + ); OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow( signedOrder.takerTokenAmount, unavailableTakerTokenAmount, @@ -167,7 +171,7 @@ export class OrderValidationUtils { zrxTokenAddress, ); - const wouldRoundingErrorOccur = await this._exchangeWrapper.isRoundingErrorAsync( + const wouldRoundingErrorOccur = await this._exchangeContract.isRoundingError.callAsync( filledTakerTokenAmount, signedOrder.takerTokenAmount, signedOrder.makerTokenAmount, diff --git a/packages/contract-wrappers/test/exchange_transfer_simulator_test.ts b/packages/contract-wrappers/test/exchange_transfer_simulator_test.ts index 8bbe04d6c..1690eb392 100644 --- a/packages/contract-wrappers/test/exchange_transfer_simulator_test.ts +++ b/packages/contract-wrappers/test/exchange_transfer_simulator_test.ts @@ -5,6 +5,7 @@ import * as chai from 'chai'; import 'make-promises-safe'; import { ContractWrappers, ExchangeContractErrs } from '../src'; +import { BalanceAndProxyAllowanceLazyStore } from '../src/stores/balance_proxy_allowance_lazy_store'; import { TradeSide, TransferType } from '../src/types'; import { ExchangeTransferSimulator } from '../src/utils/exchange_transfer_simulator'; @@ -44,7 +45,11 @@ describe('ExchangeTransferSimulator', () => { }); describe('#transferFromAsync', () => { beforeEach(() => { - exchangeTransferSimulator = new ExchangeTransferSimulator(contractWrappers.token, BlockParamLiteral.Latest); + const balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore( + contractWrappers.token, + BlockParamLiteral.Latest, + ); + exchangeTransferSimulator = new ExchangeTransferSimulator(balanceAndProxyAllowanceLazyStore); }); it("throws if the user doesn't have enough allowance", async () => { return expect( diff --git a/packages/contract-wrappers/test/order_validation_test.ts b/packages/contract-wrappers/test/order_validation_test.ts index a42a6a368..b88684dd0 100644 --- a/packages/contract-wrappers/test/order_validation_test.ts +++ b/packages/contract-wrappers/test/order_validation_test.ts @@ -8,6 +8,7 @@ import 'make-promises-safe'; import * as Sinon from 'sinon'; import { ContractWrappers, ExchangeContractErrs, SignedOrder, Token } from '../src'; +import { BalanceAndProxyAllowanceLazyStore } from '../src/stores/balance_proxy_allowance_lazy_store'; import { TradeSide, TransferType } from '../src/types'; import { ExchangeTransferSimulator } from '../src/utils/exchange_transfer_simulator'; import { OrderValidationUtils } from '../src/utils/order_validation_utils'; @@ -332,7 +333,11 @@ describe('OrderValidation', () => { return Sinon.match((value: BigNumber) => value.eq(expected)); }; beforeEach('create exchangeTransferSimulator', async () => { - exchangeTransferSimulator = new ExchangeTransferSimulator(contractWrappers.token, BlockParamLiteral.Latest); + const balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore( + contractWrappers.token, + BlockParamLiteral.Latest, + ); + exchangeTransferSimulator = new ExchangeTransferSimulator(balanceAndProxyAllowanceLazyStore); transferFromAsync = Sinon.spy(); exchangeTransferSimulator.transferFromAsync = transferFromAsync as any; }); diff --git a/packages/contracts/package.json b/packages/contracts/package.json index dcbeddbd8..d6ca3727b 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -24,7 +24,7 @@ "clean": "shx rm -rf lib src/generated_contract_wrappers", "generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers", - "lint": "tslint --project . --exclude **/src/contract_wrappers/**/* --exclude **/lib/**/*", + "lint": "tslint --project . --exclude **/src/generated_contract_wrappers/**/* --exclude **/lib/**/*", "coverage:report:text": "istanbul report text", "coverage:report:html": "istanbul report html && open coverage/index.html", "profiler:report:html": "istanbul report html && open coverage/index.html", diff --git a/packages/contracts/test/libraries/lib_mem.ts b/packages/contracts/test/libraries/lib_mem.ts index 90d54edcb..00f7c4d8b 100644 --- a/packages/contracts/test/libraries/lib_mem.ts +++ b/packages/contracts/test/libraries/lib_mem.ts @@ -30,7 +30,7 @@ describe('LibMem', () => { const memHex = toHex(memory); // Reference implementation to test against - const refMemcpy = (mem: Uint8Array, dest: number, source: number, length: number): Uint8Array => + const refMemcpy = (_mem: Uint8Array, dest: number, source: number, length: number): Uint8Array => Uint8Array.from(memory).copyWithin(dest, source, source + length); // Test vectors: destination, source, length, job description diff --git a/packages/dev-utils/src/callback_error_reporter.ts b/packages/dev-utils/src/callback_error_reporter.ts index 8432bb5d4..e69ce1c05 100644 --- a/packages/dev-utils/src/callback_error_reporter.ts +++ b/packages/dev-utils/src/callback_error_reporter.ts @@ -60,7 +60,7 @@ export const callbackErrorReporter = { done: DoneCallback, errMsg: string, ): <T>(error: Error | null, value: T | undefined) => void { - const wrapped = <T>(error: Error | null, value: T | undefined) => { + const wrapped = <T>(error: Error | null, _value: T | undefined) => { if (_.isNull(error)) { done(new Error('Expected callback to receive an error')); } else { diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json index a3e41e427..f3c54711f 100644 --- a/packages/order-utils/CHANGELOG.json +++ b/packages/order-utils/CHANGELOG.json @@ -1,5 +1,13 @@ [ { + "changes": [ + { + "note": "Export parseECSignature method", + "pr": 684 + } + ] + }, + { "version": "0.1.0", "changes": [ { diff --git a/packages/order-utils/package.json b/packages/order-utils/package.json index 6c5ad6780..8f37bb138 100644 --- a/packages/order-utils/package.json +++ b/packages/order-utils/package.json @@ -13,7 +13,7 @@ "pre_build": "run-s update_artifacts generate_contract_wrappers", "transpile": "tsc", "copy_monorepo_scripts": "copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", - "generate_contract_wrappers": "abi-gen --abis 'lib/src/artifacts/@(Exchange|IWallet|IValidator).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers", + "generate_contract_wrappers": "abi-gen --abis 'lib/src/artifacts/@(Exchange|IWallet|IValidator|DummyERC20Token|ERC20Proxy|ERC20Token).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers", "update_artifacts": "for i in ${npm_package_config_contracts}; do copyfiles -u 4 ../migrations/artifacts/2.0.0/$i.json lib/src/artifacts; done;", "test": "yarn run_mocha", "rebuild_and_test": "run-s build test", @@ -29,7 +29,7 @@ "upload_docs_json": "aws s3 cp generated_docs/index.json $S3_URL --profile 0xproject --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json" }, "config": { - "contracts": "IWallet IValidator Exchange", + "contracts": "IWallet IValidator Exchange DummyERC20Token ERC20Proxy ERC20Token", "postpublish": { "docPublishConfigs": { "extraFileIncludes": [ @@ -52,6 +52,7 @@ "homepage": "https://github.com/0xProject/0x-monorepo/packages/order-utils/README.md", "devDependencies": { "@0xproject/dev-utils": "^0.4.2", + "@0xproject/migrations": "^0.0.6", "@0xproject/monorepo-scripts": "^0.1.20", "@0xproject/tslint-config": "^0.4.18", "@types/ethereumjs-abi": "^0.6.0", diff --git a/packages/order-utils/src/abstract/abstract_balance_and_proxy_allowance_fetcher.ts b/packages/order-utils/src/abstract/abstract_balance_and_proxy_allowance_fetcher.ts index 857c6167f..b2760d98e 100644 --- a/packages/order-utils/src/abstract/abstract_balance_and_proxy_allowance_fetcher.ts +++ b/packages/order-utils/src/abstract/abstract_balance_and_proxy_allowance_fetcher.ts @@ -1,6 +1,6 @@ import { BigNumber } from '@0xproject/utils'; export abstract class AbstractBalanceAndProxyAllowanceFetcher { - public abstract async getBalanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber>; - public abstract async getProxyAllowanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber>; + public abstract async getBalanceAsync(assetData: string, userAddress: string): Promise<BigNumber>; + public abstract async getProxyAllowanceAsync(assetData: string, userAddress: string): Promise<BigNumber>; } diff --git a/packages/order-utils/src/abstract/abstract_balance_and_proxy_allowance_lazy_store.ts b/packages/order-utils/src/abstract/abstract_balance_and_proxy_allowance_lazy_store.ts new file mode 100644 index 000000000..38e08b7fe --- /dev/null +++ b/packages/order-utils/src/abstract/abstract_balance_and_proxy_allowance_lazy_store.ts @@ -0,0 +1,11 @@ +import { BigNumber } from '@0xproject/utils'; + +export abstract class AbstractBalanceAndProxyAllowanceLazyStore { + public abstract async getBalanceAsync(assetData: string, userAddress: string): Promise<BigNumber>; + public abstract async getProxyAllowanceAsync(assetData: string, userAddress: string): Promise<BigNumber>; + public abstract setBalance(assetData: string, userAddress: string, balance: BigNumber): void; + public abstract deleteBalance(assetData: string, userAddress: string): void; + public abstract setProxyAllowance(assetData: string, userAddress: string, proxyAllowance: BigNumber): void; + public abstract deleteProxyAllowance(assetData: string, userAddress: string): void; + public abstract deleteAll(): void; +} diff --git a/packages/order-utils/src/artifacts.ts b/packages/order-utils/src/artifacts.ts index f6fd00472..3d2d1e953 100644 --- a/packages/order-utils/src/artifacts.ts +++ b/packages/order-utils/src/artifacts.ts @@ -1,10 +1,14 @@ -import { Artifact } from '@0xproject/types'; +import { ContractArtifact } from '@0xproject/sol-compiler'; +import * as DummyERC20Token from './artifacts/DummyERC20Token.json'; +import * as ERC20Proxy from './artifacts/ERC20Proxy.json'; import * as Exchange from './artifacts/Exchange.json'; import * as IValidator from './artifacts/IValidator.json'; import * as IWallet from './artifacts/IWallet.json'; export const artifacts = { - Exchange: (Exchange as any) as Artifact, - IWallet: (IWallet as any) as Artifact, - IValidator: (IValidator as any) as Artifact, + ERC20Proxy: (ERC20Proxy as any) as ContractArtifact, + DummyERC20Token: (DummyERC20Token as any) as ContractArtifact, + Exchange: (Exchange as any) as ContractArtifact, + IWallet: (IWallet as any) as ContractArtifact, + IValidator: (IValidator as any) as ContractArtifact, }; diff --git a/packages/order-utils/src/constants.ts b/packages/order-utils/src/constants.ts index ec2fe744a..ed5bd8101 100644 --- a/packages/order-utils/src/constants.ts +++ b/packages/order-utils/src/constants.ts @@ -1,3 +1,8 @@ +import { BigNumber } from '@0xproject/utils'; + export const constants = { NULL_ADDRESS: '0x0000000000000000000000000000000000000000', + // tslint:disable-next-line:custom-no-magic-numbers + UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1), + TESTRPC_NETWORK_ID: 50, }; diff --git a/packages/order-utils/src/exchange_transfer_simulator.ts b/packages/order-utils/src/exchange_transfer_simulator.ts new file mode 100644 index 000000000..32d53d6a2 --- /dev/null +++ b/packages/order-utils/src/exchange_transfer_simulator.ts @@ -0,0 +1,113 @@ +import { ExchangeContractErrs } from '@0xproject/types'; +import { BigNumber } from '@0xproject/utils'; + +import { AbstractBalanceAndProxyAllowanceLazyStore } from './abstract/abstract_balance_and_proxy_allowance_lazy_store'; +import { constants } from './constants'; +import { TradeSide, TransferType } from './types'; + +enum FailureReason { + Balance = 'balance', + ProxyAllowance = 'proxyAllowance', +} + +const ERR_MSG_MAPPING = { + [FailureReason.Balance]: { + [TradeSide.Maker]: { + [TransferType.Trade]: ExchangeContractErrs.InsufficientMakerBalance, + [TransferType.Fee]: ExchangeContractErrs.InsufficientMakerFeeBalance, + }, + [TradeSide.Taker]: { + [TransferType.Trade]: ExchangeContractErrs.InsufficientTakerBalance, + [TransferType.Fee]: ExchangeContractErrs.InsufficientTakerFeeBalance, + }, + }, + [FailureReason.ProxyAllowance]: { + [TradeSide.Maker]: { + [TransferType.Trade]: ExchangeContractErrs.InsufficientMakerAllowance, + [TransferType.Fee]: ExchangeContractErrs.InsufficientMakerFeeAllowance, + }, + [TradeSide.Taker]: { + [TransferType.Trade]: ExchangeContractErrs.InsufficientTakerAllowance, + [TransferType.Fee]: ExchangeContractErrs.InsufficientTakerFeeAllowance, + }, + }, +}; + +export class ExchangeTransferSimulator { + private _store: AbstractBalanceAndProxyAllowanceLazyStore; + private static _throwValidationError( + failureReason: FailureReason, + tradeSide: TradeSide, + transferType: TransferType, + ): never { + const errMsg = ERR_MSG_MAPPING[failureReason][tradeSide][transferType]; + throw new Error(errMsg); + } + constructor(store: AbstractBalanceAndProxyAllowanceLazyStore) { + this._store = store; + } + /** + * Simulates transferFrom call performed by a proxy + * @param assetData Data of the asset being transferred. Includes + * it's identifying information and assetType, + * e.g address for ERC20, address & tokenId for ERC721 + * @param from Owner of the transferred tokens + * @param to Recipient of the transferred tokens + * @param amountInBaseUnits The amount of tokens being transferred + * @param tradeSide Is Maker/Taker transferring + * @param transferType Is it a fee payment or a value transfer + */ + public async transferFromAsync( + assetData: string, + from: string, + to: string, + amountInBaseUnits: BigNumber, + tradeSide: TradeSide, + transferType: TransferType, + ): Promise<void> { + // HACK: When simulating an open order (e.g taker is NULL_ADDRESS), we don't want to adjust balances/ + // allowances for the taker. We do however, want to increase the balance of the maker since the maker + // might be relying on those funds to fill subsequent orders or pay the order's fees. + if (from === constants.NULL_ADDRESS && tradeSide === TradeSide.Taker) { + await this._increaseBalanceAsync(assetData, to, amountInBaseUnits); + return; + } + const balance = await this._store.getBalanceAsync(assetData, from); + const proxyAllowance = await this._store.getProxyAllowanceAsync(assetData, from); + if (proxyAllowance.lessThan(amountInBaseUnits)) { + ExchangeTransferSimulator._throwValidationError(FailureReason.ProxyAllowance, tradeSide, transferType); + } + if (balance.lessThan(amountInBaseUnits)) { + ExchangeTransferSimulator._throwValidationError(FailureReason.Balance, tradeSide, transferType); + } + await this._decreaseProxyAllowanceAsync(assetData, from, amountInBaseUnits); + await this._decreaseBalanceAsync(assetData, from, amountInBaseUnits); + await this._increaseBalanceAsync(assetData, to, amountInBaseUnits); + } + private async _decreaseProxyAllowanceAsync( + assetData: string, + userAddress: string, + amountInBaseUnits: BigNumber, + ): Promise<void> { + const proxyAllowance = await this._store.getProxyAllowanceAsync(assetData, userAddress); + if (!proxyAllowance.eq(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS)) { + this._store.setProxyAllowance(assetData, userAddress, proxyAllowance.minus(amountInBaseUnits)); + } + } + private async _increaseBalanceAsync( + assetData: string, + userAddress: string, + amountInBaseUnits: BigNumber, + ): Promise<void> { + const balance = await this._store.getBalanceAsync(assetData, userAddress); + this._store.setBalance(assetData, userAddress, balance.plus(amountInBaseUnits)); + } + private async _decreaseBalanceAsync( + assetData: string, + userAddress: string, + amountInBaseUnits: BigNumber, + ): Promise<void> { + const balance = await this._store.getBalanceAsync(assetData, userAddress); + this._store.setBalance(assetData, userAddress, balance.minus(amountInBaseUnits)); + } +} diff --git a/packages/order-utils/src/index.ts b/packages/order-utils/src/index.ts index cb859dcb9..f9b37df82 100644 --- a/packages/order-utils/src/index.ts +++ b/packages/order-utils/src/index.ts @@ -7,6 +7,7 @@ export { isValidECSignature, ecSignOrderHashAsync, addSignedMessagePrefix, + parseECSignature, } from './signature_utils'; export { orderFactory } from './order_factory'; export { constants } from './constants'; @@ -18,3 +19,5 @@ export { AbstractOrderFilledCancelledFetcher } from './abstract/abstract_order_f export { RemainingFillableCalculator } from './remaining_fillable_calculator'; export { OrderStateUtils } from './order_state_utils'; export { assetProxyUtils } from './asset_proxy_utils'; +export { OrderValidationUtils } from './order_validation_utils'; +export { ExchangeTransferSimulator } from './exchange_transfer_simulator'; diff --git a/packages/order-utils/src/order_validation_utils.ts b/packages/order-utils/src/order_validation_utils.ts new file mode 100644 index 000000000..3a6704f26 --- /dev/null +++ b/packages/order-utils/src/order_validation_utils.ts @@ -0,0 +1,231 @@ +import { ExchangeContractErrs, Order, SignedOrder } from '@0xproject/types'; +import { BigNumber } from '@0xproject/utils'; +import { Provider } from 'ethereum-types'; +import * as _ from 'lodash'; + +import { OrderError, TradeSide, TransferType } from './types'; + +import { constants } from './constants'; +import { ExchangeTransferSimulator } from './exchange_transfer_simulator'; +import { ExchangeContract } from './generated_contract_wrappers/exchange'; +import { orderHashUtils } from './order_hash'; +import { isValidSignatureAsync } from './signature_utils'; +import { utils } from './utils'; + +export class OrderValidationUtils { + private _exchangeContract: ExchangeContract; + // TODO: Write some tests for the function + // const numerator = new BigNumber(20); + // const denominator = new BigNumber(999); + // const target = new BigNumber(50); + // rounding error = ((20*50/999) - floor(20*50/999)) / (20*50/999) = 0.1% + 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 + if (denominator.eq(0)) { + throw new Error('denominator cannot be 0'); + } + const remainder = target.mul(numerator).mod(denominator); + if (remainder.eq(0)) { + return false; // no rounding error + } + + // tslint:disable-next-line:custom-no-magic-numbers + const errPercentageTimes1000000 = remainder.mul(1000000).div(numerator.mul(target)); + // tslint:disable-next-line:custom-no-magic-numbers + const isError = errPercentageTimes1000000.gt(1000); + return isError; + } + public static validateCancelOrderThrowIfInvalid( + order: Order, + cancelTakerTokenAmount: BigNumber, + filledTakerTokenAmount: BigNumber, + ): void { + if (cancelTakerTokenAmount.eq(0)) { + throw new Error(ExchangeContractErrs.OrderCancelAmountZero); + } + if (order.takerAssetAmount.eq(filledTakerTokenAmount)) { + throw new Error(ExchangeContractErrs.OrderAlreadyCancelledOrFilled); + } + const currentUnixTimestampSec = utils.getCurrentUnixTimestampSec(); + if (order.expirationTimeSeconds.lessThan(currentUnixTimestampSec)) { + throw new Error(ExchangeContractErrs.OrderCancelExpired); + } + } + public static async validateFillOrderBalancesAllowancesThrowIfInvalidAsync( + exchangeTradeEmulator: ExchangeTransferSimulator, + signedOrder: SignedOrder, + fillTakerTokenAmount: BigNumber, + senderAddress: string, + zrxTokenAddress: string, + ): Promise<void> { + const fillMakerTokenAmount = OrderValidationUtils._getPartialAmount( + fillTakerTokenAmount, + signedOrder.takerAssetAmount, + signedOrder.makerAssetAmount, + ); + await exchangeTradeEmulator.transferFromAsync( + signedOrder.makerAssetData, + signedOrder.makerAddress, + senderAddress, + fillMakerTokenAmount, + TradeSide.Maker, + TransferType.Trade, + ); + await exchangeTradeEmulator.transferFromAsync( + signedOrder.takerAssetData, + senderAddress, + signedOrder.makerAddress, + fillTakerTokenAmount, + TradeSide.Taker, + TransferType.Trade, + ); + const makerFeeAmount = OrderValidationUtils._getPartialAmount( + fillTakerTokenAmount, + signedOrder.takerAssetAmount, + signedOrder.makerFee, + ); + await exchangeTradeEmulator.transferFromAsync( + zrxTokenAddress, + signedOrder.makerAddress, + signedOrder.feeRecipientAddress, + makerFeeAmount, + TradeSide.Maker, + TransferType.Fee, + ); + const takerFeeAmount = OrderValidationUtils._getPartialAmount( + fillTakerTokenAmount, + signedOrder.takerAssetAmount, + signedOrder.takerFee, + ); + await exchangeTradeEmulator.transferFromAsync( + zrxTokenAddress, + senderAddress, + signedOrder.feeRecipientAddress, + takerFeeAmount, + TradeSide.Taker, + TransferType.Fee, + ); + } + private static _validateRemainingFillAmountNotZeroOrThrow( + takerAssetAmount: BigNumber, + filledTakerTokenAmount: BigNumber, + ): void { + if (takerAssetAmount.eq(filledTakerTokenAmount)) { + throw new Error(ExchangeContractErrs.OrderRemainingFillAmountZero); + } + } + private static _validateOrderNotExpiredOrThrow(expirationTimeSeconds: BigNumber): void { + const currentUnixTimestampSec = utils.getCurrentUnixTimestampSec(); + if (expirationTimeSeconds.lessThan(currentUnixTimestampSec)) { + throw new Error(ExchangeContractErrs.OrderFillExpired); + } + } + private static _getPartialAmount(numerator: BigNumber, denominator: BigNumber, target: BigNumber): BigNumber { + const fillMakerTokenAmount = numerator + .mul(target) + .div(denominator) + .round(0); + return fillMakerTokenAmount; + } + constructor(exchangeContract: ExchangeContract) { + this._exchangeContract = exchangeContract; + } + public async validateOrderFillableOrThrowAsync( + exchangeTradeEmulator: ExchangeTransferSimulator, + signedOrder: SignedOrder, + zrxTokenAddress: string, + expectedFillTakerTokenAmount?: BigNumber, + ): Promise<void> { + const orderHash = orderHashUtils.getOrderHashHex(signedOrder); + const filledTakerTokenAmount = await this._exchangeContract.filled.callAsync(orderHash); + OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow( + signedOrder.takerAssetAmount, + filledTakerTokenAmount, + ); + OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationTimeSeconds); + let fillTakerTokenAmount = signedOrder.takerAssetAmount.minus(filledTakerTokenAmount); + if (!_.isUndefined(expectedFillTakerTokenAmount)) { + fillTakerTokenAmount = expectedFillTakerTokenAmount; + } + await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync( + exchangeTradeEmulator, + signedOrder, + fillTakerTokenAmount, + signedOrder.takerAddress, + zrxTokenAddress, + ); + } + public async validateFillOrderThrowIfInvalidAsync( + exchangeTradeEmulator: ExchangeTransferSimulator, + provider: Provider, + signedOrder: SignedOrder, + fillTakerTokenAmount: BigNumber, + takerAddress: string, + zrxTokenAddress: string, + ): Promise<BigNumber> { + if (fillTakerTokenAmount.eq(0)) { + throw new Error(ExchangeContractErrs.OrderFillAmountZero); + } + const orderHash = orderHashUtils.getOrderHashHex(signedOrder); + const isValid = await isValidSignatureAsync( + provider, + orderHash, + signedOrder.signature, + signedOrder.makerAddress, + ); + if (!isValid) { + throw new Error(OrderError.InvalidSignature); + } + const filledTakerTokenAmount = await this._exchangeContract.filled.callAsync(orderHash); + OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow( + signedOrder.takerAssetAmount, + filledTakerTokenAmount, + ); + if (signedOrder.takerAddress !== constants.NULL_ADDRESS && signedOrder.takerAddress !== takerAddress) { + throw new Error(ExchangeContractErrs.TransactionSenderIsNotFillOrderTaker); + } + OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationTimeSeconds); + const remainingTakerTokenAmount = signedOrder.takerAssetAmount.minus(filledTakerTokenAmount); + const desiredFillTakerTokenAmount = remainingTakerTokenAmount.lessThan(fillTakerTokenAmount) + ? remainingTakerTokenAmount + : fillTakerTokenAmount; + await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync( + exchangeTradeEmulator, + signedOrder, + desiredFillTakerTokenAmount, + takerAddress, + zrxTokenAddress, + ); + + const wouldRoundingErrorOccur = OrderValidationUtils.isRoundingError( + filledTakerTokenAmount, + signedOrder.takerAssetAmount, + signedOrder.makerAssetAmount, + ); + if (wouldRoundingErrorOccur) { + throw new Error(ExchangeContractErrs.OrderFillRoundingError); + } + return filledTakerTokenAmount; + } + public async validateFillOrKillOrderThrowIfInvalidAsync( + exchangeTradeEmulator: ExchangeTransferSimulator, + provider: Provider, + signedOrder: SignedOrder, + fillTakerTokenAmount: BigNumber, + takerAddress: string, + zrxTokenAddress: string, + ): Promise<void> { + const filledTakerTokenAmount = await this.validateFillOrderThrowIfInvalidAsync( + exchangeTradeEmulator, + provider, + signedOrder, + fillTakerTokenAmount, + takerAddress, + zrxTokenAddress, + ); + if (filledTakerTokenAmount !== fillTakerTokenAmount) { + throw new Error(ExchangeContractErrs.InsufficientRemainingFillAmount); + } + } +} diff --git a/packages/order-utils/src/signature_utils.ts b/packages/order-utils/src/signature_utils.ts index c3fa0b6a5..44a7203a0 100644 --- a/packages/order-utils/src/signature_utils.ts +++ b/packages/order-utils/src/signature_utils.ts @@ -90,7 +90,7 @@ export async function isValidPresignedSignatureAsync( data: string, signerAddress: string, ): Promise<boolean> { - const exchangeContract = new ExchangeContract(artifacts.Exchange.abi, signerAddress, provider); + const exchangeContract = new ExchangeContract(artifacts.Exchange.compilerOutput.abi, signerAddress, provider); const isValid = await exchangeContract.preSigned.callAsync(data, signerAddress); return isValid; } @@ -110,7 +110,7 @@ export async function isValidWalletSignatureAsync( ): Promise<boolean> { // tslint:disable-next-line:custom-no-magic-numbers const signatureWithoutType = signature.slice(-2); - const walletContract = new IWalletContract(artifacts.IWallet.abi, signerAddress, provider); + const walletContract = new IWalletContract(artifacts.IWallet.compilerOutput.abi, signerAddress, provider); const isValid = await walletContract.isValidSignature.callAsync(data, signatureWithoutType); return isValid; } @@ -129,7 +129,7 @@ export async function isValidValidatorSignatureAsync( signerAddress: string, ): Promise<boolean> { const validatorSignature = parseValidatorSignature(signature); - const exchangeContract = new ExchangeContract(artifacts.Exchange.abi, signerAddress, provider); + const exchangeContract = new ExchangeContract(artifacts.Exchange.compilerOutput.abi, signerAddress, provider); const isValidatorApproved = await exchangeContract.allowedValidators.callAsync( signerAddress, validatorSignature.validatorAddress, @@ -138,7 +138,7 @@ export async function isValidValidatorSignatureAsync( throw new Error(`Validator ${validatorSignature.validatorAddress} was not pre-approved by ${signerAddress}.`); } - const validatorContract = new IValidatorContract(artifacts.IValidator.abi, signerAddress, provider); + const validatorContract = new IValidatorContract(artifacts.IValidator.compilerOutput.abi, signerAddress, provider); const isValid = await validatorContract.isValidSignature.callAsync( data, signerAddress, @@ -260,12 +260,12 @@ export function addSignedMessagePrefix(message: string, messagePrefixType: Messa } } -function hashTrezorPersonalMessage(message: Buffer): Buffer { - const prefix = ethUtil.toBuffer('\x19Ethereum Signed Message:\n' + String.fromCharCode(message.length)); - return ethUtil.sha3(Buffer.concat([prefix, message])); -} - -function parseECSignature(signature: string): ECSignature { +/** + * Parse a 0x protocol hex-encoded signature string into it's ECSignature components + * @param signature A hex encoded ecSignature 0x Protocol signature + * @return An ECSignature object with r,s,v parameters + */ +export function parseECSignature(signature: string): ECSignature { const ecSignatureTypes = [SignatureType.EthSign, SignatureType.EIP712, SignatureType.Trezor]; assert.isOneOfExpectedSignatureTypes(signature, ecSignatureTypes); @@ -276,6 +276,11 @@ function parseECSignature(signature: string): ECSignature { return ecSignature; } +function hashTrezorPersonalMessage(message: Buffer): Buffer { + const prefix = ethUtil.toBuffer('\x19Ethereum Signed Message:\n' + String.fromCharCode(message.length)); + return ethUtil.sha3(Buffer.concat([prefix, message])); +} + function parseValidatorSignature(signature: string): ValidatorSignature { assert.isOneOfExpectedSignatureTypes(signature, [SignatureType.Validator]); // tslint:disable:custom-no-magic-numbers 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 new file mode 100644 index 000000000..08d50b924 --- /dev/null +++ b/packages/order-utils/src/store/balance_and_proxy_allowance_lazy_store.ts @@ -0,0 +1,81 @@ +import { BigNumber } from '@0xproject/utils'; +import * as _ from 'lodash'; + +import { AbstractBalanceAndProxyAllowanceFetcher } from '../abstract/abstract_balance_and_proxy_allowance_fetcher'; +import { AbstractBalanceAndProxyAllowanceLazyStore } from '../abstract/abstract_balance_and_proxy_allowance_lazy_store'; + +/** + * Copy on read store for balances/proxyAllowances of tokens/accounts + */ +export class BalanceAndProxyAllowanceLazyStore implements AbstractBalanceAndProxyAllowanceLazyStore { + private _balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher; + private _balance: { + [assetData: string]: { + [userAddress: string]: BigNumber; + }; + }; + private _proxyAllowance: { + [assetData: string]: { + [userAddress: string]: BigNumber; + }; + }; + constructor(token: AbstractBalanceAndProxyAllowanceFetcher) { + this._balanceAndProxyAllowanceFetcher = token; + this._balance = {}; + this._proxyAllowance = {}; + } + public async getBalanceAsync(assetData: string, userAddress: string): Promise<BigNumber> { + if (_.isUndefined(this._balance[assetData]) || _.isUndefined(this._balance[assetData][userAddress])) { + const balance = await this._balanceAndProxyAllowanceFetcher.getBalanceAsync(assetData, userAddress); + this.setBalance(assetData, userAddress, balance); + } + const cachedBalance = this._balance[assetData][userAddress]; + return cachedBalance; + } + public setBalance(assetData: string, userAddress: string, balance: BigNumber): void { + if (_.isUndefined(this._balance[assetData])) { + this._balance[assetData] = {}; + } + this._balance[assetData][userAddress] = balance; + } + public deleteBalance(assetData: string, userAddress: string): void { + if (!_.isUndefined(this._balance[assetData])) { + delete this._balance[assetData][userAddress]; + if (_.isEmpty(this._balance[assetData])) { + delete this._balance[assetData]; + } + } + } + public async getProxyAllowanceAsync(assetData: string, userAddress: string): Promise<BigNumber> { + if ( + _.isUndefined(this._proxyAllowance[assetData]) || + _.isUndefined(this._proxyAllowance[assetData][userAddress]) + ) { + const proxyAllowance = await this._balanceAndProxyAllowanceFetcher.getProxyAllowanceAsync( + assetData, + userAddress, + ); + this.setProxyAllowance(assetData, userAddress, proxyAllowance); + } + const cachedProxyAllowance = this._proxyAllowance[assetData][userAddress]; + return cachedProxyAllowance; + } + public setProxyAllowance(assetData: string, userAddress: string, proxyAllowance: BigNumber): void { + if (_.isUndefined(this._proxyAllowance[assetData])) { + this._proxyAllowance[assetData] = {}; + } + this._proxyAllowance[assetData][userAddress] = proxyAllowance; + } + public deleteProxyAllowance(assetData: string, userAddress: string): void { + if (!_.isUndefined(this._proxyAllowance[assetData])) { + delete this._proxyAllowance[assetData][userAddress]; + if (_.isEmpty(this._proxyAllowance[assetData])) { + delete this._proxyAllowance[assetData]; + } + } + } + public deleteAll(): void { + this._balance = {}; + this._proxyAllowance = {}; + } +} diff --git a/packages/order-utils/src/types.ts b/packages/order-utils/src/types.ts index db0bfb249..3f1fce66d 100644 --- a/packages/order-utils/src/types.ts +++ b/packages/order-utils/src/types.ts @@ -23,3 +23,13 @@ export interface MessagePrefixOpts { prefixType: MessagePrefixType; shouldAddPrefixBeforeCallingEthSign: boolean; } + +export enum TradeSide { + Maker = 'maker', + Taker = 'taker', +} + +export enum TransferType { + Trade = 'trade', + Fee = 'fee', +} diff --git a/packages/order-utils/src/utils.ts b/packages/order-utils/src/utils.ts index 3b465cece..6149316f6 100644 --- a/packages/order-utils/src/utils.ts +++ b/packages/order-utils/src/utils.ts @@ -1,3 +1,5 @@ +import { BigNumber } from '@0xproject/utils'; + export const utils = { getSignatureTypeIndexIfExists(signature: string): number { // tslint:disable-next-line:custom-no-magic-numbers @@ -6,4 +8,8 @@ export const utils = { const signatureTypeInt = parseInt(signatureTypeHex, base); return signatureTypeInt; }, + getCurrentUnixTimestampSec(): BigNumber { + const milisecondsInSecond = 1000; + return new BigNumber(Date.now() / milisecondsInSecond).round(); + }, }; diff --git a/packages/order-utils/test/exchange_transfer_simulator_test.ts b/packages/order-utils/test/exchange_transfer_simulator_test.ts new file mode 100644 index 000000000..eeae42698 --- /dev/null +++ b/packages/order-utils/test/exchange_transfer_simulator_test.ts @@ -0,0 +1,177 @@ +import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils'; +import { ExchangeContractErrs } from '@0xproject/types'; +import { BigNumber } from '@0xproject/utils'; +import * as chai from 'chai'; +import 'make-promises-safe'; + +import { artifacts } from '../src/artifacts'; +import { constants } from '../src/constants'; +import { ExchangeTransferSimulator } from '../src/exchange_transfer_simulator'; +import { DummyERC20TokenContract } from '../src/generated_contract_wrappers/dummy_e_r_c20_token'; +import { ERC20ProxyContract } from '../src/generated_contract_wrappers/e_r_c20_proxy'; +import { ERC20TokenContract } from '../src/generated_contract_wrappers/e_r_c20_token'; +import { BalanceAndProxyAllowanceLazyStore } from '../src/store/balance_and_proxy_allowance_lazy_store'; +import { TradeSide, TransferType } from '../src/types'; + +import { chaiSetup } from './utils/chai_setup'; +import { SimpleERC20BalanceAndProxyAllowanceFetcher } from './utils/simple_erc20_balance_and_proxy_allowance_fetcher'; +import { provider, web3Wrapper } from './utils/web3_wrapper'; + +chaiSetup.configure(); +const expect = chai.expect; +const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); + +describe('ExchangeTransferSimulator', async () => { + const transferAmount = new BigNumber(5); + let userAddresses: string[]; + let dummyERC20Token: DummyERC20TokenContract; + let coinbase: string; + let sender: string; + let recipient: string; + let exampleTokenAddress: string; + let exchangeTransferSimulator: ExchangeTransferSimulator; + let txHash: string; + let erc20ProxyAddress: string; + before(async function(): Promise<void> { + const mochaTestTimeoutMs = 20000; + this.timeout(mochaTestTimeoutMs); + + userAddresses = await web3Wrapper.getAvailableAddressesAsync(); + [coinbase, sender, recipient] = userAddresses; + + const txDefaults = { + gas: devConstants.GAS_LIMIT, + from: devConstants.TESTRPC_FIRST_ADDRESS, + }; + + const erc20Proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync( + artifacts.ERC20Proxy, + provider, + txDefaults, + ); + erc20ProxyAddress = erc20Proxy.address; + + const totalSupply = new BigNumber(100000000000000000000); + const name = 'Test'; + const symbol = 'TST'; + const decimals = new BigNumber(18); + // tslint:disable-next-line:no-unused-variable + dummyERC20Token = await DummyERC20TokenContract.deployFrom0xArtifactAsync( + artifacts.DummyERC20Token, + provider, + txDefaults, + name, + symbol, + decimals, + totalSupply, + ); + + exampleTokenAddress = dummyERC20Token.address; + }); + beforeEach(async () => { + await blockchainLifecycle.startAsync(); + }); + afterEach(async () => { + await blockchainLifecycle.revertAsync(); + }); + describe('#transferFromAsync', function(): void { + // HACK: For some reason these tests need a slightly longer timeout + const mochaTestTimeoutMs = 3000; + this.timeout(mochaTestTimeoutMs); + + beforeEach(() => { + const simpleERC20BalanceAndProxyAllowanceFetcher = new SimpleERC20BalanceAndProxyAllowanceFetcher( + (dummyERC20Token as any) as ERC20TokenContract, + erc20ProxyAddress, + ); + const balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore( + simpleERC20BalanceAndProxyAllowanceFetcher, + ); + exchangeTransferSimulator = new ExchangeTransferSimulator(balanceAndProxyAllowanceLazyStore); + }); + it("throws if the user doesn't have enough allowance", async () => { + return expect( + exchangeTransferSimulator.transferFromAsync( + exampleTokenAddress, + sender, + recipient, + transferAmount, + TradeSide.Taker, + TransferType.Trade, + ), + ).to.be.rejectedWith(ExchangeContractErrs.InsufficientTakerAllowance); + }); + it("throws if the user doesn't have enough balance", async () => { + txHash = await dummyERC20Token.approve.sendTransactionAsync(erc20ProxyAddress, transferAmount, { + from: sender, + }); + await web3Wrapper.awaitTransactionSuccessAsync(txHash); + return expect( + exchangeTransferSimulator.transferFromAsync( + exampleTokenAddress, + sender, + recipient, + transferAmount, + TradeSide.Maker, + TransferType.Trade, + ), + ).to.be.rejectedWith(ExchangeContractErrs.InsufficientMakerBalance); + }); + it('updates balances and proxyAllowance after transfer', async () => { + txHash = await dummyERC20Token.transfer.sendTransactionAsync(sender, transferAmount, { + from: coinbase, + }); + await web3Wrapper.awaitTransactionSuccessAsync(txHash); + + txHash = await dummyERC20Token.approve.sendTransactionAsync(erc20ProxyAddress, transferAmount, { + from: sender, + }); + await web3Wrapper.awaitTransactionSuccessAsync(txHash); + + await exchangeTransferSimulator.transferFromAsync( + exampleTokenAddress, + sender, + recipient, + transferAmount, + TradeSide.Taker, + TransferType.Trade, + ); + const store = (exchangeTransferSimulator as any)._store; + const senderBalance = await store.getBalanceAsync(exampleTokenAddress, sender); + const recipientBalance = await store.getBalanceAsync(exampleTokenAddress, recipient); + const senderProxyAllowance = await store.getProxyAllowanceAsync(exampleTokenAddress, sender); + expect(senderBalance).to.be.bignumber.equal(0); + expect(recipientBalance).to.be.bignumber.equal(transferAmount); + expect(senderProxyAllowance).to.be.bignumber.equal(0); + }); + it("doesn't update proxyAllowance after transfer if unlimited", async () => { + txHash = await dummyERC20Token.transfer.sendTransactionAsync(sender, transferAmount, { + from: coinbase, + }); + await web3Wrapper.awaitTransactionSuccessAsync(txHash); + txHash = await dummyERC20Token.approve.sendTransactionAsync( + erc20ProxyAddress, + constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS, + { + from: sender, + }, + ); + await web3Wrapper.awaitTransactionSuccessAsync(txHash); + await exchangeTransferSimulator.transferFromAsync( + exampleTokenAddress, + sender, + recipient, + transferAmount, + TradeSide.Taker, + TransferType.Trade, + ); + const store = (exchangeTransferSimulator as any)._store; + const senderBalance = await store.getBalanceAsync(exampleTokenAddress, sender); + const recipientBalance = await store.getBalanceAsync(exampleTokenAddress, recipient); + const senderProxyAllowance = await store.getProxyAllowanceAsync(exampleTokenAddress, sender); + expect(senderBalance).to.be.bignumber.equal(0); + expect(recipientBalance).to.be.bignumber.equal(transferAmount); + expect(senderProxyAllowance).to.be.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); + }); + }); +}); diff --git a/packages/order-utils/test/order_validation_utils_test.ts b/packages/order-utils/test/order_validation_utils_test.ts new file mode 100644 index 000000000..d3ff867d7 --- /dev/null +++ b/packages/order-utils/test/order_validation_utils_test.ts @@ -0,0 +1,70 @@ +import { BigNumber } from '@0xproject/utils'; +import * as chai from 'chai'; +import 'mocha'; + +import { OrderValidationUtils } from '../src/order_validation_utils'; + +import { chaiSetup } from './utils/chai_setup'; + +chaiSetup.configure(); +const expect = chai.expect; + +describe('OrderValidationUtils', () => { + describe('#isRoundingError', () => { + it('should return false if there is a rounding error of 0.1%', async () => { + const numerator = new BigNumber(20); + const denominator = new BigNumber(999); + const target = new BigNumber(50); + // rounding error = ((20*50/999) - floor(20*50/999)) / (20*50/999) = 0.1% + const isRoundingError = OrderValidationUtils.isRoundingError(numerator, denominator, target); + expect(isRoundingError).to.be.false(); + }); + + it('should return false if there is a rounding of 0.09%', async () => { + const numerator = new BigNumber(20); + const denominator = new BigNumber(9991); + const target = new BigNumber(500); + // rounding error = ((20*500/9991) - floor(20*500/9991)) / (20*500/9991) = 0.09% + const isRoundingError = OrderValidationUtils.isRoundingError(numerator, denominator, target); + expect(isRoundingError).to.be.false(); + }); + + it('should return true if there is a rounding error of 0.11%', async () => { + const numerator = new BigNumber(20); + const denominator = new BigNumber(9989); + const target = new BigNumber(500); + // rounding error = ((20*500/9989) - floor(20*500/9989)) / (20*500/9989) = 0.011% + const isRoundingError = OrderValidationUtils.isRoundingError(numerator, denominator, target); + expect(isRoundingError).to.be.true(); + }); + + it('should return true if there is a rounding error > 0.1%', async () => { + const numerator = new BigNumber(3); + const denominator = new BigNumber(7); + const target = new BigNumber(10); + // rounding error = ((3*10/7) - floor(3*10/7)) / (3*10/7) = 6.67% + const isRoundingError = OrderValidationUtils.isRoundingError(numerator, denominator, target); + expect(isRoundingError).to.be.true(); + }); + + it('should return false when there is no rounding error', async () => { + const numerator = new BigNumber(1); + const denominator = new BigNumber(2); + const target = new BigNumber(10); + + const isRoundingError = OrderValidationUtils.isRoundingError(numerator, denominator, target); + expect(isRoundingError).to.be.false(); + }); + + it('should return false when there is rounding error <= 0.1%', async () => { + // randomly generated numbers + const numerator = new BigNumber(76564); + const denominator = new BigNumber(676373677); + const target = new BigNumber(105762562); + // rounding error = ((76564*105762562/676373677) - floor(76564*105762562/676373677)) / + // (76564*105762562/676373677) = 0.0007% + const isRoundingError = OrderValidationUtils.isRoundingError(numerator, denominator, target); + expect(isRoundingError).to.be.false(); + }); + }); +}); diff --git a/packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts b/packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts new file mode 100644 index 000000000..d41eaca40 --- /dev/null +++ b/packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts @@ -0,0 +1,26 @@ +import { BigNumber } from '@0xproject/utils'; + +import { AbstractBalanceAndProxyAllowanceFetcher } from '../../src/abstract/abstract_balance_and_proxy_allowance_fetcher'; + +import { ERC20TokenContract } from '../../src/generated_contract_wrappers/e_r_c20_token'; + +export class SimpleERC20BalanceAndProxyAllowanceFetcher implements AbstractBalanceAndProxyAllowanceFetcher { + private _erc20TokenContract: ERC20TokenContract; + private _erc20ProxyAddress: string; + constructor(erc20TokenWrapper: ERC20TokenContract, erc20ProxyAddress: string) { + this._erc20TokenContract = erc20TokenWrapper; + this._erc20ProxyAddress = erc20ProxyAddress; + } + public async getBalanceAsync(_assetData: string, userAddress: string): Promise<BigNumber> { + // HACK: We cheat and don't pass in the assetData since it's always the same token used + // in our tests. + const balance = await this._erc20TokenContract.balanceOf.callAsync(userAddress); + return balance; + } + public async getProxyAllowanceAsync(_assetData: string, userAddress: string): Promise<BigNumber> { + // HACK: We cheat and don't pass in the assetData since it's always the same token used + // in our tests. + const proxyAllowance = await this._erc20TokenContract.allowance.callAsync(userAddress, this._erc20ProxyAddress); + return proxyAllowance; + } +} diff --git a/packages/order-watcher/src/order_watcher/expiration_watcher.ts b/packages/order-watcher/src/order_watcher/expiration_watcher.ts index ec2c1ec35..31fda7dca 100644 --- a/packages/order-watcher/src/order_watcher/expiration_watcher.ts +++ b/packages/order-watcher/src/order_watcher/expiration_watcher.ts @@ -19,6 +19,8 @@ export class ExpirationWatcher { private _expirationMarginMs: number; private _orderExpirationCheckingIntervalIdIfExists?: NodeJS.Timer; constructor(expirationMarginIfExistsMs?: number, orderExpirationCheckingIntervalIfExistsMs?: number) { + this._orderExpirationCheckingIntervalMs = + orderExpirationCheckingIntervalIfExistsMs || DEFAULT_ORDER_EXPIRATION_CHECKING_INTERVAL_MS; this._expirationMarginMs = expirationMarginIfExistsMs || DEFAULT_EXPIRATION_MARGIN_MS; this._orderExpirationCheckingIntervalMs = expirationMarginIfExistsMs || DEFAULT_ORDER_EXPIRATION_CHECKING_INTERVAL_MS; diff --git a/packages/order-watcher/test/expiration_watcher_test.ts b/packages/order-watcher/test/expiration_watcher_test.ts index 068c267c3..fbea93c06 100644 --- a/packages/order-watcher/test/expiration_watcher_test.ts +++ b/packages/order-watcher/test/expiration_watcher_test.ts @@ -107,7 +107,7 @@ describe('ExpirationWatcher', () => { ); const orderHash = getOrderHashHex(signedOrder); expirationWatcher.addOrder(orderHash, signedOrder.expirationUnixTimestampSec.times(MILISECONDS_IN_SECOND)); - const callbackAsync = callbackErrorReporter.reportNoErrorCallbackErrors(done)(async (hash: string) => { + const callbackAsync = callbackErrorReporter.reportNoErrorCallbackErrors(done)(async (_hash: string) => { done(new Error('Emitted expiration went before the order actually expired')); }); expirationWatcher.subscribe(callbackAsync); diff --git a/packages/order-watcher/test/order_watcher_test.ts b/packages/order-watcher/test/order_watcher_test.ts index a4713a56c..ef5c7b8e0 100644 --- a/packages/order-watcher/test/order_watcher_test.ts +++ b/packages/order-watcher/test/order_watcher_test.ts @@ -159,7 +159,7 @@ describe('OrderWatcher', () => { fillableAmount, ); orderWatcher.addOrder(signedOrder); - const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((_orderState: OrderState) => { throw new Error('OrderState callback fired for irrelevant order'); }); orderWatcher.subscribe(callback); diff --git a/packages/react-docs/src/components/documentation.tsx b/packages/react-docs/src/components/documentation.tsx index 2b021f04c..a4e6f4f6e 100644 --- a/packages/react-docs/src/components/documentation.tsx +++ b/packages/react-docs/src/components/documentation.tsx @@ -73,7 +73,7 @@ export class Documentation extends React.Component<DocumentationProps, Documenta public componentWillUnmount(): void { window.removeEventListener('hashchange', this._onHashChanged.bind(this), false); } - public componentDidUpdate(prevProps: DocumentationProps, prevState: DocumentationState): void { + public componentDidUpdate(prevProps: DocumentationProps, _prevState: DocumentationState): void { if (!_.isEqual(prevProps.docAgnosticFormat, this.props.docAgnosticFormat)) { const hash = window.location.hash.slice(1); sharedUtils.scrollToHash(hash, sharedConstants.SCROLL_CONTAINER_ID); @@ -364,7 +364,7 @@ export class Documentation extends React.Component<DocumentationProps, Documenta /> ); } - private _onSidebarHover(event: React.FormEvent<HTMLInputElement>): void { + private _onSidebarHover(_event: React.FormEvent<HTMLInputElement>): void { this.setState({ isHoveringSidebar: true, }); @@ -374,7 +374,7 @@ export class Documentation extends React.Component<DocumentationProps, Documenta isHoveringSidebar: false, }); } - private _onHashChanged(event: any): void { + private _onHashChanged(_event: any): void { const hash = window.location.hash.slice(1); sharedUtils.scrollToHash(hash, sharedConstants.SCROLL_CONTAINER_ID); } diff --git a/packages/react-docs/src/components/enum.tsx b/packages/react-docs/src/components/enum.tsx index 536385d90..dee866790 100644 --- a/packages/react-docs/src/components/enum.tsx +++ b/packages/react-docs/src/components/enum.tsx @@ -8,7 +8,7 @@ export interface EnumProps { } export const Enum = (props: EnumProps) => { - const values = _.map(props.values, (value, i) => { + const values = _.map(props.values, value => { const defaultValueIfAny = !_.isUndefined(value.defaultValue) ? ` = ${value.defaultValue}` : ''; return `\n\t${value.name}${defaultValueIfAny},`; }); diff --git a/packages/react-shared/src/components/markdown_code_block.tsx b/packages/react-shared/src/components/markdown_code_block.tsx index bca8a7a90..3b28424cd 100644 --- a/packages/react-shared/src/components/markdown_code_block.tsx +++ b/packages/react-shared/src/components/markdown_code_block.tsx @@ -11,7 +11,7 @@ export interface MarkdownCodeBlockState {} export class MarkdownCodeBlock extends React.Component<MarkdownCodeBlockProps, MarkdownCodeBlockState> { // Re-rendering a codeblock causes any use selection to become de-selected. This is annoying when trying // to copy-paste code examples. We therefore noop re-renders on this component if it's props haven't changed. - public shouldComponentUpdate(nextProps: MarkdownCodeBlockProps, nextState: MarkdownCodeBlockState): boolean { + public shouldComponentUpdate(nextProps: MarkdownCodeBlockProps, _nextState: MarkdownCodeBlockState): boolean { return nextProps.value !== this.props.value || nextProps.language !== this.props.language; } public render(): React.ReactNode { diff --git a/packages/react-shared/src/components/markdown_link_block.tsx b/packages/react-shared/src/components/markdown_link_block.tsx index 0b489b749..f083a91cf 100644 --- a/packages/react-shared/src/components/markdown_link_block.tsx +++ b/packages/react-shared/src/components/markdown_link_block.tsx @@ -13,7 +13,7 @@ export interface MarkdownLinkBlockState {} export class MarkdownLinkBlock extends React.Component<MarkdownLinkBlockProps, MarkdownLinkBlockState> { // Re-rendering a linkBlock causes it to remain unclickable. // We therefore noop re-renders on this component if it's props haven't changed. - public shouldComponentUpdate(nextProps: MarkdownLinkBlockProps, nextState: MarkdownLinkBlockState): boolean { + public shouldComponentUpdate(nextProps: MarkdownLinkBlockProps, _nextState: MarkdownLinkBlockState): boolean { return nextProps.href !== this.props.href; } public render(): React.ReactNode { diff --git a/packages/react-shared/src/components/version_drop_down.tsx b/packages/react-shared/src/components/version_drop_down.tsx index 115fe3c6a..e41590957 100644 --- a/packages/react-shared/src/components/version_drop_down.tsx +++ b/packages/react-shared/src/components/version_drop_down.tsx @@ -31,7 +31,7 @@ export class VersionDropDown extends React.Component<VersionDropDownProps, Versi }); return items; } - private _updateSelectedVersion(e: any, index: number, semver: string): void { + private _updateSelectedVersion(_e: any, _index: number, semver: string): void { this.props.onVersionSelected(semver); } } diff --git a/packages/sol-cov/src/trace_collection_subprovider.ts b/packages/sol-cov/src/trace_collection_subprovider.ts index ba9f03897..fe73546e8 100644 --- a/packages/sol-cov/src/trace_collection_subprovider.ts +++ b/packages/sol-cov/src/trace_collection_subprovider.ts @@ -73,7 +73,7 @@ export class TraceCollectionSubprovider extends Subprovider { * @param end Callback to call if subprovider handled the request and wants to pass back the request. */ // tslint:disable-next-line:prefer-function-over-method async-suffix - public async handleRequest(payload: JSONRPCRequestPayload, next: NextCallback, end: ErrorCallback): Promise<void> { + public async handleRequest(payload: JSONRPCRequestPayload, next: NextCallback, _end: ErrorCallback): Promise<void> { if (this._isEnabled) { switch (payload.method) { case 'eth_sendTransaction': @@ -155,8 +155,8 @@ export class TraceCollectionSubprovider extends Subprovider { } private async _onCallOrGasEstimateExecutedAsync( callData: Partial<CallData>, - err: Error | null, - callResult: string, + _err: Error | null, + _callResult: string, cb: Callback, ): Promise<void> { await this._recordCallOrGasEstimateTraceAsync(callData); diff --git a/packages/subproviders/src/subproviders/ganache.ts b/packages/subproviders/src/subproviders/ganache.ts index 73d0513cc..61b6bb5e9 100644 --- a/packages/subproviders/src/subproviders/ganache.ts +++ b/packages/subproviders/src/subproviders/ganache.ts @@ -28,7 +28,7 @@ export class GanacheSubprovider extends Subprovider { * @param end Callback to call if subprovider handled the request and wants to pass back the request. */ // tslint:disable-next-line:prefer-function-over-method async-suffix - public async handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback): Promise<void> { + public async handleRequest(payload: JSONRPCRequestPayload, _next: Callback, end: ErrorCallback): Promise<void> { this._ganacheProvider.sendAsync(payload, (err: Error | null, result: any) => { end(err, result && result.result); }); diff --git a/packages/subproviders/src/subproviders/nonce_tracker.ts b/packages/subproviders/src/subproviders/nonce_tracker.ts index 98773e79c..dcc421574 100644 --- a/packages/subproviders/src/subproviders/nonce_tracker.ts +++ b/packages/subproviders/src/subproviders/nonce_tracker.ts @@ -75,7 +75,7 @@ export class NonceTrackerSubprovider extends Subprovider { return next(); } case 'eth_sendRawTransaction': - return next((sendTransactionError: Error | null, txResult: any, cb: Callback) => { + return next((sendTransactionError: Error | null, _txResult: any, cb: Callback) => { if (_.isNull(sendTransactionError)) { this._handleSuccessfulTransaction(payload); } else { diff --git a/packages/subproviders/test/unit/ledger_subprovider_test.ts b/packages/subproviders/test/unit/ledger_subprovider_test.ts index d3efb6abc..bd1dad1f9 100644 --- a/packages/subproviders/test/unit/ledger_subprovider_test.ts +++ b/packages/subproviders/test/unit/ledger_subprovider_test.ts @@ -48,7 +48,7 @@ describe('LedgerSubprovider', () => { }; return ecSignature; }, - signTransaction: async (derivationPath: string, txHex: string) => { + signTransaction: async (_derivationPath: string, _txHex: string) => { const ecSignature = { v: '77', r: '88a95ef1378487bc82be558e82c8478baf840c545d5b887536bb1da63673a98b', @@ -193,7 +193,7 @@ describe('LedgerSubprovider', () => { params: [FAKE_ADDRESS, nonHexMessage], id: 1, }; - const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => { expect(err).to.not.be.a('null'); expect(err.message).to.be.equal('Expected data to be of type HexString, encountered: hello world'); done(); @@ -208,7 +208,7 @@ describe('LedgerSubprovider', () => { params: [nonHexMessage, FAKE_ADDRESS], id: 1, }; - const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => { expect(err).to.not.be.a('null'); expect(err.message).to.be.equal('Expected data to be of type HexString, encountered: hello world'); done(); @@ -226,7 +226,7 @@ describe('LedgerSubprovider', () => { params: [tx], id: 1, }; - const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => { expect(err).to.not.be.a('null'); expect(err.message).to.be.equal(WalletSubproviderErrors.SenderInvalidOrNotSupplied); done(); @@ -245,7 +245,7 @@ describe('LedgerSubprovider', () => { params: [tx], id: 1, }; - const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => { expect(err).to.not.be.a('null'); expect(err.message).to.be.equal(WalletSubproviderErrors.SenderInvalidOrNotSupplied); done(); diff --git a/packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts b/packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts index 794c40d1d..331e52ea1 100644 --- a/packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts +++ b/packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts @@ -130,7 +130,7 @@ describe('MnemonicWalletSubprovider', () => { params: [fixtureData.TEST_RPC_ACCOUNT_0, nonHexMessage], id: 1, }; - const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => { expect(err).to.not.be.a('null'); expect(err.message).to.be.equal('Expected data to be of type HexString, encountered: hello world'); done(); @@ -145,7 +145,7 @@ describe('MnemonicWalletSubprovider', () => { params: [nonHexMessage, fixtureData.TEST_RPC_ACCOUNT_0], id: 1, }; - const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => { expect(err).to.not.be.a('null'); expect(err.message).to.be.equal('Expected data to be of type HexString, encountered: hello world'); done(); @@ -160,7 +160,7 @@ describe('MnemonicWalletSubprovider', () => { params: [messageHex, fixtureData.NULL_ADDRESS], id: 1, }; - const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => { expect(err).to.not.be.a('null'); expect(err.message).to.be.equal( `${WalletSubproviderErrors.AddressNotFound}: ${fixtureData.NULL_ADDRESS}`, @@ -180,7 +180,7 @@ describe('MnemonicWalletSubprovider', () => { params: [tx], id: 1, }; - const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => { expect(err).to.not.be.a('null'); expect(err.message).to.be.equal(WalletSubproviderErrors.SenderInvalidOrNotSupplied); done(); @@ -199,7 +199,7 @@ describe('MnemonicWalletSubprovider', () => { params: [tx], id: 1, }; - const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => { expect(err).to.not.be.a('null'); expect(err.message).to.be.equal(WalletSubproviderErrors.SenderInvalidOrNotSupplied); done(); diff --git a/packages/subproviders/test/unit/nonce_tracker_subprovider_test.ts b/packages/subproviders/test/unit/nonce_tracker_subprovider_test.ts index 2475dde7a..d799bce9e 100644 --- a/packages/subproviders/test/unit/nonce_tracker_subprovider_test.ts +++ b/packages/subproviders/test/unit/nonce_tracker_subprovider_test.ts @@ -41,7 +41,7 @@ describe('NonceTrackerSubprovider', () => { let isFirstGetTransactionCount = true; const fixedBlockNumberAndTransactionCountProvider = new FixtureSubprovider({ eth_getBlockByNumber: '0x01', - eth_getTransactionCount: (data: any, next: any, end: any) => { + eth_getTransactionCount: (_data: any, _next: any, end: any) => { // For testing caching we return different results on the second call if (isFirstGetTransactionCount) { isFirstGetTransactionCount = false; @@ -88,7 +88,7 @@ describe('NonceTrackerSubprovider', () => { provider.addProvider(createFixtureSubprovider()); provider.addProvider( new FixtureSubprovider({ - eth_sendRawTransaction: (data: any, next: any, end: any) => { + eth_sendRawTransaction: (_data: any, _next: any, end: any) => { end(new Error('Transaction nonce is too low')); }, }), @@ -123,7 +123,7 @@ describe('NonceTrackerSubprovider', () => { provider.addProvider(createFixtureSubprovider()); provider.addProvider( new FixtureSubprovider({ - eth_sendRawTransaction: (data: any, next: any, end: any) => { + eth_sendRawTransaction: (_data: any, _next: any, end: any) => { end(null); }, }), diff --git a/packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts b/packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts index ef7919801..34295c25e 100644 --- a/packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts +++ b/packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts @@ -101,7 +101,7 @@ describe('PrivateKeyWalletSubprovider', () => { params: [fixtureData.TEST_RPC_ACCOUNT_0, nonHexMessage], id: 1, }; - const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => { expect(err).to.not.be.a('null'); expect(err.message).to.be.equal('Expected data to be of type HexString, encountered: hello world'); done(); @@ -116,7 +116,7 @@ describe('PrivateKeyWalletSubprovider', () => { params: [nonHexMessage, fixtureData.TEST_RPC_ACCOUNT_0], id: 1, }; - const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => { expect(err).to.not.be.a('null'); expect(err.message).to.be.equal('Expected data to be of type HexString, encountered: hello world'); done(); @@ -131,7 +131,7 @@ describe('PrivateKeyWalletSubprovider', () => { params: [messageHex, fixtureData.TEST_RPC_ACCOUNT_1], id: 1, }; - const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => { expect(err).to.not.be.a('null'); expect(err.message).to.be.equal( `Requested to sign message with address: ${ @@ -153,7 +153,7 @@ describe('PrivateKeyWalletSubprovider', () => { params: [tx], id: 1, }; - const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => { expect(err).to.not.be.a('null'); expect(err.message).to.be.equal(WalletSubproviderErrors.SenderInvalidOrNotSupplied); done(); @@ -172,7 +172,7 @@ describe('PrivateKeyWalletSubprovider', () => { params: [tx], id: 1, }; - const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => { expect(err).to.not.be.a('null'); expect(err.message).to.be.equal(WalletSubproviderErrors.SenderInvalidOrNotSupplied); done(); @@ -187,7 +187,7 @@ describe('PrivateKeyWalletSubprovider', () => { params: [messageHex, '0x0'], id: 1, }; - const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => { + const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => { expect(err).to.not.be.a('null'); expect(err.message).to.be.equal(`Expected address to be of type ETHAddressHex, encountered: 0x0`); done(); diff --git a/packages/testnet-faucets/src/ts/handler.ts b/packages/testnet-faucets/src/ts/handler.ts index ae7492400..3a60d396c 100644 --- a/packages/testnet-faucets/src/ts/handler.ts +++ b/packages/testnet-faucets/src/ts/handler.ts @@ -71,9 +71,9 @@ export class Handler { }; }); } - public getQueueInfo(req: express.Request, res: express.Response): void { + public getQueueInfo(_req: express.Request, res: express.Response): void { res.setHeader('Content-Type', 'application/json'); - const queueInfo = _.mapValues(rpcUrls, (rpcUrl: string, networkId: string) => { + const queueInfo = _.mapValues(rpcUrls, (_rpcUrl: string, networkId: string) => { const dispatchQueue = this._networkConfigByNetworkId[networkId].dispatchQueue; return { full: dispatchQueue.isFull(), @@ -95,7 +95,7 @@ export class Handler { public async dispenseZRXOrderAsync( req: express.Request, res: express.Response, - next: express.NextFunction, + _next: express.NextFunction, ): Promise<void> { await this._dispenseOrderAsync(req, res, RequestedAssetType.ZRX); } @@ -171,8 +171,6 @@ export class Handler { ...order, ecSignature: signature, }; - // tslint:disable-next-line:no-unused-variable - const signedOrderHash = ZeroEx.getOrderHashHex(signedOrder); const payload = JSON.stringify(signedOrder); logUtils.log(`Dispensed signed order: ${payload}`); res.status(constants.SUCCESS_STATUS).send(payload); diff --git a/packages/testnet-faucets/src/ts/server.ts b/packages/testnet-faucets/src/ts/server.ts index 55c1d55d8..5416cdcc3 100644 --- a/packages/testnet-faucets/src/ts/server.ts +++ b/packages/testnet-faucets/src/ts/server.ts @@ -11,6 +11,7 @@ errorReporter.setup(); const app = express(); app.use(bodyParser.json()); // for parsing application/json +// tslint:disable-next-line:no-unused-variable app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); @@ -18,6 +19,7 @@ app.use((req, res, next) => { }); const handler = new Handler(); +// tslint:disable-next-line:no-unused-variable app.get('/ping', (req: express.Request, res: express.Response) => { res.status(constants.SUCCESS_STATUS).send('pong'); }); diff --git a/packages/tslint-config/tslint.json b/packages/tslint-config/tslint.json index 680883f47..05efd158a 100644 --- a/packages/tslint-config/tslint.json +++ b/packages/tslint-config/tslint.json @@ -45,7 +45,7 @@ "no-parameter-reassignment": true, "no-redundant-jsdoc": true, "no-return-await": true, - "no-unused-variable": true, + "no-unused-variable": [true, "check-parameters"], "no-string-throw": true, "no-submodule-imports": false, "no-unnecessary-type-assertion": true, diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 6e4d03e27..c955e1033 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -132,7 +132,7 @@ export class Blockchain { return provider; } - constructor(dispatcher: Dispatcher, isSalePage: boolean = false) { + constructor(dispatcher: Dispatcher) { this._dispatcher = dispatcher; const defaultGasPrice = GWEI_IN_WEI * 30; this._defaultGasPrice = new BigNumber(defaultGasPrice); @@ -577,13 +577,13 @@ export class Blockchain { trackedTokensByAddress[token.address] = token; }); if (!_.isUndefined(this._userAddressIfExists)) { - _.each(trackedTokensByAddress, (token: Token, address: string) => { + _.each(trackedTokensByAddress, (token: Token) => { trackedTokenStorage.addTrackedTokenToUser(this._userAddressIfExists, this.networkId, token); }); } } else { // Properly set all tokenRegistry tokens `isTracked` to true if they are in the existing trackedTokens array - _.each(trackedTokensByAddress, (trackedToken: Token, address: string) => { + _.each(trackedTokensByAddress, (_trackedToken: Token, address: string) => { if (!_.isUndefined(tokenRegistryTokensByAddress[address])) { tokenRegistryTokensByAddress[address].isTracked = true; } @@ -754,7 +754,7 @@ export class Blockchain { const tokenRegistryTokens = await this._contractWrappers.tokenRegistry.getTokensAsync(); const tokenByAddress: TokenByAddress = {}; - _.each(tokenRegistryTokens, (t: ZeroExToken, i: number) => { + _.each(tokenRegistryTokens, (t: ZeroExToken) => { // HACK: For now we have a hard-coded list of iconUrls for the dummyTokens // TODO: Refactor this out and pull the iconUrl directly from the TokenRegistry const iconUrl = configs.ICON_URL_BY_SYMBOL[t.symbol]; diff --git a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx index 196414407..c9727b553 100644 --- a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx +++ b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx @@ -250,7 +250,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps, }); return true; } - private _onDerivationPathChanged(e: any, derivationPath: string): void { + private _onDerivationPathChanged(_event: any, derivationPath: string): void { let derivationErrMsg = ''; if (!_.startsWith(derivationPath, VALID_ETHEREUM_DERIVATION_PATH_PREFIX)) { derivationErrMsg = 'Must be valid Ethereum path.'; @@ -295,7 +295,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps, } return userAddresses; } - private _onSelectedNetworkUpdated(e: any, index: number, networkId: number): void { + private _onSelectedNetworkUpdated(_event: any, _index: number, networkId: number): void { this.setState({ preferredNetworkId: networkId, }); diff --git a/packages/website/ts/components/eth_wrappers.tsx b/packages/website/ts/components/eth_wrappers.tsx index ca8634693..20b446155 100644 --- a/packages/website/ts/components/eth_wrappers.tsx +++ b/packages/website/ts/components/eth_wrappers.tsx @@ -221,9 +221,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt </TableHeaderColumn> </TableRow> </TableHeader> - <TableBody displayRowCheckbox={false}> - {this._renderOutdatedWeths(etherToken, this.state.ethTokenState)} - </TableBody> + <TableBody displayRowCheckbox={false}>{this._renderOutdatedWeths(etherToken)}</TableBody> </Table> </div> </div> @@ -249,7 +247,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt </div> ); } - private _renderOutdatedWeths(etherToken: Token, etherTokenState: TokenState): React.ReactNode { + private _renderOutdatedWeths(etherToken: Token): React.ReactNode { const rows = _.map( configs.OUTDATED_WRAPPED_ETHERS, (outdatedWETHByNetworkId: OutdatedWrappedEtherByNetworkId) => { diff --git a/packages/website/ts/components/fill_order.tsx b/packages/website/ts/components/fill_order.tsx index b6b52993e..f3ea44286 100644 --- a/packages/website/ts/components/fill_order.tsx +++ b/packages/website/ts/components/fill_order.tsx @@ -351,7 +351,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> { this._onFillOrderClickFireAndForgetAsync(); } } - private _onFillAmountChange(isValid: boolean, amount?: BigNumber): void { + private _onFillAmountChange(_isValid: boolean, amount?: BigNumber): void { this.props.dispatcher.updateOrderFillAmount(amount); } private _onFillOrderJSONChanged(event: any): void { diff --git a/packages/website/ts/components/footer.tsx b/packages/website/ts/components/footer.tsx index c44e41084..9fb332a98 100644 --- a/packages/website/ts/components/footer.tsx +++ b/packages/website/ts/components/footer.tsx @@ -235,7 +235,7 @@ export class Footer extends React.Component<FooterProps, FooterState> { </div> ); } - private _updateLanguage(e: any, index: number, value: Language): void { + private _updateLanguage(_event: any, _index: number, value: Language): void { this.setState({ selectedLanguage: value, }); diff --git a/packages/website/ts/components/generate_order/generate_order_form.tsx b/packages/website/ts/components/generate_order/generate_order_form.tsx index 52e3b73cd..d26b5c3fa 100644 --- a/packages/website/ts/components/generate_order/generate_order_form.tsx +++ b/packages/website/ts/components/generate_order/generate_order_form.tsx @@ -226,7 +226,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G </div> ); } - private _onTokenAmountChange(token: Token, side: Side, isValid: boolean, amount?: BigNumber): void { + private _onTokenAmountChange(token: Token, side: Side, _isValid: boolean, amount?: BigNumber): void { this.props.dispatcher.updateChosenAssetToken(side, { address: token.address, amount, 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 a9b8e9589..176a0807b 100644 --- a/packages/website/ts/components/generate_order/new_token_form.tsx +++ b/packages/website/ts/components/generate_order/new_token_form.tsx @@ -152,7 +152,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor }; this.props.onNewTokenSubmitted(newToken); } - private _onTokenNameChanged(e: any, name: string): void { + private _onTokenNameChanged(_event: any, name: string): void { let nameErrText = ''; const maxLength = 30; const tokens = _.values(this.props.tokenByAddress); @@ -173,7 +173,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor nameErrText, }); } - private _onTokenSymbolChanged(e: any, symbol: string): void { + private _onTokenSymbolChanged(_event: any, symbol: string): void { let symbolErrText = ''; const maxLength = 5; const tokens = _.values(this.props.tokenByAddress); @@ -193,7 +193,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor symbolErrText, }); } - private _onTokenDecimalsChanged(e: any, decimals: string): void { + private _onTokenDecimalsChanged(_event: any, decimals: string): void { let decimalsErrText = ''; const maxLength = 2; if (decimals === '') { diff --git a/packages/website/ts/components/inputs/balance_bounded_input.tsx b/packages/website/ts/components/inputs/balance_bounded_input.tsx index e5b502b25..968609030 100644 --- a/packages/website/ts/components/inputs/balance_bounded_input.tsx +++ b/packages/website/ts/components/inputs/balance_bounded_input.tsx @@ -104,7 +104,7 @@ export class BalanceBoundedInput extends React.Component<BalanceBoundedInputProp /> ); } - private _onValueChange(e: any, amountString: string): void { + private _onValueChange(_event: any, amountString: string): void { this._setAmountState(amountString, this.props.balance, () => { const isValid = _.isUndefined(this._validate(amountString, this.props.balance)); const isPositiveNumber = utils.isNumeric(amountString) && !_.includes(amountString, '-'); diff --git a/packages/website/ts/components/inputs/expiration_input.tsx b/packages/website/ts/components/inputs/expiration_input.tsx index 5c68080fe..79dd2f568 100644 --- a/packages/website/ts/components/inputs/expiration_input.tsx +++ b/packages/website/ts/components/inputs/expiration_input.tsx @@ -80,7 +80,7 @@ export class ExpirationInput extends React.Component<ExpirationInputProps, Expir const defaultDateTime = utils.initialOrderExpiryUnixTimestampSec(); this.props.updateOrderExpiry(defaultDateTime); } - private _onDateChanged(e: any, date: Date): void { + private _onDateChanged(_event: any, date: Date): void { const dateMoment = moment(date); this.setState({ dateMoment, @@ -88,7 +88,7 @@ export class ExpirationInput extends React.Component<ExpirationInputProps, Expir const timestamp = utils.convertToUnixTimestampSeconds(dateMoment, this.state.timeMoment); this.props.updateOrderExpiry(timestamp); } - private _onTimeChanged(e: any, time: Date): void { + private _onTimeChanged(_event: any, time: Date): void { const timeMoment = moment(time); this.setState({ timeMoment, diff --git a/packages/website/ts/components/legacy_portal/legacy_portal.tsx b/packages/website/ts/components/legacy_portal/legacy_portal.tsx index 35e917eec..b4a174a03 100644 --- a/packages/website/ts/components/legacy_portal/legacy_portal.tsx +++ b/packages/website/ts/components/legacy_portal/legacy_portal.tsx @@ -310,7 +310,7 @@ export class LegacyPortal extends React.Component<LegacyPortalProps, LegacyPorta /> ); } - private _renderFillOrder(match: any, location: Location, history: History): React.ReactNode { + private _renderFillOrder(_match: any, _location: Location, _history: History): React.ReactNode { const initialFillOrder = !_.isUndefined(this.props.userSuppliedOrderCache) ? this.props.userSuppliedOrderCache : this._sharedOrderIfExists; @@ -329,7 +329,7 @@ export class LegacyPortal extends React.Component<LegacyPortalProps, LegacyPorta /> ); } - private _renderGenerateOrderForm(match: any, location: Location, history: History): React.ReactNode { + private _renderGenerateOrderForm(_match: any, _location: Location, _history: History): React.ReactNode { return ( <GenerateOrderForm blockchain={this._blockchain} diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index fb40a9580..1b3bf3dae 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -634,7 +634,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { const tokenSymbols = _.keys(tokenAddressBySymbol); try { const priceBySymbol = await backendClient.getPriceInfoAsync(tokenSymbols); - const priceByAddress = _.mapKeys(priceBySymbol, (value, symbol) => _.get(tokenAddressBySymbol, symbol)); + const priceByAddress = _.mapKeys(priceBySymbol, (_value, symbol) => _.get(tokenAddressBySymbol, symbol)); const result = _.mapValues(priceByAddress, price => { const priceBigNumber = new BigNumber(price); return priceBigNumber; diff --git a/packages/website/ts/components/redirecter.tsx b/packages/website/ts/components/redirecter.tsx index 07432a926..477aecb77 100644 --- a/packages/website/ts/components/redirecter.tsx +++ b/packages/website/ts/components/redirecter.tsx @@ -4,6 +4,6 @@ interface RedirecterProps { location: string; } -export function Redirecter(props: RedirecterProps): void { +export function Redirecter(_props: RedirecterProps): void { window.location.href = constants.URL_ANGELLIST; } diff --git a/packages/website/ts/components/token_balances.tsx b/packages/website/ts/components/token_balances.tsx index 555a59830..2a051651d 100644 --- a/packages/website/ts/components/token_balances.tsx +++ b/packages/website/ts/components/token_balances.tsx @@ -581,7 +581,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala } return true; } - private _onErrorDialogToggle(isOpen: boolean): void { + private _onErrorDialogToggle(_isOpen: boolean): void { this.setState({ errorType: undefined, }); diff --git a/packages/website/ts/components/ui/drop_down.tsx b/packages/website/ts/components/ui/drop_down.tsx index db79ca1df..22cb942f8 100644 --- a/packages/website/ts/components/ui/drop_down.tsx +++ b/packages/website/ts/components/ui/drop_down.tsx @@ -42,7 +42,7 @@ export class DropDown extends React.Component<DropDownProps, DropDownState> { public componentWillUnmount(): void { window.clearInterval(this._popoverCloseCheckIntervalId); } - public componentWillReceiveProps(nextProps: DropDownProps): void { + public componentWillReceiveProps(_nextProps: DropDownProps): void { // HACK: If the popoverContent is updated to a different dimension and the users // mouse is no longer above it, the dropdown can enter an inconsistent state where // it believes the user is still hovering over it. In order to remedy this, we diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index bc2ee227d..f80be6313 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -222,7 +222,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> { </div> ); } - private _onSidebarHover(event: React.FormEvent<HTMLInputElement>): void { + private _onSidebarHover(_event: React.FormEvent<HTMLInputElement>): void { this.setState({ isHoveringSidebar: true, }); @@ -314,7 +314,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> { ); return _.map(trackedTokensStartingWithEtherToken, this._renderTokenRow.bind(this)); } - private _renderTokenRow(token: Token, index: number): React.ReactNode { + private _renderTokenRow(token: Token, _index: number): React.ReactNode { const tokenState = this.props.trackedTokenStateByAddress[token.address]; const tokenLink = sharedUtils.getEtherScanLinkIfExists( token.address, diff --git a/packages/website/ts/components/wallet/wrap_ether_item.tsx b/packages/website/ts/components/wallet/wrap_ether_item.tsx index a5052735b..f65257142 100644 --- a/packages/website/ts/components/wallet/wrap_ether_item.tsx +++ b/packages/website/ts/components/wallet/wrap_ether_item.tsx @@ -145,7 +145,7 @@ export class WrapEtherItem extends React.Component<WrapEtherItemProps, WrapEther </div> ); } - private _onValueChange(isValid: boolean, amount?: BigNumber): void { + private _onValueChange(_isValid: boolean, amount?: BigNumber): void { this.setState({ currentInputAmount: amount, }); diff --git a/packages/website/ts/containers/about.ts b/packages/website/ts/containers/about.ts index 3dbdcd16b..3b1c99d79 100644 --- a/packages/website/ts/containers/about.ts +++ b/packages/website/ts/containers/about.ts @@ -14,7 +14,7 @@ interface ConnectedDispatch { dispatcher: Dispatcher; } -const mapStateToProps = (state: State, ownProps: AboutProps): ConnectedState => ({ +const mapStateToProps = (state: State, _ownProps: AboutProps): ConnectedState => ({ translate: state.translate, }); diff --git a/packages/website/ts/containers/connect_documentation.ts b/packages/website/ts/containers/connect_documentation.ts index 2ecd8107a..f939ef0df 100644 --- a/packages/website/ts/containers/connect_documentation.ts +++ b/packages/website/ts/containers/connect_documentation.ts @@ -89,7 +89,7 @@ interface ConnectedDispatch { dispatcher: Dispatcher; } -const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({ +const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({ docsVersion: state.docsVersion, availableDocVersions: state.availableDocVersions, translate: state.translate, diff --git a/packages/website/ts/containers/ethereum_types_documentation.ts b/packages/website/ts/containers/ethereum_types_documentation.ts index f6d614779..285438835 100644 --- a/packages/website/ts/containers/ethereum_types_documentation.ts +++ b/packages/website/ts/containers/ethereum_types_documentation.ts @@ -106,7 +106,7 @@ interface ConnectedDispatch { dispatcher: Dispatcher; } -const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({ +const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({ docsVersion: state.docsVersion, availableDocVersions: state.availableDocVersions, translate: state.translate, diff --git a/packages/website/ts/containers/faq.ts b/packages/website/ts/containers/faq.ts index b91c47889..a2b5735f6 100644 --- a/packages/website/ts/containers/faq.ts +++ b/packages/website/ts/containers/faq.ts @@ -14,7 +14,7 @@ interface ConnectedDispatch { dispatcher: Dispatcher; } -const mapStateToProps = (state: State, ownProps: FAQProps): ConnectedState => ({ +const mapStateToProps = (state: State, _ownProps: FAQProps): ConnectedState => ({ translate: state.translate, }); diff --git a/packages/website/ts/containers/generate_order_form.ts b/packages/website/ts/containers/generate_order_form.ts index 44979b104..92296dbab 100644 --- a/packages/website/ts/containers/generate_order_form.ts +++ b/packages/website/ts/containers/generate_order_form.ts @@ -30,7 +30,7 @@ interface ConnectedState { lastForceTokenStateRefetch: number; } -const mapStateToProps = (state: State, ownProps: GenerateOrderFormProps): ConnectedState => ({ +const mapStateToProps = (state: State, _ownProps: GenerateOrderFormProps): ConnectedState => ({ blockchainErr: state.blockchainErr, blockchainIsLoaded: state.blockchainIsLoaded, orderExpiryTimestamp: state.orderExpiryTimestamp, diff --git a/packages/website/ts/containers/json_schemas_documentation.ts b/packages/website/ts/containers/json_schemas_documentation.ts index 4df7ddecb..67740d4c6 100644 --- a/packages/website/ts/containers/json_schemas_documentation.ts +++ b/packages/website/ts/containers/json_schemas_documentation.ts @@ -70,7 +70,7 @@ interface ConnectedDispatch { dispatcher: Dispatcher; } -const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({ +const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({ docsVersion: state.docsVersion, availableDocVersions: state.availableDocVersions, translate: state.translate, diff --git a/packages/website/ts/containers/landing.ts b/packages/website/ts/containers/landing.ts index a9fc1d9d1..972ed4c23 100644 --- a/packages/website/ts/containers/landing.ts +++ b/packages/website/ts/containers/landing.ts @@ -14,7 +14,7 @@ interface ConnectedDispatch { dispatcher: Dispatcher; } -const mapStateToProps = (state: State, ownProps: LandingProps): ConnectedState => ({ +const mapStateToProps = (state: State, _ownProps: LandingProps): ConnectedState => ({ translate: state.translate, }); diff --git a/packages/website/ts/containers/legacy_portal.ts b/packages/website/ts/containers/legacy_portal.ts index eae450c21..e99f47fb7 100644 --- a/packages/website/ts/containers/legacy_portal.ts +++ b/packages/website/ts/containers/legacy_portal.ts @@ -37,7 +37,7 @@ interface ConnectedDispatch { dispatcher: Dispatcher; } -const mapStateToProps = (state: State, ownProps: LegacyPortalComponentProps): ConnectedState => { +const mapStateToProps = (state: State, _ownProps: LegacyPortalComponentProps): ConnectedState => { const receiveAssetToken = state.sideToAssetToken[Side.Receive]; const depositAssetToken = state.sideToAssetToken[Side.Deposit]; const receiveAddress = !_.isUndefined(receiveAssetToken.address) diff --git a/packages/website/ts/containers/not_found.ts b/packages/website/ts/containers/not_found.ts index 4fdc325ea..f384dab89 100644 --- a/packages/website/ts/containers/not_found.ts +++ b/packages/website/ts/containers/not_found.ts @@ -14,7 +14,7 @@ interface ConnectedDispatch { dispatcher: Dispatcher; } -const mapStateToProps = (state: State, ownProps: NotFoundProps): ConnectedState => ({ +const mapStateToProps = (state: State, _ownProps: NotFoundProps): ConnectedState => ({ translate: state.translate, }); diff --git a/packages/website/ts/containers/order_utils_documentation.ts b/packages/website/ts/containers/order_utils_documentation.ts index cdf97e5c8..37b7f2273 100644 --- a/packages/website/ts/containers/order_utils_documentation.ts +++ b/packages/website/ts/containers/order_utils_documentation.ts @@ -81,7 +81,7 @@ interface ConnectedDispatch { dispatcher: Dispatcher; } -const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({ +const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({ docsVersion: state.docsVersion, availableDocVersions: state.availableDocVersions, translate: state.translate, diff --git a/packages/website/ts/containers/portal.ts b/packages/website/ts/containers/portal.ts index b8c8fb999..5876e65f5 100644 --- a/packages/website/ts/containers/portal.ts +++ b/packages/website/ts/containers/portal.ts @@ -34,7 +34,7 @@ interface ConnectedDispatch { dispatcher: Dispatcher; } -const mapStateToProps = (state: State, ownProps: PortalComponentProps): ConnectedState => { +const mapStateToProps = (state: State, _ownProps: PortalComponentProps): ConnectedState => { const receiveAssetToken = state.sideToAssetToken[Side.Receive]; const depositAssetToken = state.sideToAssetToken[Side.Deposit]; const receiveAddress = !_.isUndefined(receiveAssetToken.address) diff --git a/packages/website/ts/containers/portal_onboarding_flow.ts b/packages/website/ts/containers/portal_onboarding_flow.ts index 0ad9aef13..4298ab275 100644 --- a/packages/website/ts/containers/portal_onboarding_flow.ts +++ b/packages/website/ts/containers/portal_onboarding_flow.ts @@ -28,7 +28,7 @@ interface ConnectedDispatch { updateOnboardingStep: (stepIndex: number) => void; } -const mapStateToProps = (state: State, ownProps: PortalOnboardingFlowProps): ConnectedState => ({ +const mapStateToProps = (state: State, _ownProps: PortalOnboardingFlowProps): ConnectedState => ({ stepIndex: state.portalOnboardingStep, isRunning: state.isPortalOnboardingShowing, userAddress: state.userAddress, diff --git a/packages/website/ts/containers/smart_contracts_documentation.ts b/packages/website/ts/containers/smart_contracts_documentation.ts index 27328909c..c88c3b365 100644 --- a/packages/website/ts/containers/smart_contracts_documentation.ts +++ b/packages/website/ts/containers/smart_contracts_documentation.ts @@ -75,7 +75,7 @@ interface ConnectedDispatch { docsInfo: DocsInfo; } -const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({ +const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({ docsVersion: state.docsVersion, availableDocVersions: state.availableDocVersions, translate: state.translate, diff --git a/packages/website/ts/containers/sol_compiler_documentation.ts b/packages/website/ts/containers/sol_compiler_documentation.ts index 4ccc1850f..8720e2c1d 100644 --- a/packages/website/ts/containers/sol_compiler_documentation.ts +++ b/packages/website/ts/containers/sol_compiler_documentation.ts @@ -67,7 +67,7 @@ interface ConnectedDispatch { dispatcher: Dispatcher; } -const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({ +const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({ docsVersion: state.docsVersion, availableDocVersions: state.availableDocVersions, translate: state.translate, diff --git a/packages/website/ts/containers/sol_cov_documentation.ts b/packages/website/ts/containers/sol_cov_documentation.ts index 73cc99a8c..a8009071f 100644 --- a/packages/website/ts/containers/sol_cov_documentation.ts +++ b/packages/website/ts/containers/sol_cov_documentation.ts @@ -96,7 +96,7 @@ interface ConnectedDispatch { dispatcher: Dispatcher; } -const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({ +const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({ docsVersion: state.docsVersion, availableDocVersions: state.availableDocVersions, translate: state.translate, diff --git a/packages/website/ts/containers/subproviders_documentation.ts b/packages/website/ts/containers/subproviders_documentation.ts index 0c7e73f38..6d4230e53 100644 --- a/packages/website/ts/containers/subproviders_documentation.ts +++ b/packages/website/ts/containers/subproviders_documentation.ts @@ -128,7 +128,7 @@ interface ConnectedDispatch { dispatcher: Dispatcher; } -const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({ +const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({ docsVersion: state.docsVersion, availableDocVersions: state.availableDocVersions, translate: state.translate, diff --git a/packages/website/ts/containers/web3_wrapper_documentation.ts b/packages/website/ts/containers/web3_wrapper_documentation.ts index 34633f14d..b04a83ac4 100644 --- a/packages/website/ts/containers/web3_wrapper_documentation.ts +++ b/packages/website/ts/containers/web3_wrapper_documentation.ts @@ -105,7 +105,7 @@ interface ConnectedDispatch { dispatcher: Dispatcher; } -const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({ +const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({ docsVersion: state.docsVersion, availableDocVersions: state.availableDocVersions, translate: state.translate, diff --git a/packages/website/ts/containers/wiki.ts b/packages/website/ts/containers/wiki.ts index af7228dbe..357f8bbf4 100644 --- a/packages/website/ts/containers/wiki.ts +++ b/packages/website/ts/containers/wiki.ts @@ -14,7 +14,7 @@ interface ConnectedDispatch { dispatcher: Dispatcher; } -const mapStateToProps = (state: State, ownProps: WikiProps): ConnectedState => ({ +const mapStateToProps = (state: State, _ownProps: WikiProps): ConnectedState => ({ translate: state.translate, }); diff --git a/packages/website/ts/containers/zero_ex_js_documentation.ts b/packages/website/ts/containers/zero_ex_js_documentation.ts index 9c3f447fb..a8890a07a 100644 --- a/packages/website/ts/containers/zero_ex_js_documentation.ts +++ b/packages/website/ts/containers/zero_ex_js_documentation.ts @@ -209,7 +209,7 @@ interface ConnectedDispatch { dispatcher: Dispatcher; } -const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({ +const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({ docsVersion: state.docsVersion, availableDocVersions: state.availableDocVersions, docsInfo, diff --git a/packages/website/ts/local_storage/trade_history_storage.tsx b/packages/website/ts/local_storage/trade_history_storage.tsx index cc764d98e..2e2f4e64e 100644 --- a/packages/website/ts/local_storage/trade_history_storage.tsx +++ b/packages/website/ts/local_storage/trade_history_storage.tsx @@ -57,7 +57,7 @@ export const tradeHistoryStorage = { return {}; } const userFillsByHash = JSON.parse(userFillsJSONString); - _.each(userFillsByHash, (fill, hash) => { + _.each(userFillsByHash, fill => { fill.paidMakerFee = new BigNumber(fill.paidMakerFee); fill.paidTakerFee = new BigNumber(fill.paidTakerFee); fill.filledTakerTokenAmount = new BigNumber(fill.filledTakerTokenAmount); diff --git a/packages/website/ts/pages/not_found.tsx b/packages/website/ts/pages/not_found.tsx index a94ba5863..2fe3b1f45 100644 --- a/packages/website/ts/pages/not_found.tsx +++ b/packages/website/ts/pages/not_found.tsx @@ -11,7 +11,7 @@ export interface NotFoundProps { dispatcher: Dispatcher; } -export const NotFound = (props: NotFoundProps) => { +export const NotFound = (_props: NotFoundProps) => { return ( <div> <TopBar blockchainIsLoaded={false} location={this.props.location} translate={this.props.translate} /> diff --git a/packages/website/ts/pages/wiki/wiki.tsx b/packages/website/ts/pages/wiki/wiki.tsx index bdefe0fda..9659900be 100644 --- a/packages/website/ts/pages/wiki/wiki.tsx +++ b/packages/website/ts/pages/wiki/wiki.tsx @@ -233,7 +233,7 @@ export class Wiki extends React.Component<WikiProps, WikiState> { } return menuSubsectionsBySection; } - private _onSidebarHover(event: React.FormEvent<HTMLInputElement>): void { + private _onSidebarHover(_event: React.FormEvent<HTMLInputElement>): void { this.setState({ isHoveringSidebar: true, }); @@ -243,7 +243,7 @@ export class Wiki extends React.Component<WikiProps, WikiState> { isHoveringSidebar: false, }); } - private _onHashChanged(event: any): void { + private _onHashChanged(_event: any): void { const hash = window.location.hash.slice(1); sharedUtils.scrollToHash(hash, sharedConstants.SCROLL_CONTAINER_ID); } diff --git a/packages/website/ts/utils/error_reporter.ts b/packages/website/ts/utils/error_reporter.ts index 548d4d41d..f875141fe 100644 --- a/packages/website/ts/utils/error_reporter.ts +++ b/packages/website/ts/utils/error_reporter.ts @@ -37,7 +37,7 @@ export const errorReporter = { return; // Let's not log development errors to rollbar } - return new Promise((resolve, reject) => { + return new Promise((resolve, _reject) => { rollbar.error(err, (rollbarErr: Error) => { if (rollbarErr) { logUtils.log(`Error reporting to rollbar, ignoring: ${rollbarErr}`); diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index 6961784c6..651a4212a 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -152,7 +152,7 @@ export const utils = { const intervalId = setTimeout(() => { resolve(false); }, getApiVersionTimeoutMs); - u2f.getApiVersion((version: number) => { + u2f.getApiVersion((_version: number) => { clearTimeout(intervalId); resolve(true); }); @@ -279,7 +279,7 @@ export const utils = { if (document.readyState === 'complete') { return; // Already loaded } - return new Promise<void>((resolve, reject) => { + return new Promise<void>((resolve, _reject) => { window.onload = () => resolve(); }); }, |