aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabio Berger <me@fabioberger.com>2018-06-12 06:14:19 +0800
committerGitHub <noreply@github.com>2018-06-12 06:14:19 +0800
commitbc0ae6be318a15bf8670a6da9a59d9bdb12cadae (patch)
treed4d2ffbac9270c332b1e788c2ac39829a5e89359
parente0c0584c593e3d948652c1cb58f39042c5b8f488 (diff)
parentc03119d10ad0f2633a78980bd939c65fedfd0531 (diff)
downloaddexon-sol-tools-bc0ae6be318a15bf8670a6da9a59d9bdb12cadae.tar.gz
dexon-sol-tools-bc0ae6be318a15bf8670a6da9a59d9bdb12cadae.tar.zst
dexon-sol-tools-bc0ae6be318a15bf8670a6da9a59d9bdb12cadae.zip
Merge pull request #684 from 0xProject/fix/contract-wrappers/exchangeTransferSimulator
Move ExchangeTransferSimulator & OrderValidationUtils to Order-Utils
-rw-r--r--packages/0x.js/package.json2
-rw-r--r--packages/base-contract/src/index.ts4
-rw-r--r--packages/connect/src/http_client.ts2
-rw-r--r--packages/connect/src/ws_orderbook_channel.ts2
-rw-r--r--packages/contract-wrappers/src/abstract/abstract_balance_and_proxy_allowance_lazy_store.ts11
-rw-r--r--packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts84
-rw-r--r--packages/contract-wrappers/src/stores/balance_proxy_allowance_lazy_store.ts4
-rw-r--r--packages/contract-wrappers/src/utils/exchange_transfer_simulator.ts12
-rw-r--r--packages/contract-wrappers/src/utils/order_validation_utils.ts18
-rw-r--r--packages/contract-wrappers/test/exchange_transfer_simulator_test.ts7
-rw-r--r--packages/contract-wrappers/test/order_validation_test.ts7
-rw-r--r--packages/contracts/package.json2
-rw-r--r--packages/contracts/test/libraries/lib_mem.ts2
-rw-r--r--packages/dev-utils/src/callback_error_reporter.ts2
-rw-r--r--packages/order-utils/CHANGELOG.json8
-rw-r--r--packages/order-utils/package.json5
-rw-r--r--packages/order-utils/src/abstract/abstract_balance_and_proxy_allowance_fetcher.ts4
-rw-r--r--packages/order-utils/src/abstract/abstract_balance_and_proxy_allowance_lazy_store.ts11
-rw-r--r--packages/order-utils/src/artifacts.ts12
-rw-r--r--packages/order-utils/src/constants.ts5
-rw-r--r--packages/order-utils/src/exchange_transfer_simulator.ts113
-rw-r--r--packages/order-utils/src/index.ts3
-rw-r--r--packages/order-utils/src/order_validation_utils.ts231
-rw-r--r--packages/order-utils/src/signature_utils.ts25
-rw-r--r--packages/order-utils/src/store/balance_and_proxy_allowance_lazy_store.ts81
-rw-r--r--packages/order-utils/src/types.ts10
-rw-r--r--packages/order-utils/src/utils.ts6
-rw-r--r--packages/order-utils/test/exchange_transfer_simulator_test.ts177
-rw-r--r--packages/order-utils/test/order_validation_utils_test.ts70
-rw-r--r--packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts26
-rw-r--r--packages/order-watcher/src/order_watcher/expiration_watcher.ts2
-rw-r--r--packages/order-watcher/test/expiration_watcher_test.ts2
-rw-r--r--packages/order-watcher/test/order_watcher_test.ts2
-rw-r--r--packages/react-docs/src/components/documentation.tsx6
-rw-r--r--packages/react-docs/src/components/enum.tsx2
-rw-r--r--packages/react-shared/src/components/markdown_code_block.tsx2
-rw-r--r--packages/react-shared/src/components/markdown_link_block.tsx2
-rw-r--r--packages/react-shared/src/components/version_drop_down.tsx2
-rw-r--r--packages/sol-cov/src/trace_collection_subprovider.ts6
-rw-r--r--packages/subproviders/src/subproviders/ganache.ts2
-rw-r--r--packages/subproviders/src/subproviders/nonce_tracker.ts2
-rw-r--r--packages/subproviders/test/unit/ledger_subprovider_test.ts10
-rw-r--r--packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts10
-rw-r--r--packages/subproviders/test/unit/nonce_tracker_subprovider_test.ts6
-rw-r--r--packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts12
-rw-r--r--packages/testnet-faucets/src/ts/handler.ts8
-rw-r--r--packages/testnet-faucets/src/ts/server.ts2
-rw-r--r--packages/tslint-config/tslint.json2
-rw-r--r--packages/website/ts/blockchain.ts8
-rw-r--r--packages/website/ts/components/dialogs/ledger_config_dialog.tsx4
-rw-r--r--packages/website/ts/components/eth_wrappers.tsx6
-rw-r--r--packages/website/ts/components/fill_order.tsx2
-rw-r--r--packages/website/ts/components/footer.tsx2
-rw-r--r--packages/website/ts/components/generate_order/generate_order_form.tsx2
-rw-r--r--packages/website/ts/components/generate_order/new_token_form.tsx6
-rw-r--r--packages/website/ts/components/inputs/balance_bounded_input.tsx2
-rw-r--r--packages/website/ts/components/inputs/expiration_input.tsx4
-rw-r--r--packages/website/ts/components/legacy_portal/legacy_portal.tsx4
-rw-r--r--packages/website/ts/components/portal/portal.tsx2
-rw-r--r--packages/website/ts/components/redirecter.tsx2
-rw-r--r--packages/website/ts/components/token_balances.tsx2
-rw-r--r--packages/website/ts/components/ui/drop_down.tsx2
-rw-r--r--packages/website/ts/components/wallet/wallet.tsx4
-rw-r--r--packages/website/ts/components/wallet/wrap_ether_item.tsx2
-rw-r--r--packages/website/ts/containers/about.ts2
-rw-r--r--packages/website/ts/containers/connect_documentation.ts2
-rw-r--r--packages/website/ts/containers/ethereum_types_documentation.ts2
-rw-r--r--packages/website/ts/containers/faq.ts2
-rw-r--r--packages/website/ts/containers/generate_order_form.ts2
-rw-r--r--packages/website/ts/containers/json_schemas_documentation.ts2
-rw-r--r--packages/website/ts/containers/landing.ts2
-rw-r--r--packages/website/ts/containers/legacy_portal.ts2
-rw-r--r--packages/website/ts/containers/not_found.ts2
-rw-r--r--packages/website/ts/containers/order_utils_documentation.ts2
-rw-r--r--packages/website/ts/containers/portal.ts2
-rw-r--r--packages/website/ts/containers/portal_onboarding_flow.ts2
-rw-r--r--packages/website/ts/containers/smart_contracts_documentation.ts2
-rw-r--r--packages/website/ts/containers/sol_compiler_documentation.ts2
-rw-r--r--packages/website/ts/containers/sol_cov_documentation.ts2
-rw-r--r--packages/website/ts/containers/subproviders_documentation.ts2
-rw-r--r--packages/website/ts/containers/web3_wrapper_documentation.ts2
-rw-r--r--packages/website/ts/containers/wiki.ts2
-rw-r--r--packages/website/ts/containers/zero_ex_js_documentation.ts2
-rw-r--r--packages/website/ts/local_storage/trade_history_storage.tsx2
-rw-r--r--packages/website/ts/pages/not_found.tsx2
-rw-r--r--packages/website/ts/pages/wiki/wiki.tsx4
-rw-r--r--packages/website/ts/utils/error_reporter.ts2
-rw-r--r--packages/website/ts/utils/utils.ts4
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 7500e5bd3..8b5168c45 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();
});
},