Compare commits

..

34 Commits

Author SHA1 Message Date
Fabio Berger
f684cc3711 Publish
- 0x.js@0.29.0
 - @0xproject/abi-gen@0.0.4
 - @0xproject/assert@0.0.9
 - @0xproject/connect@0.3.2
 - contracts@2.1.1
 - @0xproject/dev-utils@0.0.3
 - @0xproject/json-schemas@0.7.1
 - @0xproject/kovan_faucets@1.0.2
 - @0xproject/monorepo-scripts@0.1.2
 - @0xproject/subproviders@0.2.0
 - @0xproject/tslint-config@0.4.0
 - @0xproject/types@0.1.2
 - @0xproject/utils@0.1.2
 - @0xproject/web3-wrapper@0.1.2
 - @0xproject/website@0.0.4
2017-12-28 10:57:04 +01:00
Fabio Berger
ab0c8c3496 Add dates to CHANGELOG entries 2017-12-28 10:36:06 +01:00
Fabio Berger
47534b200d Update subproviders CHANGELOG 2017-12-28 10:29:52 +01:00
Fabio Berger
f2976af734 Support both personal_sign and eth_sign 2017-12-28 10:28:27 +01:00
Fabio Berger
ee463058f1 Fix Ledger tests given change from personal_sign to eth_sign 2017-12-28 09:46:50 +01:00
Fabio Berger
c36a7471a8 Merge pull request #300 from cavanmflynn/fix/ledger-subprovider-signing
Update subprovider to catch correct RPC method
2017-12-28 09:45:41 +01:00
Cavan Flynn
6ea8cee551 Update subprovider to catch correct RPC method
ZeroEx uses web3.eth.sign, rather than web3.eth.personal.sign. In addition, the message to sign is the second parameter; not the first. The first parameter is the address.
2017-12-27 19:48:58 -05:00
Fabio Berger
69806c8839 Rename guide 2017-12-25 17:54:24 +01:00
Fabio Berger
690036aa30 Update contribution guide 2017-12-25 17:53:18 +01:00
Brandon Millman
eda6b8d01b Fix broken links in the abi-gen README 2017-12-24 19:46:45 -05:00
Brandon Millman
cbf06b2165 Merge pull request #289 from 0xProject/fix/missingBigNumberConfigs
Add missing calls to bigNumberConfigs in packages where we are instan…
2017-12-21 21:04:50 -05:00
Fabio Berger
e884eb9882 Merge pull request #288 from 0xProject/fix/docLinks
Fix doc anchor link collisions
2017-12-21 22:45:22 +01:00
Brandon Millman
f8cbfea4a1 Remove unused import 2017-12-21 15:40:09 -05:00
Fabio Berger
e01c0f054d Merge branch 'development' into fix/docLinks
* development:
  Update and standardize contracts README
  Add to CHANGELOG
  Refactor toBaseUnitAmount so that it throws if user supplies unitAmount with too many decimals
  Make assertion stricter so that one cannot submit invalid baseUnit amounts to `toUnitAmount`
  Add some missed underscores, update changelog and comments
  Add new underscore-privates rule to @0xproject/tslint-config and fix lint errors

# Conflicts:
#	packages/website/ts/pages/documentation/documentation.tsx
#	packages/website/ts/pages/shared/nested_sidebar_menu.tsx
2017-12-21 21:24:54 +01:00
Brandon Millman
12dc8c0d15 Add missing calls to bigNumberConfigs in packages where we are instantiating BigNumbers 2017-12-21 14:55:55 -05:00
Brandon Millman
cb3582289f Merge pull request #285 from 0xProject/fix/underscorePrivate
Add new underscore-privates rule to @0xproject/tslint-config and fix …
2017-12-21 13:16:25 -05:00
Fabio Berger
734d220d60 Merge pull request #287 from 0xProject/fix/toBaseUnitAmount
Fix toBaseUnitAmount Issue
2017-12-21 18:22:28 +01:00
Fabio Berger
d725de7286 Create types sectionName constant 2017-12-21 17:28:20 +01:00
Fabio Berger
3e91773cd9 Add sectionName prefix to all anchor links in order to fix method name collisions between sections 2017-12-21 17:28:06 +01:00
Amir Bandeali
dc1d2a33a5 Merge pull request #286 from 0xProject/feature/updateContractsReadme
Update and standardize contracts README
2017-12-21 09:26:33 -06:00
Amir Bandeali
ac4074911d Update and standardize contracts README 2017-12-21 09:21:10 -06:00
Fabio Berger
66cf60f9cb Fix Max button bug 2017-12-21 15:32:23 +01:00
Fabio Berger
fffe8c355e Add to CHANGELOG 2017-12-21 14:40:18 +01:00
Fabio Berger
b94d13b413 Refactor toBaseUnitAmount so that it throws if user supplies unitAmount with too many decimals 2017-12-21 09:34:50 +01:00
Fabio Berger
85e16c1233 Make assertion stricter so that one cannot submit invalid baseUnit amounts to toUnitAmount 2017-12-21 09:33:57 +01:00
Brandon Millman
2d53b7d9a4 Add some missed underscores, update changelog and comments 2017-12-20 19:08:11 -05:00
Brandon Millman
23052a5c2e Merge branch 'development' into fix/underscorePrivate
* development: (29 commits)
  Move call to error reporter to end of handler so that even if reporting the error takes a while, it doesn't block the UI
  Update outdated WETH ranges
  Fix conditional
  Fix top-padding
  Publish
  Update CHANGELOGs
  Add slashes to base URLs
  Fix linter issue
  Fix WETH symbol
  Update snapshot and artifacts
  Replace our EtherTokens with WETH9 from maker
  Fix test description
  Fix a typo
  Add err==null assertions
  Add WETH9 tests
  Use the new snapshot including WETH9 and it's artifacts
  Add WETH9 and mirations
  Fix WETH events watching
  Fix a typo
  Init the _etherTokenContractsByAddress
  ...
2017-12-20 19:07:54 -05:00
Fabio Berger
42b3a7c9d7 Move call to error reporter to end of handler so that even if reporting the error takes a while, it doesn't block the UI 2017-12-20 18:36:12 +01:00
Fabio Berger
33315046cd Update outdated WETH ranges 2017-12-20 18:31:01 +01:00
Fabio Berger
2cf647d5ad Fix conditional 2017-12-20 17:40:01 +01:00
Fabio Berger
b1d88ca643 Merge branch 'development' of github.com:0xProject/0x.js into development
* 'development' of github.com:0xProject/0x.js:
  Publish
2017-12-20 17:24:19 +01:00
Fabio Berger
b79b48cfbe Fix top-padding 2017-12-20 17:24:12 +01:00
Leonid Logvinov
a2bf19efc1 Publish
- 0x.js@0.28.0
 - @0xproject/abi-gen@0.0.3
 - @0xproject/assert@0.0.8
 - @0xproject/connect@0.3.1
 - contracts@2.1.0
 - @0xproject/dev-utils@0.0.2
 - @0xproject/json-schemas@0.7.0
 - @0xproject/kovan_faucets@1.0.1
 - @0xproject/monorepo-scripts@0.1.1
 - @0xproject/subproviders@0.1.1
 - @0xproject/tslint-config@0.3.0
 - @0xproject/types@0.1.1
 - @0xproject/utils@0.1.1
 - @0xproject/web3-wrapper@0.1.1
 - @0xproject/website@0.0.3
2017-12-20 17:10:12 +01:00
Brandon Millman
cb11aec84d Add new underscore-privates rule to @0xproject/tslint-config and fix lint errors 2017-12-20 15:30:25 +01:00
126 changed files with 1742 additions and 1545 deletions

View File

@@ -1,62 +1,47 @@
# 0x.js CONTRIBUTING.md
0x Contribution Guide
---------------------
Thank you for your interest in contributing to 0x.js! We welcome contributions from anyone on the internet, and are grateful for even the smallest of fixes!
Thank you for your interest in contributing to 0x protocol! We welcome contributions from anyone on the internet, and are grateful for even the smallest of fixes!
## Developer's guide
### How to contribute
## How to contribute
If you'd like to contribute to 0x protocol, please fork the repo, fix, commit and send a pull request against the `development` branch for the maintainers to review and merge into the main code base. If you wish to submit more complex changes though, please check with a core dev first on [our RocketChat #dev channel](http://chat.0xproject.com) to ensure those changes are in-line with the general philosophy of the project and/or to get some early feedback which can make both your efforts easier as well as our review and merge procedures quick and simple.
If you'd like to contribute to 0x.js, please fork the repo, fix, commit and send a pull request against the `development` branch for the maintainers to review and merge into the main code base. If you wish to submit more complex changes though, please check up with a core dev first on [our gitter channel](https://gitter.im/0xProject/Lobby) or in the `#dev` channel on our [slack](https://slack.0xproject.com/) to ensure those changes are in line with the general philosophy of the project and/or to get some early feedback which can make both your efforts easier as well as our review and merge procedures quick and simple.
We encourage a “PR early” approach so create the PR as early as possible even without the fix/feature ready, so that devs and other volunteers know you have picked up the issue. These early PRs should indicate an 'in progress' status by adding the '[WIP]' prefix to the PR title. Please make sure your contributions adhere to our coding guidelines:
We encourage a “PR early” approach so create the PR as early as possible even without the fix/feature ready, so that devs and other contributors know you have picked up the issue. These early PRs should indicate an 'in progress' status by adding the '[WIP]' prefix to the PR title. Please make sure your contributions adhere to our coding guidelines:
* Pull requests adding features or refactoring should be opened against the `development` branch
* Pull requests fixing bugs in the latest release version should be opened again the `master` branch
* Write [good commit messages](https://chris.beams.io/posts/git-commit/)
## Code quality
### Code quality
Because 0x.js is used by multiple relayers in production and their businesses depend on it, we strive for exceptional code quality. Please follow the existing code standards and conventions. `tslint` and `prettier` (described below) will help you.
Because 0x.js is used by multiple relayers in production and their businesses depend on it, we strive for excellent code quality. Please follow the existing code standards and conventions. `tslint` (described below) will help you.
If you're adding functionality, please also add tests and make sure they pass. We have an automatic coverage reporting tool, so we'll see it if they are missing ;)
If you're adding a new public function/member, make sure you document it with Java doc-style comments. We use typedoc to generate [awesome documentation](https://0xproject.com/docs/0xjs) from the comments within our source code.
## Running and building
If the sub-package you are modifying has a `CHANGELOG.md` file, make sure to add an entry in it for the change made to the package. For published packages, only changes that modify the public interface or behavior of the package need a CHANGELOG entry.
First thing to do with an unknown code base is to run the tests.
We assume that you have `npm` and `yarn` installed.
### Styleguide
To do that:
* Install dependencies: `yarn`
* Initialize the testrpc state (migrate the contracts) by doing one of the following:
* Manual contracts migration:
* Run testrpc: `yarn testrpc`
* Clone the `[contracts](https://github.com/0xProject/contracts)` repo and run `yarn migrate`
* Use one of the existing testrpc snapshots
* Check out `circle.yml` for an example
* Run tests: `yarn test`
To build run: `yarn build`
We also recommend you read through the tests.
## Styleguide
We use [TSLint](https://palantir.github.io/tslint/) with [custom configs](https://github.com/0xProject/tslint-config-0xproject) to keep our code style consistent.
We use [TSLint](https://palantir.github.io/tslint/) with [custom configs](https://github.com/0xProject/0x.js/tree/development/packages/tslint-config) to keep our code style consistent.
To lint your code just run: `yarn lint`
We also use [Prettier](https://prettier.io/) to auto-format our code. Be sure to either add a [text editor integration](https://prettier.io/docs/en/editors.html) or a [pre-commit hook](https://prettier.io/docs/en/precommit.html) to properly format your code changes.
If using the Atom text editor, we recommend you install the following packages:
* [atom-typescript](https://atom.io/packages/atom-typescript)
* [linter-tslint](https://atom.io/packages/linter-tslint)
* [prettier-atom](https://atom.io/packages/prettier-atom)
* [language-ethereum](https://atom.io/packages/language-ethereum)
Our CI will also run it as a part of the test run when you submit your PR.
Our CI will also run TSLint and Prettier as a part of the test run when you submit your PR. Make sure that the CI tests pass for your contribution.
### Branch structure & versioning
## Branch structure & versioning
We use [semantic versioning](http://semver.org/), but before we reach v1.0.0 all breaking changes as well as new features will be minor version bumps.
We use [semantic versioning](http://semver.org/), but before a package reaches v1.0.0 all breaking changes as well as new features will be minor version bumps.
We have two main branches: `master` and `development`.

View File

@@ -1,5 +1,10 @@
# CHANGELOG
v0.29.0 - _December 28, 2017_
------------------------
* Assert baseUnit amount supplied to `toUnitAmount` is integer amount. (#287)
* `toBaseUnitAmount` throws if amount supplied has too many decimals (#287)
v0.28.0 - _December 20, 2017_
------------------------
* Add `etherTokenAddress` arg to `depositAsync` and `withdrawAsync` methods on `zeroEx.etherToken` (#267)

View File

@@ -1,6 +1,6 @@
{
"name": "0x.js",
"version": "0.27.2",
"version": "0.29.0",
"description": "A javascript library for interacting with the 0x protocol",
"keywords": [
"0x.js",
@@ -45,10 +45,10 @@
"node": ">=6.0.0"
},
"devDependencies": {
"@0xproject/abi-gen": "^0.0.2",
"@0xproject/tslint-config": "^0.2.1",
"@0xproject/types": "^0.1.0",
"@0xproject/dev-utils": "^0.0.1",
"@0xproject/abi-gen": "^0.0.4",
"@0xproject/dev-utils": "^0.0.3",
"@0xproject/tslint-config": "^0.4.0",
"@0xproject/types": "^0.1.2",
"@types/bintrees": "^1.0.2",
"@types/jsonschema": "^1.1.1",
"@types/lodash": "^4.14.86",
@@ -84,10 +84,10 @@
"webpack": "^3.1.0"
},
"dependencies": {
"@0xproject/assert": "^0.0.7",
"@0xproject/json-schemas": "^0.6.10",
"@0xproject/utils": "^0.1.0",
"@0xproject/web3-wrapper": "^0.1.0",
"@0xproject/assert": "^0.0.9",
"@0xproject/json-schemas": "^0.7.1",
"@0xproject/utils": "^0.1.2",
"@0xproject/web3-wrapper": "^0.1.2",
"bignumber.js": "~4.1.0",
"bintrees": "^1.0.2",
"bn.js": "^4.11.8",

View File

@@ -128,7 +128,7 @@ export class ZeroEx {
* @return The amount in units.
*/
public static toUnitAmount(amount: BigNumber, decimals: number): BigNumber {
assert.isBigNumber('amount', amount);
assert.isValidBaseUnitAmount('amount', amount);
assert.isNumber('decimals', decimals);
const aUnit = new BigNumber(10).pow(decimals);
@@ -149,6 +149,10 @@ export class ZeroEx {
const unit = new BigNumber(10).pow(decimals);
const baseUnitAmount = amount.times(unit);
const hasDecimals = baseUnitAmount.decimalPlaces() !== 0;
if (hasDecimals) {
throw new Error(`Invalid unit amount: ${amount.toString()} - Too many decimal places`);
}
return baseUnitAmount;
}
/**

View File

@@ -14,62 +14,62 @@ const DEFAULT_ORDER_EXPIRATION_CHECKING_INTERVAL_MS = 50;
* It stores them in a min heap by expiration time and checks for expired ones every `orderExpirationCheckingIntervalMs`
*/
export class ExpirationWatcher {
private orderHashByExpirationRBTree: RBTree<string>;
private expiration: {[orderHash: string]: BigNumber} = {};
private orderExpirationCheckingIntervalMs: number;
private expirationMarginMs: number;
private orderExpirationCheckingIntervalIdIfExists?: NodeJS.Timer;
private _orderHashByExpirationRBTree: RBTree<string>;
private _expiration: {[orderHash: string]: BigNumber} = {};
private _orderExpirationCheckingIntervalMs: number;
private _expirationMarginMs: number;
private _orderExpirationCheckingIntervalIdIfExists?: NodeJS.Timer;
constructor(expirationMarginIfExistsMs?: number,
orderExpirationCheckingIntervalIfExistsMs?: number) {
this.expirationMarginMs = expirationMarginIfExistsMs ||
this._expirationMarginMs = expirationMarginIfExistsMs ||
DEFAULT_EXPIRATION_MARGIN_MS;
this.orderExpirationCheckingIntervalMs = expirationMarginIfExistsMs ||
this._orderExpirationCheckingIntervalMs = expirationMarginIfExistsMs ||
DEFAULT_ORDER_EXPIRATION_CHECKING_INTERVAL_MS;
const scoreFunction = (orderHash: string) => this.expiration[orderHash].toNumber();
const scoreFunction = (orderHash: string) => this._expiration[orderHash].toNumber();
const comparator = (lhs: string, rhs: string) => scoreFunction(lhs) - scoreFunction(rhs);
this.orderHashByExpirationRBTree = new RBTree(comparator);
this._orderHashByExpirationRBTree = new RBTree(comparator);
}
public subscribe(callback: (orderHash: string) => void): void {
if (!_.isUndefined(this.orderExpirationCheckingIntervalIdIfExists)) {
if (!_.isUndefined(this._orderExpirationCheckingIntervalIdIfExists)) {
throw new Error(ZeroExError.SubscriptionAlreadyPresent);
}
this.orderExpirationCheckingIntervalIdIfExists = intervalUtils.setAsyncExcludingInterval(
this.pruneExpiredOrders.bind(this, callback), this.orderExpirationCheckingIntervalMs,
this._orderExpirationCheckingIntervalIdIfExists = intervalUtils.setAsyncExcludingInterval(
this._pruneExpiredOrders.bind(this, callback), this._orderExpirationCheckingIntervalMs,
);
}
public unsubscribe(): void {
if (_.isUndefined(this.orderExpirationCheckingIntervalIdIfExists)) {
if (_.isUndefined(this._orderExpirationCheckingIntervalIdIfExists)) {
throw new Error(ZeroExError.SubscriptionNotFound);
}
intervalUtils.clearAsyncExcludingInterval(this.orderExpirationCheckingIntervalIdIfExists);
delete this.orderExpirationCheckingIntervalIdIfExists;
intervalUtils.clearAsyncExcludingInterval(this._orderExpirationCheckingIntervalIdIfExists);
delete this._orderExpirationCheckingIntervalIdIfExists;
}
public addOrder(orderHash: string, expirationUnixTimestampMs: BigNumber): void {
this.expiration[orderHash] = expirationUnixTimestampMs;
this.orderHashByExpirationRBTree.insert(orderHash);
this._expiration[orderHash] = expirationUnixTimestampMs;
this._orderHashByExpirationRBTree.insert(orderHash);
}
public removeOrder(orderHash: string): void {
this.orderHashByExpirationRBTree.remove(orderHash);
delete this.expiration[orderHash];
this._orderHashByExpirationRBTree.remove(orderHash);
delete this._expiration[orderHash];
}
private pruneExpiredOrders(callback: (orderHash: string) => void): void {
private _pruneExpiredOrders(callback: (orderHash: string) => void): void {
const currentUnixTimestampMs = utils.getCurrentUnixTimestampMs();
while (true) {
const hasTrakedOrders = this.orderHashByExpirationRBTree.size === 0;
const hasTrakedOrders = this._orderHashByExpirationRBTree.size === 0;
if (hasTrakedOrders) {
break;
}
const nextOrderHashToExpire = this.orderHashByExpirationRBTree.min();
const hasNoExpiredOrders = this.expiration[nextOrderHashToExpire].greaterThan(
currentUnixTimestampMs.plus(this.expirationMarginMs),
const nextOrderHashToExpire = this._orderHashByExpirationRBTree.min();
const hasNoExpiredOrders = this._expiration[nextOrderHashToExpire].greaterThan(
currentUnixTimestampMs.plus(this._expirationMarginMs),
);
const isSubscriptionActive = _.isUndefined(this.orderExpirationCheckingIntervalIdIfExists);
const isSubscriptionActive = _.isUndefined(this._orderExpirationCheckingIntervalIdIfExists);
if (hasNoExpiredOrders || isSubscriptionActive) {
break;
}
const orderHash = this.orderHashByExpirationRBTree.min();
this.orderHashByExpirationRBTree.remove(orderHash);
delete this.expiration[orderHash];
const orderHash = this._orderHashByExpirationRBTree.min();
this._orderHashByExpirationRBTree.remove(orderHash);
delete this._expiration[orderHash];
callback(orderHash);
}
}

View File

@@ -111,7 +111,7 @@ export class OrderStateWatcher {
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
assert.isValidSignature(orderHash, signedOrder.ecSignature, signedOrder.maker);
this._orderByOrderHash[orderHash] = signedOrder;
this.addToDependentOrderHashes(signedOrder, orderHash);
this._addToDependentOrderHashes(signedOrder, orderHash);
const expirationUnixTimestampMs = signedOrder.expirationUnixTimestampSec.times(1000);
this._expirationWatcher.addOrder(orderHash, expirationUnixTimestampMs);
}
@@ -127,10 +127,10 @@ export class OrderStateWatcher {
}
delete this._orderByOrderHash[orderHash];
delete this._orderStateByOrderHashCache[orderHash];
const exchange = (this._orderFilledCancelledLazyStore as any).exchange as ExchangeWrapper;
const exchange = (this._orderFilledCancelledLazyStore as any)._exchange as ExchangeWrapper;
const zrxTokenAddress = exchange.getZRXTokenAddress();
this.removeFromDependentOrderHashes(signedOrder.maker, zrxTokenAddress, orderHash);
this.removeFromDependentOrderHashes(signedOrder.maker, signedOrder.makerTokenAddress, orderHash);
this._removeFromDependentOrderHashes(signedOrder.maker, zrxTokenAddress, orderHash);
this._removeFromDependentOrderHashes(signedOrder.maker, signedOrder.makerTokenAddress, orderHash);
this._expirationWatcher.removeOrder(orderHash);
}
/**
@@ -327,7 +327,7 @@ export class OrderStateWatcher {
this._callbackIfExists(orderState);
}
}
private addToDependentOrderHashes(signedOrder: SignedOrder, orderHash: string): void {
private _addToDependentOrderHashes(signedOrder: SignedOrder, orderHash: string): void {
if (_.isUndefined(this._dependentOrderHashes[signedOrder.maker])) {
this._dependentOrderHashes[signedOrder.maker] = {};
}
@@ -341,7 +341,7 @@ export class OrderStateWatcher {
}
this._dependentOrderHashes[signedOrder.maker][zrxTokenAddress].add(orderHash);
}
private removeFromDependentOrderHashes(makerAddress: string, tokenAddress: string, orderHash: string) {
private _removeFromDependentOrderHashes(makerAddress: string, tokenAddress: string, orderHash: string) {
this._dependentOrderHashes[makerAddress][tokenAddress].delete(orderHash);
if (this._dependentOrderHashes[makerAddress][tokenAddress].size === 0) {
delete this._dependentOrderHashes[makerAddress][tokenAddress];
@@ -351,7 +351,7 @@ export class OrderStateWatcher {
}
}
private _getZRXTokenAddress(): string {
const exchange = (this._orderFilledCancelledLazyStore as any).exchange as ExchangeWrapper;
const exchange = (this._orderFilledCancelledLazyStore as any)._exchange as ExchangeWrapper;
const zrxTokenAddress = exchange.getZRXTokenAddress();
return zrxTokenAddress;
}

View File

@@ -3,69 +3,69 @@ import {BigNumber} from 'bignumber.js';
import {SignedOrder} from '../types';
export class RemainingFillableCalculator {
private signedOrder: SignedOrder;
private isMakerTokenZRX: boolean;
private _signedOrder: SignedOrder;
private _isMakerTokenZRX: boolean;
// Transferrable Amount is the minimum of Approval and Balance
private transferrableMakerTokenAmount: BigNumber;
private transferrableMakerFeeTokenAmount: BigNumber;
private remainingMakerTokenAmount: BigNumber;
private remainingMakerFeeAmount: BigNumber;
private _transferrableMakerTokenAmount: BigNumber;
private _transferrableMakerFeeTokenAmount: BigNumber;
private _remainingMakerTokenAmount: BigNumber;
private _remainingMakerFeeAmount: BigNumber;
constructor(signedOrder: SignedOrder,
isMakerTokenZRX: boolean,
transferrableMakerTokenAmount: BigNumber,
transferrableMakerFeeTokenAmount: BigNumber,
remainingMakerTokenAmount: BigNumber) {
this.signedOrder = signedOrder;
this.isMakerTokenZRX = isMakerTokenZRX;
this.transferrableMakerTokenAmount = transferrableMakerTokenAmount;
this.transferrableMakerFeeTokenAmount = transferrableMakerFeeTokenAmount;
this.remainingMakerTokenAmount = remainingMakerTokenAmount;
this.remainingMakerFeeAmount = remainingMakerTokenAmount.times(signedOrder.makerFee)
this._signedOrder = signedOrder;
this._isMakerTokenZRX = isMakerTokenZRX;
this._transferrableMakerTokenAmount = transferrableMakerTokenAmount;
this._transferrableMakerFeeTokenAmount = transferrableMakerFeeTokenAmount;
this._remainingMakerTokenAmount = remainingMakerTokenAmount;
this._remainingMakerFeeAmount = remainingMakerTokenAmount.times(signedOrder.makerFee)
.dividedToIntegerBy(signedOrder.makerTokenAmount);
}
public computeRemainingMakerFillable(): BigNumber {
if (this.hasSufficientFundsForFeeAndTransferAmount()) {
return this.remainingMakerTokenAmount;
if (this._hasSufficientFundsForFeeAndTransferAmount()) {
return this._remainingMakerTokenAmount;
}
if (this.signedOrder.makerFee.isZero()) {
return BigNumber.min(this.remainingMakerTokenAmount, this.transferrableMakerTokenAmount);
if (this._signedOrder.makerFee.isZero()) {
return BigNumber.min(this._remainingMakerTokenAmount, this._transferrableMakerTokenAmount);
}
return this.calculatePartiallyFillableMakerTokenAmount();
return this._calculatePartiallyFillableMakerTokenAmount();
}
public computeRemainingTakerFillable(): BigNumber {
return this.computeRemainingMakerFillable().times(this.signedOrder.takerTokenAmount)
.dividedToIntegerBy(this.signedOrder.makerTokenAmount);
return this.computeRemainingMakerFillable().times(this._signedOrder.takerTokenAmount)
.dividedToIntegerBy(this._signedOrder.makerTokenAmount);
}
private hasSufficientFundsForFeeAndTransferAmount(): boolean {
if (this.isMakerTokenZRX) {
const totalZRXTransferAmountRequired = this.remainingMakerTokenAmount.plus(this.remainingMakerFeeAmount);
const hasSufficientFunds = this.transferrableMakerTokenAmount.greaterThanOrEqualTo(
private _hasSufficientFundsForFeeAndTransferAmount(): boolean {
if (this._isMakerTokenZRX) {
const totalZRXTransferAmountRequired = this._remainingMakerTokenAmount.plus(this._remainingMakerFeeAmount);
const hasSufficientFunds = this._transferrableMakerTokenAmount.greaterThanOrEqualTo(
totalZRXTransferAmountRequired);
return hasSufficientFunds;
} else {
const hasSufficientFundsForTransferAmount = this.transferrableMakerTokenAmount.greaterThanOrEqualTo(
this.remainingMakerTokenAmount);
const hasSufficientFundsForFeeAmount = this.transferrableMakerFeeTokenAmount.greaterThanOrEqualTo(
this.remainingMakerFeeAmount);
const hasSufficientFundsForTransferAmount = this._transferrableMakerTokenAmount.greaterThanOrEqualTo(
this._remainingMakerTokenAmount);
const hasSufficientFundsForFeeAmount = this._transferrableMakerFeeTokenAmount.greaterThanOrEqualTo(
this._remainingMakerFeeAmount);
const hasSufficientFunds = hasSufficientFundsForTransferAmount && hasSufficientFundsForFeeAmount;
return hasSufficientFunds;
}
}
private calculatePartiallyFillableMakerTokenAmount(): BigNumber {
private _calculatePartiallyFillableMakerTokenAmount(): BigNumber {
// Given an order for 200 wei for 2 ZRXwei fee, find 100 wei for 1 ZRXwei. Order ratio is then 100:1
const orderToFeeRatio = this.signedOrder.makerTokenAmount.dividedBy(this.signedOrder.makerFee);
const orderToFeeRatio = this._signedOrder.makerTokenAmount.dividedBy(this._signedOrder.makerFee);
// The number of times the maker can fill the order, if each fill only required the transfer of a single
// baseUnit of fee tokens.
// Given 2 ZRXwei, the maximum amount of times Maker can fill this order, in terms of fees, is 2
const fillableTimesInFeeTokenBaseUnits = BigNumber.min(this.transferrableMakerFeeTokenAmount,
this.remainingMakerFeeAmount);
const fillableTimesInFeeTokenBaseUnits = BigNumber.min(this._transferrableMakerFeeTokenAmount,
this._remainingMakerFeeAmount);
// The number of times the Maker can fill the order, given the Maker Token Balance
// Assuming a balance of 150 wei, and an orderToFeeRatio of 100:1, maker can fill this order 1 time.
let fillableTimesInMakerTokenUnits = this.transferrableMakerTokenAmount.dividedBy(orderToFeeRatio);
if (this.isMakerTokenZRX) {
let fillableTimesInMakerTokenUnits = this._transferrableMakerTokenAmount.dividedBy(orderToFeeRatio);
if (this._isMakerTokenZRX) {
// If ZRX is the maker token, the Fee and the Maker amount need to be removed from the same pool;
// 200 ZRXwei for 2ZRXwei fee can only be filled once (need 202 ZRXwei)
const totalZRXTokenPooled = this.transferrableMakerTokenAmount;
const totalZRXTokenPooled = this._transferrableMakerTokenAmount;
// The purchasing power here is less as the tokens are taken from the same Pool
// For every one number of fills, we have to take an extra ZRX out of the pool
fillableTimesInMakerTokenUnits = totalZRXTokenPooled.dividedBy(
@@ -75,11 +75,11 @@ export class RemainingFillableCalculator {
// When Ratio is not fully divisible there can be remainders which cannot be represented, so they are floored.
// This can result in a RoundingError being thrown by the Exchange Contract.
const partiallyFillableMakerTokenAmount = fillableTimesInMakerTokenUnits
.times(this.signedOrder.makerTokenAmount)
.dividedToIntegerBy(this.signedOrder.makerFee);
.times(this._signedOrder.makerTokenAmount)
.dividedToIntegerBy(this._signedOrder.makerFee);
const partiallyFillableFeeTokenAmount = fillableTimesInFeeTokenBaseUnits
.times(this.signedOrder.makerTokenAmount)
.dividedToIntegerBy(this.signedOrder.makerFee);
.times(this._signedOrder.makerTokenAmount)
.dividedToIntegerBy(this._signedOrder.makerFee);
const partiallyFillableAmount = BigNumber.min(partiallyFillableMakerTokenAmount,
partiallyFillableFeeTokenAmount);
return partiallyFillableAmount;

View File

@@ -8,77 +8,77 @@ import {BlockParamLiteral} from '../types';
* Copy on read store for balances/proxyAllowances of tokens/accounts
*/
export class BalanceAndProxyAllowanceLazyStore {
private token: TokenWrapper;
private defaultBlock: BlockParamLiteral;
private balance: {
private _token: TokenWrapper;
private _defaultBlock: BlockParamLiteral;
private _balance: {
[tokenAddress: string]: {
[userAddress: string]: BigNumber;
};
};
private proxyAllowance: {
private _proxyAllowance: {
[tokenAddress: string]: {
[userAddress: string]: BigNumber;
};
};
constructor(token: TokenWrapper, defaultBlock: BlockParamLiteral) {
this.token = token;
this.defaultBlock = defaultBlock;
this.balance = {};
this.proxyAllowance = {};
this._token = token;
this._defaultBlock = defaultBlock;
this._balance = {};
this._proxyAllowance = {};
}
public async getBalanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber> {
if (_.isUndefined(this.balance[tokenAddress]) || _.isUndefined(this.balance[tokenAddress][userAddress])) {
if (_.isUndefined(this._balance[tokenAddress]) || _.isUndefined(this._balance[tokenAddress][userAddress])) {
const methodOpts = {
defaultBlock: this.defaultBlock,
defaultBlock: this._defaultBlock,
};
const balance = await this.token.getBalanceAsync(tokenAddress, userAddress, methodOpts);
const balance = await this._token.getBalanceAsync(tokenAddress, userAddress, methodOpts);
this.setBalance(tokenAddress, userAddress, balance);
}
const cachedBalance = this.balance[tokenAddress][userAddress];
const cachedBalance = this._balance[tokenAddress][userAddress];
return cachedBalance;
}
public setBalance(tokenAddress: string, userAddress: string, balance: BigNumber): void {
if (_.isUndefined(this.balance[tokenAddress])) {
this.balance[tokenAddress] = {};
if (_.isUndefined(this._balance[tokenAddress])) {
this._balance[tokenAddress] = {};
}
this.balance[tokenAddress][userAddress] = balance;
this._balance[tokenAddress][userAddress] = balance;
}
public deleteBalance(tokenAddress: string, userAddress: string): void {
if (!_.isUndefined(this.balance[tokenAddress])) {
delete this.balance[tokenAddress][userAddress];
if (_.isEmpty(this.balance[tokenAddress])) {
delete this.balance[tokenAddress];
if (!_.isUndefined(this._balance[tokenAddress])) {
delete this._balance[tokenAddress][userAddress];
if (_.isEmpty(this._balance[tokenAddress])) {
delete this._balance[tokenAddress];
}
}
}
public async getProxyAllowanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber> {
if (_.isUndefined(this.proxyAllowance[tokenAddress]) ||
_.isUndefined(this.proxyAllowance[tokenAddress][userAddress])) {
if (_.isUndefined(this._proxyAllowance[tokenAddress]) ||
_.isUndefined(this._proxyAllowance[tokenAddress][userAddress])) {
const methodOpts = {
defaultBlock: this.defaultBlock,
defaultBlock: this._defaultBlock,
};
const proxyAllowance = await this.token.getProxyAllowanceAsync(tokenAddress, userAddress, methodOpts);
const proxyAllowance = await this._token.getProxyAllowanceAsync(tokenAddress, userAddress, methodOpts);
this.setProxyAllowance(tokenAddress, userAddress, proxyAllowance);
}
const cachedProxyAllowance = this.proxyAllowance[tokenAddress][userAddress];
const cachedProxyAllowance = this._proxyAllowance[tokenAddress][userAddress];
return cachedProxyAllowance;
}
public setProxyAllowance(tokenAddress: string, userAddress: string, proxyAllowance: BigNumber): void {
if (_.isUndefined(this.proxyAllowance[tokenAddress])) {
this.proxyAllowance[tokenAddress] = {};
if (_.isUndefined(this._proxyAllowance[tokenAddress])) {
this._proxyAllowance[tokenAddress] = {};
}
this.proxyAllowance[tokenAddress][userAddress] = proxyAllowance;
this._proxyAllowance[tokenAddress][userAddress] = proxyAllowance;
}
public deleteProxyAllowance(tokenAddress: string, userAddress: string): void {
if (!_.isUndefined(this.proxyAllowance[tokenAddress])) {
delete this.proxyAllowance[tokenAddress][userAddress];
if (_.isEmpty(this.proxyAllowance[tokenAddress])) {
delete this.proxyAllowance[tokenAddress];
if (!_.isUndefined(this._proxyAllowance[tokenAddress])) {
delete this._proxyAllowance[tokenAddress][userAddress];
if (_.isEmpty(this._proxyAllowance[tokenAddress])) {
delete this._proxyAllowance[tokenAddress];
}
}
}
public deleteAll(): void {
this.balance = {};
this.proxyAllowance = {};
this._balance = {};
this._proxyAllowance = {};
}
}

View File

@@ -8,54 +8,54 @@ import {BlockParamLiteral} from '../types';
* Copy on read store for filled/cancelled taker amounts
*/
export class OrderFilledCancelledLazyStore {
private exchange: ExchangeWrapper;
private filledTakerAmount: {
private _exchange: ExchangeWrapper;
private _filledTakerAmount: {
[orderHash: string]: BigNumber;
};
private cancelledTakerAmount: {
private _cancelledTakerAmount: {
[orderHash: string]: BigNumber;
};
constructor(exchange: ExchangeWrapper) {
this.exchange = exchange;
this.filledTakerAmount = {};
this.cancelledTakerAmount = {};
this._exchange = exchange;
this._filledTakerAmount = {};
this._cancelledTakerAmount = {};
}
public async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber> {
if (_.isUndefined(this.filledTakerAmount[orderHash])) {
if (_.isUndefined(this._filledTakerAmount[orderHash])) {
const methodOpts = {
defaultBlock: BlockParamLiteral.Pending,
};
const filledTakerAmount = await this.exchange.getFilledTakerAmountAsync(orderHash, methodOpts);
const filledTakerAmount = await this._exchange.getFilledTakerAmountAsync(orderHash, methodOpts);
this.setFilledTakerAmount(orderHash, filledTakerAmount);
}
const cachedFilled = this.filledTakerAmount[orderHash];
const cachedFilled = this._filledTakerAmount[orderHash];
return cachedFilled;
}
public setFilledTakerAmount(orderHash: string, filledTakerAmount: BigNumber): void {
this.filledTakerAmount[orderHash] = filledTakerAmount;
this._filledTakerAmount[orderHash] = filledTakerAmount;
}
public deleteFilledTakerAmount(orderHash: string): void {
delete this.filledTakerAmount[orderHash];
delete this._filledTakerAmount[orderHash];
}
public async getCancelledTakerAmountAsync(orderHash: string): Promise<BigNumber> {
if (_.isUndefined(this.cancelledTakerAmount[orderHash])) {
if (_.isUndefined(this._cancelledTakerAmount[orderHash])) {
const methodOpts = {
defaultBlock: BlockParamLiteral.Pending,
};
const cancelledTakerAmount = await this.exchange.getCancelledTakerAmountAsync(orderHash, methodOpts);
const cancelledTakerAmount = await this._exchange.getCancelledTakerAmountAsync(orderHash, methodOpts);
this.setCancelledTakerAmount(orderHash, cancelledTakerAmount);
}
const cachedCancelled = this.cancelledTakerAmount[orderHash];
const cachedCancelled = this._cancelledTakerAmount[orderHash];
return cachedCancelled;
}
public setCancelledTakerAmount(orderHash: string, cancelledTakerAmount: BigNumber): void {
this.cancelledTakerAmount[orderHash] = cancelledTakerAmount;
this._cancelledTakerAmount[orderHash] = cancelledTakerAmount;
}
public deleteCancelledTakerAmount(orderHash: string): void {
delete this.cancelledTakerAmount[orderHash];
delete this._cancelledTakerAmount[orderHash];
}
public deleteAll(): void {
this.filledTakerAmount = {};
this.cancelledTakerAmount = {};
this._filledTakerAmount = {};
this._cancelledTakerAmount = {};
}
}

View File

@@ -6,9 +6,9 @@ import * as SolidityCoder from 'web3/lib/solidity/coder';
import {AbiType, ContractEventArgs, DecodedLogArgs, LogWithDecodedArgs, RawLog, SolidityTypes} from '../types';
export class AbiDecoder {
private savedABIs: Web3.AbiDefinition[] = [];
private methodIds: {[signatureHash: string]: Web3.EventAbi} = {};
private static padZeros(address: string) {
private _savedABIs: Web3.AbiDefinition[] = [];
private _methodIds: {[signatureHash: string]: Web3.EventAbi} = {};
private static _padZeros(address: string) {
let formatted = address;
if (_.startsWith(formatted, '0x')) {
formatted = formatted.slice(2);
@@ -18,13 +18,13 @@ export class AbiDecoder {
return `0x${formatted}`;
}
constructor(abiArrays: Web3.AbiDefinition[][]) {
_.map(abiArrays, this.addABI.bind(this));
_.map(abiArrays, this._addABI.bind(this));
}
// This method can only decode logs from the 0x & ERC20 smart contracts
public tryToDecodeLogOrNoop<ArgsType extends ContractEventArgs>(
log: Web3.LogEntry): LogWithDecodedArgs<ArgsType>|RawLog {
const methodId = log.topics[0];
const event = this.methodIds[methodId];
const event = this._methodIds[methodId];
if (_.isUndefined(event)) {
return log;
}
@@ -41,7 +41,7 @@ export class AbiDecoder {
// Indexed parameters are stored in topics. Non-indexed ones in decodedData
let value = param.indexed ? log.topics[topicsIndex++] : decodedData[dataIndex++];
if (param.type === SolidityTypes.Address) {
value = AbiDecoder.padZeros(new BigNumber(value).toString(16));
value = AbiDecoder._padZeros(new BigNumber(value).toString(16));
} else if (param.type === SolidityTypes.Uint256 ||
param.type === SolidityTypes.Uint8 ||
param.type === SolidityTypes.Uint) {
@@ -56,14 +56,14 @@ export class AbiDecoder {
args: decodedParams,
};
}
private addABI(abiArray: Web3.AbiDefinition[]): void {
private _addABI(abiArray: Web3.AbiDefinition[]): void {
_.map(abiArray, (abi: Web3.AbiDefinition) => {
if (abi.type === AbiType.Event) {
const signature = `${abi.name}(${_.map(abi.inputs, input => input.type).join(',')})`;
const signatureHash = new Web3().sha3(signature);
this.methodIds[signatureHash] = abi;
this._methodIds[signatureHash] = abi;
}
});
this.savedABIs = this.savedABIs.concat(abiArray);
this._savedABIs = this._savedABIs.concat(abiArray);
}
}

View File

@@ -34,16 +34,16 @@ const ERR_MSG_MAPPING = {
};
export class ExchangeTransferSimulator {
private store: BalanceAndProxyAllowanceLazyStore;
private UNLIMITED_ALLOWANCE_IN_BASE_UNITS: BigNumber;
private static throwValidationError(failureReason: FailureReason, tradeSide: TradeSide,
transferType: TransferType): never {
private _store: BalanceAndProxyAllowanceLazyStore;
private _UNLIMITED_ALLOWANCE_IN_BASE_UNITS: BigNumber;
private static _throwValidationError(failureReason: FailureReason, tradeSide: TradeSide,
transferType: TransferType): never {
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;
this._store = new BalanceAndProxyAllowanceLazyStore(token, defaultBlock);
this._UNLIMITED_ALLOWANCE_IN_BASE_UNITS = token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
}
/**
* Simulates transferFrom call performed by a proxy
@@ -57,33 +57,33 @@ export class ExchangeTransferSimulator {
public async transferFromAsync(tokenAddress: string, from: string, to: string,
amountInBaseUnits: BigNumber, tradeSide: TradeSide,
transferType: TransferType): Promise<void> {
const balance = await this.store.getBalanceAsync(tokenAddress, from);
const proxyAllowance = await this.store.getProxyAllowanceAsync(tokenAddress, from);
const balance = await this._store.getBalanceAsync(tokenAddress, from);
const proxyAllowance = await this._store.getProxyAllowanceAsync(tokenAddress, from);
if (proxyAllowance.lessThan(amountInBaseUnits)) {
ExchangeTransferSimulator.throwValidationError(FailureReason.ProxyAllowance, tradeSide, transferType);
ExchangeTransferSimulator._throwValidationError(FailureReason.ProxyAllowance, tradeSide, transferType);
}
if (balance.lessThan(amountInBaseUnits)) {
ExchangeTransferSimulator.throwValidationError(FailureReason.Balance, tradeSide, transferType);
ExchangeTransferSimulator._throwValidationError(FailureReason.Balance, tradeSide, transferType);
}
await this.decreaseProxyAllowanceAsync(tokenAddress, from, amountInBaseUnits);
await this.decreaseBalanceAsync(tokenAddress, from, amountInBaseUnits);
await this.increaseBalanceAsync(tokenAddress, to, amountInBaseUnits);
await this._decreaseProxyAllowanceAsync(tokenAddress, from, amountInBaseUnits);
await this._decreaseBalanceAsync(tokenAddress, from, amountInBaseUnits);
await this._increaseBalanceAsync(tokenAddress, to, amountInBaseUnits);
}
private async decreaseProxyAllowanceAsync(tokenAddress: string, userAddress: string,
amountInBaseUnits: BigNumber): Promise<void> {
const proxyAllowance = await this.store.getProxyAllowanceAsync(tokenAddress, userAddress);
if (!proxyAllowance.eq(this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS)) {
this.store.setProxyAllowance(tokenAddress, userAddress, proxyAllowance.minus(amountInBaseUnits));
private async _decreaseProxyAllowanceAsync(tokenAddress: string, userAddress: string,
amountInBaseUnits: BigNumber): Promise<void> {
const proxyAllowance = await this._store.getProxyAllowanceAsync(tokenAddress, userAddress);
if (!proxyAllowance.eq(this._UNLIMITED_ALLOWANCE_IN_BASE_UNITS)) {
this._store.setProxyAllowance(tokenAddress, userAddress, proxyAllowance.minus(amountInBaseUnits));
}
}
private async increaseBalanceAsync(tokenAddress: string, userAddress: string,
amountInBaseUnits: BigNumber): Promise<void> {
const balance = await this.store.getBalanceAsync(tokenAddress, userAddress);
this.store.setBalance(tokenAddress, userAddress, balance.plus(amountInBaseUnits));
private async _increaseBalanceAsync(tokenAddress: string, userAddress: string,
amountInBaseUnits: BigNumber): Promise<void> {
const balance = await this._store.getBalanceAsync(tokenAddress, userAddress);
this._store.setBalance(tokenAddress, userAddress, balance.plus(amountInBaseUnits));
}
private async decreaseBalanceAsync(tokenAddress: string, userAddress: string,
amountInBaseUnits: BigNumber): Promise<void> {
const balance = await this.store.getBalanceAsync(tokenAddress, userAddress);
this.store.setBalance(tokenAddress, userAddress, balance.minus(amountInBaseUnits));
private async _decreaseBalanceAsync(tokenAddress: string, userAddress: string,
amountInBaseUnits: BigNumber): Promise<void> {
const balance = await this._store.getBalanceAsync(tokenAddress, userAddress);
this._store.setBalance(tokenAddress, userAddress, balance.minus(amountInBaseUnits));
}
}

View File

@@ -18,9 +18,9 @@ import {
const ACCEPTABLE_RELATIVE_ROUNDING_ERROR = 0.0001;
export class OrderStateUtils {
private balanceAndProxyAllowanceLazyStore: BalanceAndProxyAllowanceLazyStore;
private orderFilledCancelledLazyStore: OrderFilledCancelledLazyStore;
private static validateIfOrderIsValid(signedOrder: SignedOrder, orderRelevantState: OrderRelevantState): void {
private _balanceAndProxyAllowanceLazyStore: BalanceAndProxyAllowanceLazyStore;
private _orderFilledCancelledLazyStore: OrderFilledCancelledLazyStore;
private static _validateIfOrderIsValid(signedOrder: SignedOrder, orderRelevantState: OrderRelevantState): void {
const unavailableTakerTokenAmount = orderRelevantState.cancelledTakerTokenAmount.add(
orderRelevantState.filledTakerTokenAmount,
);
@@ -53,14 +53,14 @@ export class OrderStateUtils {
}
constructor(balanceAndProxyAllowanceLazyStore: BalanceAndProxyAllowanceLazyStore,
orderFilledCancelledLazyStore: OrderFilledCancelledLazyStore) {
this.balanceAndProxyAllowanceLazyStore = balanceAndProxyAllowanceLazyStore;
this.orderFilledCancelledLazyStore = orderFilledCancelledLazyStore;
this._balanceAndProxyAllowanceLazyStore = balanceAndProxyAllowanceLazyStore;
this._orderFilledCancelledLazyStore = orderFilledCancelledLazyStore;
}
public async getOrderStateAsync(signedOrder: SignedOrder): Promise<OrderState> {
const orderRelevantState = await this.getOrderRelevantStateAsync(signedOrder);
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
try {
OrderStateUtils.validateIfOrderIsValid(signedOrder, orderRelevantState);
OrderStateUtils._validateIfOrderIsValid(signedOrder, orderRelevantState);
const orderState: OrderStateValid = {
isValid: true,
orderHash,
@@ -81,23 +81,23 @@ export class OrderStateUtils {
// If we pass it from the instantiator - there is no opportunity to get it there
// because JS doesn't support async constructors.
// Moreover - it's cached under the hood so it's equivalent to an async constructor.
const exchange = (this.orderFilledCancelledLazyStore as any).exchange as ExchangeWrapper;
const exchange = (this._orderFilledCancelledLazyStore as any)._exchange as ExchangeWrapper;
const zrxTokenAddress = exchange.getZRXTokenAddress();
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
const makerBalance = await this.balanceAndProxyAllowanceLazyStore.getBalanceAsync(
const makerBalance = await this._balanceAndProxyAllowanceLazyStore.getBalanceAsync(
signedOrder.makerTokenAddress, signedOrder.maker,
);
const makerProxyAllowance = await this.balanceAndProxyAllowanceLazyStore.getProxyAllowanceAsync(
const makerProxyAllowance = await this._balanceAndProxyAllowanceLazyStore.getProxyAllowanceAsync(
signedOrder.makerTokenAddress, signedOrder.maker,
);
const makerFeeBalance = await this.balanceAndProxyAllowanceLazyStore.getBalanceAsync(
const makerFeeBalance = await this._balanceAndProxyAllowanceLazyStore.getBalanceAsync(
zrxTokenAddress, signedOrder.maker,
);
const makerFeeProxyAllowance = await this.balanceAndProxyAllowanceLazyStore.getProxyAllowanceAsync(
const makerFeeProxyAllowance = await this._balanceAndProxyAllowanceLazyStore.getProxyAllowanceAsync(
zrxTokenAddress, signedOrder.maker,
);
const filledTakerTokenAmount = await this.orderFilledCancelledLazyStore.getFilledTakerAmountAsync(orderHash);
const cancelledTakerTokenAmount = await this.orderFilledCancelledLazyStore.getCancelledTakerAmountAsync(
const filledTakerTokenAmount = await this._orderFilledCancelledLazyStore.getFilledTakerAmountAsync(orderHash);
const cancelledTakerTokenAmount = await this._orderFilledCancelledLazyStore.getCancelledTakerAmountAsync(
orderHash,
);
const unavailableTakerTokenAmount = await exchange.getUnavailableTakerAmountAsync(orderHash);

View File

@@ -10,7 +10,7 @@ import {utils} from '../utils/utils';
import {ExchangeTransferSimulator} from './exchange_transfer_simulator';
export class OrderValidationUtils {
private exchangeWrapper: ExchangeWrapper;
private _exchangeWrapper: ExchangeWrapper;
public static validateCancelOrderThrowIfInvalid(
order: Order, cancelTakerTokenAmount: BigNumber, unavailableTakerTokenAmount: BigNumber,
): void {
@@ -29,7 +29,7 @@ export class OrderValidationUtils {
exchangeTradeEmulator: ExchangeTransferSimulator, signedOrder: SignedOrder,
fillTakerTokenAmount: BigNumber, senderAddress: string, zrxTokenAddress: string,
): Promise<void> {
const fillMakerTokenAmount = OrderValidationUtils.getPartialAmount(
const fillMakerTokenAmount = OrderValidationUtils._getPartialAmount(
fillTakerTokenAmount,
signedOrder.takerTokenAmount,
signedOrder.makerTokenAmount,
@@ -42,7 +42,7 @@ export class OrderValidationUtils {
signedOrder.takerTokenAddress, senderAddress, signedOrder.maker, fillTakerTokenAmount,
TradeSide.Taker, TransferType.Trade,
);
const makerFeeAmount = OrderValidationUtils.getPartialAmount(
const makerFeeAmount = OrderValidationUtils._getPartialAmount(
fillTakerTokenAmount,
signedOrder.takerTokenAmount,
signedOrder.makerFee,
@@ -51,7 +51,7 @@ export class OrderValidationUtils {
zrxTokenAddress, signedOrder.maker, signedOrder.feeRecipient, makerFeeAmount, TradeSide.Maker,
TransferType.Fee,
);
const takerFeeAmount = OrderValidationUtils.getPartialAmount(
const takerFeeAmount = OrderValidationUtils._getPartialAmount(
fillTakerTokenAmount,
signedOrder.takerTokenAmount,
signedOrder.takerFee,
@@ -61,21 +61,21 @@ export class OrderValidationUtils {
TransferType.Fee,
);
}
private static validateRemainingFillAmountNotZeroOrThrow(
private static _validateRemainingFillAmountNotZeroOrThrow(
takerTokenAmount: BigNumber, unavailableTakerTokenAmount: BigNumber,
) {
if (takerTokenAmount.eq(unavailableTakerTokenAmount)) {
throw new Error(ExchangeContractErrs.OrderRemainingFillAmountZero);
}
}
private static validateOrderNotExpiredOrThrow(expirationUnixTimestampSec: BigNumber) {
private static _validateOrderNotExpiredOrThrow(expirationUnixTimestampSec: BigNumber) {
const currentUnixTimestampSec = utils.getCurrentUnixTimestampSec();
if (expirationUnixTimestampSec.lessThan(currentUnixTimestampSec)) {
throw new Error(ExchangeContractErrs.OrderFillExpired);
}
}
private static getPartialAmount(numerator: BigNumber, denominator: BigNumber,
target: BigNumber): BigNumber {
private static _getPartialAmount(numerator: BigNumber, denominator: BigNumber,
target: BigNumber): BigNumber {
const fillMakerTokenAmount = numerator
.mul(target)
.div(denominator)
@@ -83,22 +83,22 @@ export class OrderValidationUtils {
return fillMakerTokenAmount;
}
constructor(exchangeWrapper: ExchangeWrapper) {
this.exchangeWrapper = exchangeWrapper;
this._exchangeWrapper = exchangeWrapper;
}
public async validateOrderFillableOrThrowAsync(
exchangeTradeEmulator: ExchangeTransferSimulator, signedOrder: SignedOrder, zrxTokenAddress: string,
expectedFillTakerTokenAmount?: BigNumber): Promise<void> {
const orderHash = utils.getOrderHashHex(signedOrder);
const unavailableTakerTokenAmount = await this.exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
OrderValidationUtils.validateRemainingFillAmountNotZeroOrThrow(
const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow(
signedOrder.takerTokenAmount, unavailableTakerTokenAmount,
);
OrderValidationUtils.validateOrderNotExpiredOrThrow(signedOrder.expirationUnixTimestampSec);
OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationUnixTimestampSec);
let fillTakerTokenAmount = signedOrder.takerTokenAmount.minus(unavailableTakerTokenAmount);
if (!_.isUndefined(expectedFillTakerTokenAmount)) {
fillTakerTokenAmount = expectedFillTakerTokenAmount;
}
const fillMakerTokenAmount = OrderValidationUtils.getPartialAmount(
const fillMakerTokenAmount = OrderValidationUtils._getPartialAmount(
fillTakerTokenAmount,
signedOrder.takerTokenAmount,
signedOrder.makerTokenAmount,
@@ -107,7 +107,7 @@ export class OrderValidationUtils {
signedOrder.makerTokenAddress, signedOrder.maker, signedOrder.taker, fillMakerTokenAmount,
TradeSide.Maker, TransferType.Trade,
);
const makerFeeAmount = OrderValidationUtils.getPartialAmount(
const makerFeeAmount = OrderValidationUtils._getPartialAmount(
fillTakerTokenAmount,
signedOrder.takerTokenAmount,
signedOrder.makerFee,
@@ -128,14 +128,14 @@ export class OrderValidationUtils {
if (!ZeroEx.isValidSignature(orderHash, signedOrder.ecSignature, signedOrder.maker)) {
throw new Error(ZeroExError.InvalidSignature);
}
const unavailableTakerTokenAmount = await this.exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
OrderValidationUtils.validateRemainingFillAmountNotZeroOrThrow(
const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow(
signedOrder.takerTokenAmount, unavailableTakerTokenAmount,
);
if (signedOrder.taker !== constants.NULL_ADDRESS && signedOrder.taker !== takerAddress) {
throw new Error(ExchangeContractErrs.TransactionSenderIsNotFillOrderTaker);
}
OrderValidationUtils.validateOrderNotExpiredOrThrow(signedOrder.expirationUnixTimestampSec);
OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationUnixTimestampSec);
const remainingTakerTokenAmount = signedOrder.takerTokenAmount.minus(unavailableTakerTokenAmount);
const filledTakerTokenAmount = remainingTakerTokenAmount.lessThan(fillTakerTokenAmount) ?
remainingTakerTokenAmount :
@@ -144,7 +144,7 @@ export class OrderValidationUtils {
exchangeTradeEmulator, signedOrder, filledTakerTokenAmount, takerAddress, zrxTokenAddress,
);
const wouldRoundingErrorOccur = await this.exchangeWrapper.isRoundingErrorAsync(
const wouldRoundingErrorOccur = await this._exchangeWrapper.isRoundingErrorAsync(
filledTakerTokenAmount, signedOrder.takerTokenAmount, signedOrder.makerTokenAmount,
);
if (wouldRoundingErrorOccur) {

View File

@@ -114,6 +114,12 @@ describe('ZeroEx library', () => {
});
});
describe('#toUnitAmount', () => {
it('should throw if invalid baseUnit amount supplied as argument', () => {
const invalidBaseUnitAmount = new BigNumber(1000000000.4);
const decimals = 6;
expect(() => ZeroEx.toUnitAmount(invalidBaseUnitAmount, decimals))
.to.throw('amount should be in baseUnits (no decimals), found value: 1000000000.4');
});
it('Should return the expected unit amount for the decimals passed in', () => {
const baseUnitAmount = new BigNumber(1000000000);
const decimals = 6;
@@ -130,6 +136,12 @@ describe('ZeroEx library', () => {
const expectedUnitAmount = new BigNumber(1000000000);
expect(baseUnitAmount).to.be.bignumber.equal(expectedUnitAmount);
});
it('should throw if unitAmount has more decimals then specified as the max decimal precision', () => {
const unitAmount = new BigNumber(0.823091);
const decimals = 5;
expect(() => ZeroEx.toBaseUnitAmount(unitAmount, decimals))
.to.throw('Invalid unit amount: 0.823091 - Too many decimal places');
});
});
describe('#getOrderHashHex', () => {
const expectedOrderHash = '0x39da987067a3c9e5f1617694f1301326ba8c8b0498ebef5df4863bed394e3c83';

View File

@@ -65,7 +65,7 @@ describe('ExchangeTransferSimulator', () => {
await exchangeTransferSimulator.transferFromAsync(
exampleTokenAddress, sender, recipient, transferAmount, TradeSide.Taker, TransferType.Trade,
);
const store = (exchangeTransferSimulator as any).store;
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);
@@ -81,7 +81,7 @@ describe('ExchangeTransferSimulator', () => {
await exchangeTransferSimulator.transferFromAsync(
exampleTokenAddress, sender, recipient, transferAmount, TradeSide.Taker, TransferType.Trade,
);
const store = (exchangeTransferSimulator as any).store;
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);

View File

@@ -11,24 +11,24 @@ import {constants} from './constants';
const INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS = new BigNumber(100);
export class FillScenarios {
private zeroEx: ZeroEx;
private userAddresses: string[];
private tokens: Token[];
private coinbase: string;
private zrxTokenAddress: string;
private exchangeContractAddress: string;
private _zeroEx: ZeroEx;
private _userAddresses: string[];
private _tokens: Token[];
private _coinbase: string;
private _zrxTokenAddress: string;
private _exchangeContractAddress: string;
constructor(zeroEx: ZeroEx, userAddresses: string[],
tokens: Token[], zrxTokenAddress: string, exchangeContractAddress: string) {
this.zeroEx = zeroEx;
this.userAddresses = userAddresses;
this.tokens = tokens;
this.coinbase = userAddresses[0];
this.zrxTokenAddress = zrxTokenAddress;
this.exchangeContractAddress = exchangeContractAddress;
this._zeroEx = zeroEx;
this._userAddresses = userAddresses;
this._tokens = tokens;
this._coinbase = userAddresses[0];
this._zrxTokenAddress = zrxTokenAddress;
this._exchangeContractAddress = exchangeContractAddress;
}
public async initTokenBalancesAsync() {
const web3Wrapper = (this.zeroEx as any)._web3Wrapper as Web3Wrapper;
for (const token of this.tokens) {
const web3Wrapper = (this._zeroEx as any)._web3Wrapper as Web3Wrapper;
for (const token of this._tokens) {
if (token.symbol !== 'ZRX' && token.symbol !== 'WETH') {
const contractInstance = web3Wrapper.getContractInstance(
artifacts.DummyTokenArtifact.abi, token.address,
@@ -36,10 +36,10 @@ export class FillScenarios {
const defaults = {};
const dummyToken = new DummyTokenContract(contractInstance, defaults);
const tokenSupply = ZeroEx.toBaseUnitAmount(INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS, token.decimals);
const txHash = await dummyToken.setBalance.sendTransactionAsync(this.coinbase, tokenSupply, {
from: this.coinbase,
const txHash = await dummyToken.setBalance.sendTransactionAsync(this._coinbase, tokenSupply, {
from: this._coinbase,
});
await this.zeroEx.awaitTransactionMinedAsync(txHash);
await this._zeroEx.awaitTransactionMinedAsync(txHash);
}
}
}
@@ -60,7 +60,7 @@ export class FillScenarios {
fillableAmount: BigNumber,
feeRecepient: string, expirationUnixTimestampSec?: BigNumber,
): Promise<SignedOrder> {
return this.createAsymmetricFillableSignedOrderWithFeesAsync(
return this._createAsymmetricFillableSignedOrderWithFeesAsync(
makerTokenAddress, takerTokenAddress, makerFee, takerFee, makerAddress, takerAddress,
fillableAmount, fillableAmount, feeRecepient, expirationUnixTimestampSec,
);
@@ -72,7 +72,7 @@ export class FillScenarios {
const makerFee = new BigNumber(0);
const takerFee = new BigNumber(0);
const feeRecepient = constants.NULL_ADDRESS;
return this.createAsymmetricFillableSignedOrderWithFeesAsync(
return this._createAsymmetricFillableSignedOrderWithFeesAsync(
makerTokenAddress, takerTokenAddress, makerFee, takerFee, makerAddress, takerAddress,
makerFillableAmount, takerFillableAmount, feeRecepient, expirationUnixTimestampSec,
);
@@ -80,18 +80,18 @@ export class FillScenarios {
public async createPartiallyFilledSignedOrderAsync(makerTokenAddress: string, takerTokenAddress: string,
takerAddress: string, fillableAmount: BigNumber,
partialFillAmount: BigNumber) {
const [makerAddress] = this.userAddresses;
const [makerAddress] = this._userAddresses;
const signedOrder = await this.createAsymmetricFillableSignedOrderAsync(
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
fillableAmount, fillableAmount,
);
const shouldThrowOnInsufficientBalanceOrAllowance = false;
await this.zeroEx.exchange.fillOrderAsync(
await this._zeroEx.exchange.fillOrderAsync(
signedOrder, partialFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
);
return signedOrder;
}
private async createAsymmetricFillableSignedOrderWithFeesAsync(
private async _createAsymmetricFillableSignedOrderWithFeesAsync(
makerTokenAddress: string, takerTokenAddress: string,
makerFee: BigNumber, takerFee: BigNumber,
makerAddress: string, takerAddress: string,
@@ -99,39 +99,39 @@ export class FillScenarios {
feeRecepient: string, expirationUnixTimestampSec?: BigNumber): Promise<SignedOrder> {
await Promise.all([
this.increaseBalanceAndAllowanceAsync(makerTokenAddress, makerAddress, makerFillableAmount),
this.increaseBalanceAndAllowanceAsync(takerTokenAddress, takerAddress, takerFillableAmount),
this._increaseBalanceAndAllowanceAsync(makerTokenAddress, makerAddress, makerFillableAmount),
this._increaseBalanceAndAllowanceAsync(takerTokenAddress, takerAddress, takerFillableAmount),
]);
await Promise.all([
this.increaseBalanceAndAllowanceAsync(this.zrxTokenAddress, makerAddress, makerFee),
this.increaseBalanceAndAllowanceAsync(this.zrxTokenAddress, takerAddress, takerFee),
this._increaseBalanceAndAllowanceAsync(this._zrxTokenAddress, makerAddress, makerFee),
this._increaseBalanceAndAllowanceAsync(this._zrxTokenAddress, takerAddress, takerFee),
]);
const signedOrder = await orderFactory.createSignedOrderAsync(this.zeroEx,
const signedOrder = await orderFactory.createSignedOrderAsync(this._zeroEx,
makerAddress, takerAddress, makerFee, takerFee,
makerFillableAmount, makerTokenAddress, takerFillableAmount, takerTokenAddress,
this.exchangeContractAddress, feeRecepient, expirationUnixTimestampSec);
this._exchangeContractAddress, feeRecepient, expirationUnixTimestampSec);
return signedOrder;
}
private async increaseBalanceAndAllowanceAsync(
private async _increaseBalanceAndAllowanceAsync(
tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
if (amount.isZero() || address === ZeroEx.NULL_ADDRESS) {
return; // noop
}
await Promise.all([
this.increaseBalanceAsync(tokenAddress, address, amount),
this.increaseAllowanceAsync(tokenAddress, address, amount),
this._increaseBalanceAsync(tokenAddress, address, amount),
this._increaseAllowanceAsync(tokenAddress, address, amount),
]);
}
private async increaseBalanceAsync(
private async _increaseBalanceAsync(
tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
await this.zeroEx.token.transferAsync(tokenAddress, this.coinbase, address, amount);
await this._zeroEx.token.transferAsync(tokenAddress, this._coinbase, address, amount);
}
private async increaseAllowanceAsync(
private async _increaseAllowanceAsync(
tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
const oldMakerAllowance = await this.zeroEx.token.getProxyAllowanceAsync(tokenAddress, address);
const oldMakerAllowance = await this._zeroEx.token.getProxyAllowanceAsync(tokenAddress, address);
const newMakerAllowance = oldMakerAllowance.plus(amount);
await this.zeroEx.token.setProxyAllowanceAsync(
await this._zeroEx.token.setProxyAllowanceAsync(
tokenAddress, address, newMakerAllowance,
);
}

View File

@@ -9,16 +9,16 @@ import {JSONRPCPayload} from '../../../src/types';
* Source: https://github.com/MetaMask/provider-engine/blob/master/subproviders/subprovider.js
*/
export class FakeGasEstimateSubprovider {
private constantGasAmount: number;
private _constantGasAmount: number;
constructor(constantGasAmount: number) {
this.constantGasAmount = constantGasAmount;
this._constantGasAmount = constantGasAmount;
}
// This method needs to be here to satisfy the interface but linter wants it to be static.
// tslint:disable-next-line:prefer-function-over-method
public handleRequest(payload: JSONRPCPayload, next: () => void, end: (err: Error|null, result: any) => void) {
switch (payload.method) {
case 'eth_estimateGas':
end(null, this.constantGasAmount);
end(null, this._constantGasAmount);
return;
default:

View File

@@ -6,26 +6,26 @@ const PROTOCOL_TOKEN_SYMBOL = 'ZRX';
const WETH_TOKEN_SYMBOL = 'WETH';
export class TokenUtils {
private tokens: Token[];
private _tokens: Token[];
constructor(tokens: Token[]) {
this.tokens = tokens;
this._tokens = tokens;
}
public getProtocolTokenOrThrow(): Token {
const zrxToken = _.find(this.tokens, {symbol: PROTOCOL_TOKEN_SYMBOL});
const zrxToken = _.find(this._tokens, {symbol: PROTOCOL_TOKEN_SYMBOL});
if (_.isUndefined(zrxToken)) {
throw new Error(InternalZeroExError.ZrxNotInTokenRegistry);
}
return zrxToken;
}
public getWethTokenOrThrow(): Token {
const wethToken = _.find(this.tokens, {symbol: WETH_TOKEN_SYMBOL});
const wethToken = _.find(this._tokens, {symbol: WETH_TOKEN_SYMBOL});
if (_.isUndefined(wethToken)) {
throw new Error(InternalZeroExError.WethNotInTokenRegistry);
}
return wethToken;
}
public getDummyTokens(): Token[] {
const dummyTokens = _.filter(this.tokens, token => {
const dummyTokens = _.filter(this._tokens, token => {
return !_.includes([PROTOCOL_TOKEN_SYMBOL, WETH_TOKEN_SYMBOL], token.symbol);
});
return dummyTokens;

View File

@@ -5,9 +5,9 @@ It's heavily inspired by [Geth abigen](https://github.com/ethereum/go-ethereum/w
You can write your custom handlebars templates which will allow you to seamlessly integrate the generated code into your existing codebase with existing conventions.
For an example of the generated [wrapper files](https://github.com/0xProject/0x.js/tree/development/packages/0x.js/src/contract_wrappers/generated) check out 0x.js.
[Here](https://github.com/0xProject/0x.js/tree/development/packages/0x.js/src/contract_templates) are the templates used to generate those files.
[Here](https://github.com/0xProject/0x.js/tree/development/packages/0x.js/contract_templates) are the templates used to generate those files.
## Instalation
## Installation
`yarn add -g @0xproject/abi-gen`
## Usage
```
@@ -29,8 +29,8 @@ We could've just used `--abiGlob 'src/artifacts/*.json` but we wanted to exclude
The abi file should be either a [Truffle](http://truffleframework.com/) contract artifact (a JSON object with an abi key) or a JSON abi array.
## How to write custom templates?
The best way to get started is to copy [0x.js templates](https://github.com/0xProject/0x.js/tree/development/packages/0x.js/src/contract_templates) and start adjusting them for your needs.
We use [handlebars](handlebarsjs.com) template engine under the hood.
The best way to get started is to copy [0x.js templates](https://github.com/0xProject/0x.js/tree/development/packages/0x.js/contract_templates) and start adjusting them for your needs.
We use [handlebars](http://handlebarsjs.com/) template engine under the hood.
You need to have a master template called `contract.mustache`. it will be used to generate each contract wrapper. Although - you don't need and probably shouldn't write all your logic in a single template file. You can write [partial templates](http://handlebarsjs.com/partials.html) and as long as they are within a partials folder - they will be registered and available.
## Which data/context do I get in my templates?
For now you don't get much on top of methods abi, some useful helpers and a contract name because it was enough for our use-case, but if you need something else - create a PR.

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/abi-gen",
"version": "0.0.2",
"version": "0.0.4",
"description": "Generate contract wrappers from ABI and handlebars templates",
"main": "lib/index.js",
"types": "lib/index.d.ts",
@@ -33,7 +33,7 @@
"yargs": "^10.0.3"
},
"devDependencies": {
"@0xproject/tslint-config": "^0.2.1",
"@0xproject/tslint-config": "^0.4.0",
"@types/glob": "^5.0.33",
"@types/handlebars": "^4.0.36",
"@types/mkdirp": "^0.5.1",

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/assert",
"version": "0.0.7",
"version": "0.0.9",
"description": "Provides a standard way of performing type and schema validation across 0x projects",
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
@@ -23,7 +23,7 @@
},
"homepage": "https://github.com/0xProject/0x.js/packages/assert/README.md",
"devDependencies": {
"@0xproject/tslint-config": "^0.2.1",
"@0xproject/tslint-config": "^0.4.0",
"@types/lodash": "^4.14.86",
"@types/mocha": "^2.2.42",
"@types/valid-url": "^1.0.2",
@@ -37,8 +37,8 @@
"typescript": "~2.6.1"
},
"dependencies": {
"@0xproject/json-schemas": "^0.6.10",
"@0xproject/utils": "^0.1.0",
"@0xproject/json-schemas": "^0.7.1",
"@0xproject/utils": "^0.1.2",
"bignumber.js": "~4.1.0",
"lodash": "^4.17.4",
"valid-url": "^1.0.9"

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/connect",
"version": "0.3.0",
"version": "0.3.2",
"description": "A javascript library for interacting with the standard relayer api",
"keywords": [
"connect",
@@ -36,8 +36,9 @@
},
"homepage": "https://github.com/0xProject/0x.js/packages/connect/README.md",
"dependencies": {
"@0xproject/assert": "^0.0.7",
"@0xproject/json-schemas": "^0.6.10",
"@0xproject/assert": "^0.0.9",
"@0xproject/json-schemas": "^0.7.1",
"@0xproject/utils": "^0.1.2",
"bignumber.js": "~4.1.0",
"isomorphic-fetch": "^2.2.1",
"lodash": "^4.17.4",
@@ -45,7 +46,7 @@
"websocket": "^1.0.25"
},
"devDependencies": {
"@0xproject/tslint-config": "^0.2.1",
"@0xproject/tslint-config": "^0.4.0",
"@types/fetch-mock": "^5.12.1",
"@types/lodash": "^4.14.86",
"@types/mocha": "^2.2.42",

View File

@@ -1,6 +1,5 @@
import {assert} from '@0xproject/assert';
import {schemas} from '@0xproject/json-schemas';
import {BigNumber} from 'bignumber.js';
import 'isomorphic-fetch';
import * as _ from 'lodash';
import * as queryString from 'query-string';
@@ -21,17 +20,12 @@ import {
} from './types';
import {typeConverters} from './utils/type_converters';
// TODO: move this and bigNumberConfigs in the 0x.js package into one place
BigNumber.config({
EXPONENTIAL_AT: 1000,
});
/**
* This class includes all the functionality related to interacting with a set of HTTP endpoints
* that implement the standard relayer API v0
*/
export class HttpClient implements Client {
private apiEndpointUrl: string;
private _apiEndpointUrl: string;
/**
* Instantiates a new HttpClient instance
* @param url The relayer API base HTTP url you would like to interact with
@@ -39,7 +33,7 @@ export class HttpClient implements Client {
*/
constructor(url: string) {
assert.isHttpUrl('url', url);
this.apiEndpointUrl = url;
this._apiEndpointUrl = url;
}
/**
* Retrieve token pair info from the API
@@ -152,7 +146,7 @@ export class HttpClient implements Client {
const stringifiedParams = queryString.stringify(params);
query = `?${stringifiedParams}`;
}
const url = `${this.apiEndpointUrl}/v0${path}${query}`;
const url = `${this._apiEndpointUrl}/v0${path}${query}`;
const headers = new Headers({
'content-type': 'application/json',
});

View File

@@ -1,3 +1,8 @@
import {bigNumberConfigs} from '@0xproject/utils';
// Customize our BigNumber instances
bigNumberConfigs.configure();
export {HttpClient} from './http_client';
export {WebSocketOrderbookChannel} from './ws_orderbook_channel';
export {

View File

@@ -18,10 +18,10 @@ import {orderbookChannelMessageParsers} from './utils/orderbook_channel_message_
* that implements the standard relayer API v0
*/
export class WebSocketOrderbookChannel implements OrderbookChannel {
private apiEndpointUrl: string;
private client: WebSocket.client;
private connectionIfExists?: WebSocket.connection;
private subscriptionCounter = 0;
private _apiEndpointUrl: string;
private _client: WebSocket.client;
private _connectionIfExists?: WebSocket.connection;
private _subscriptionCounter = 0;
/**
* Instantiates a new WebSocketOrderbookChannel instance
* @param url The relayer API base WS url you would like to interact with
@@ -29,8 +29,8 @@ export class WebSocketOrderbookChannel implements OrderbookChannel {
*/
constructor(url: string) {
assert.isUri('url', url);
this.apiEndpointUrl = url;
this.client = new WebSocket.client();
this._apiEndpointUrl = url;
this._client = new WebSocket.client();
}
/**
* Subscribe to orderbook snapshots and updates from the websocket
@@ -46,11 +46,11 @@ export class WebSocketOrderbookChannel implements OrderbookChannel {
assert.isFunction('handler.onUpdate', _.get(handler, 'onUpdate'));
assert.isFunction('handler.onError', _.get(handler, 'onError'));
assert.isFunction('handler.onClose', _.get(handler, 'onClose'));
this.subscriptionCounter += 1;
this._subscriptionCounter += 1;
const subscribeMessage = {
type: 'subscribe',
channel: 'orderbook',
requestId: this.subscriptionCounter,
requestId: this._subscriptionCounter,
payload: subscriptionOpts,
};
this._getConnection((error, connection) => {
@@ -74,22 +74,22 @@ export class WebSocketOrderbookChannel implements OrderbookChannel {
* Close the websocket and stop receiving updates
*/
public close() {
if (!_.isUndefined(this.connectionIfExists)) {
this.connectionIfExists.close();
if (!_.isUndefined(this._connectionIfExists)) {
this._connectionIfExists.close();
}
}
private _getConnection(callback: (error?: Error, connection?: WebSocket.connection) => void) {
if (!_.isUndefined(this.connectionIfExists) && this.connectionIfExists.connected) {
callback(undefined, this.connectionIfExists);
if (!_.isUndefined(this._connectionIfExists) && this._connectionIfExists.connected) {
callback(undefined, this._connectionIfExists);
} else {
this.client.on(WebsocketClientEventType.Connect, connection => {
this.connectionIfExists = connection;
callback(undefined, this.connectionIfExists);
this._client.on(WebsocketClientEventType.Connect, connection => {
this._connectionIfExists = connection;
callback(undefined, this._connectionIfExists);
});
this.client.on(WebsocketClientEventType.ConnectFailed, error => {
this._client.on(WebsocketClientEventType.ConnectFailed, error => {
callback(error, undefined);
});
this.client.connect(this.apiEndpointUrl);
this._client.connect(this._apiEndpointUrl);
}
}
private _handleWebSocketMessage(requestId: number, subscriptionOpts: OrderbookChannelSubscriptionOpts,

View File

@@ -1,51 +1,65 @@
Contracts
-----
--------
## Useful 0x Wiki Articles
Smart contracts that implement the 0x protocol.
* [Architecture](https://0xproject.com/wiki#Architecture)
* [Contract Interactions](https://0xproject.com/wiki#Contract-Interactions)
* [Contract deployed addresses](https://0xproject.com/wiki#Deployed-Addresses)
* [0x Protocol Message Format](https://0xproject.com/wiki#Message-Format)
* [Bug Bounty Program](https://0xproject.com/wiki#Bug-Bounty)
## Usage
## Setup
### Installing Dependencies
Install [Node](https://nodejs.org/en/download/releases/)
Install [yarn](https://yarnpkg.com/lang/en/docs/install/) in order to install the project dependencies more deterministically.
Install project dependencies:
```
yarn
```
### Running Tests
Start Testrpc
```
yarn testrpc
```
Run tests
```
yarn test
```
* [Docs](https://0xproject.com/docs/contracts)
* [Overview of 0x protocol architecture](https://0xproject.com/wiki#Architecture)
* [0x smart contract interactions](https://0xproject.com/wiki#Contract-Interactions)
* [Deployed smart contract addresses](https://0xproject.com/wiki#Deployed-Addresses)
* [0x protocol message format](https://0xproject.com/wiki#Message-Format)
## Contributing
0x protocol is intended to serve as an open technical standard for EVM blockchains and we strongly encourage our community members to help us make improvements and to determine the future direction of the protocol. To report bugs within the 0x smart contracts or unit tests, please create an issue in this repository.
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
### ZEIPs
Significant changes to 0x protocol's smart contracts, architecture, message format or functionality should be proposed in the [0x Improvement Proposals (ZEIPs)](https://github.com/0xProject/ZEIPs) repository. Follow the contribution guidelines provided therein.
For proposals regarding the 0x protocol's smart contract architecture, message format, or additional functionality, go to the [0x Improvement Proposals (ZEIPs)](https://github.com/0xProject/ZEIPs) repository and follow the contribution guidelines provided therein.
### Coding conventions
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
We use a custom set of [TSLint](https://palantir.github.io/tslint/) rules to enforce our coding conventions.
### Install Dependencies
In order to see style violation errors, install a tslinter for your text editor. e.g Atom's [atom-typescript](https://atom.io/packages/atom-typescript).
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
```bash
yarn config set workspaces-experimental true
```
Then install dependencies
```bash
yarn install
```
### Build
```bash
yarn build
```
### Clean
```bash
yarn clean
```
### Lint
```bash
yarn lint
```
### Run Tests
Before running the tests, you will need to spin up a [TestRPC](https://www.npmjs.com/package/ethereumjs-testrpc) instance.
In a separate terminal, start TestRPC (a convenience command is provided as part of the [0x.js monorepo](https://github.com/0xProject/0x.js))
```bash
cd ../..
yarn testrpc
```
Then in your main terminal run
```bash
yarn test
```

View File

@@ -19,18 +19,18 @@ import {utils} from './utils/utils';
const SOLIDITY_FILE_EXTENSION = '.sol';
export class Compiler {
private contractsDir: string;
private networkId: number;
private optimizerEnabled: number;
private artifactsDir: string;
private contractSourcesIfExists?: ContractSources;
private solcErrors: Set<string>;
private _contractsDir: string;
private _networkId: number;
private _optimizerEnabled: number;
private _artifactsDir: string;
private _contractSourcesIfExists?: ContractSources;
private _solcErrors: Set<string>;
/**
* Recursively retrieves Solidity source code from directory.
* @param dirPath Directory to search.
* @return Mapping of contract name to contract source.
*/
private static async getContractSourcesAsync(dirPath: string): Promise<ContractSources> {
private static async _getContractSourcesAsync(dirPath: string): Promise<ContractSources> {
let dirContents: string[] = [];
try {
dirContents = await fsWrapper.readdirAsync(dirPath);
@@ -52,7 +52,7 @@ export class Compiler {
}
} else {
try {
const nestedSources = await Compiler.getContractSourcesAsync(contentPath);
const nestedSources = await Compiler._getContractSourcesAsync(contentPath);
sources = {
...sources,
...nestedSources,
@@ -69,7 +69,7 @@ export class Compiler {
* @param source Source code of contract.
* @return Solc compiler version.
*/
private static parseSolidityVersion(source: string): string {
private static _parseSolidityVersion(source: string): string {
const solcVersionMatch = source.match(/(?:solidity\s\^?)([0-9]{1,2}[.][0-9]{1,2}[.][0-9]{1,2})/);
if (_.isNull(solcVersionMatch)) {
throw new Error('Could not find Solidity version in source');
@@ -85,7 +85,7 @@ export class Compiler {
* @param errMsg An error message from the compiled output.
* @return The error message with directories truncated from the contract path.
*/
private static getNormalizedErrMsg(errMsg: string): string {
private static _getNormalizedErrMsg(errMsg: string): string {
const errPathMatch = errMsg.match(/(.*\.sol)/);
if (_.isNull(errPathMatch)) {
throw new Error('Could not find a path in error message');
@@ -101,26 +101,26 @@ export class Compiler {
* @return An instance of the Compiler class.
*/
constructor(opts: CompilerOptions) {
this.contractsDir = opts.contractsDir;
this.networkId = opts.networkId;
this.optimizerEnabled = opts.optimizerEnabled;
this.artifactsDir = opts.artifactsDir;
this.solcErrors = new Set();
this._contractsDir = opts.contractsDir;
this._networkId = opts.networkId;
this._optimizerEnabled = opts.optimizerEnabled;
this._artifactsDir = opts.artifactsDir;
this._solcErrors = new Set();
}
/**
* Compiles all Solidity files found in contractsDir and writes JSON artifacts to artifactsDir.
*/
public async compileAllAsync(): Promise<void> {
await this.createArtifactsDirIfDoesNotExistAsync();
this.contractSourcesIfExists = await Compiler.getContractSourcesAsync(this.contractsDir);
await this._createArtifactsDirIfDoesNotExistAsync();
this._contractSourcesIfExists = await Compiler._getContractSourcesAsync(this._contractsDir);
const contractBaseNames = _.keys(this.contractSourcesIfExists);
const contractBaseNames = _.keys(this._contractSourcesIfExists);
const compiledContractPromises = _.map(contractBaseNames, async (contractBaseName: string): Promise<void> => {
return this.compileContractAsync(contractBaseName);
return this._compileContractAsync(contractBaseName);
});
await Promise.all(compiledContractPromises);
this.solcErrors.forEach(errMsg => {
this._solcErrors.forEach(errMsg => {
utils.consoleLog(errMsg);
});
}
@@ -128,14 +128,14 @@ export class Compiler {
* Compiles contract and saves artifact to artifactsDir.
* @param contractBaseName Name of contract with '.sol' extension.
*/
private async compileContractAsync(contractBaseName: string): Promise<void> {
if (_.isUndefined(this.contractSourcesIfExists)) {
private async _compileContractAsync(contractBaseName: string): Promise<void> {
if (_.isUndefined(this._contractSourcesIfExists)) {
throw new Error('Contract sources not yet initialized');
}
const source = this.contractSourcesIfExists[contractBaseName];
const source = this._contractSourcesIfExists[contractBaseName];
const contractName = path.basename(contractBaseName, SOLIDITY_FILE_EXTENSION);
const currentArtifactPath = `${this.artifactsDir}/${contractName}.json`;
const currentArtifactPath = `${this._artifactsDir}/${contractName}.json`;
const sourceHash = `0x${ethUtil.sha3(source).toString('hex')}`;
let currentArtifactString: string;
@@ -149,10 +149,10 @@ export class Compiler {
currentArtifactString = await fsWrapper.readFileAsync(currentArtifactPath, opts);
currentArtifact = JSON.parse(currentArtifactString);
oldNetworks = currentArtifact.networks;
const oldNetwork: ContractData = oldNetworks[this.networkId];
const oldNetwork: ContractData = oldNetworks[this._networkId];
shouldCompile = _.isUndefined(oldNetwork) ||
oldNetwork.keccak256 !== sourceHash ||
oldNetwork.optimizer_enabled !== this.optimizerEnabled;
oldNetwork.optimizer_enabled !== this._optimizerEnabled;
} catch (err) {
shouldCompile = true;
}
@@ -164,7 +164,7 @@ export class Compiler {
const input = {
[contractBaseName]: source,
};
const solcVersion = Compiler.parseSolidityVersion(source);
const solcVersion = Compiler._parseSolidityVersion(source);
const fullSolcVersion = binPaths[solcVersion];
const solcBinPath = `./../solc/solc_bin/${fullSolcVersion}`;
const solcBin = require(solcBinPath);
@@ -175,13 +175,13 @@ export class Compiler {
sources: input,
};
const compiled = solcInstance.compile(sourcesToCompile,
this.optimizerEnabled,
this.findImportsIfSourcesExist.bind(this));
this._optimizerEnabled,
this._findImportsIfSourcesExist.bind(this));
if (!_.isUndefined(compiled.errors)) {
_.each(compiled.errors, errMsg => {
const normalizedErrMsg = Compiler.getNormalizedErrMsg(errMsg);
this.solcErrors.add(normalizedErrMsg);
const normalizedErrMsg = Compiler._getNormalizedErrMsg(errMsg);
this._solcErrors.add(normalizedErrMsg);
});
}
@@ -192,7 +192,7 @@ export class Compiler {
const contractData: ContractData = {
solc_version: solcVersion,
keccak256: sourceHash,
optimizer_enabled: this.optimizerEnabled,
optimizer_enabled: this._optimizerEnabled,
abi,
unlinked_binary,
updated_at,
@@ -204,14 +204,14 @@ export class Compiler {
...currentArtifact,
networks: {
...oldNetworks,
[this.networkId]: contractData,
[this._networkId]: contractData,
},
};
} else {
newArtifact = {
contract_name: contractName,
networks: {
[this.networkId]: contractData,
[this._networkId]: contractData,
},
};
}
@@ -226,12 +226,12 @@ export class Compiler {
* @param importPath Path to an imported dependency.
* @return Import contents object containing source code of dependency.
*/
private findImportsIfSourcesExist(importPath: string): ImportContents {
if (_.isUndefined(this.contractSourcesIfExists)) {
private _findImportsIfSourcesExist(importPath: string): ImportContents {
if (_.isUndefined(this._contractSourcesIfExists)) {
throw new Error('Contract sources not yet initialized');
}
const contractBaseName = path.basename(importPath);
const source = this.contractSourcesIfExists[contractBaseName];
const source = this._contractSourcesIfExists[contractBaseName];
const importContents: ImportContents = {
contents: source,
};
@@ -240,10 +240,10 @@ export class Compiler {
/**
* Creates the artifacts directory if it does not already exist.
*/
private async createArtifactsDirIfDoesNotExistAsync(): Promise<void> {
if (!fsWrapper.doesPathExistSync(this.artifactsDir)) {
private async _createArtifactsDirIfDoesNotExistAsync(): Promise<void> {
if (!fsWrapper.doesPathExistSync(this._artifactsDir)) {
utils.consoleLog('Creating artifacts directory...');
await fsWrapper.mkdirAsync(this.artifactsDir);
await fsWrapper.mkdirAsync(this._artifactsDir);
}
}
}

View File

@@ -18,19 +18,19 @@ const EXTRA_GAS = 200000;
export class Deployer {
public web3Wrapper: Web3Wrapper;
private artifactsDir: string;
private jsonrpcPort: number;
private networkId: number;
private defaults: Partial<TxData>;
private _artifactsDir: string;
private _jsonrpcPort: number;
private _networkId: number;
private _defaults: Partial<TxData>;
constructor(opts: DeployerOptions) {
this.artifactsDir = opts.artifactsDir;
this.jsonrpcPort = opts.jsonrpcPort;
this.networkId = opts.networkId;
const jsonrpcUrl = `http://localhost:${this.jsonrpcPort}`;
this._artifactsDir = opts.artifactsDir;
this._jsonrpcPort = opts.jsonrpcPort;
this._networkId = opts.networkId;
const jsonrpcUrl = `http://localhost:${this._jsonrpcPort}`;
const web3Provider = new Web3.providers.HttpProvider(jsonrpcUrl);
this.defaults = opts.defaults;
this.web3Wrapper = new Web3Wrapper(web3Provider, this.defaults);
this._defaults = opts.defaults;
this.web3Wrapper = new Web3Wrapper(web3Provider, this._defaults);
}
/**
* Loads contract artifact and deploys contract with given arguments.
@@ -39,21 +39,21 @@ export class Deployer {
* @return Deployed contract instance.
*/
public async deployAsync(contractName: string, args: any[] = []): Promise<Web3.ContractInstance> {
const contractArtifact: ContractArtifact = this.loadContractArtifactIfExists(contractName);
const contractData: ContractData = this.getContractDataFromArtifactIfExists(contractArtifact);
const contractArtifact: ContractArtifact = this._loadContractArtifactIfExists(contractName);
const contractData: ContractData = this._getContractDataFromArtifactIfExists(contractArtifact);
const data = contractData.unlinked_binary;
const from = await this.getFromAddressAsync();
const gas = await this.getAllowableGasEstimateAsync(data);
const from = await this._getFromAddressAsync();
const gas = await this._getAllowableGasEstimateAsync(data);
const txData = {
gasPrice: this.defaults.gasPrice,
gasPrice: this._defaults.gasPrice,
from,
data,
gas,
};
const abi = contractData.abi;
const web3ContractInstance = await this.deployFromAbiAsync(abi, args, txData);
const web3ContractInstance = await this._deployFromAbiAsync(abi, args, txData);
utils.consoleLog(`${contractName}.sol successfully deployed at ${web3ContractInstance.address}`);
const contractInstance = new Contract(web3ContractInstance, this.defaults);
const contractInstance = new Contract(web3ContractInstance, this._defaults);
return contractInstance;
}
/**
@@ -64,7 +64,7 @@ export class Deployer {
*/
public async deployAndSaveAsync(contractName: string, args: any[] = []): Promise<Web3.ContractInstance> {
const contractInstance = await this.deployAsync(contractName, args);
await this.saveContractDataToArtifactAsync(contractName, contractInstance.address, args);
await this._saveContractDataToArtifactAsync(contractName, contractInstance.address, args);
return contractInstance;
}
/**
@@ -74,7 +74,7 @@ export class Deployer {
* @param txData Tx options used for deployment.
* @return Promise that resolves to a web3 contract instance.
*/
private async deployFromAbiAsync(abi: Web3.ContractAbi, args: any[], txData: Web3.TxData): Promise<any> {
private async _deployFromAbiAsync(abi: Web3.ContractAbi, args: any[], txData: Web3.TxData): Promise<any> {
const contract: Web3.Contract<Web3.ContractInstance> = this.web3Wrapper.getContractFromAbi(abi);
const deployPromise = new Promise((resolve, reject) => {
/**
@@ -99,10 +99,10 @@ export class Deployer {
* @param contractAddress Contract address to save to artifact.
* @param args Contract constructor arguments that will be encoded and saved to artifact.
*/
private async saveContractDataToArtifactAsync(contractName: string,
contractAddress: string, args: any[]): Promise<void> {
const contractArtifact: ContractArtifact = this.loadContractArtifactIfExists(contractName);
const contractData: ContractData = this.getContractDataFromArtifactIfExists(contractArtifact);
private async _saveContractDataToArtifactAsync(contractName: string,
contractAddress: string, args: any[]): Promise<void> {
const contractArtifact: ContractArtifact = this._loadContractArtifactIfExists(contractName);
const contractData: ContractData = this._getContractDataFromArtifactIfExists(contractArtifact);
const abi = contractData.abi;
const encodedConstructorArgs = encoder.encodeConstructorArgsFromAbi(args, abi);
const newContractData = {
@@ -114,11 +114,11 @@ export class Deployer {
...contractArtifact,
networks: {
...contractArtifact.networks,
[this.networkId]: newContractData,
[this._networkId]: newContractData,
},
};
const artifactString = utils.stringifyWithFormatting(newArtifact);
const artifactPath = `${this.artifactsDir}/${contractName}.json`;
const artifactPath = `${this._artifactsDir}/${contractName}.json`;
await fsWrapper.writeFileAsync(artifactPath, artifactString);
}
/**
@@ -126,8 +126,8 @@ export class Deployer {
* @param contractName Name of the contract, without the extension.
* @return The contract artifact.
*/
private loadContractArtifactIfExists(contractName: string): ContractArtifact {
const artifactPath = `${this.artifactsDir}/${contractName}.json`;
private _loadContractArtifactIfExists(contractName: string): ContractArtifact {
const artifactPath = `${this._artifactsDir}/${contractName}.json`;
try {
const contractArtifact: ContractArtifact = require(artifactPath);
return contractArtifact;
@@ -140,8 +140,8 @@ export class Deployer {
* @param contractArtifact The contract artifact.
* @return Network specific contract data.
*/
private getContractDataFromArtifactIfExists(contractArtifact: ContractArtifact): ContractData {
const contractData = contractArtifact.networks[this.networkId];
private _getContractDataFromArtifactIfExists(contractArtifact: ContractArtifact): ContractData {
const contractData = contractArtifact.networks[this._networkId];
if (_.isUndefined(contractData)) {
throw new Error(`Data not found in artifact for contract: ${contractArtifact.contract_name}`);
}
@@ -151,13 +151,13 @@ export class Deployer {
* Gets the address to use for sending a transaction.
* @return The default from address. If not specified, returns the first address accessible by web3.
*/
private async getFromAddressAsync(): Promise<string> {
private async _getFromAddressAsync(): Promise<string> {
let from: string;
if (_.isUndefined(this.defaults.from)) {
if (_.isUndefined(this._defaults.from)) {
const accounts = await this.web3Wrapper.getAvailableAddressesAsync();
from = accounts[0];
} else {
from = this.defaults.from;
from = this._defaults.from;
}
return from;
}
@@ -167,7 +167,7 @@ export class Deployer {
* @param data Bytecode to estimate gas for.
* @return Gas estimate for transaction data.
*/
private async getAllowableGasEstimateAsync(data: string): Promise<number> {
private async _getAllowableGasEstimateAsync(data: string): Promise<number> {
const block = await this.web3Wrapper.getBlockAsync('latest');
let gas: number;
try {

View File

@@ -8,55 +8,55 @@ import {AbiType} from './types';
export class Contract implements Web3.ContractInstance {
public address: string;
public abi: Web3.ContractAbi;
private contract: Web3.ContractInstance;
private defaults: Partial<Web3.TxData>;
private validator: SchemaValidator;
private _contract: Web3.ContractInstance;
private _defaults: Partial<Web3.TxData>;
private _validator: SchemaValidator;
// This class instance is going to be populated with functions and events depending on the ABI
// and we don't know their types in advance
[name: string]: any;
constructor(web3ContractInstance: Web3.ContractInstance, defaults: Partial<Web3.TxData>) {
this.contract = web3ContractInstance;
this._contract = web3ContractInstance;
this.address = web3ContractInstance.address;
this.abi = web3ContractInstance.abi;
this.defaults = defaults;
this.populateEvents();
this.populateFunctions();
this.validator = new SchemaValidator();
this._defaults = defaults;
this._populateEvents();
this._populateFunctions();
this._validator = new SchemaValidator();
}
private populateFunctions(): void {
private _populateFunctions(): void {
const functionsAbi = _.filter(this.abi, abiPart => abiPart.type === AbiType.Function);
_.forEach(functionsAbi, (functionAbi: Web3.MethodAbi) => {
if (functionAbi.constant) {
const cbStyleCallFunction = this.contract[functionAbi.name].call;
const cbStyleCallFunction = this._contract[functionAbi.name].call;
this[functionAbi.name] = {
callAsync: promisify(cbStyleCallFunction, this.contract),
callAsync: promisify(cbStyleCallFunction, this._contract),
};
} else {
const cbStyleFunction = this.contract[functionAbi.name];
const cbStyleEstimateGasFunction = this.contract[functionAbi.name].estimateGas;
const cbStyleFunction = this._contract[functionAbi.name];
const cbStyleEstimateGasFunction = this._contract[functionAbi.name].estimateGas;
this[functionAbi.name] = {
estimateGasAsync: promisify(cbStyleEstimateGasFunction, this.contract),
sendTransactionAsync: this.promisifyWithDefaultParams(cbStyleFunction),
estimateGasAsync: promisify(cbStyleEstimateGasFunction, this._contract),
sendTransactionAsync: this._promisifyWithDefaultParams(cbStyleFunction),
};
}
});
}
private populateEvents(): void {
private _populateEvents(): void {
const eventsAbi = _.filter(this.abi, abiPart => abiPart.type === AbiType.Event);
_.forEach(eventsAbi, (eventAbi: Web3.EventAbi) => {
this[eventAbi.name] = this.contract[eventAbi.name];
this[eventAbi.name] = this._contract[eventAbi.name];
});
}
private promisifyWithDefaultParams(fn: (...args: any[]) => void): (...args: any[]) => Promise<any> {
private _promisifyWithDefaultParams(fn: (...args: any[]) => void): (...args: any[]) => Promise<any> {
const promisifiedWithDefaultParams = async (...args: any[]) => {
const promise = new Promise((resolve, reject) => {
const lastArg = args[args.length - 1];
let txData: Partial<Web3.TxData> = {};
if (this.isTxData(lastArg)) {
if (this._isTxData(lastArg)) {
txData = args.pop();
}
txData = {
...this.defaults,
...this._defaults,
...txData,
};
const callback = (err: Error, data: any) => {
@@ -68,14 +68,14 @@ export class Contract implements Web3.ContractInstance {
};
args.push(txData);
args.push(callback);
fn.apply(this.contract, args);
fn.apply(this._contract, args);
});
return promise;
};
return promisifiedWithDefaultParams;
}
private isTxData(lastArg: any): boolean {
const isValid = this.validator.isValid(lastArg, schemas.txDataSchema);
private _isTxData(lastArg: any): boolean {
const isValid = this._validator.isValid(lastArg, schemas.txDataSchema);
return isValid;
}
}

View File

@@ -1,7 +1,7 @@
{
"private": true,
"name": "contracts",
"version": "2.0.0",
"version": "2.1.1",
"description": "Smart contract components of 0x protocol",
"main": "index.js",
"directories": {
@@ -29,9 +29,9 @@
},
"homepage": "https://github.com/0xProject/0x.js/packages/contracts/README.md",
"devDependencies": {
"@0xproject/dev-utils": "^0.0.1",
"@0xproject/tslint-config": "^0.2.1",
"@0xproject/types": "^0.1.0",
"@0xproject/dev-utils": "^0.0.3",
"@0xproject/tslint-config": "^0.4.0",
"@0xproject/types": "^0.1.2",
"@types/bluebird": "^3.5.3",
"@types/lodash": "^4.14.86",
"@types/node": "^8.0.53",
@@ -55,10 +55,10 @@
"yargs": "^10.0.3"
},
"dependencies": {
"0x.js": "~0.27.2",
"@0xproject/json-schemas": "^0.6.10",
"@0xproject/utils": "^0.1.0",
"@0xproject/web3-wrapper": "^0.1.0",
"0x.js": "^0.29.0",
"@0xproject/json-schemas": "^0.7.1",
"@0xproject/utils": "^0.1.2",
"@0xproject/web3-wrapper": "^0.1.2",
"bignumber.js": "~4.1.0",
"bluebird": "^3.5.0",
"bn.js": "^4.11.8",

View File

@@ -7,16 +7,16 @@ import {BalancesByOwner, ContractInstance} from './types';
bigNumberConfigs.configure();
export class Balances {
private tokenContractInstances: ContractInstance[];
private ownerAddresses: string[];
private _tokenContractInstances: ContractInstance[];
private _ownerAddresses: string[];
constructor(tokenContractInstances: ContractInstance[], ownerAddresses: string[]) {
this.tokenContractInstances = tokenContractInstances;
this.ownerAddresses = ownerAddresses;
this._tokenContractInstances = tokenContractInstances;
this._ownerAddresses = ownerAddresses;
}
public async getAsync(): Promise<BalancesByOwner> {
const balancesByOwner: BalancesByOwner = {};
for (const tokenContractInstance of this.tokenContractInstances) {
for (const ownerAddress of this.ownerAddresses) {
for (const tokenContractInstance of this._tokenContractInstances) {
for (const ownerAddress of this._ownerAddresses) {
let balance = await tokenContractInstance.balanceOf(ownerAddress);
balance = new BigNumber(balance);
if (_.isUndefined(balancesByOwner[ownerAddress])) {

View File

@@ -6,9 +6,9 @@ import {Order} from './order';
import {ContractInstance} from './types';
export class ExchangeWrapper {
private exchange: ContractInstance;
private _exchange: ContractInstance;
constructor(exchangeContractInstance: ContractInstance) {
this.exchange = exchangeContractInstance;
this._exchange = exchangeContractInstance;
}
public async fillOrderAsync(order: Order, from: string,
opts: {
@@ -17,7 +17,7 @@ export class ExchangeWrapper {
} = {}) {
const shouldThrowOnInsufficientBalanceOrAllowance = !!opts.shouldThrowOnInsufficientBalanceOrAllowance;
const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance, opts.fillTakerTokenAmount);
const tx = await this.exchange.fillOrder(
const tx = await this._exchange.fillOrder(
params.orderAddresses,
params.orderValues,
params.fillTakerTokenAmount,
@@ -33,7 +33,7 @@ export class ExchangeWrapper {
public async cancelOrderAsync(order: Order, from: string,
opts: {cancelTakerTokenAmount?: BigNumber} = {}) {
const params = order.createCancel(opts.cancelTakerTokenAmount);
const tx = await this.exchange.cancelOrder(
const tx = await this._exchange.cancelOrder(
params.orderAddresses,
params.orderValues,
params.cancelTakerTokenAmount,
@@ -46,7 +46,7 @@ export class ExchangeWrapper {
opts: {fillTakerTokenAmount?: BigNumber} = {}) {
const shouldThrowOnInsufficientBalanceOrAllowance = true;
const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance, opts.fillTakerTokenAmount);
const tx = await this.exchange.fillOrKillOrder(
const tx = await this._exchange.fillOrKillOrder(
params.orderAddresses,
params.orderValues,
params.fillTakerTokenAmount,
@@ -66,7 +66,7 @@ export class ExchangeWrapper {
const shouldThrowOnInsufficientBalanceOrAllowance = !!opts.shouldThrowOnInsufficientBalanceOrAllowance;
const params = formatters.createBatchFill(
orders, shouldThrowOnInsufficientBalanceOrAllowance, opts.fillTakerTokenAmounts);
const tx = await this.exchange.batchFillOrders(
const tx = await this._exchange.batchFillOrders(
params.orderAddresses,
params.orderValues,
params.fillTakerTokenAmounts,
@@ -82,7 +82,7 @@ export class ExchangeWrapper {
public async batchFillOrKillOrdersAsync(orders: Order[], from: string,
opts: {fillTakerTokenAmounts?: BigNumber[]} = {}) {
const params = formatters.createBatchFill(orders, undefined, opts.fillTakerTokenAmounts);
const tx = await this.exchange.batchFillOrKillOrders(
const tx = await this._exchange.batchFillOrKillOrders(
params.orderAddresses,
params.orderValues,
params.fillTakerTokenAmounts,
@@ -103,7 +103,7 @@ export class ExchangeWrapper {
const params = formatters.createFillUpTo(orders,
shouldThrowOnInsufficientBalanceOrAllowance,
opts.fillTakerTokenAmount);
const tx = await this.exchange.fillOrdersUpTo(
const tx = await this._exchange.fillOrdersUpTo(
params.orderAddresses,
params.orderValues,
params.fillTakerTokenAmount,
@@ -119,7 +119,7 @@ export class ExchangeWrapper {
public async batchCancelOrdersAsync(orders: Order[], from: string,
opts: {cancelTakerTokenAmounts?: BigNumber[]} = {}) {
const params = formatters.createBatchCancel(orders, opts.cancelTakerTokenAmounts);
const tx = await this.exchange.batchCancelOrders(
const tx = await this._exchange.batchCancelOrders(
params.orderAddresses,
params.orderValues,
params.cancelTakerTokenAmounts,
@@ -131,11 +131,11 @@ export class ExchangeWrapper {
public async getOrderHashAsync(order: Order): Promise<string> {
const shouldThrowOnInsufficientBalanceOrAllowance = false;
const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance);
const orderHash = await this.exchange.getOrderHash(params.orderAddresses, params.orderValues);
const orderHash = await this._exchange.getOrderHash(params.orderAddresses, params.orderValues);
return orderHash;
}
public async isValidSignatureAsync(order: Order): Promise<boolean> {
const isValidSignature = await this.exchange.isValidSignature(
const isValidSignature = await this._exchange.isValidSignature(
order.params.maker,
order.params.orderHashHex,
order.params.v,
@@ -146,12 +146,12 @@ export class ExchangeWrapper {
}
public async isRoundingErrorAsync(numerator: BigNumber, denominator: BigNumber,
target: BigNumber): Promise<boolean> {
const isRoundingError = await this.exchange.isRoundingError(numerator, denominator, target);
const isRoundingError = await this._exchange.isRoundingError(numerator, denominator, target);
return isRoundingError;
}
public async getPartialAmountAsync(numerator: BigNumber, denominator: BigNumber,
target: BigNumber): Promise<BigNumber> {
const partialAmount = new BigNumber(await this.exchange.getPartialAmount(numerator, denominator, target));
const partialAmount = new BigNumber(await this._exchange.getPartialAmount(numerator, denominator, target));
return partialAmount;
}
}

View File

@@ -6,7 +6,7 @@ import * as Web3 from 'web3';
import {ContractInstance, TransactionDataParams} from './types';
export class MultiSigWrapper {
private multiSig: ContractInstance;
private _multiSig: ContractInstance;
public static encodeFnArgs(name: string, abi: Web3.AbiDefinition[], args: any[]) {
const abiEntity = _.find(abi, {name}) as Web3.MethodAbi;
if (_.isUndefined(abiEntity)) {
@@ -22,13 +22,13 @@ export class MultiSigWrapper {
return funcSig + argsData.join('');
}
constructor(multiSigContractInstance: ContractInstance) {
this.multiSig = multiSigContractInstance;
this._multiSig = multiSigContractInstance;
}
public async submitTransactionAsync(destination: string, from: string,
dataParams: TransactionDataParams,
value: number = 0) {
const {name, abi, args = []} = dataParams;
const encoded = MultiSigWrapper.encodeFnArgs(name, abi, args);
return this.multiSig.submitTransaction(destination, value, encoded, {from});
return this._multiSig.submitTransaction(destination, value, encoded, {from});
}
}

View File

@@ -21,7 +21,7 @@ export class Order {
if (_.isUndefined(v) || _.isUndefined(r) || _.isUndefined(s)) {
throw new Error('Cannot call isValidSignature on unsigned order');
}
const orderHash = this.getOrderHash();
const orderHash = this._getOrderHash();
const msgHash = ethUtil.hashPersonalMessage(ethUtil.toBuffer(orderHash));
try {
const pubKey = ethUtil.ecrecover(msgHash, v, ethUtil.toBuffer(r), ethUtil.toBuffer(s));
@@ -32,7 +32,7 @@ export class Order {
}
}
public async signAsync() {
const orderHash = this.getOrderHash();
const orderHash = this._getOrderHash();
const signature = await promisify<string>(web3.eth.sign)(this.params.maker, orderHash);
const {v, r, s} = ethUtil.fromRpcSig(signature);
this.params = _.assign(this.params, {
@@ -88,7 +88,7 @@ export class Order {
};
return cancel;
}
private getOrderHash(): string {
private _getOrderHash(): string {
const orderHash = crypto.solSHA3([
this.params.exchangeContractAddress,
this.params.maker,

View File

@@ -6,9 +6,9 @@ import {Order} from './order';
import {DefaultOrderParams, OptionalOrderParams, OrderParams} from './types';
export class OrderFactory {
private defaultOrderParams: DefaultOrderParams;
private _defaultOrderParams: DefaultOrderParams;
constructor(defaultOrderParams: DefaultOrderParams) {
this.defaultOrderParams = defaultOrderParams;
this._defaultOrderParams = defaultOrderParams;
}
public async newSignedOrderAsync(customOrderParams: OptionalOrderParams = {}) {
const randomExpiration = new BigNumber(Math.floor((Date.now() + (Math.random() * 100000000000)) / 1000));
@@ -16,7 +16,7 @@ export class OrderFactory {
expirationTimestampInSec: randomExpiration,
salt: ZeroEx.generatePseudoRandomSalt(),
taker: ZeroEx.NULL_ADDRESS,
}, this.defaultOrderParams, customOrderParams);
}, this._defaultOrderParams, customOrderParams);
const order = new Order(orderParams);
await order.signAsync();
return order;

View File

@@ -1,12 +1,12 @@
import {ContractInstance, Token} from './types';
export class TokenRegWrapper {
private tokenReg: ContractInstance;
private _tokenReg: ContractInstance;
constructor(tokenRegContractInstance: ContractInstance) {
this.tokenReg = tokenRegContractInstance;
this._tokenReg = tokenRegContractInstance;
}
public addTokenAsync(token: Token, from: string) {
const tx = this.tokenReg.addToken(
const tx = this._tokenReg.addToken(
token.address,
token.name,
token.symbol,
@@ -18,7 +18,7 @@ export class TokenRegWrapper {
return tx;
}
public async getTokenMetaDataAsync(tokenAddress: string) {
const data = await this.tokenReg.getTokenMetaData(tokenAddress);
const data = await this._tokenReg.getTokenMetaData(tokenAddress);
const token: Token = {
address: data[0],
name: data[1],
@@ -30,7 +30,7 @@ export class TokenRegWrapper {
return token;
}
public async getTokenByNameAsync(tokenName: string) {
const data = await this.tokenReg.getTokenByName(tokenName);
const data = await this._tokenReg.getTokenByName(tokenName);
const token: Token = {
address: data[0],
name: data[1],
@@ -42,7 +42,7 @@ export class TokenRegWrapper {
return token;
}
public async getTokenBySymbolAsync(tokenSymbol: string) {
const data = await this.tokenReg.getTokenBySymbol(tokenSymbol);
const data = await this._tokenReg.getTokenBySymbol(tokenSymbol);
const token: Token = {
address: data[0],
name: data[1],

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/dev-utils",
"version": "0.0.1",
"version": "0.0.3",
"description": "0x dev TS utils",
"main": "lib/index.js",
"types": "lib/index.d.ts",
@@ -19,14 +19,14 @@
},
"homepage": "https://github.com/0xProject/0x.js/packages/dev-utils/README.md",
"devDependencies": {
"@0xproject/tslint-config": "^0.2.0",
"@0xproject/tslint-config": "^0.4.0",
"@types/lodash": "^4.14.86",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
"tslint": "5.8.0",
"typescript": "~2.6.1",
"types-bn": "^0.0.1",
"types-ethereumjs-util": "0xProject/types-ethereumjs-util"
"types-ethereumjs-util": "0xProject/types-ethereumjs-util",
"typescript": "~2.6.1"
},
"dependencies": {
"bignumber.js": "~4.1.0",

View File

@@ -1,21 +1,21 @@
import {RPC} from './rpc';
export class BlockchainLifecycle {
private rpc: RPC;
private snapshotIdsStack: number[];
private _rpc: RPC;
private _snapshotIdsStack: number[];
constructor(url: string) {
this.rpc = new RPC(url);
this.snapshotIdsStack = [];
this._rpc = new RPC(url);
this._snapshotIdsStack = [];
}
// TODO: In order to run these tests on an actual node, we should check if we are running against
// TestRPC, if so, use snapshots, otherwise re-deploy contracts before every test
public async startAsync(): Promise<void> {
const snapshotId = await this.rpc.takeSnapshotAsync();
this.snapshotIdsStack.push(snapshotId);
const snapshotId = await this._rpc.takeSnapshotAsync();
this._snapshotIdsStack.push(snapshotId);
}
public async revertAsync(): Promise<void> {
const snapshotId = this.snapshotIdsStack.pop() as number;
const didRevert = await this.rpc.revertSnapshotAsync(snapshotId);
const snapshotId = this._snapshotIdsStack.pop() as number;
const didRevert = await this._rpc.revertSnapshotAsync(snapshotId);
if (!didRevert) {
throw new Error(`Snapshot with id #${snapshotId} failed to revert`);
}

View File

@@ -2,52 +2,52 @@ import * as ethUtil from 'ethereumjs-util';
import * as request from 'request-promise-native';
export class RPC {
private url: string;
private id: number;
private _url: string;
private _id: number;
constructor(url: string) {
this.url = url;
this.id = 0;
this._url = url;
this._id = 0;
}
public async takeSnapshotAsync(): Promise<number> {
const method = 'evm_snapshot';
const params: any[] = [];
const payload = this.toPayload(method, params);
const snapshotIdHex = await this.sendAsync(payload);
const payload = this._toPayload(method, params);
const snapshotIdHex = await this._sendAsync(payload);
const snapshotId = ethUtil.bufferToInt(ethUtil.toBuffer(snapshotIdHex));
return snapshotId;
}
public async revertSnapshotAsync(snapshotId: number): Promise<boolean> {
const method = 'evm_revert';
const params = [snapshotId];
const payload = this.toPayload(method, params);
const didRevert = await this.sendAsync(payload);
const payload = this._toPayload(method, params);
const didRevert = await this._sendAsync(payload);
return didRevert;
}
public async increaseTimeAsync(time: number) {
const method = 'evm_increaseTime';
const params = [time];
const payload = this.toPayload(method, params);
return this.sendAsync(payload);
const payload = this._toPayload(method, params);
return this._sendAsync(payload);
}
public async mineBlockAsync(): Promise<void> {
const method = 'evm_mine';
const params: any[] = [];
const payload = this.toPayload(method, params);
await this.sendAsync(payload);
const payload = this._toPayload(method, params);
await this._sendAsync(payload);
}
private toPayload(method: string, params: any[] = []): string {
private _toPayload(method: string, params: any[] = []): string {
const payload = JSON.stringify({
id: this.id,
id: this._id,
method,
params,
});
this.id += 1;
this._url += 1;
return payload;
}
private async sendAsync(payload: string): Promise<any> {
private async _sendAsync(payload: string): Promise<any> {
const opts = {
method: 'POST',
uri: this.url,
uri: this._url,
body: payload,
headers: {
'content-type': 'application/json',

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/json-schemas",
"version": "0.6.10",
"version": "0.7.1",
"description": "0x-related json schemas",
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
@@ -27,8 +27,8 @@
"lodash.values": "^4.3.0"
},
"devDependencies": {
"@0xproject/tslint-config": "^0.2.1",
"@0xproject/utils": "^0.1.0",
"@0xproject/tslint-config": "^0.4.0",
"@0xproject/utils": "^0.1.2",
"@types/lodash.foreach": "^4.5.3",
"@types/lodash.values": "^4.3.3",
"@types/mocha": "^2.2.42",

View File

@@ -4,15 +4,15 @@ import values = require('lodash.values');
import {schemas} from './schemas';
export class SchemaValidator {
private validator: Validator;
private _validator: Validator;
constructor() {
this.validator = new Validator();
this._validator = new Validator();
for (const schema of values(schemas)) {
this.validator.addSchema(schema, schema.id);
this._validator.addSchema(schema, schema.id);
}
}
public addSchema(schema: Schema) {
this.validator.addSchema(schema, schema.id);
this._validator.addSchema(schema, schema.id);
}
// In order to validate a complex JS object using jsonschema, we must replace any complex
// sub-types (e.g BigNumber) with a simpler string representation. Since BigNumber and other
@@ -20,7 +20,7 @@ export class SchemaValidator {
// then parse it. The resultant object can then be checked using jsonschema.
public validate(instance: any, schema: Schema): ValidatorResult {
const jsonSchemaCompatibleObject = JSON.parse(JSON.stringify(instance));
return this.validator.validate(jsonSchemaCompatibleObject, schema);
return this._validator.validate(jsonSchemaCompatibleObject, schema);
}
public isValid(instance: any, schema: Schema): boolean {
const isValid = this.validate(instance, schema).errors.length === 0;

View File

@@ -1,7 +1,7 @@
{
"private": true,
"name": "@0xproject/kovan_faucets",
"version": "1.0.0",
"version": "1.0.2",
"description": "A faucet micro-service that dispenses test ERC20 tokens or Ether",
"main": "server.js",
"scripts": {
@@ -14,8 +14,8 @@
"author": "Fabio Berger",
"license": "Apache-2.0",
"dependencies": {
"@0xproject/utils": "^0.1.0",
"0x.js": "~0.27.2",
"0x.js": "^0.29.0",
"@0xproject/utils": "^0.1.2",
"bignumber.js": "~4.1.0",
"body-parser": "^1.17.1",
"ethereumjs-tx": "^1.3.3",
@@ -26,7 +26,7 @@
"web3-provider-engine": "^13.0.1"
},
"devDependencies": {
"@0xproject/tslint-config": "^0.2.1",
"@0xproject/tslint-config": "^0.4.0",
"@types/body-parser": "^1.16.1",
"@types/express": "^4.0.35",
"@types/lodash": "^4.14.86",

View File

@@ -18,25 +18,25 @@ import {ZRXRequestQueue} from './zrx_request_queue';
import * as Web3 from 'web3';
export class Handler {
private etherRequestQueue: EtherRequestQueue;
private zrxRequestQueue: ZRXRequestQueue;
private web3: Web3;
private _etherRequestQueue: EtherRequestQueue;
private _zrxRequestQueue: ZRXRequestQueue;
private _web3: Web3;
constructor() {
// Setup provider engine to talk with RPC node
const providerObj = this.createProviderEngine(configs.RPC_URL);
this.web3 = new Web3(providerObj);
const providerObj = this._createProviderEngine(configs.RPC_URL);
this._web3 = new Web3(providerObj);
this.etherRequestQueue = new EtherRequestQueue(this.web3);
this.zrxRequestQueue = new ZRXRequestQueue(this.web3);
this._etherRequestQueue = new EtherRequestQueue(this._web3);
this._zrxRequestQueue = new ZRXRequestQueue(this._web3);
}
public dispenseEther(req: express.Request, res: express.Response) {
const recipientAddress = req.params.recipient;
if (_.isUndefined(recipientAddress) || !this.isValidEthereumAddress(recipientAddress)) {
if (_.isUndefined(recipientAddress) || !this._isValidEthereumAddress(recipientAddress)) {
res.status(400).send('INVALID_REQUEST');
return;
}
const lowerCaseRecipientAddress = recipientAddress.toLowerCase();
const didAddToQueue = this.etherRequestQueue.add(lowerCaseRecipientAddress);
const didAddToQueue = this._etherRequestQueue.add(lowerCaseRecipientAddress);
if (!didAddToQueue) {
res.status(503).send('QUEUE_IS_FULL');
return;
@@ -46,12 +46,12 @@ export class Handler {
}
public dispenseZRX(req: express.Request, res: express.Response) {
const recipientAddress = req.params.recipient;
if (_.isUndefined(recipientAddress) || !this.isValidEthereumAddress(recipientAddress)) {
if (_.isUndefined(recipientAddress) || !this._isValidEthereumAddress(recipientAddress)) {
res.status(400).send('INVALID_REQUEST');
return;
}
const lowerCaseRecipientAddress = recipientAddress.toLowerCase();
const didAddToQueue = this.zrxRequestQueue.add(lowerCaseRecipientAddress);
const didAddToQueue = this._zrxRequestQueue.add(lowerCaseRecipientAddress);
if (!didAddToQueue) {
res.status(503).send('QUEUE_IS_FULL');
return;
@@ -63,18 +63,18 @@ export class Handler {
res.setHeader('Content-Type', 'application/json');
const payload = JSON.stringify({
ether: {
full: this.etherRequestQueue.isFull(),
size: this.etherRequestQueue.size(),
full: this._etherRequestQueue.isFull(),
size: this._etherRequestQueue.size(),
},
zrx: {
full: this.zrxRequestQueue.isFull(),
size: this.zrxRequestQueue.size(),
full: this._zrxRequestQueue.isFull(),
size: this._zrxRequestQueue.size(),
},
});
res.status(200).send(payload);
}
// tslint:disable-next-line:prefer-function-over-method
private createProviderEngine(rpcUrl: string) {
private _createProviderEngine(rpcUrl: string) {
const engine = new ProviderEngine();
engine.addProvider(new NonceSubprovider());
engine.addProvider(new HookedWalletSubprovider(idManagement));
@@ -84,8 +84,8 @@ export class Handler {
engine.start();
return engine;
}
private isValidEthereumAddress(address: string): boolean {
private _isValidEthereumAddress(address: string): boolean {
const lowercaseAddress = address.toLowerCase();
return this.web3.isAddress(lowercaseAddress);
return this._web3.isAddress(lowercaseAddress);
}
}

View File

@@ -17,20 +17,20 @@ const DISPENSE_AMOUNT_ZRX = new BigNumber(0.1);
const QUEUE_INTERVAL_MS = 5000;
export class ZRXRequestQueue extends RequestQueue {
private zeroEx: ZeroEx;
private _zeroEx: ZeroEx;
constructor(web3: Web3) {
super(web3);
this.queueIntervalMs = QUEUE_INTERVAL_MS;
const zeroExConfig = {
networkId: configs.KOVAN_NETWORK_ID,
};
this.zeroEx = new ZeroEx(web3.currentProvider, zeroExConfig);
this._zeroEx = new ZeroEx(web3.currentProvider, zeroExConfig);
}
protected async processNextRequestFireAndForgetAsync(recipientAddress: string) {
utils.consoleLog(`Processing ZRX ${recipientAddress}`);
const baseUnitAmount = ZeroEx.toBaseUnitAmount(DISPENSE_AMOUNT_ZRX, 18);
try {
await this.zeroEx.token.transferAsync(
await this._zeroEx.token.transferAsync(
configs.ZRX_TOKEN_ADDRESS, configs.DISPENSER_ADDRESS, recipientAddress, baseUnitAmount,
);
utils.consoleLog(`Sent ${DISPENSE_AMOUNT_ZRX} ZRX to ${recipientAddress}`);

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/monorepo-scripts",
"version": "0.1.0",
"version": "0.1.2",
"private": true,
"description": "Helper scripts for the monorepo",
"scripts": {
@@ -19,7 +19,7 @@
},
"homepage": "https://github.com/0xProject/0x.js/packages/monorepo-scripts/README.md",
"devDependencies": {
"@0xproject/tslint-config": "^0.2.1",
"@0xproject/tslint-config": "^0.4.0",
"@types/glob": "^5.0.33",
"@types/node": "^8.0.53",
"shx": "^0.2.2",

View File

@@ -1,5 +1,9 @@
# CHANGELOG
v0.3.0 - _December 28, 2017_
------------------------
* Allow LedgerSubprovider to handle `eth_sign` in addition to `personal_sign` RPC requests
v0.2.0 - _December 20, 2017_
------------------------
* Improve the performance of address fetching (#271)

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/subproviders",
"version": "0.1.0",
"version": "0.2.0",
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"license": "Apache-2.0",
@@ -17,8 +17,8 @@
"test:integration": "run-s clean build run_mocha_integration"
},
"dependencies": {
"@0xproject/assert": "^0.0.7",
"@0xproject/utils": "^0.1.0",
"@0xproject/assert": "^0.0.9",
"@0xproject/utils": "^0.1.2",
"bn.js": "^4.11.8",
"es6-promisify": "^5.0.0",
"ethereumjs-tx": "^1.3.3",
@@ -31,8 +31,8 @@
"web3-provider-engine": "^13.0.1"
},
"devDependencies": {
"@0xproject/tslint-config": "^0.2.1",
"@0xproject/utils": "^0.1.0",
"@0xproject/tslint-config": "^0.4.0",
"@0xproject/utils": "^0.1.2",
"@types/lodash": "^4.14.86",
"@types/mocha": "^2.2.42",
"@types/node": "^8.0.53",

View File

@@ -9,29 +9,29 @@ import Web3ProviderEngine = require('web3-provider-engine');
* Source: https://github.com/MetaMask/provider-engine/blob/master/subproviders/subprovider.js
*/
export class InjectedWeb3Subprovider {
private injectedWeb3: Web3;
private _injectedWeb3: Web3;
constructor(injectedWeb3: Web3) {
this.injectedWeb3 = injectedWeb3;
this._injectedWeb3 = injectedWeb3;
}
public handleRequest(
payload: Web3.JSONRPCRequestPayload, next: () => void, end: (err: Error|null, result: any) => void,
) {
switch (payload.method) {
case 'web3_clientVersion':
this.injectedWeb3.version.getNode(end);
this._injectedWeb3.version.getNode(end);
return;
case 'eth_accounts':
this.injectedWeb3.eth.getAccounts(end);
this._injectedWeb3.eth.getAccounts(end);
return;
case 'eth_sendTransaction':
const [txParams] = payload.params;
this.injectedWeb3.eth.sendTransaction(txParams, end);
this._injectedWeb3.eth.sendTransaction(txParams, end);
return;
case 'eth_sign':
const [address, message] = payload.params;
this.injectedWeb3.eth.sign(address, message, end);
this._injectedWeb3.eth.sign(address, message, end);
return;
default:

View File

@@ -32,7 +32,7 @@ export class LedgerSubprovider extends Subprovider {
private _ledgerEthereumClientFactoryAsync: LedgerEthereumClientFactoryAsync;
private _ledgerClientIfExists?: LedgerEthereumClient;
private _shouldAlwaysAskForConfirmation: boolean;
private static validateSender(sender: string) {
private static _validateSender(sender: string) {
if (_.isUndefined(sender) || !addressUtils.isAddress(sender)) {
throw new Error(LedgerSubproviderErrors.SenderInvalidOrNotSupplied);
}
@@ -88,8 +88,8 @@ export class LedgerSubprovider extends Subprovider {
case 'eth_sendTransaction':
txParams = payload.params[0];
try {
LedgerSubprovider.validateSender(txParams.from);
const result = await this.sendTransactionAsync(txParams);
LedgerSubprovider._validateSender(txParams.from);
const result = await this._sendTransactionAsync(txParams);
end(null, result);
} catch (err) {
end(err);
@@ -99,15 +99,16 @@ export class LedgerSubprovider extends Subprovider {
case 'eth_signTransaction':
txParams = payload.params[0];
try {
const result = await this.signTransactionWithoutSendingAsync(txParams);
const result = await this._signTransactionWithoutSendingAsync(txParams);
end(null, result);
} catch (err) {
end(err);
}
return;
case 'eth_sign':
case 'personal_sign':
const data = payload.params[0];
const data = payload.method === 'eth_sign' ? payload.params[1] : payload.params[0];
try {
if (_.isUndefined(data)) {
throw new Error(LedgerSubproviderErrors.DataMissingForSignPersonalMessage);
@@ -126,7 +127,7 @@ export class LedgerSubprovider extends Subprovider {
}
}
public async getAccountsAsync(): Promise<string[]> {
this._ledgerClientIfExists = await this.createLedgerClientAsync();
this._ledgerClientIfExists = await this._createLedgerClientAsync();
let ledgerResponse;
try {
@@ -134,7 +135,7 @@ export class LedgerSubprovider extends Subprovider {
this._derivationPath, this._shouldAlwaysAskForConfirmation, SHOULD_GET_CHAIN_CODE,
);
} finally {
await this.destoryLedgerClientAsync();
await this._destroyLedgerClientAsync();
}
const hdKey = new HDNode();
@@ -155,7 +156,7 @@ export class LedgerSubprovider extends Subprovider {
return accounts;
}
public async signTransactionAsync(txParams: PartialTxParams): Promise<string> {
this._ledgerClientIfExists = await this.createLedgerClientAsync();
this._ledgerClientIfExists = await this._createLedgerClientAsync();
const tx = new EthereumTx(txParams);
@@ -166,7 +167,7 @@ export class LedgerSubprovider extends Subprovider {
const txHex = tx.serialize().toString('hex');
try {
const derivationPath = this.getDerivationPath();
const derivationPath = this._getDerivationPath();
const result = await this._ledgerClientIfExists.signTransaction_async(derivationPath, txHex);
// Store signature in transaction
tx.r = Buffer.from(result.r, 'hex');
@@ -176,23 +177,23 @@ export class LedgerSubprovider extends Subprovider {
// EIP155: v should be chain_id * 2 + {35, 36}
const signedChainId = Math.floor((tx.v[0] - 35) / 2);
if (signedChainId !== this._networkId) {
await this.destoryLedgerClientAsync();
await this._destroyLedgerClientAsync();
const err = new Error(LedgerSubproviderErrors.TooOldLedgerFirmware);
throw err;
}
const signedTxHex = `0x${tx.serialize().toString('hex')}`;
await this.destoryLedgerClientAsync();
await this._destroyLedgerClientAsync();
return signedTxHex;
} catch (err) {
await this.destoryLedgerClientAsync();
await this._destroyLedgerClientAsync();
throw err;
}
}
public async signPersonalMessageAsync(data: string): Promise<string> {
this._ledgerClientIfExists = await this.createLedgerClientAsync();
this._ledgerClientIfExists = await this._createLedgerClientAsync();
try {
const derivationPath = this.getDerivationPath();
const derivationPath = this._getDerivationPath();
const result = await this._ledgerClientIfExists.signPersonalMessage_async(
derivationPath, ethUtil.stripHexPrefix(data));
const v = result.v - 27;
@@ -201,18 +202,18 @@ export class LedgerSubprovider extends Subprovider {
vHex = `0${v}`;
}
const signature = `0x${result.r}${result.s}${vHex}`;
await this.destoryLedgerClientAsync();
await this._destroyLedgerClientAsync();
return signature;
} catch (err) {
await this.destoryLedgerClientAsync();
await this._destroyLedgerClientAsync();
throw err;
}
}
private getDerivationPath() {
private _getDerivationPath() {
const derivationPath = `${this.getPath()}/${this._derivationPathIndex}`;
return derivationPath;
}
private async createLedgerClientAsync(): Promise<LedgerEthereumClient> {
private async _createLedgerClientAsync(): Promise<LedgerEthereumClient> {
await this._connectionLock.wait();
if (!_.isUndefined(this._ledgerClientIfExists)) {
this._connectionLock.signal();
@@ -222,7 +223,7 @@ export class LedgerSubprovider extends Subprovider {
this._connectionLock.signal();
return ledgerEthereumClient;
}
private async destoryLedgerClientAsync() {
private async _destroyLedgerClientAsync() {
await this._connectionLock.wait();
if (_.isUndefined(this._ledgerClientIfExists)) {
this._connectionLock.signal();
@@ -232,11 +233,11 @@ export class LedgerSubprovider extends Subprovider {
this._ledgerClientIfExists = undefined;
this._connectionLock.signal();
}
private async sendTransactionAsync(txParams: PartialTxParams): Promise<Web3.JSONRPCResponsePayload> {
private async _sendTransactionAsync(txParams: PartialTxParams): Promise<Web3.JSONRPCResponsePayload> {
await this._nonceLock.wait();
try {
// fill in the extras
const filledParams = await this.populateMissingTxParamsAsync(txParams);
const filledParams = await this._populateMissingTxParamsAsync(txParams);
// sign it
const signedTx = await this.signTransactionAsync(filledParams);
// emit a submit
@@ -252,11 +253,11 @@ export class LedgerSubprovider extends Subprovider {
throw err;
}
}
private async signTransactionWithoutSendingAsync(txParams: PartialTxParams): Promise<ResponseWithTxParams> {
private async _signTransactionWithoutSendingAsync(txParams: PartialTxParams): Promise<ResponseWithTxParams> {
await this._nonceLock.wait();
try {
// fill in the extras
const filledParams = await this.populateMissingTxParamsAsync(txParams);
const filledParams = await this._populateMissingTxParamsAsync(txParams);
// sign it
const signedTx = await this.signTransactionAsync(filledParams);
@@ -271,7 +272,7 @@ export class LedgerSubprovider extends Subprovider {
throw err;
}
}
private async populateMissingTxParamsAsync(txParams: PartialTxParams): Promise<PartialTxParams> {
private async _populateMissingTxParamsAsync(txParams: PartialTxParams): Promise<PartialTxParams> {
if (_.isUndefined(txParams.gasPrice)) {
const gasPriceResult = await this.emitPayloadAsync({
method: 'eth_gasPrice',

View File

@@ -7,8 +7,8 @@ import {JSONRPCPayload} from '../types';
import {Subprovider} from './subprovider';
export class RedundantRPCSubprovider extends Subprovider {
private rpcs: RpcSubprovider[];
private static async firstSuccessAsync(
private _rpcs: RpcSubprovider[];
private static async _firstSuccessAsync(
rpcs: RpcSubprovider[], payload: JSONRPCPayload, next: () => void,
): Promise<any> {
let lastErr: Error|undefined;
@@ -27,7 +27,7 @@ export class RedundantRPCSubprovider extends Subprovider {
}
constructor(endpoints: string[]) {
super();
this.rpcs = _.map(endpoints, endpoint => {
this._rpcs = _.map(endpoints, endpoint => {
return new RpcSubprovider({
rpcUrl: endpoint,
});
@@ -36,9 +36,9 @@ export class RedundantRPCSubprovider extends Subprovider {
// tslint:disable-next-line:async-suffix
public async handleRequest(payload: JSONRPCPayload, next: () => void,
end: (err: Error|null, data?: any) => void): Promise<void> {
const rpcsCopy = this.rpcs.slice();
const rpcsCopy = this._rpcs.slice();
try {
const data = await RedundantRPCSubprovider.firstSuccessAsync(rpcsCopy, payload, next);
const data = await RedundantRPCSubprovider._firstSuccessAsync(rpcsCopy, payload, next);
end(null, data);
} catch (err) {
end(err);

View File

@@ -10,9 +10,9 @@ import {
* Altered version of: https://github.com/MetaMask/provider-engine/blob/master/subproviders/subprovider.js
*/
export class Subprovider {
private engine: any;
private _engine: any;
// Ported from: https://github.com/MetaMask/provider-engine/blob/master/util/random-id.js
private static getRandomId() {
private static _getRandomId() {
const extraDigits = 3;
// 13 time digits
const datePart = new Date().getTime() * Math.pow(10, extraDigits);
@@ -21,10 +21,10 @@ export class Subprovider {
// 16 digits
return datePart + extraPart;
}
private static createFinalPayload(payload: JSONRPCPayload): Web3.JSONRPCRequestPayload {
private static _createFinalPayload(payload: JSONRPCPayload): Web3.JSONRPCRequestPayload {
const finalPayload = {
// defaults
id: Subprovider.getRandomId(),
id: Subprovider._getRandomId(),
jsonrpc: '2.0',
params: [],
...payload,
@@ -32,11 +32,11 @@ export class Subprovider {
return finalPayload;
}
public setEngine(engine: any): void {
this.engine = engine;
this._engine = engine;
}
public async emitPayloadAsync(payload: JSONRPCPayload): Promise<any> {
const finalPayload = Subprovider.createFinalPayload(payload);
const response = await promisify(this.engine.sendAsync, this.engine)(finalPayload);
const finalPayload = Subprovider._createFinalPayload(payload);
const response = await promisify(this._engine.sendAsync, this._engine)(finalPayload);
return response;
}
}

View File

@@ -85,7 +85,27 @@ describe('LedgerSubprovider', () => {
});
ledgerProvider.sendAsync(payload, callback);
});
it('signs a personal message', (done: DoneCallback) => {
it('signs a personal message with eth_sign', (done: DoneCallback) => {
(async () => {
const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer('hello world'));
const accounts = await ledgerSubprovider.getAccountsAsync();
const signer = accounts[0];
const payload = {
jsonrpc: '2.0',
method: 'eth_sign',
params: [signer, messageHex],
id: 1,
};
const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => {
expect(err).to.be.a('null');
expect(response.result.length).to.be.equal(132);
expect(response.result.substr(0, 2)).to.be.equal('0x');
done();
});
ledgerProvider.sendAsync(payload, callback);
})().catch(done);
});
it('signs a personal message with personal_sign', (done: DoneCallback) => {
(async () => {
const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer('hello world'));
const accounts = await ledgerSubprovider.getAccountsAsync();

View File

@@ -117,7 +117,23 @@ describe('LedgerSubprovider', () => {
});
provider.sendAsync(payload, callback);
});
it('signs a personal message', (done: DoneCallback) => {
it('signs a personal message with eth_sign', (done: DoneCallback) => {
const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer('hello world'));
const payload = {
jsonrpc: '2.0',
method: 'eth_sign',
params: ['0x0000000000000000000000000000000000000000', messageHex],
id: 1,
};
const callback = reportCallbackErrors(done)((err: Error, response: Web3.JSONRPCResponsePayload) => {
expect(err).to.be.a('null');
// tslint:disable-next-line:max-line-length
expect(response.result).to.be.equal('0xa6cc284bff14b42bdf5e9286730c152be91719d478605ec46b3bebcd0ae491480652a1a7b742ceb0213d1e744316e285f41f878d8af0b8e632cbca4c279132d001');
done();
});
provider.sendAsync(payload, callback);
});
it('signs a personal message with personal_sign', (done: DoneCallback) => {
const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer('hello world'));
const payload = {
jsonrpc: '2.0',
@@ -157,6 +173,21 @@ describe('LedgerSubprovider', () => {
});
});
describe('failure cases', () => {
it('should throw if `data` param not hex when calling eth_sign', (done: DoneCallback) => {
const nonHexMessage = 'hello world';
const payload = {
jsonrpc: '2.0',
method: 'eth_sign',
params: ['0x0000000000000000000000000000000000000000', nonHexMessage],
id: 1,
};
const callback = reportCallbackErrors(done)((err: Error, response: Web3.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();
});
provider.sendAsync(payload, callback);
});
it('should throw if `data` param not hex when calling personal_sign', (done: DoneCallback) => {
const nonHexMessage = 'hello world';
const payload = {

View File

@@ -1,5 +1,10 @@
# CHANGELOG
v0.4.0 - _December 28, 2017_
------------------------
* Added custom 'underscore-privates' rule, requiring underscores to be prepended to private variable names
* Because our tools can be used in both a TS and JS environment, we want to make the private methods of any public facing interface show up at the bottom of auto-complete lists. Additionally, we wanted to remain consistent with respect to our usage of underscores in order to enforce this rule with a linter rule, rather then manual code reviews.
v0.3.0 - _December 20, 2017_
------------------------
* Added rules for unused imports, variables and Async suffixes (#265)

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/tslint-config",
"version": "0.2.1",
"version": "0.4.0",
"description": "Lint rules related to 0xProject for TSLint",
"main": "tslint.json",
"scripts": {

View File

@@ -0,0 +1,61 @@
import * as Lint from 'tslint';
import * as ts from 'typescript';
const UNDERSCORE = '_';
type RelevantClassMember =
| ts.MethodDeclaration
| ts.PropertyDeclaration
| ts.GetAccessorDeclaration
| ts.SetAccessorDeclaration;
// Copied from: https://github.com/DanielRosenwasser/underscore-privates-tslint-rule
// The version on github is not published on npm
export class Rule extends Lint.Rules.AbstractRule {
public static FAILURE_STRING = 'private members must be prefixed with an underscore';
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, walk);
}
}
function walk(ctx: Lint.WalkContext<void>): void {
traverse(ctx.sourceFile);
function traverse(node: ts.Node): void {
checkNodeForViolations(ctx, node);
return ts.forEachChild(node, traverse);
}
}
function checkNodeForViolations(ctx: Lint.WalkContext<void>, node: ts.Node): void {
if (!isRelevantClassMember(node)) {
return;
}
// The declaration might have a computed property name or a numeric name.
const name = node.name;
if (!nameIsIdentifier(name)) {
return;
}
if (!nameStartsWithUnderscore(name.text) && memberIsPrivate(node)) {
ctx.addFailureAtNode(name, Rule.FAILURE_STRING);
}
}
function isRelevantClassMember(node: ts.Node): node is RelevantClassMember {
switch (node.kind) {
case ts.SyntaxKind.MethodDeclaration:
case ts.SyntaxKind.PropertyDeclaration:
case ts.SyntaxKind.GetAccessor:
case ts.SyntaxKind.SetAccessor:
return true;
default:
return false;
}
}
function nameStartsWithUnderscore(text: string) {
return text.charCodeAt(0) === UNDERSCORE.charCodeAt(0);
}
function memberIsPrivate(node: ts.Declaration) {
return Lint.hasModifier(node.modifiers, ts.SyntaxKind.PrivateKeyword);
}
function nameIsIdentifier(node: ts.Node): node is ts.Identifier {
return node.kind === ts.SyntaxKind.Identifier;
}

View File

@@ -81,6 +81,7 @@
],
"space-within-parens": false,
"type-literal-delimiter": true,
"underscore-privates": true,
"variable-name": [true,
"ban-keywords",
"allow-pascal-case"

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/types",
"version": "0.1.0",
"version": "0.1.2",
"description": "0x types",
"main": "lib/index.js",
"types": "lib/index.d.ts",
@@ -19,7 +19,7 @@
},
"homepage": "https://github.com/0xProject/0x.js/packages/types/README.md",
"devDependencies": {
"@0xproject/tslint-config": "^0.2.1",
"@0xproject/tslint-config": "^0.4.0",
"bignumber.js": "^5.0.0",
"shx": "^0.2.2",
"tslint": "5.8.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/utils",
"version": "0.1.0",
"version": "0.1.2",
"description": "0x TS utils",
"main": "lib/index.js",
"types": "lib/index.d.ts",
@@ -19,7 +19,7 @@
},
"homepage": "https://github.com/0xProject/0x.js/packages/utils/README.md",
"devDependencies": {
"@0xproject/tslint-config": "^0.2.1",
"@0xproject/tslint-config": "^0.4.0",
"@types/lodash": "^4.14.86",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/web3-wrapper",
"version": "0.1.0",
"version": "0.1.2",
"description": "Wraps around web3 and gives a nicer interface",
"main": "lib/index.js",
"types": "lib/index.d.ts",
@@ -19,8 +19,8 @@
},
"homepage": "https://github.com/0xProject/0x.js/packages/web3-wrapper/README.md",
"devDependencies": {
"@0xproject/tslint-config": "^0.2.1",
"@0xproject/types": "^0.1.0",
"@0xproject/tslint-config": "^0.4.0",
"@0xproject/types": "^0.1.2",
"@types/lodash": "^4.14.86",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
@@ -29,7 +29,7 @@
"web3-typescript-typings": "^0.7.2"
},
"dependencies": {
"@0xproject/utils": "^0.1.0",
"@0xproject/utils": "^0.1.2",
"bignumber.js": "~4.1.0",
"lodash": "^4.17.4",
"web3": "^0.20.0"

View File

@@ -1,5 +1,8 @@
import {TransactionReceipt, TxData} from '@0xproject/types';
import {promisify} from '@0xproject/utils';
import {
bigNumberConfigs,
promisify,
} from '@0xproject/utils';
import BigNumber from 'bignumber.js';
import * as _ from 'lodash';
import * as Web3 from 'web3';
@@ -15,10 +18,13 @@ interface RawLogEntry {
topics: string[];
}
// Customize our BigNumber instances
bigNumberConfigs.configure();
export class Web3Wrapper {
private web3: Web3;
private defaults: Partial<TxData>;
private jsonRpcRequestId: number;
private _web3: Web3;
private _defaults: Partial<TxData>;
private _jsonRpcRequestId: number;
constructor(provider: Web3.Provider, defaults?: Partial<TxData>) {
if (_.isUndefined((provider as any).sendAsync)) {
// Web3@1.0 provider doesn't support synchronous http requests,
@@ -26,69 +32,69 @@ export class Web3Wrapper {
// We re-assign the send method so that Web3@1.0 providers work with 0x.js
(provider as any).sendAsync = (provider as any).send;
}
this.web3 = new Web3();
this.web3.setProvider(provider);
this.defaults = defaults || {};
this.jsonRpcRequestId = 0;
this._web3 = new Web3();
this._web3.setProvider(provider);
this._defaults = defaults || {};
this._jsonRpcRequestId = 0;
}
public getContractDefaults(): Partial<TxData> {
return this.defaults;
return this._defaults;
}
public setProvider(provider: Web3.Provider, networkId: number) {
this.web3.setProvider(provider);
this._web3.setProvider(provider);
}
public isAddress(address: string): boolean {
return this.web3.isAddress(address);
return this._web3.isAddress(address);
}
public async isSenderAddressAvailableAsync(senderAddress: string): Promise<boolean> {
const addresses = await this.getAvailableAddressesAsync();
return _.includes(addresses, senderAddress);
}
public async getNodeVersionAsync(): Promise<string> {
const nodeVersion = await promisify<string>(this.web3.version.getNode)();
const nodeVersion = await promisify<string>(this._web3.version.getNode)();
return nodeVersion;
}
public async getNetworkIdAsync(): Promise<number> {
const networkIdStr = await promisify<string>(this.web3.version.getNetwork)();
const networkIdStr = await promisify<string>(this._web3.version.getNetwork)();
const networkId = _.parseInt(networkIdStr);
return networkId;
}
public async getTransactionReceiptAsync(txHash: string): Promise<TransactionReceipt> {
const transactionReceipt = await promisify<TransactionReceipt>(this.web3.eth.getTransactionReceipt)(txHash);
const transactionReceipt = await promisify<TransactionReceipt>(this._web3.eth.getTransactionReceipt)(txHash);
if (!_.isNull(transactionReceipt)) {
transactionReceipt.status = this.normalizeTxReceiptStatus(transactionReceipt.status);
transactionReceipt.status = this._normalizeTxReceiptStatus(transactionReceipt.status);
}
return transactionReceipt;
}
public getCurrentProvider(): Web3.Provider {
return this.web3.currentProvider;
return this._web3.currentProvider;
}
public toWei(ethAmount: BigNumber): BigNumber {
const balanceWei = this.web3.toWei(ethAmount, 'ether');
const balanceWei = this._web3.toWei(ethAmount, 'ether');
return balanceWei;
}
public async getBalanceInWeiAsync(owner: string): Promise<BigNumber> {
let balanceInWei = await promisify<BigNumber>(this.web3.eth.getBalance)(owner);
let balanceInWei = await promisify<BigNumber>(this._web3.eth.getBalance)(owner);
// Rewrap in a new BigNumber
balanceInWei = new BigNumber(balanceInWei);
return balanceInWei;
}
public async doesContractExistAtAddressAsync(address: string): Promise<boolean> {
const code = await promisify<string>(this.web3.eth.getCode)(address);
const code = await promisify<string>(this._web3.eth.getCode)(address);
// Regex matches 0x0, 0x00, 0x in order to accommodate poorly implemented clients
const codeIsEmpty = /^0x0{0,40}$/i.test(code);
return !codeIsEmpty;
}
public async signTransactionAsync(address: string, message: string): Promise<string> {
const signData = await promisify<string>(this.web3.eth.sign)(address, message);
const signData = await promisify<string>(this._web3.eth.sign)(address, message);
return signData;
}
public async getBlockNumberAsync(): Promise<number> {
const blockNumber = await promisify<number>(this.web3.eth.getBlockNumber)();
const blockNumber = await promisify<number>(this._web3.eth.getBlockNumber)();
return blockNumber;
}
public async getBlockAsync(blockParam: string|Web3.BlockParam): Promise<Web3.BlockWithoutTransactionData> {
const block = await promisify<Web3.BlockWithoutTransactionData>(this.web3.eth.getBlock)(blockParam);
const block = await promisify<Web3.BlockWithoutTransactionData>(this._web3.eth.getBlock)(blockParam);
return block;
}
public async getBlockTimestampAsync(blockParam: string|Web3.BlockParam): Promise<number> {
@@ -96,17 +102,17 @@ export class Web3Wrapper {
return timestamp;
}
public async getAvailableAddressesAsync(): Promise<string[]> {
const addresses = await promisify<string[]>(this.web3.eth.getAccounts)();
const addresses = await promisify<string[]>(this._web3.eth.getAccounts)();
return addresses;
}
public async getLogsAsync(filter: Web3.FilterObject): Promise<Web3.LogEntry[]> {
let fromBlock = filter.fromBlock;
if (_.isNumber(fromBlock)) {
fromBlock = this.web3.toHex(fromBlock);
fromBlock = this._web3.toHex(fromBlock);
}
let toBlock = filter.toBlock;
if (_.isNumber(toBlock)) {
toBlock = this.web3.toHex(toBlock);
toBlock = this._web3.toHex(toBlock);
}
const serializedFilter = {
...filter,
@@ -115,16 +121,16 @@ export class Web3Wrapper {
};
const payload = {
jsonrpc: '2.0',
id: this.jsonRpcRequestId++,
id: this._jsonRpcRequestId++,
method: 'eth_getLogs',
params: [serializedFilter],
};
const rawLogs = await this.sendRawPayloadAsync<RawLogEntry[]>(payload);
const formattedLogs = _.map(rawLogs, this.formatLog.bind(this));
const rawLogs = await this._sendRawPayloadAsync<RawLogEntry[]>(payload);
const formattedLogs = _.map(rawLogs, this._formatLog.bind(this));
return formattedLogs;
}
public getContractFromAbi(abi: Web3.ContractAbi): Web3.Contract<any> {
const web3Contract = this.web3.eth.contract(abi);
const web3Contract = this._web3.eth.contract(abi);
return web3Contract;
}
public getContractInstance(abi: Web3.ContractAbi, address: string): Web3.ContractInstance {
@@ -132,43 +138,43 @@ export class Web3Wrapper {
return web3ContractInstance;
}
public async estimateGasAsync(data: string): Promise<number> {
const gas = await promisify<number>(this.web3.eth.estimateGas)({data});
const gas = await promisify<number>(this._web3.eth.estimateGas)({data});
return gas;
}
private async sendRawPayloadAsync<A>(payload: Web3.JSONRPCRequestPayload): Promise<A> {
const sendAsync = this.web3.currentProvider.sendAsync.bind(this.web3.currentProvider);
private async _sendRawPayloadAsync<A>(payload: Web3.JSONRPCRequestPayload): Promise<A> {
const sendAsync = this._web3.currentProvider.sendAsync.bind(this._web3.currentProvider);
const response = await promisify<Web3.JSONRPCResponsePayload>(sendAsync)(payload);
const result = response.result;
return result;
}
private normalizeTxReceiptStatus(status: undefined|null|string|0|1): null|0|1 {
private _normalizeTxReceiptStatus(status: undefined|null|string|0|1): null|0|1 {
// Transaction status might have four values
// undefined - Testrpc and other old clients
// null - New clients on old transactions
// number - Parity
// hex - Geth
if (_.isString(status)) {
return this.web3.toDecimal(status) as 0|1;
return this._web3.toDecimal(status) as 0|1;
} else if (_.isUndefined(status)) {
return null;
} else {
return status;
}
}
private formatLog(rawLog: RawLogEntry): Web3.LogEntry {
private _formatLog(rawLog: RawLogEntry): Web3.LogEntry {
const formattedLog = {
...rawLog,
logIndex: this.hexToDecimal(rawLog.logIndex),
blockNumber: this.hexToDecimal(rawLog.blockNumber),
transactionIndex: this.hexToDecimal(rawLog.transactionIndex),
logIndex: this._hexToDecimal(rawLog.logIndex),
blockNumber: this._hexToDecimal(rawLog.blockNumber),
transactionIndex: this._hexToDecimal(rawLog.transactionIndex),
};
return formattedLog;
}
private hexToDecimal(hex: string|null): number|null {
private _hexToDecimal(hex: string|null): number|null {
if (_.isNull(hex)) {
return null;
}
const decimal = this.web3.toDecimal(hex);
const decimal = this._web3.toDecimal(hex);
return decimal;
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/website",
"version": "0.0.2",
"version": "0.0.4",
"private": true,
"description": "Website and 0x portal dapp",
"scripts": {
@@ -18,9 +18,9 @@
"author": "Fabio Berger",
"license": "Apache-2.0",
"dependencies": {
"0x.js": "~0.27.2",
"@0xproject/subproviders": "^0.1.0",
"@0xproject/utils": "^0.1.0",
"0x.js": "^0.29.0",
"@0xproject/subproviders": "^0.2.0",
"@0xproject/utils": "^0.1.2",
"accounting": "^0.4.1",
"basscss": "^8.0.3",
"bignumber.js": "~4.1.0",

View File

@@ -59,15 +59,15 @@ const BLOCK_NUMBER_BACK_TRACK = 50;
export class Blockchain {
public networkId: number;
public nodeVersion: string;
private zeroEx: ZeroEx;
private dispatcher: Dispatcher;
private web3Wrapper?: Web3Wrapper;
private exchangeAddress: string;
private userAddress: string;
private cachedProvider: Web3.Provider;
private ledgerSubprovider: LedgerWalletSubprovider;
private zrxPollIntervalId: NodeJS.Timer;
private static async onPageLoadAsync() {
private _zeroEx: ZeroEx;
private _dispatcher: Dispatcher;
private _web3Wrapper?: Web3Wrapper;
private _exchangeAddress: string;
private _userAddress: string;
private _cachedProvider: Web3.Provider;
private _ledgerSubprovider: LedgerWalletSubprovider;
private _zrxPollIntervalId: NodeJS.Timer;
private static async _onPageLoadAsync() {
if (document.readyState === 'complete') {
return; // Already loaded
}
@@ -75,7 +75,7 @@ export class Blockchain {
window.onload = resolve;
});
}
private static getNameGivenProvider(provider: Web3.Provider): string {
private static _getNameGivenProvider(provider: Web3.Provider): string {
if (!_.isUndefined((provider as any).isMetaMask)) {
return constants.PROVIDER_NAME_METAMASK;
}
@@ -89,7 +89,7 @@ export class Blockchain {
return constants.PROVIDER_NAME_GENERIC;
}
private static async getProviderAsync(injectedWeb3: Web3, networkIdIfExists: number) {
private static async _getProviderAsync(injectedWeb3: Web3, networkIdIfExists: number) {
const doesInjectedWeb3Exist = !_.isUndefined(injectedWeb3);
const publicNodeUrlsIfExistsForNetworkId = configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkIdIfExists];
const isPublicNodeAvailableForNetworkId = !_.isUndefined(publicNodeUrlsIfExistsForNetworkId);
@@ -126,29 +126,29 @@ export class Blockchain {
return provider;
}
constructor(dispatcher: Dispatcher, isSalePage: boolean = false) {
this.dispatcher = dispatcher;
this.userAddress = '';
this._dispatcher = dispatcher;
this._userAddress = '';
// tslint:disable-next-line:no-floating-promises
this.onPageLoadInitFireAndForgetAsync();
this._onPageLoadInitFireAndForgetAsync();
}
public async networkIdUpdatedFireAndForgetAsync(newNetworkId: number) {
const isConnected = !_.isUndefined(newNetworkId);
if (!isConnected) {
this.networkId = newNetworkId;
this.dispatcher.encounteredBlockchainError(BlockchainErrs.DisconnectedFromEthereumNode);
this.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
this._dispatcher.encounteredBlockchainError(BlockchainErrs.DisconnectedFromEthereumNode);
this._dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
} else if (this.networkId !== newNetworkId) {
this.networkId = newNetworkId;
this.dispatcher.encounteredBlockchainError(BlockchainErrs.NoError);
await this.fetchTokenInformationAsync();
await this.rehydrateStoreWithContractEvents();
this._dispatcher.encounteredBlockchainError(BlockchainErrs.NoError);
await this._fetchTokenInformationAsync();
await this._rehydrateStoreWithContractEvents();
}
}
public async userAddressUpdatedFireAndForgetAsync(newUserAddress: string) {
if (this.userAddress !== newUserAddress) {
this.userAddress = newUserAddress;
await this.fetchTokenInformationAsync();
await this.rehydrateStoreWithContractEvents();
if (this._userAddress !== newUserAddress) {
this._userAddress = newUserAddress;
await this._fetchTokenInformationAsync();
await this._rehydrateStoreWithContractEvents();
}
}
public async nodeVersionUpdatedFireAndForgetAsync(nodeVersion: string) {
@@ -157,7 +157,7 @@ export class Blockchain {
}
}
public async isAddressInTokenRegistryAsync(tokenAddress: string): Promise<boolean> {
utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
// HACK: temporarily whitelist the new WETH token address `as if` they were
// already in the tokenRegistry.
// TODO: Remove this hack once we've updated the TokenRegistries
@@ -166,30 +166,30 @@ export class Blockchain {
tokenAddress === configs.NEW_WRAPPED_ETHERS[this.networkId]) {
return true;
}
const tokenIfExists = await this.zeroEx.tokenRegistry.getTokenIfExistsAsync(tokenAddress);
const tokenIfExists = await this._zeroEx.tokenRegistry.getTokenIfExistsAsync(tokenAddress);
return !_.isUndefined(tokenIfExists);
}
public getLedgerDerivationPathIfExists(): string {
if (_.isUndefined(this.ledgerSubprovider)) {
if (_.isUndefined(this._ledgerSubprovider)) {
return undefined;
}
const path = this.ledgerSubprovider.getPath();
const path = this._ledgerSubprovider.getPath();
return path;
}
public updateLedgerDerivationPathIfExists(path: string) {
if (_.isUndefined(this.ledgerSubprovider)) {
if (_.isUndefined(this._ledgerSubprovider)) {
return; // noop
}
this.ledgerSubprovider.setPath(path);
this._ledgerSubprovider.setPath(path);
}
public updateLedgerDerivationIndex(pathIndex: number) {
if (_.isUndefined(this.ledgerSubprovider)) {
if (_.isUndefined(this._ledgerSubprovider)) {
return; // noop
}
this.ledgerSubprovider.setPathIndex(pathIndex);
this._ledgerSubprovider.setPathIndex(pathIndex);
}
public async providerTypeUpdatedFireAndForgetAsync(providerType: ProviderType) {
utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
// Should actually be Web3.Provider|ProviderEngine union type but it causes issues
// later on in the logic.
let provider;
@@ -201,17 +201,17 @@ export class Blockchain {
}
// Cache injected provider so that we can switch the user back to it easily
this.cachedProvider = this.web3Wrapper.getProviderObj();
this._cachedProvider = this._web3Wrapper.getProviderObj();
this.dispatcher.updateUserAddress(''); // Clear old userAddress
this._dispatcher.updateUserAddress(''); // Clear old userAddress
provider = new ProviderEngine();
const ledgerWalletConfigs = {
networkId: this.networkId,
ledgerEthereumClientFactoryAsync: ledgerEthereumBrowserClientFactoryAsync,
};
this.ledgerSubprovider = new LedgerSubprovider(ledgerWalletConfigs);
provider.addProvider(this.ledgerSubprovider);
this._ledgerSubprovider = new LedgerSubprovider(ledgerWalletConfigs);
provider.addProvider(this._ledgerSubprovider);
provider.addProvider(new FilterSubprovider());
const networkId = configs.IS_MAINNET_ENABLED ?
constants.NETWORK_ID_MAINNET :
@@ -220,25 +220,25 @@ export class Blockchain {
configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId],
));
provider.start();
this.web3Wrapper.destroy();
this._web3Wrapper.destroy();
const shouldPollUserAddress = false;
this.web3Wrapper = new Web3Wrapper(this.dispatcher, provider, this.networkId, shouldPollUserAddress);
this.zeroEx.setProvider(provider, networkId);
await this.postInstantiationOrUpdatingProviderZeroExAsync();
this._web3Wrapper = new Web3Wrapper(this._dispatcher, provider, this.networkId, shouldPollUserAddress);
this._zeroEx.setProvider(provider, networkId);
await this._postInstantiationOrUpdatingProviderZeroExAsync();
break;
}
case ProviderType.Injected: {
if (_.isUndefined(this.cachedProvider)) {
if (_.isUndefined(this._cachedProvider)) {
return; // Going from injected to injected, so we noop
}
provider = this.cachedProvider;
provider = this._cachedProvider;
const shouldPollUserAddress = true;
this.web3Wrapper = new Web3Wrapper(this.dispatcher, provider, this.networkId, shouldPollUserAddress);
this.zeroEx.setProvider(provider, this.networkId);
await this.postInstantiationOrUpdatingProviderZeroExAsync();
delete this.ledgerSubprovider;
delete this.cachedProvider;
this._web3Wrapper = new Web3Wrapper(this._dispatcher, provider, this.networkId, shouldPollUserAddress);
this._zeroEx.setProvider(provider, this.networkId);
await this._postInstantiationOrUpdatingProviderZeroExAsync();
delete this._ledgerSubprovider;
delete this._cachedProvider;
break;
}
@@ -246,28 +246,28 @@ export class Blockchain {
throw utils.spawnSwitchErr('providerType', providerType);
}
await this.fetchTokenInformationAsync();
await this._fetchTokenInformationAsync();
}
public async setProxyAllowanceAsync(token: Token, amountInBaseUnits: BigNumber): Promise<void> {
utils.assert(this.isValidAddress(token.address), BlockchainCallErrs.TokenAddressIsInvalid);
utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
const txHash = await this.zeroEx.token.setProxyAllowanceAsync(
token.address, this.userAddress, amountInBaseUnits,
const txHash = await this._zeroEx.token.setProxyAllowanceAsync(
token.address, this._userAddress, amountInBaseUnits,
);
await this.showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
await this._showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
const allowance = amountInBaseUnits;
this.dispatcher.replaceTokenAllowanceByAddress(token.address, allowance);
this._dispatcher.replaceTokenAllowanceByAddress(token.address, allowance);
}
public async transferAsync(token: Token, toAddress: string,
amountInBaseUnits: BigNumber): Promise<void> {
const txHash = await this.zeroEx.token.transferAsync(
token.address, this.userAddress, toAddress, amountInBaseUnits,
const txHash = await this._zeroEx.token.transferAsync(
token.address, this._userAddress, toAddress, amountInBaseUnits,
);
await this.showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
await this._showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
const etherScanLinkIfExists = utils.getEtherScanLinkIfExists(txHash, this.networkId, EtherscanLinkSuffixes.Tx);
this.dispatcher.showFlashMessage(React.createElement(TokenSendCompleted, {
this._dispatcher.showFlashMessage(React.createElement(TokenSendCompleted, {
etherScanLinkIfExists,
token,
toAddress,
@@ -302,16 +302,16 @@ export class Blockchain {
}
public async fillOrderAsync(signedOrder: SignedOrder,
fillTakerTokenAmount: BigNumber): Promise<BigNumber> {
utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
const shouldThrowOnInsufficientBalanceOrAllowance = true;
const txHash = await this.zeroEx.exchange.fillOrderAsync(
signedOrder, fillTakerTokenAmount, shouldThrowOnInsufficientBalanceOrAllowance, this.userAddress,
const txHash = await this._zeroEx.exchange.fillOrderAsync(
signedOrder, fillTakerTokenAmount, shouldThrowOnInsufficientBalanceOrAllowance, this._userAddress,
);
const receipt = await this.showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
const receipt = await this._showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
const logs: Array<LogWithDecodedArgs<ExchangeContractEventArgs>> = receipt.logs as any;
this.zeroEx.exchange.throwLogErrorsAsErrors(logs);
this._zeroEx.exchange.throwLogErrorsAsErrors(logs);
const logFill = _.find(logs, {event: 'LogFill'});
const args = logFill.args as any as LogFillContractEventArgs;
const filledTakerTokenAmount = args.filledTakerTokenAmount;
@@ -319,12 +319,12 @@ export class Blockchain {
}
public async cancelOrderAsync(signedOrder: SignedOrder,
cancelTakerTokenAmount: BigNumber): Promise<BigNumber> {
const txHash = await this.zeroEx.exchange.cancelOrderAsync(
const txHash = await this._zeroEx.exchange.cancelOrderAsync(
signedOrder, cancelTakerTokenAmount,
);
const receipt = await this.showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
const receipt = await this._showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
const logs: Array<LogWithDecodedArgs<ExchangeContractEventArgs>> = receipt.logs as any;
this.zeroEx.exchange.throwLogErrorsAsErrors(logs);
this._zeroEx.exchange.throwLogErrorsAsErrors(logs);
const logCancel = _.find(logs, {event: ExchangeEvents.LogCancel});
const args = logCancel.args as any as LogCancelContractEventArgs;
const cancelledTakerTokenAmount = args.cancelledTakerTokenAmount;
@@ -332,95 +332,95 @@ export class Blockchain {
}
public async getUnavailableTakerAmountAsync(orderHash: string): Promise<BigNumber> {
utils.assert(ZeroEx.isValidOrderHash(orderHash), 'Must be valid orderHash');
utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
const unavailableTakerAmount = await this.zeroEx.exchange.getUnavailableTakerAmountAsync(orderHash);
utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
const unavailableTakerAmount = await this._zeroEx.exchange.getUnavailableTakerAmountAsync(orderHash);
return unavailableTakerAmount;
}
public getExchangeContractAddressIfExists() {
return this.exchangeAddress;
return this._exchangeAddress;
}
public async validateFillOrderThrowIfInvalidAsync(signedOrder: SignedOrder,
fillTakerTokenAmount: BigNumber,
takerAddress: string): Promise<void> {
await this.zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
await this._zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
signedOrder, fillTakerTokenAmount, takerAddress);
}
public async validateCancelOrderThrowIfInvalidAsync(order: Order,
cancelTakerTokenAmount: BigNumber): Promise<void> {
await this.zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(order, cancelTakerTokenAmount);
await this._zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(order, cancelTakerTokenAmount);
}
public isValidAddress(address: string): boolean {
const lowercaseAddress = address.toLowerCase();
return this.web3Wrapper.isAddress(lowercaseAddress);
return this._web3Wrapper.isAddress(lowercaseAddress);
}
public async pollTokenBalanceAsync(token: Token) {
utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
const [currBalance] = await this.getTokenBalanceAndAllowanceAsync(this.userAddress, token.address);
const [currBalance] = await this.getTokenBalanceAndAllowanceAsync(this._userAddress, token.address);
this.zrxPollIntervalId = intervalUtils.setAsyncExcludingInterval(async () => {
const [balance] = await this.getTokenBalanceAndAllowanceAsync(this.userAddress, token.address);
this._zrxPollIntervalId = intervalUtils.setAsyncExcludingInterval(async () => {
const [balance] = await this.getTokenBalanceAndAllowanceAsync(this._userAddress, token.address);
if (!balance.eq(currBalance)) {
this.dispatcher.replaceTokenBalanceByAddress(token.address, balance);
clearInterval(this.zrxPollIntervalId);
delete this.zrxPollIntervalId;
this._dispatcher.replaceTokenBalanceByAddress(token.address, balance);
clearInterval(this._zrxPollIntervalId);
delete this._zrxPollIntervalId;
}
}, 5000);
}
public async signOrderHashAsync(orderHash: string): Promise<SignatureData> {
utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
const makerAddress = this.userAddress;
utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
const makerAddress = this._userAddress;
// If makerAddress is undefined, this means they have a web3 instance injected into their browser
// but no account addresses associated with it.
if (_.isUndefined(makerAddress)) {
throw new Error('Tried to send a sign request but user has no associated addresses');
}
const ecSignature = await this.zeroEx.signOrderHashAsync(orderHash, makerAddress);
const ecSignature = await this._zeroEx.signOrderHashAsync(orderHash, makerAddress);
const signatureData = _.extend({}, ecSignature, {
hash: orderHash,
});
this.dispatcher.updateSignatureData(signatureData);
this._dispatcher.updateSignatureData(signatureData);
return signatureData;
}
public async mintTestTokensAsync(token: Token) {
utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
const mintableContract = await this.instantiateContractIfExistsAsync(MintableArtifacts, token.address);
const mintableContract = await this._instantiateContractIfExistsAsync(MintableArtifacts, token.address);
await mintableContract.mint(constants.MINT_AMOUNT, {
from: this.userAddress,
from: this._userAddress,
});
const balanceDelta = constants.MINT_AMOUNT;
this.dispatcher.updateTokenBalanceByAddress(token.address, balanceDelta);
this._dispatcher.updateTokenBalanceByAddress(token.address, balanceDelta);
}
public async getBalanceInEthAsync(owner: string): Promise<BigNumber> {
const balance = await this.web3Wrapper.getBalanceInEthAsync(owner);
const balance = await this._web3Wrapper.getBalanceInEthAsync(owner);
return balance;
}
public async convertEthToWrappedEthTokensAsync(etherTokenAddress: string, amount: BigNumber): Promise<void> {
utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
const txHash = await this.zeroEx.etherToken.depositAsync(etherTokenAddress, amount, this.userAddress);
await this.showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
const txHash = await this._zeroEx.etherToken.depositAsync(etherTokenAddress, amount, this._userAddress);
await this._showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
}
public async convertWrappedEthTokensToEthAsync(etherTokenAddress: string, amount: BigNumber): Promise<void> {
utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
const txHash = await this.zeroEx.etherToken.withdrawAsync(etherTokenAddress, amount, this.userAddress);
await this.showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
const txHash = await this._zeroEx.etherToken.withdrawAsync(etherTokenAddress, amount, this._userAddress);
await this._showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
}
public async doesContractExistAtAddressAsync(address: string) {
const doesContractExist = await this.web3Wrapper.doesContractExistAtAddressAsync(address);
const doesContractExist = await this._web3Wrapper.doesContractExistAtAddressAsync(address);
return doesContractExist;
}
public async getCurrentUserTokenBalanceAndAllowanceAsync(tokenAddress: string): Promise<BigNumber[]> {
const tokenBalanceAndAllowance = await this.getTokenBalanceAndAllowanceAsync(this.userAddress, tokenAddress);
const tokenBalanceAndAllowance = await this.getTokenBalanceAndAllowanceAsync(this._userAddress, tokenAddress);
return tokenBalanceAndAllowance;
}
public async getTokenBalanceAndAllowanceAsync(ownerAddress: string, tokenAddress: string):
Promise<BigNumber[]> {
utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
if (_.isEmpty(ownerAddress)) {
const zero = new BigNumber(0);
@@ -428,9 +428,9 @@ export class Blockchain {
}
let balance = new BigNumber(0);
let allowance = new BigNumber(0);
if (this.doesUserAddressExist()) {
balance = await this.zeroEx.token.getBalanceAsync(tokenAddress, ownerAddress);
allowance = await this.zeroEx.token.getProxyAllowanceAsync(tokenAddress, ownerAddress);
if (this._doesUserAddressExist()) {
balance = await this._zeroEx.token.getBalanceAsync(tokenAddress, ownerAddress);
allowance = await this._zeroEx.token.getProxyAllowanceAsync(tokenAddress, ownerAddress);
}
return [balance, allowance];
}
@@ -439,11 +439,11 @@ export class Blockchain {
for (const token of tokens) {
let balance = new BigNumber(0);
let allowance = new BigNumber(0);
if (this.doesUserAddressExist()) {
if (this._doesUserAddressExist()) {
[
balance,
allowance,
] = await this.getTokenBalanceAndAllowanceAsync(this.userAddress, token.address);
] = await this.getTokenBalanceAndAllowanceAsync(this._userAddress, token.address);
}
const tokenState = {
balance,
@@ -451,61 +451,61 @@ export class Blockchain {
};
tokenStateByAddress[token.address] = tokenState;
}
this.dispatcher.updateTokenStateByAddress(tokenStateByAddress);
this._dispatcher.updateTokenStateByAddress(tokenStateByAddress);
}
public async getUserAccountsAsync() {
utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
const userAccountsIfExists = await this.zeroEx.getAvailableAddressesAsync();
utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
const userAccountsIfExists = await this._zeroEx.getAvailableAddressesAsync();
return userAccountsIfExists;
}
// HACK: When a user is using a Ledger, we simply dispatch the selected userAddress, which
// by-passes the web3Wrapper logic for updating the prevUserAddress. We therefore need to
// manually update it. This should only be called by the LedgerConfigDialog.
public updateWeb3WrapperPrevUserAddress(newUserAddress: string) {
this.web3Wrapper.updatePrevUserAddress(newUserAddress);
this._web3Wrapper.updatePrevUserAddress(newUserAddress);
}
public destroy() {
clearInterval(this.zrxPollIntervalId);
this.web3Wrapper.destroy();
this.stopWatchingExchangeLogFillEvents();
clearInterval(this._zrxPollIntervalId);
this._web3Wrapper.destroy();
this._stopWatchingExchangeLogFillEvents();
}
private async showEtherScanLinkAndAwaitTransactionMinedAsync(
private async _showEtherScanLinkAndAwaitTransactionMinedAsync(
txHash: string): Promise<TransactionReceiptWithDecodedLogs> {
const etherScanLinkIfExists = utils.getEtherScanLinkIfExists(txHash, this.networkId, EtherscanLinkSuffixes.Tx);
this.dispatcher.showFlashMessage(React.createElement(TransactionSubmitted, {
this._dispatcher.showFlashMessage(React.createElement(TransactionSubmitted, {
etherScanLinkIfExists,
}));
const receipt = await this.zeroEx.awaitTransactionMinedAsync(txHash);
const receipt = await this._zeroEx.awaitTransactionMinedAsync(txHash);
return receipt;
}
private doesUserAddressExist(): boolean {
return this.userAddress !== '';
private _doesUserAddressExist(): boolean {
return this._userAddress !== '';
}
private async rehydrateStoreWithContractEvents() {
private async _rehydrateStoreWithContractEvents() {
// Ensure we are only ever listening to one set of events
this.stopWatchingExchangeLogFillEvents();
this._stopWatchingExchangeLogFillEvents();
if (!this.doesUserAddressExist()) {
if (!this._doesUserAddressExist()) {
return; // short-circuit
}
if (!_.isUndefined(this.zeroEx)) {
if (!_.isUndefined(this._zeroEx)) {
// Since we do not have an index on the `taker` address and want to show
// transactions where an account is either the `maker` or `taker`, we loop
// through all fill events, and filter/cache them client-side.
const filterIndexObj = {};
await this.startListeningForExchangeLogFillEventsAsync(filterIndexObj);
await this._startListeningForExchangeLogFillEventsAsync(filterIndexObj);
}
}
private async startListeningForExchangeLogFillEventsAsync(indexFilterValues: IndexedFilterValues): Promise<void> {
utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
private async _startListeningForExchangeLogFillEventsAsync(indexFilterValues: IndexedFilterValues): Promise<void> {
utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
// Fetch historical logs
await this.fetchHistoricalExchangeLogFillEventsAsync(indexFilterValues);
await this._fetchHistoricalExchangeLogFillEventsAsync(indexFilterValues);
// Start a subscription for new logs
this.zeroEx.exchange.subscribe(
this._zeroEx.exchange.subscribe(
ExchangeEvents.LogFill, indexFilterValues,
async (err: Error, decodedLogEvent: DecodedLogEvent<LogFillContractEventArgs>) => {
if (err) {
@@ -517,40 +517,40 @@ export class Blockchain {
return;
} else {
const decodedLog = decodedLogEvent.log;
if (!this.doesLogEventInvolveUser(decodedLog)) {
if (!this._doesLogEventInvolveUser(decodedLog)) {
return; // We aren't interested in the fill event
}
this.updateLatestFillsBlockIfNeeded(decodedLog.blockNumber);
const fill = await this.convertDecodedLogToFillAsync(decodedLog);
this._updateLatestFillsBlockIfNeeded(decodedLog.blockNumber);
const fill = await this._convertDecodedLogToFillAsync(decodedLog);
if (decodedLogEvent.isRemoved) {
tradeHistoryStorage.removeFillFromUser(this.userAddress, this.networkId, fill);
tradeHistoryStorage.removeFillFromUser(this._userAddress, this.networkId, fill);
} else {
tradeHistoryStorage.addFillToUser(this.userAddress, this.networkId, fill);
tradeHistoryStorage.addFillToUser(this._userAddress, this.networkId, fill);
}
}
});
}
private async fetchHistoricalExchangeLogFillEventsAsync(indexFilterValues: IndexedFilterValues) {
const fromBlock = tradeHistoryStorage.getFillsLatestBlock(this.userAddress, this.networkId);
private async _fetchHistoricalExchangeLogFillEventsAsync(indexFilterValues: IndexedFilterValues) {
const fromBlock = tradeHistoryStorage.getFillsLatestBlock(this._userAddress, this.networkId);
const blockRange: BlockRange = {
fromBlock,
toBlock: 'latest' as BlockParam,
};
const decodedLogs = await this.zeroEx.exchange.getLogsAsync<LogFillContractEventArgs>(
const decodedLogs = await this._zeroEx.exchange.getLogsAsync<LogFillContractEventArgs>(
ExchangeEvents.LogFill, blockRange, indexFilterValues,
);
for (const decodedLog of decodedLogs) {
if (!this.doesLogEventInvolveUser(decodedLog)) {
if (!this._doesLogEventInvolveUser(decodedLog)) {
continue; // We aren't interested in the fill event
}
this.updateLatestFillsBlockIfNeeded(decodedLog.blockNumber);
const fill = await this.convertDecodedLogToFillAsync(decodedLog);
tradeHistoryStorage.addFillToUser(this.userAddress, this.networkId, fill);
this._updateLatestFillsBlockIfNeeded(decodedLog.blockNumber);
const fill = await this._convertDecodedLogToFillAsync(decodedLog);
tradeHistoryStorage.addFillToUser(this._userAddress, this.networkId, fill);
}
}
private async convertDecodedLogToFillAsync(decodedLog: LogWithDecodedArgs<LogFillContractEventArgs>) {
private async _convertDecodedLogToFillAsync(decodedLog: LogWithDecodedArgs<LogFillContractEventArgs>) {
const args = decodedLog.args;
const blockTimestamp = await this.web3Wrapper.getBlockTimestampAsync(decodedLog.blockHash);
const blockTimestamp = await this._web3Wrapper.getBlockTimestampAsync(decodedLog.blockHash);
const fill = {
filledTakerTokenAmount: args.filledTakerTokenAmount,
filledMakerTokenAmount: args.filledMakerTokenAmount,
@@ -567,13 +567,13 @@ export class Blockchain {
};
return fill;
}
private doesLogEventInvolveUser(decodedLog: LogWithDecodedArgs<LogFillContractEventArgs>) {
private _doesLogEventInvolveUser(decodedLog: LogWithDecodedArgs<LogFillContractEventArgs>) {
const args = decodedLog.args;
const isUserMakerOrTaker = args.maker === this.userAddress ||
args.taker === this.userAddress;
const isUserMakerOrTaker = args.maker === this._userAddress ||
args.taker === this._userAddress;
return isUserMakerOrTaker;
}
private updateLatestFillsBlockIfNeeded(blockNumber: number) {
private _updateLatestFillsBlockIfNeeded(blockNumber: number) {
const isBlockPending = _.isNull(blockNumber);
if (!isBlockPending) {
// Hack: I've observed the behavior where a client won't register certain fill events
@@ -585,15 +585,15 @@ export class Blockchain {
const blockNumberToSet = blockNumber - BLOCK_NUMBER_BACK_TRACK < 0 ?
0 :
blockNumber - BLOCK_NUMBER_BACK_TRACK;
tradeHistoryStorage.setFillsLatestBlock(this.userAddress, this.networkId, blockNumberToSet);
tradeHistoryStorage.setFillsLatestBlock(this._userAddress, this.networkId, blockNumberToSet);
}
}
private stopWatchingExchangeLogFillEvents(): void {
this.zeroEx.exchange.unsubscribeAll();
private _stopWatchingExchangeLogFillEvents(): void {
this._zeroEx.exchange.unsubscribeAll();
}
private async getTokenRegistryTokensByAddressAsync(): Promise<TokenByAddress> {
utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
const tokenRegistryTokens = await this.zeroEx.tokenRegistry.getTokensAsync();
private async _getTokenRegistryTokensByAddressAsync(): Promise<TokenByAddress> {
utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
const tokenRegistryTokens = await this._zeroEx.tokenRegistry.getTokensAsync();
const tokenByAddress: TokenByAddress = {};
_.each(tokenRegistryTokens, (t: ZeroExToken, i: number) => {
@@ -626,8 +626,8 @@ export class Blockchain {
});
return tokenByAddress;
}
private async onPageLoadInitFireAndForgetAsync() {
await Blockchain.onPageLoadAsync(); // wait for page to load
private async _onPageLoadInitFireAndForgetAsync() {
await Blockchain._onPageLoadAsync(); // wait for page to load
// Hack: We need to know the networkId the injectedWeb3 is connected to (if it is defined) in
// order to properly instantiate the web3Wrapper. Since we must use the async call, we cannot
@@ -645,7 +645,7 @@ export class Blockchain {
}
}
const provider = await Blockchain.getProviderAsync(injectedWeb3, networkIdIfExists);
const provider = await Blockchain._getProviderAsync(injectedWeb3, networkIdIfExists);
const networkId = !_.isUndefined(networkIdIfExists) ? networkIdIfExists :
configs.IS_MAINNET_ENABLED ?
constants.NETWORK_ID_MAINNET :
@@ -653,45 +653,45 @@ export class Blockchain {
const zeroExConfigs = {
networkId,
};
this.zeroEx = new ZeroEx(provider, zeroExConfigs);
this.updateProviderName(injectedWeb3);
this._zeroEx = new ZeroEx(provider, zeroExConfigs);
this._updateProviderName(injectedWeb3);
const shouldPollUserAddress = true;
this.web3Wrapper = new Web3Wrapper(this.dispatcher, provider, networkId, shouldPollUserAddress);
await this.postInstantiationOrUpdatingProviderZeroExAsync();
this._web3Wrapper = new Web3Wrapper(this._dispatcher, provider, networkId, shouldPollUserAddress);
await this._postInstantiationOrUpdatingProviderZeroExAsync();
}
// This method should always be run after instantiating or updating the provider
// of the ZeroEx instance.
private async postInstantiationOrUpdatingProviderZeroExAsync() {
utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
this.exchangeAddress = this.zeroEx.exchange.getContractAddress();
private async _postInstantiationOrUpdatingProviderZeroExAsync() {
utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
this._exchangeAddress = this._zeroEx.exchange.getContractAddress();
}
private updateProviderName(injectedWeb3: Web3) {
private _updateProviderName(injectedWeb3: Web3) {
const doesInjectedWeb3Exist = !_.isUndefined(injectedWeb3);
const providerName = doesInjectedWeb3Exist ?
Blockchain.getNameGivenProvider(injectedWeb3.currentProvider) :
Blockchain._getNameGivenProvider(injectedWeb3.currentProvider) :
constants.PROVIDER_NAME_PUBLIC;
this.dispatcher.updateInjectedProviderName(providerName);
this._dispatcher.updateInjectedProviderName(providerName);
}
private async fetchTokenInformationAsync() {
private async _fetchTokenInformationAsync() {
utils.assert(!_.isUndefined(this.networkId),
'Cannot call fetchTokenInformationAsync if disconnected from Ethereum node');
this.dispatcher.updateBlockchainIsLoaded(false);
this.dispatcher.clearTokenByAddress();
this._dispatcher.updateBlockchainIsLoaded(false);
this._dispatcher.clearTokenByAddress();
const tokenRegistryTokensByAddress = await this.getTokenRegistryTokensByAddressAsync();
const tokenRegistryTokensByAddress = await this._getTokenRegistryTokensByAddressAsync();
// HACK: We need to fetch the userAddress here because otherwise we cannot save the
// tracked tokens in localStorage under the users address nor fetch the token
// balances and allowances and we need to do this in order not to trigger the blockchain
// loading dialog to show up twice. First to load the contracts, and second to load the
// balances and allowances.
this.userAddress = await this.web3Wrapper.getFirstAccountIfExistsAsync();
if (!_.isEmpty(this.userAddress)) {
this.dispatcher.updateUserAddress(this.userAddress);
this._userAddress = await this._web3Wrapper.getFirstAccountIfExistsAsync();
if (!_.isEmpty(this._userAddress)) {
this._dispatcher.updateUserAddress(this._userAddress);
}
let trackedTokensIfExists = trackedTokenStorage.getTrackedTokensIfExists(this.userAddress, this.networkId);
let trackedTokensIfExists = trackedTokenStorage.getTrackedTokensIfExists(this._userAddress, this.networkId);
const tokenRegistryTokens = _.values(tokenRegistryTokensByAddress);
if (_.isUndefined(trackedTokensIfExists)) {
trackedTokensIfExists = _.map(configs.DEFAULT_TRACKED_TOKEN_SYMBOLS, symbol => {
@@ -700,7 +700,7 @@ export class Blockchain {
return token;
});
_.each(trackedTokensIfExists, token => {
trackedTokenStorage.addTrackedTokenToUser(this.userAddress, this.networkId, token);
trackedTokenStorage.addTrackedTokenToUser(this._userAddress, this.networkId, token);
});
} else {
// Properly set all tokenRegistry tokens `isTracked` to true if they are in the existing trackedTokens array
@@ -711,7 +711,7 @@ export class Blockchain {
});
}
const allTokens = _.uniq([...tokenRegistryTokens, ...trackedTokensIfExists]);
this.dispatcher.updateTokenByAddress(allTokens);
this._dispatcher.updateTokenByAddress(allTokens);
// Get balance/allowance for tracked tokens
await this.updateTokenBalancesAndAllowancesAsync(trackedTokensIfExists);
@@ -720,13 +720,13 @@ export class Blockchain {
_.find(allTokens, {symbol: configs.DEFAULT_TRACKED_TOKEN_SYMBOLS[0]}),
_.find(allTokens, {symbol: configs.DEFAULT_TRACKED_TOKEN_SYMBOLS[1]}),
];
this.dispatcher.updateChosenAssetTokenAddress(Side.Deposit, mostPopularTradingPairTokens[0].address);
this.dispatcher.updateChosenAssetTokenAddress(Side.Receive, mostPopularTradingPairTokens[1].address);
this.dispatcher.updateBlockchainIsLoaded(true);
this._dispatcher.updateChosenAssetTokenAddress(Side.Deposit, mostPopularTradingPairTokens[0].address);
this._dispatcher.updateChosenAssetTokenAddress(Side.Receive, mostPopularTradingPairTokens[1].address);
this._dispatcher.updateBlockchainIsLoaded(true);
}
private async instantiateContractIfExistsAsync(artifact: any, address?: string): Promise<ContractInstance> {
private async _instantiateContractIfExistsAsync(artifact: any, address?: string): Promise<ContractInstance> {
const c = await contract(artifact);
const providerObj = this.web3Wrapper.getProviderObj();
const providerObj = this._web3Wrapper.getProviderObj();
c.setProvider(providerObj);
const artifactNetworkConfigs = artifact.networks[this.networkId];

View File

@@ -31,7 +31,7 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp
const hasWalletAddress = this.props.userAddress !== '';
return (
<Dialog
title={this.getTitle(hasWalletAddress)}
title={this._getTitle(hasWalletAddress)}
titleStyle={{fontWeight: 100}}
actions={dialogActions}
open={this.props.isOpen}
@@ -40,12 +40,12 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp
autoScrollBodyContent={true}
>
<div className="pt2" style={{color: colors.grey700}}>
{this.renderExplanation(hasWalletAddress)}
{this._renderExplanation(hasWalletAddress)}
</div>
</Dialog>
);
}
private getTitle(hasWalletAddress: boolean) {
private _getTitle(hasWalletAddress: boolean) {
if (this.props.blockchainErr === BlockchainErrs.AContractNotDeployedOnNetwork) {
return '0x smart contracts not found';
} else if (!hasWalletAddress) {
@@ -56,18 +56,18 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp
return 'Unexpected error';
}
}
private renderExplanation(hasWalletAddress: boolean) {
private _renderExplanation(hasWalletAddress: boolean) {
if (this.props.blockchainErr === BlockchainErrs.AContractNotDeployedOnNetwork) {
return this.renderContractsNotDeployedExplanation();
return this._renderContractsNotDeployedExplanation();
} else if (!hasWalletAddress) {
return this.renderNoWalletFoundExplanation();
return this._renderNoWalletFoundExplanation();
} else if (this.props.blockchainErr === BlockchainErrs.DisconnectedFromEthereumNode) {
return this.renderDisconnectedFromNode();
return this._renderDisconnectedFromNode();
} else {
return this.renderUnexpectedErrorExplanation();
return this._renderUnexpectedErrorExplanation();
}
}
private renderDisconnectedFromNode() {
private _renderDisconnectedFromNode() {
return (
<div>
You were disconnected from the backing Ethereum node.
@@ -78,14 +78,14 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp
</div>
);
}
private renderUnexpectedErrorExplanation() {
private _renderUnexpectedErrorExplanation() {
return (
<div>
We encountered an unexpected error. Please try refreshing the page.
</div>
);
}
private renderNoWalletFoundExplanation() {
private _renderNoWalletFoundExplanation() {
return (
<div>
<div>
@@ -122,7 +122,7 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp
</div>
);
}
private renderContractsNotDeployedExplanation() {
private _renderContractsNotDeployedExplanation() {
return (
<div>
<div>

View File

@@ -29,7 +29,7 @@ export class EthWethConversionDialog extends
super();
this.state = {
shouldShowIncompleteErrs: false,
hasErrors: true,
hasErrors: false,
};
}
public render() {
@@ -37,13 +37,13 @@ export class EthWethConversionDialog extends
<FlatButton
key="cancel"
label="Cancel"
onTouchTap={this.onCancel.bind(this)}
onTouchTap={this._onCancel.bind(this)}
/>,
<FlatButton
key="convert"
label="Convert"
primary={true}
onTouchTap={this.onConvertClick.bind(this)}
onTouchTap={this._onConvertClick.bind(this)}
/>,
];
const title = this.props.direction === Side.Deposit ? 'Wrap ETH' : 'Unwrap WETH';
@@ -55,11 +55,11 @@ export class EthWethConversionDialog extends
contentStyle={{width: 448}}
open={this.props.isOpen}
>
{this.renderConversionDialogBody()}
{this._renderConversionDialogBody()}
</Dialog>
);
}
private renderConversionDialogBody() {
private _renderConversionDialogBody() {
const explanation = this.props.direction === Side.Deposit ?
'Convert your Ether into a tokenized, tradable form.' :
'Convert your Wrapped Ether back into it\'s native form.';
@@ -71,14 +71,14 @@ export class EthWethConversionDialog extends
</div>
<div className="mx-auto" style={{maxWidth: 312}}>
<div className="flex">
{this.renderCurrency(isWrappedVersion)}
{this._renderCurrency(isWrappedVersion)}
<div style={{paddingTop: 68}}>
<i
style={{fontSize: 28, color: colors.darkBlue}}
className="zmdi zmdi-arrow-right"
/>
</div>
{this.renderCurrency(!isWrappedVersion)}
{this._renderCurrency(!isWrappedVersion)}
</div>
<div
className="pt2 mx-auto"
@@ -91,14 +91,14 @@ export class EthWethConversionDialog extends
shouldShowIncompleteErrs={this.state.shouldShowIncompleteErrs}
shouldCheckBalance={true}
shouldCheckAllowance={false}
onChange={this.onValueChange.bind(this)}
onChange={this._onValueChange.bind(this)}
amount={this.state.value}
onVisitBalancesPageClick={this.props.onCancelled}
/> :
<EthAmountInput
balance={this.props.etherBalance}
amount={this.state.value}
onChange={this.onValueChange.bind(this)}
onChange={this._onValueChange.bind(this)}
shouldCheckBalance={true}
shouldShowIncompleteErrs={this.state.shouldShowIncompleteErrs}
onVisitBalancesPageClick={this.props.onCancelled}
@@ -112,7 +112,7 @@ export class EthWethConversionDialog extends
{this.props.direction === Side.Receive &&
<div
className="right"
onClick={this.onMaxClick.bind(this)}
onClick={this._onMaxClick.bind(this)}
style={{color: colors.darkBlue, textDecoration: 'underline', cursor: 'pointer'}}
>
Max
@@ -124,7 +124,7 @@ export class EthWethConversionDialog extends
</div>
);
}
private renderCurrency(isWrappedVersion: boolean) {
private _renderCurrency(isWrappedVersion: boolean) {
const name = isWrappedVersion ? 'Wrapped Ether' : 'Ether';
const iconUrl = isWrappedVersion ? '/images/token_icons/ether_erc20.png' : '/images/ether.png';
const symbol = isWrappedVersion ? 'WETH' : 'ETH';
@@ -145,18 +145,18 @@ export class EthWethConversionDialog extends
</div>
);
}
private onMaxClick() {
private _onMaxClick() {
this.setState({
value: this.props.tokenState.balance,
});
}
private onValueChange(isValid: boolean, amount?: BigNumber) {
private _onValueChange(isValid: boolean, amount?: BigNumber) {
this.setState({
value: amount,
hasErrors: !isValid,
});
}
private onConvertClick() {
private _onConvertClick() {
if (this.state.hasErrors) {
this.setState({
shouldShowIncompleteErrs: true,
@@ -169,7 +169,7 @@ export class EthWethConversionDialog extends
this.props.onComplete(this.props.direction, value);
}
}
private onCancel() {
private _onCancel() {
this.setState({
value: undefined,
});

View File

@@ -62,7 +62,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
<FlatButton
key="ledgerConnectCancel"
label="Cancel"
onTouchTap={this.onClose.bind(this)}
onTouchTap={this._onClose.bind(this)}
/>,
];
const dialogTitle = this.state.stepIndex === LedgerSteps.CONNECT ?
@@ -74,22 +74,22 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
titleStyle={{fontWeight: 100}}
actions={dialogActions}
open={this.props.isOpen}
onRequestClose={this.onClose.bind(this)}
onRequestClose={this._onClose.bind(this)}
autoScrollBodyContent={true}
bodyStyle={{paddingBottom: 0}}
>
<div style={{color: colors.grey700, paddingTop: 1}}>
{this.state.stepIndex === LedgerSteps.CONNECT &&
this.renderConnectStep()
this._renderConnectStep()
}
{this.state.stepIndex === LedgerSteps.SELECT_ADDRESS &&
this.renderSelectAddressStep()
this._renderSelectAddressStep()
}
</div>
</Dialog>
);
}
private renderConnectStep() {
private _renderConnectStep() {
return (
<div>
<div className="h4 pt3">
@@ -113,7 +113,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
labelReady="Connect to Ledger"
labelLoading="Connecting..."
labelComplete="Connected!"
onClickAsyncFn={this.onConnectLedgerClickAsync.bind(this, true)}
onClickAsyncFn={this._onConnectLedgerClickAsync.bind(this, true)}
/>
{this.state.didConnectFail &&
<div className="pt2 left-align" style={{color: colors.red200}}>
@@ -124,13 +124,13 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
</div>
);
}
private renderSelectAddressStep() {
private _renderSelectAddressStep() {
return (
<div>
<div>
<Table
bodyStyle={{height: 300}}
onRowSelection={this.onAddressSelected.bind(this)}
onRowSelection={this._onAddressSelected.bind(this)}
>
<TableHeader displaySelectAll={false}>
<TableRow>
@@ -139,7 +139,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
</TableRow>
</TableHeader>
<TableBody>
{this.renderAddressTableRows()}
{this._renderAddressTableRows()}
</TableBody>
</Table>
</div>
@@ -151,7 +151,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
floatingLabelText="Update path derivation (advanced)"
value={this.state.derivationPath}
errorText={this.state.derivationErrMsg}
onChange={this.onDerivationPathChanged.bind(this)}
onChange={this._onDerivationPathChanged.bind(this)}
/>
</div>
<div className="pl2" style={{paddingTop: 28}}>
@@ -159,14 +159,14 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
labelReady="Update"
labelLoading="Updating..."
labelComplete="Updated!"
onClickAsyncFn={this.onFetchAddressesForDerivationPathAsync.bind(this, true)}
onClickAsyncFn={this._onFetchAddressesForDerivationPathAsync.bind(this, true)}
/>
</div>
</div>
</div>
);
}
private renderAddressTableRows() {
private _renderAddressTableRows() {
const rows = _.map(this.state.userAddresses, (userAddress: string, i: number) => {
const balance = this.state.addressBalances[i];
const addressTooltipId = `address-${userAddress}`;
@@ -201,14 +201,14 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
});
return rows;
}
private onClose() {
private _onClose() {
this.setState({
didConnectFail: false,
});
const isOpen = false;
this.props.toggleDialogFn(isOpen);
}
private onAddressSelected(selectedRowIndexes: number[]) {
private _onAddressSelected(selectedRowIndexes: number[]) {
const selectedRowIndex = selectedRowIndexes[0];
this.props.blockchain.updateLedgerDerivationIndex(selectedRowIndex);
const selectedAddress = this.state.userAddresses[selectedRowIndex];
@@ -222,13 +222,13 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
const isOpen = false;
this.props.toggleDialogFn(isOpen);
}
private async onFetchAddressesForDerivationPathAsync() {
private async _onFetchAddressesForDerivationPathAsync() {
const currentlySetPath = this.props.blockchain.getLedgerDerivationPathIfExists();
if (currentlySetPath === this.state.derivationPath) {
return;
}
this.props.blockchain.updateLedgerDerivationPathIfExists(this.state.derivationPath);
const didSucceed = await this.fetchAddressesAndBalancesAsync();
const didSucceed = await this._fetchAddressesAndBalancesAsync();
if (!didSucceed) {
this.setState({
derivationErrMsg: 'Failed to connect to Ledger.',
@@ -236,11 +236,11 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
}
return didSucceed;
}
private async fetchAddressesAndBalancesAsync() {
private async _fetchAddressesAndBalancesAsync() {
let userAddresses: string[];
const addressBalances: BigNumber[] = [];
try {
userAddresses = await this.getUserAddressesAsync();
userAddresses = await this._getUserAddressesAsync();
for (const address of userAddresses) {
const balance = await this.props.blockchain.getBalanceInEthAsync(address);
addressBalances.push(balance);
@@ -258,7 +258,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
});
return true;
}
private onDerivationPathChanged(e: any, derivationPath: string) {
private _onDerivationPathChanged(e: any, derivationPath: string) {
let derivationErrMsg = '';
if (!_.startsWith(derivationPath, VALID_ETHEREUM_DERIVATION_PATH_PREFIX)) {
derivationErrMsg = 'Must be valid Ethereum path.';
@@ -269,8 +269,8 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
derivationErrMsg,
});
}
private async onConnectLedgerClickAsync() {
const didSucceed = await this.fetchAddressesAndBalancesAsync();
private async _onConnectLedgerClickAsync() {
const didSucceed = await this._fetchAddressesAndBalancesAsync();
if (didSucceed) {
this.setState({
stepIndex: LedgerSteps.SELECT_ADDRESS,
@@ -278,7 +278,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
}
return didSucceed;
}
private async getUserAddressesAsync(): Promise<string[]> {
private async _getUserAddressesAsync(): Promise<string[]> {
let userAddresses: string[];
userAddresses = await this.props.blockchain.getUserAccountsAsync();

View File

@@ -36,14 +36,14 @@ export class SendDialog extends React.Component<SendDialogProps, SendDialogState
<FlatButton
key="cancelTransfer"
label="Cancel"
onTouchTap={this.onCancel.bind(this)}
onTouchTap={this._onCancel.bind(this)}
/>,
<FlatButton
key="sendTransfer"
disabled={this.hasErrors()}
disabled={this._hasErrors()}
label="Send"
primary={true}
onTouchTap={this.onSendClick.bind(this)}
onTouchTap={this._onSendClick.bind(this)}
/>,
];
return (
@@ -53,17 +53,17 @@ export class SendDialog extends React.Component<SendDialogProps, SendDialogState
actions={transferDialogActions}
open={this.props.isOpen}
>
{this.renderSendDialogBody()}
{this._renderSendDialogBody()}
</Dialog>
);
}
private renderSendDialogBody() {
private _renderSendDialogBody() {
return (
<div className="mx-auto" style={{maxWidth: 300}}>
<div style={{height: 80}}>
<AddressInput
initialAddress={this.state.recipient}
updateAddress={this.onRecipientChange.bind(this)}
updateAddress={this._onRecipientChange.bind(this)}
isRequired={true}
label={'Recipient address'}
hintText={'Address'}
@@ -76,27 +76,27 @@ export class SendDialog extends React.Component<SendDialogProps, SendDialogState
shouldShowIncompleteErrs={this.state.shouldShowIncompleteErrs}
shouldCheckBalance={true}
shouldCheckAllowance={false}
onChange={this.onValueChange.bind(this)}
onChange={this._onValueChange.bind(this)}
amount={this.state.value}
onVisitBalancesPageClick={this.props.onCancelled}
/>
</div>
);
}
private onRecipientChange(recipient?: string) {
private _onRecipientChange(recipient?: string) {
this.setState({
shouldShowIncompleteErrs: false,
recipient,
});
}
private onValueChange(isValid: boolean, amount?: BigNumber) {
private _onValueChange(isValid: boolean, amount?: BigNumber) {
this.setState({
isAmountValid: isValid,
value: amount,
});
}
private onSendClick() {
if (this.hasErrors()) {
private _onSendClick() {
if (this._hasErrors()) {
this.setState({
shouldShowIncompleteErrs: true,
});
@@ -109,13 +109,13 @@ export class SendDialog extends React.Component<SendDialogProps, SendDialogState
this.props.onComplete(this.state.recipient, value);
}
}
private onCancel() {
private _onCancel() {
this.setState({
value: undefined,
});
this.props.onCancelled();
}
private hasErrors() {
private _hasErrors() {
return _.isUndefined(this.state.recipient) ||
_.isUndefined(this.state.value) ||
!this.state.isAmountValid;

View File

@@ -41,12 +41,12 @@ export class TrackTokenConfirmationDialog extends
<FlatButton
key="trackNo"
label="No"
onTouchTap={this.onTrackConfirmationRespondedAsync.bind(this, false)}
onTouchTap={this._onTrackConfirmationRespondedAsync.bind(this, false)}
/>,
<FlatButton
key="trackYes"
label="Yes"
onTouchTap={this.onTrackConfirmationRespondedAsync.bind(this, true)}
onTouchTap={this._onTrackConfirmationRespondedAsync.bind(this, true)}
/>,
]}
open={this.props.isOpen}
@@ -64,7 +64,7 @@ export class TrackTokenConfirmationDialog extends
</Dialog>
);
}
private async onTrackConfirmationRespondedAsync(didUserAcceptTracking: boolean) {
private async _onTrackConfirmationRespondedAsync(didUserAcceptTracking: boolean) {
if (!didUserAcceptTracking) {
this.props.onToggleDialog(didUserAcceptTracking);
return;

View File

@@ -59,13 +59,13 @@ export class EthWethConversionButton extends
labelStyle={labelStyle}
disabled={this.props.isDisabled || this.state.isEthConversionHappening}
label={this.state.isEthConversionHappening ? inProgressLabel : callToActionLabel}
onClick={this.toggleConversionDialog.bind(this)}
onClick={this._toggleConversionDialog.bind(this)}
/>
<EthWethConversionDialog
direction={this.props.direction}
isOpen={this.state.isEthConversionDialogVisible}
onComplete={this.onConversionAmountSelectedAsync.bind(this)}
onCancelled={this.toggleConversionDialog.bind(this)}
onComplete={this._onConversionAmountSelectedAsync.bind(this)}
onCancelled={this._toggleConversionDialog.bind(this)}
etherBalance={this.props.userEtherBalance}
token={this.props.ethToken}
tokenState={this.props.ethTokenState}
@@ -73,16 +73,16 @@ export class EthWethConversionButton extends
</div>
);
}
private toggleConversionDialog() {
private _toggleConversionDialog() {
this.setState({
isEthConversionDialogVisible: !this.state.isEthConversionDialogVisible,
});
}
private async onConversionAmountSelectedAsync(direction: Side, value: BigNumber) {
private async _onConversionAmountSelectedAsync(direction: Side, value: BigNumber) {
this.setState({
isEthConversionHappening: true,
});
this.toggleConversionDialog();
this._toggleConversionDialog();
const token = this.props.ethToken;
const tokenState = this.props.ethTokenState;
let balance = tokenState.balance;
@@ -109,11 +109,11 @@ export class EthWethConversionButton extends
} else if (!_.includes(errMsg, 'User denied transaction')) {
utils.consoleLog(`Unexpected error encountered: ${err}`);
utils.consoleLog(err.stack);
await errorReporter.reportAsync(err);
const errorMsg = direction === Side.Deposit ?
'Failed to wrap your ETH. Please try again.' :
'Failed to unwrap your WETH. Please try again.';
this.props.dispatcher.showFlashMessage(errorMsg);
await errorReporter.reportAsync(err);
}
}
this.setState({

View File

@@ -61,7 +61,7 @@ interface EthWrappersState {
export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersState> {
constructor(props: EthWrappersProps) {
super(props);
const outdatedWETHAddresses = this.getOutdatedWETHAddresses();
const outdatedWETHAddresses = this._getOutdatedWETHAddresses();
const outdatedWETHAddressToIsStateLoaded: OutdatedWETHAddressToIsStateLoaded = {};
const outdatedWETHStateByAddress: OutdatedWETHStateByAddress = {};
_.each(outdatedWETHAddresses, outdatedWETHAddress => {
@@ -79,7 +79,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
public componentDidMount() {
window.scrollTo(0, 0);
// tslint:disable-next-line:no-floating-promises
this.fetchOutdatedWETHStateAsync();
this._fetchOutdatedWETHStateAsync();
}
public render() {
const tokens = _.values(this.props.tokenByAddress);
@@ -90,7 +90,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
const etherscanUrl = utils.getEtherScanLinkIfExists(
etherToken.address, this.props.networkId, EtherscanLinkSuffixes.Address,
);
const tokenLabel = this.renderToken('Wrapped Ether', etherToken.address, configs.ICON_URL_BY_SYMBOL.WETH);
const tokenLabel = this._renderToken('Wrapped Ether', etherToken.address, configs.ICON_URL_BY_SYMBOL.WETH);
return (
<div className="clearfix lg-px4 md-px4 sm-px2" style={{minHeight: 600}}>
<div className="relative">
@@ -125,7 +125,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
<TableHeaderColumn>ETH Token</TableHeaderColumn>
<TableHeaderColumn>Balance</TableHeaderColumn>
<TableHeaderColumn className="center">
{this.renderActionColumnTitle(isBidirectional)}
{this._renderActionColumnTitle(isBidirectional)}
</TableHeaderColumn>
</TableRow>
</TableHeader>
@@ -162,7 +162,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
</TableRow>
<TableRow key="WETH">
<TableRowColumn className="py1">
{this.renderTokenLink(tokenLabel, etherscanUrl)}
{this._renderTokenLink(tokenLabel, etherscanUrl)}
</TableRowColumn>
<TableRowColumn>
{wethBalance.toFixed(PRECISION)} WETH
@@ -207,12 +207,12 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
<TableHeaderColumn>WETH Version</TableHeaderColumn>
<TableHeaderColumn>Balance</TableHeaderColumn>
<TableHeaderColumn className="center">
{this.renderActionColumnTitle(!isBidirectional)}
{this._renderActionColumnTitle(!isBidirectional)}
</TableHeaderColumn>
</TableRow>
</TableHeader>
<TableBody displayRowCheckbox={false}>
{this.renderOutdatedWeths(etherToken, etherTokenState)}
{this._renderOutdatedWeths(etherToken, etherTokenState)}
</TableBody>
</Table>
</div>
@@ -220,7 +220,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
</div>
);
}
private renderActionColumnTitle(isBidirectional: boolean) {
private _renderActionColumnTitle(isBidirectional: boolean) {
let iconClass = 'zmdi-long-arrow-right';
let leftSymbol = 'WETH';
let rightSymbol = 'ETH';
@@ -242,7 +242,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
</div>
);
}
private renderOutdatedWeths(etherToken: Token, etherTokenState: TokenState) {
private _renderOutdatedWeths(etherToken: Token, etherTokenState: TokenState) {
const rows = _.map(configs.OUTDATED_WRAPPED_ETHERS,
(outdatedWETHByNetworkId: OutdatedWrappedEtherByNetworkId) => {
const outdatedWETHIfExists = outdatedWETHByNetworkId[this.props.networkId];
@@ -269,17 +269,17 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
outdatedEtherTokenState.balance, constants.DECIMAL_PLACES_ETH,
).toFixed(PRECISION) :
undefined;
const onConversionSuccessful = this.onOutdatedConversionSuccessfulAsync.bind(
const onConversionSuccessful = this._onOutdatedConversionSuccessfulAsync.bind(
this, outdatedWETHIfExists.address,
);
const etherscanUrl = utils.getEtherScanLinkIfExists(
outdatedWETHIfExists.address, this.props.networkId, EtherscanLinkSuffixes.Address,
);
const tokenLabel = this.renderToken(dateRange, outdatedEtherToken.address, OUTDATED_WETH_ICON_PATH);
const tokenLabel = this._renderToken(dateRange, outdatedEtherToken.address, OUTDATED_WETH_ICON_PATH);
return (
<TableRow key={`weth-${outdatedWETHIfExists.address}`}>
<TableRowColumn className="py1">
{this.renderTokenLink(tokenLabel, etherscanUrl)}
{this._renderTokenLink(tokenLabel, etherscanUrl)}
</TableRowColumn>
<TableRowColumn>
{isStateLoaded ?
@@ -305,7 +305,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
});
return rows;
}
private renderTokenLink(tokenLabel: React.ReactNode, etherscanUrl: string) {
private _renderTokenLink(tokenLabel: React.ReactNode, etherscanUrl: string) {
return (
<span>
{_.isUndefined(etherscanUrl) ?
@@ -317,7 +317,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
</span>
);
}
private renderToken(name: string, address: string, imgPath: string) {
private _renderToken(name: string, address: string, imgPath: string) {
const tooltipId = `tooltip-${address}`;
return (
<div className="flex">
@@ -340,7 +340,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
</div>
);
}
private async onOutdatedConversionSuccessfulAsync(outdatedWETHAddress: string) {
private async _onOutdatedConversionSuccessfulAsync(outdatedWETHAddress: string) {
this.setState({
outdatedWETHAddressToIsStateLoaded: {
...this.state.outdatedWETHAddressToIsStateLoaded,
@@ -364,8 +364,8 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
},
});
}
private async fetchOutdatedWETHStateAsync() {
const outdatedWETHAddresses = this.getOutdatedWETHAddresses();
private async _fetchOutdatedWETHStateAsync() {
const outdatedWETHAddresses = this._getOutdatedWETHAddresses();
const outdatedWETHAddressToIsStateLoaded: OutdatedWETHAddressToIsStateLoaded = {};
const outdatedWETHStateByAddress: OutdatedWETHStateByAddress = {};
for (const address of outdatedWETHAddresses) {
@@ -383,7 +383,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
outdatedWETHAddressToIsStateLoaded,
});
}
private getOutdatedWETHAddresses(): string[] {
private _getOutdatedWETHAddresses(): string[] {
const outdatedWETHAddresses = _.compact(_.map(configs.OUTDATED_WRAPPED_ETHERS,
outdatedWrappedEtherByNetwork => {
const outdatedWrappedEtherIfExists = outdatedWrappedEtherByNetwork[this.props.networkId];

View File

@@ -66,7 +66,7 @@ interface FillOrderState {
}
export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
private validator: SchemaValidator;
private _validator: SchemaValidator;
constructor(props: FillOrderProps) {
super(props);
this.state = {
@@ -87,12 +87,12 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
isConfirmingTokenTracking: false,
tokensToTrack: [],
};
this.validator = new SchemaValidator();
this._validator = new SchemaValidator();
}
public componentWillMount() {
if (!_.isEmpty(this.state.orderJSON)) {
// tslint:disable-next-line:no-floating-promises
this.validateFillOrderFireAndForgetAsync(this.state.orderJSON);
this._validateFillOrderFireAndForgetAsync(this.state.orderJSON);
}
}
public componentDidMount() {
@@ -115,15 +115,15 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
tokenByAddress={this.props.tokenByAddress}
networkId={this.props.networkId}
orderJSON={this.state.orderJSON}
onFillOrderJSONChanged={this.onFillOrderJSONChanged.bind(this)}
onFillOrderJSONChanged={this._onFillOrderJSONChanged.bind(this)}
/>
{this.renderOrderJsonNotices()}
{this._renderOrderJsonNotices()}
</div>
}
<div>
{!_.isUndefined(this.state.parsedOrder) && this.state.didOrderValidationRun
&& this.state.areAllInvolvedTokensTracked &&
this.renderVisualOrder()
this._renderVisualOrder()
}
</div>
{this.props.isOrderInUrl &&
@@ -140,17 +140,17 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
tokenByAddress={this.props.tokenByAddress}
networkId={this.props.networkId}
orderJSON={this.state.orderJSON}
onFillOrderJSONChanged={this.onFillOrderJSONChanged.bind(this)}
onFillOrderJSONChanged={this._onFillOrderJSONChanged.bind(this)}
/>
</CardText>
</Card>
{this.renderOrderJsonNotices()}
{this._renderOrderJsonNotices()}
</div>
}
</div>
<FillWarningDialog
isOpen={this.state.isFillWarningDialogOpen}
onToggleDialog={this.onFillWarningClosed.bind(this)}
onToggleDialog={this._onFillWarningClosed.bind(this)}
/>
<TrackTokenConfirmationDialog
userAddress={this.props.userAddress}
@@ -160,12 +160,12 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
dispatcher={this.props.dispatcher}
tokens={this.state.tokensToTrack}
isOpen={this.state.isConfirmingTokenTracking}
onToggleDialog={this.onToggleTrackConfirmDialog.bind(this)}
onToggleDialog={this._onToggleTrackConfirmDialog.bind(this)}
/>
</div>
);
}
private renderOrderJsonNotices() {
private _renderOrderJsonNotices() {
return (
<div>
{!_.isUndefined(this.props.initialOrder) && !this.state.didOrderValidationRun &&
@@ -182,7 +182,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
</div>
);
}
private renderVisualOrder() {
private _renderVisualOrder() {
const takerTokenAddress = this.state.parsedOrder.taker.token.address;
const takerToken = this.props.tokenByAddress[takerTokenAddress];
const orderTakerAmount = new BigNumber(this.state.parsedOrder.taker.amount);
@@ -211,7 +211,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
let orderReceiveAmount = 0;
if (!_.isUndefined(this.props.orderFillAmount)) {
const orderReceiveAmountBigNumber = exchangeRate.mul(this.props.orderFillAmount);
orderReceiveAmount = this.formatCurrencyAmount(orderReceiveAmountBigNumber, makerToken.decimals);
orderReceiveAmount = this._formatCurrencyAmount(orderReceiveAmountBigNumber, makerToken.decimals);
}
const isUserMaker = !_.isUndefined(this.state.parsedOrder) &&
this.state.parsedOrder.maker.address === this.props.userAddress;
@@ -261,7 +261,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
<div className="clearfix mx-auto relative" style={{width: 235, height: 108}}>
<TokenAmountInput
label="Fill amount"
onChange={this.onFillAmountChange.bind(this)}
onChange={this._onFillAmountChange.bind(this)}
shouldShowIncompleteErrs={false}
token={fillToken}
tokenState={fillTokenState}
@@ -284,12 +284,12 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
style={{width: '100%'}}
disabled={this.state.isCancelling}
label={this.state.isCancelling ? 'Cancelling order...' : 'Cancel order'}
onClick={this.onCancelOrderClickFireAndForgetAsync.bind(this)}
onClick={this._onCancelOrderClickFireAndForgetAsync.bind(this)}
/>
{this.state.didCancelOrderSucceed &&
<Alert
type={AlertTypes.SUCCESS}
message={this.renderCancelSuccessMsg()}
message={this._renderCancelSuccessMsg()}
/>
}
</div> :
@@ -298,7 +298,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
style={{width: '100%'}}
disabled={this.state.isFilling}
label={this.state.isFilling ? 'Filling order...' : 'Fill order'}
onClick={this.onFillOrderClick.bind(this)}
onClick={this._onFillOrderClick.bind(this)}
/>
{!_.isEmpty(this.state.globalErrMsg) &&
<Alert type={AlertTypes.ERROR} message={this.state.globalErrMsg} />
@@ -306,7 +306,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
{this.state.didFillOrderSucceed &&
<Alert
type={AlertTypes.SUCCESS}
message={this.renderFillSuccessMsg()}
message={this._renderFillSuccessMsg()}
/>
}
</div>
@@ -315,7 +315,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
</div>
);
}
private renderFillSuccessMsg() {
private _renderFillSuccessMsg() {
return (
<div>
Order successfully filled. See the trade details in your{' '}
@@ -328,45 +328,45 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
</div>
);
}
private renderCancelSuccessMsg() {
private _renderCancelSuccessMsg() {
return (
<div>
Order successfully cancelled.
</div>
);
}
private onFillOrderClick() {
private _onFillOrderClick() {
if (!this.state.isMakerTokenAddressInRegistry || !this.state.isTakerTokenAddressInRegistry) {
this.setState({
isFillWarningDialogOpen: true,
});
} else {
// tslint:disable-next-line:no-floating-promises
this.onFillOrderClickFireAndForgetAsync();
this._onFillOrderClickFireAndForgetAsync();
}
}
private onFillWarningClosed(didUserCancel: boolean) {
private _onFillWarningClosed(didUserCancel: boolean) {
this.setState({
isFillWarningDialogOpen: false,
});
if (!didUserCancel) {
// tslint:disable-next-line:no-floating-promises
this.onFillOrderClickFireAndForgetAsync();
this._onFillOrderClickFireAndForgetAsync();
}
}
private onFillAmountChange(isValid: boolean, amount?: BigNumber) {
private _onFillAmountChange(isValid: boolean, amount?: BigNumber) {
this.props.dispatcher.updateOrderFillAmount(amount);
}
private onFillOrderJSONChanged(event: any) {
private _onFillOrderJSONChanged(event: any) {
const orderJSON = event.target.value;
this.setState({
didOrderValidationRun: _.isEmpty(orderJSON) && _.isEmpty(this.state.orderJSONErrMsg),
didFillOrderSucceed: false,
});
// tslint:disable-next-line:no-floating-promises
this.validateFillOrderFireAndForgetAsync(orderJSON);
this._validateFillOrderFireAndForgetAsync(orderJSON);
}
private async checkForUntrackedTokensAndAskToAdd() {
private async _checkForUntrackedTokensAndAskToAdd() {
if (!_.isEmpty(this.state.orderJSONErrMsg)) {
return;
}
@@ -410,12 +410,12 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
});
}
}
private async validateFillOrderFireAndForgetAsync(orderJSON: string) {
private async _validateFillOrderFireAndForgetAsync(orderJSON: string) {
let orderJSONErrMsg = '';
let parsedOrder: Order;
try {
const order = JSON.parse(orderJSON);
const validationResult = this.validator.validate(order, orderSchema);
const validationResult = this._validator.validate(order, orderSchema);
if (validationResult.errors.length > 0) {
orderJSONErrMsg = 'Submitted order JSON is not a valid order';
utils.consoleLog(`Unexpected order JSON validation error: ${validationResult.errors.join(', ')}`);
@@ -508,9 +508,9 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
unavailableTakerAmount,
});
await this.checkForUntrackedTokensAndAskToAdd();
await this._checkForUntrackedTokensAndAskToAdd();
}
private async onFillOrderClickFireAndForgetAsync(): Promise<void> {
private async _onFillOrderClickFireAndForgetAsync(): Promise<void> {
if (!_.isEmpty(this.props.blockchainErr) || _.isEmpty(this.props.userAddress)) {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
return;
@@ -594,14 +594,14 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
}
globalErrMsg = 'Failed to fill order, please refresh and try again';
utils.consoleLog(`${err}`);
await errorReporter.reportAsync(err);
this.setState({
globalErrMsg,
});
await errorReporter.reportAsync(err);
return;
}
}
private async onCancelOrderClickFireAndForgetAsync(): Promise<void> {
private async _onCancelOrderClickFireAndForgetAsync(): Promise<void> {
if (!_.isEmpty(this.props.blockchainErr) || _.isEmpty(this.props.userAddress)) {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
return;
@@ -677,19 +677,19 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
}
globalErrMsg = 'Failed to cancel order, please refresh and try again';
utils.consoleLog(`${err}`);
await errorReporter.reportAsync(err);
this.setState({
globalErrMsg,
});
await errorReporter.reportAsync(err);
return;
}
}
private formatCurrencyAmount(amount: BigNumber, decimals: number): number {
private _formatCurrencyAmount(amount: BigNumber, decimals: number): number {
const unitAmount = ZeroEx.toUnitAmount(amount, decimals);
const roundedUnitAmount = Math.round(unitAmount.toNumber() * 100000) / 100000;
return roundedUnitAmount;
}
private onToggleTrackConfirmDialog(didConfirmTokenTracking: boolean) {
private _onToggleTrackConfirmDialog(didConfirmTokenTracking: boolean) {
if (!didConfirmTokenTracking) {
this.setState({
orderJSON: '',

View File

@@ -133,20 +133,20 @@ export class Footer extends React.Component<FooterProps, FooterState> {
<div className="col lg-col-8 md-col-8 col-12 lg-pl4 md-pl4">
<div className="col lg-col-4 md-col-4 col-12">
<div className="lg-right md-right sm-center">
{this.renderHeader(Sections.Documentation)}
{_.map(menuItemsBySection[Sections.Documentation], this.renderMenuItem.bind(this))}
{this._renderHeader(Sections.Documentation)}
{_.map(menuItemsBySection[Sections.Documentation], this._renderMenuItem.bind(this))}
</div>
</div>
<div className="col lg-col-4 md-col-4 col-12 lg-pr2 md-pr2">
<div className="lg-right md-right sm-center">
{this.renderHeader(Sections.Community)}
{_.map(menuItemsBySection[Sections.Community], this.renderMenuItem.bind(this))}
{this._renderHeader(Sections.Community)}
{_.map(menuItemsBySection[Sections.Community], this._renderMenuItem.bind(this))}
</div>
</div>
<div className="col lg-col-4 md-col-4 col-12">
<div className="lg-right md-right sm-center">
{this.renderHeader(Sections.Organization)}
{_.map(menuItemsBySection[Sections.Organization], this.renderMenuItem.bind(this))}
{this._renderHeader(Sections.Organization)}
{_.map(menuItemsBySection[Sections.Organization], this._renderMenuItem.bind(this))}
</div>
</div>
</div>
@@ -154,14 +154,14 @@ export class Footer extends React.Component<FooterProps, FooterState> {
</div>
);
}
private renderIcon(fileName: string) {
private _renderIcon(fileName: string) {
return (
<div style={{height: ICON_DIMENSION, width: ICON_DIMENSION}}>
<img src={`/images/social/${fileName}`} style={{width: ICON_DIMENSION}} />
</div>
);
}
private renderMenuItem(item: FooterMenuItem) {
private _renderMenuItem(item: FooterMenuItem) {
const iconIfExists = titleToIcon[item.title];
return (
<div
@@ -180,7 +180,7 @@ export class Footer extends React.Component<FooterProps, FooterState> {
<div className="sm-mx-auto" style={{width: 65}}>
<div className="flex">
<div className="pr1">
{this.renderIcon(iconIfExists)}
{this._renderIcon(iconIfExists)}
</div>
<div>{item.title}</div>
</div>
@@ -196,7 +196,7 @@ export class Footer extends React.Component<FooterProps, FooterState> {
<div>
{!_.isUndefined(iconIfExists) &&
<div className="pr1">
{this.renderIcon(iconIfExists)}
{this._renderIcon(iconIfExists)}
</div>
}
{item.title}
@@ -206,7 +206,7 @@ export class Footer extends React.Component<FooterProps, FooterState> {
</div>
);
}
private renderHeader(title: string) {
private _renderHeader(title: string) {
const headerStyle = {
textTransform: 'uppercase',
color: colors.grey400,

View File

@@ -47,7 +47,7 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
public static defaultProps: Partial<AssetPickerProps> = {
tokenVisibility: TokenVisibility.ALL,
};
private dialogConfigsByAssetView: {[assetView: string]: DialogConfigs};
private _dialogConfigsByAssetView: {[assetView: string]: DialogConfigs};
constructor(props: AssetPickerProps) {
super(props);
this.state = {
@@ -56,7 +56,7 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
chosenTrackTokenAddress: undefined,
isAddingTokenToTracked: false,
};
this.dialogConfigsByAssetView = {
this._dialogConfigsByAssetView = {
[AssetViews.ASSET_PICKER]: {
title: 'Select token',
isModal: false,
@@ -74,19 +74,19 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
<FlatButton
key="noTracking"
label="No"
onTouchTap={this.onTrackConfirmationRespondedAsync.bind(this, false)}
onTouchTap={this._onTrackConfirmationRespondedAsync.bind(this, false)}
/>,
<FlatButton
key="yesTrack"
label="Yes"
onTouchTap={this.onTrackConfirmationRespondedAsync.bind(this, true)}
onTouchTap={this._onTrackConfirmationRespondedAsync.bind(this, true)}
/>,
],
},
};
}
public render() {
const dialogConfigs: DialogConfigs = this.dialogConfigsByAssetView[this.state.assetView];
const dialogConfigs: DialogConfigs = this._dialogConfigsByAssetView[this.state.assetView];
return (
<Dialog
title={dialogConfigs.title}
@@ -94,25 +94,25 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
modal={dialogConfigs.isModal}
open={this.props.isOpen}
actions={dialogConfigs.actions}
onRequestClose={this.onCloseDialog.bind(this)}
onRequestClose={this._onCloseDialog.bind(this)}
>
{this.state.assetView === AssetViews.ASSET_PICKER &&
this.renderAssetPicker()
this._renderAssetPicker()
}
{this.state.assetView === AssetViews.NEW_TOKEN_FORM &&
<NewTokenForm
blockchain={this.props.blockchain}
onNewTokenSubmitted={this.onNewTokenSubmitted.bind(this)}
onNewTokenSubmitted={this._onNewTokenSubmitted.bind(this)}
tokenByAddress={this.props.tokenByAddress}
/>
}
{this.state.assetView === AssetViews.CONFIRM_TRACK_TOKEN &&
this.renderConfirmTrackToken()
this._renderConfirmTrackToken()
}
</Dialog>
);
}
private renderConfirmTrackToken() {
private _renderConfirmTrackToken() {
const token = this.props.tokenByAddress[this.state.chosenTrackTokenAddress];
return (
<TrackTokenConfirmation
@@ -123,17 +123,17 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
/>
);
}
private renderAssetPicker() {
private _renderAssetPicker() {
return (
<div
className="clearfix flex flex-wrap"
style={{overflowY: 'auto', maxWidth: 720, maxHeight: 356, marginBottom: 10}}
>
{this.renderGridTiles()}
{this._renderGridTiles()}
</div>
);
}
private renderGridTiles() {
private _renderGridTiles() {
let isHovered;
let tileStyles;
const gridTiles = _.map(this.props.tokenByAddress, (token: Token, address: string) => {
@@ -151,9 +151,9 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
key={address}
style={{width: TILE_DIMENSION, height: TILE_DIMENSION, ...tileStyles}}
className="p2 mx-auto"
onClick={this.onChooseToken.bind(this, address)}
onMouseEnter={this.onToggleHover.bind(this, address, true)}
onMouseLeave={this.onToggleHover.bind(this, address, false)}
onClick={this._onChooseToken.bind(this, address)}
onMouseEnter={this._onToggleHover.bind(this, address, true)}
onMouseLeave={this._onToggleHover.bind(this, address, false)}
>
<div className="p1 center">
<TokenIcon token={token} diameter={TOKEN_ICON_DIMENSION} />
@@ -174,9 +174,9 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
key={otherTokenKey}
style={{width: TILE_DIMENSION, height: TILE_DIMENSION, ...tileStyles}}
className="p2 mx-auto"
onClick={this.onCustomAssetChosen.bind(this)}
onMouseEnter={this.onToggleHover.bind(this, otherTokenKey, true)}
onMouseLeave={this.onToggleHover.bind(this, otherTokenKey, false)}
onClick={this._onCustomAssetChosen.bind(this)}
onMouseEnter={this._onToggleHover.bind(this, otherTokenKey, true)}
onMouseLeave={this._onToggleHover.bind(this, otherTokenKey, false)}
>
<div className="p1 center">
<i
@@ -190,19 +190,19 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
}
return gridTiles;
}
private onToggleHover(address: string, isHovered: boolean) {
private _onToggleHover(address: string, isHovered: boolean) {
const hoveredAddress = isHovered ? address : undefined;
this.setState({
hoveredAddress,
});
}
private onCloseDialog() {
private _onCloseDialog() {
this.setState({
assetView: AssetViews.ASSET_PICKER,
});
this.props.onTokenChosen(this.props.currentTokenAddress);
}
private onChooseToken(tokenAddress: string) {
private _onChooseToken(tokenAddress: string) {
const token = this.props.tokenByAddress[tokenAddress];
if (token.isTracked) {
this.props.onTokenChosen(tokenAddress);
@@ -213,12 +213,12 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
});
}
}
private onCustomAssetChosen() {
private _onCustomAssetChosen() {
this.setState({
assetView: AssetViews.NEW_TOKEN_FORM,
});
}
private onNewTokenSubmitted(newToken: Token, newTokenState: TokenState) {
private _onNewTokenSubmitted(newToken: Token, newTokenState: TokenState) {
this.props.dispatcher.updateTokenStateByAddress({
[newToken.address]: newTokenState,
});
@@ -229,14 +229,14 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
});
this.props.onTokenChosen(newToken.address);
}
private async onTrackConfirmationRespondedAsync(didUserAcceptTracking: boolean) {
private async _onTrackConfirmationRespondedAsync(didUserAcceptTracking: boolean) {
if (!didUserAcceptTracking) {
this.setState({
isAddingTokenToTracked: false,
assetView: AssetViews.ASSET_PICKER,
chosenTrackTokenAddress: undefined,
});
this.onCloseDialog();
this._onCloseDialog();
return;
}
this.setState({

View File

@@ -63,7 +63,7 @@ interface GenerateOrderFormState {
}
export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, GenerateOrderFormState> {
private validator: SchemaValidator;
private _validator: SchemaValidator;
constructor(props: GenerateOrderFormProps) {
super(props);
this.state = {
@@ -71,7 +71,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
shouldShowIncompleteErrs: false,
signingState: SigningState.UNSIGNED,
};
this.validator = new SchemaValidator();
this._validator = new SchemaValidator();
}
public componentDidMount() {
window.scrollTo(0, 0);
@@ -113,7 +113,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
token={depositToken}
tokenState={depositTokenState}
amount={this.props.sideToAssetToken[Side.Deposit].amount}
onChange={this.onTokenAmountChange.bind(this, depositToken, Side.Deposit)}
onChange={this._onTokenAmountChange.bind(this, depositToken, Side.Deposit)}
shouldShowIncompleteErrs={this.state.shouldShowIncompleteErrs}
shouldCheckBalance={true}
shouldCheckAllowance={true}
@@ -144,7 +144,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
token={receiveToken}
tokenState={receiveTokenState}
amount={this.props.sideToAssetToken[Side.Receive].amount}
onChange={this.onTokenAmountChange.bind(this, receiveToken, Side.Receive)}
onChange={this._onTokenAmountChange.bind(this, receiveToken, Side.Receive)}
shouldShowIncompleteErrs={this.state.shouldShowIncompleteErrs}
shouldCheckBalance={false}
shouldCheckAllowance={false}
@@ -165,7 +165,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
<IdenticonAddressInput
label="Taker"
initialAddress={this.props.orderTakerAddress}
updateOrderAddress={this.updateOrderAddress.bind(this)}
updateOrderAddress={this._updateOrderAddress.bind(this)}
/>
<div className="pt3">
<div className="pl1">
@@ -189,7 +189,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
labelReady="Sign hash"
labelLoading="Signing..."
labelComplete="Hash signed!"
onClickAsyncFn={this.onSignClickedAsync.bind(this)}
onClickAsyncFn={this._onSignClickedAsync.bind(this)}
/>
</div>
{this.state.globalErrMsg !== '' &&
@@ -202,7 +202,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
titleStyle={{fontWeight: 100}}
modal={false}
open={this.state.signingState === SigningState.SIGNED}
onRequestClose={this.onCloseOrderJSONDialog.bind(this)}
onRequestClose={this._onCloseOrderJSONDialog.bind(this)}
>
<OrderJSON
exchangeContractIfExists={exchangeContractIfExists}
@@ -222,10 +222,10 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
</div>
);
}
private onTokenAmountChange(token: Token, side: Side, isValid: boolean, amount?: BigNumber) {
private _onTokenAmountChange(token: Token, side: Side, isValid: boolean, amount?: BigNumber) {
this.props.dispatcher.updateChosenAssetToken(side, {address: token.address, amount});
}
private onCloseOrderJSONDialog() {
private _onCloseOrderJSONDialog() {
// Upon closing the order JSON dialog, we update the orderSalt stored in the Redux store
// with a new value so that if a user signs the identical order again, the newly signed
// orderHash will not collide with the previously generated orderHash.
@@ -234,7 +234,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
signingState: SigningState.UNSIGNED,
});
}
private async onSignClickedAsync(): Promise<boolean> {
private async _onSignClickedAsync(): Promise<boolean> {
if (this.props.blockchainErr !== BlockchainErrs.NoError) {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
return false;
@@ -249,7 +249,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
debitToken.amount.gt(0) && receiveAmount.gt(0) &&
this.props.userAddress !== '' &&
debitBalance.gte(debitToken.amount) && debitAllowance.gte(debitToken.amount)) {
const didSignSuccessfully = await this.signTransactionAsync();
const didSignSuccessfully = await this._signTransactionAsync();
if (didSignSuccessfully) {
this.setState({
globalErrMsg: '',
@@ -270,7 +270,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
return false;
}
}
private async signTransactionAsync(): Promise<boolean> {
private async _signTransactionAsync(): Promise<boolean> {
this.setState({
signingState: SigningState.SIGNING,
});
@@ -308,7 +308,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
this.props.userAddress, hashData.makerFee, hashData.takerFee,
hashData.feeRecipientAddress, signatureData, this.props.tokenByAddress,
hashData.orderSalt);
const validationResult = this.validator.validate(order, orderSchema);
const validationResult = this._validator.validate(order, orderSchema);
if (validationResult.errors.length > 0) {
globalErrMsg = 'Order signing failed. Please refresh and try again';
utils.consoleLog(`Unexpected error occured: Order validation failed:
@@ -331,7 +331,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
});
return globalErrMsg === '';
}
private updateOrderAddress(address?: string): void {
private _updateOrderAddress(address?: string): void {
if (!_.isUndefined(address)) {
this.props.dispatcher.updateOrderTakerAddress(address);
}

View File

@@ -53,7 +53,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
floatingLabelText={<RequiredLabel label="Name" />}
value={this.state.name}
errorText={this.state.nameErrText}
onChange={this.onTokenNameChanged.bind(this)}
onChange={this._onTokenNameChanged.bind(this)}
/>
</div>
<div>
@@ -63,7 +63,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
floatingLabelText={<RequiredLabel label="Symbol" />}
value={this.state.symbol}
errorText={this.state.symbolErrText}
onChange={this.onTokenSymbolChanged.bind(this)}
onChange={this._onTokenSymbolChanged.bind(this)}
/>
</div>
<div>
@@ -72,7 +72,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
label="Contract address"
initialAddress=""
shouldShowIncompleteErrs={this.state.shouldShowAddressIncompleteErr}
updateAddress={this.onTokenAddressChanged.bind(this)}
updateAddress={this._onTokenAddressChanged.bind(this)}
/>
</div>
<div>
@@ -82,7 +82,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
floatingLabelText={<RequiredLabel label="Decimals" />}
value={this.state.decimals}
errorText={this.state.decimalsErrText}
onChange={this.onTokenDecimalsChanged.bind(this)}
onChange={this._onTokenDecimalsChanged.bind(this)}
/>
</div>
<div className="pt2 mx-auto" style={{width: 120}}>
@@ -90,7 +90,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
labelReady="Add"
labelLoading="Adding..."
labelComplete="Added!"
onClickAsyncFn={this.onAddNewTokenClickAsync.bind(this)}
onClickAsyncFn={this._onAddNewTokenClickAsync.bind(this)}
/>
</div>
{this.state.globalErrMsg !== '' &&
@@ -99,11 +99,11 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
</div>
);
}
private async onAddNewTokenClickAsync() {
private async _onAddNewTokenClickAsync() {
// Trigger validation of name and symbol
this.onTokenNameChanged(undefined, this.state.name);
this.onTokenSymbolChanged(undefined, this.state.symbol);
this.onTokenDecimalsChanged(undefined, this.state.decimals);
this._onTokenNameChanged(undefined, this.state.name);
this._onTokenSymbolChanged(undefined, this.state.symbol);
this._onTokenDecimalsChanged(undefined, this.state.decimals);
const isAddressIncomplete = this.state.address === '';
let doesContractExist = false;
@@ -160,7 +160,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
};
this.props.onNewTokenSubmitted(newToken, newTokenState);
}
private onTokenNameChanged(e: any, name: string) {
private _onTokenNameChanged(e: any, name: string) {
let nameErrText = '';
const maxLength = 30;
const tokens = _.values(this.props.tokenByAddress);
@@ -168,7 +168,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
const tokenWithNameExists = !_.isUndefined(tokenWithNameIfExists);
if (name === '') {
nameErrText = 'Name is required';
} else if (!this.isValidName(name)) {
} else if (!this._isValidName(name)) {
nameErrText = 'Name should only contain letters, digits and spaces';
} else if (name.length > maxLength) {
nameErrText = `Max length is ${maxLength}`;
@@ -181,14 +181,14 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
nameErrText,
});
}
private onTokenSymbolChanged(e: any, symbol: string) {
private _onTokenSymbolChanged(e: any, symbol: string) {
let symbolErrText = '';
const maxLength = 5;
const tokens = _.values(this.props.tokenByAddress);
const tokenWithSymbolExists = !_.isUndefined(_.find(tokens, {symbol}));
if (symbol === '') {
symbolErrText = 'Symbol is required';
} else if (!this.isLetters(symbol)) {
} else if (!this._isLetters(symbol)) {
symbolErrText = 'Can only include letters';
} else if (symbol.length > maxLength) {
symbolErrText = `Max length is ${maxLength}`;
@@ -201,12 +201,12 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
symbolErrText,
});
}
private onTokenDecimalsChanged(e: any, decimals: string) {
private _onTokenDecimalsChanged(e: any, decimals: string) {
let decimalsErrText = '';
const maxLength = 2;
if (decimals === '') {
decimalsErrText = 'Decimals is required';
} else if (!this.isInteger(decimals)) {
} else if (!this._isInteger(decimals)) {
decimalsErrText = 'Must be an integer';
} else if (decimals.length > maxLength) {
decimalsErrText = `Max length is ${maxLength}`;
@@ -217,20 +217,20 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
decimalsErrText,
});
}
private onTokenAddressChanged(address?: string) {
private _onTokenAddressChanged(address?: string) {
if (!_.isUndefined(address)) {
this.setState({
address,
});
}
}
private isValidName(input: string) {
private _isValidName(input: string) {
return /^[a-z0-9 ]+$/i.test(input);
}
private isInteger(input: string) {
private _isInteger(input: string) {
return /^[0-9]+$/i.test(input);
}
private isLetters(input: string) {
private _isLetters(input: string) {
return /^[a-zA-Z]+$/i.test(input);
}
}

View File

@@ -54,12 +54,12 @@ export class AddressInput extends React.Component<AddressInputProps, AddressInpu
floatingLabelText={label}
errorText={this.state.errMsg}
value={this.state.address}
onChange={this.onOrderTakerAddressUpdated.bind(this)}
onChange={this._onOrderTakerAddressUpdated.bind(this)}
/>
</div>
);
}
private onOrderTakerAddressUpdated(e: any) {
private _onOrderTakerAddressUpdated(e: any) {
const address = e.target.value.toLowerCase();
const isValidAddress = addressUtils.isAddress(address) || address === '';
const errMsg = isValidAddress ? '' : 'Invalid ethereum address';

View File

@@ -46,8 +46,8 @@ export class AllowanceToggle extends React.Component<AllowanceToggleProps, Allow
<div>
<Toggle
disabled={this.state.isSpinnerVisible}
toggled={this.isAllowanceSet()}
onToggle={this.onToggleAllowanceAsync.bind(this, this.props.token)}
toggled={this._isAllowanceSet()}
onToggle={this._onToggleAllowanceAsync.bind(this, this.props.token)}
/>
</div>
{this.state.isSpinnerVisible &&
@@ -58,7 +58,7 @@ export class AllowanceToggle extends React.Component<AllowanceToggleProps, Allow
</div>
);
}
private async onToggleAllowanceAsync() {
private async _onToggleAllowanceAsync() {
if (this.props.userAddress === '') {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
return false;
@@ -69,7 +69,7 @@ export class AllowanceToggle extends React.Component<AllowanceToggleProps, Allow
});
let newAllowanceAmountInBaseUnits = new BigNumber(0);
if (!this.isAllowanceSet()) {
if (!this._isAllowanceSet()) {
newAllowanceAmountInBaseUnits = DEFAULT_ALLOWANCE_AMOUNT_IN_BASE_UNITS;
}
try {
@@ -84,11 +84,11 @@ export class AllowanceToggle extends React.Component<AllowanceToggleProps, Allow
}
utils.consoleLog(`Unexpected error encountered: ${err}`);
utils.consoleLog(err.stack);
await errorReporter.reportAsync(err);
this.props.onErrorOccurred(BalanceErrs.allowanceSettingFailed);
await errorReporter.reportAsync(err);
}
}
private isAllowanceSet() {
private _isAllowanceSet() {
return !this.props.tokenState.allowance.eq(0);
}
}

View File

@@ -35,7 +35,7 @@ export class BalanceBoundedInput extends
super(props);
const amountString = this.props.amount ? this.props.amount.toString() : '';
this.state = {
errMsg: this.validate(amountString, props.balance),
errMsg: this._validate(amountString, props.balance),
amountString,
};
}
@@ -57,14 +57,14 @@ export class BalanceBoundedInput extends
if (shouldResetState) {
const amountString = nextProps.amount.toString();
this.setState({
errMsg: this.validate(amountString, nextProps.balance),
errMsg: this._validate(amountString, nextProps.balance),
amountString,
});
}
} else if (isCurrentAmountNumeric) {
const amountString = '';
this.setState({
errMsg: this.validate(amountString, nextProps.balance),
errMsg: this._validate(amountString, nextProps.balance),
amountString,
});
}
@@ -87,13 +87,13 @@ export class BalanceBoundedInput extends
errorText={errorText}
value={this.state.amountString}
hintText={<span style={{textTransform: 'capitalize'}}>amount</span>}
onChange={this.onValueChange.bind(this)}
onChange={this._onValueChange.bind(this)}
underlineStyle={{width: 'calc(100% + 50px)'}}
/>
);
}
private onValueChange(e: any, amountString: string) {
const errMsg = this.validate(amountString, this.props.balance);
private _onValueChange(e: any, amountString: string) {
const errMsg = this._validate(amountString, this.props.balance);
this.setState({
amountString,
errMsg,
@@ -106,7 +106,7 @@ export class BalanceBoundedInput extends
}
});
}
private validate(amountString: string, balance: BigNumber): InputErrMsg {
private _validate(amountString: string, balance: BigNumber): InputErrMsg {
if (!utils.isNumeric(amountString)) {
return amountString !== '' ? 'Must be a number' : '';
}
@@ -118,14 +118,14 @@ export class BalanceBoundedInput extends
return (
<span>
Insufficient balance.{' '}
{this.renderIncreaseBalanceLink()}
{this._renderIncreaseBalanceLink()}
</span>
);
}
const errMsg = _.isUndefined(this.props.validate) ? undefined : this.props.validate(amount);
return errMsg;
}
private renderIncreaseBalanceLink() {
private _renderIncreaseBalanceLink() {
if (this.props.shouldHideVisitBalancesLink) {
return null;
}

View File

@@ -30,7 +30,7 @@ export class EthAmountInput extends React.Component<EthAmountInputProps, EthAmou
label={this.props.label}
balance={this.props.balance}
amount={amount}
onChange={this.onChange.bind(this)}
onChange={this._onChange.bind(this)}
shouldCheckBalance={this.props.shouldCheckBalance}
shouldShowIncompleteErrs={this.props.shouldShowIncompleteErrs}
onVisitBalancesPageClick={this.props.onVisitBalancesPageClick}
@@ -42,7 +42,7 @@ export class EthAmountInput extends React.Component<EthAmountInputProps, EthAmou
</div>
);
}
private onChange(isValid: boolean, amount?: BigNumber) {
private _onChange(isValid: boolean, amount?: BigNumber) {
const baseUnitAmountIfExists = _.isUndefined(amount) ?
undefined :
ZeroEx.toBaseUnitAmount(amount, constants.DECIMAL_PLACES_ETH);

View File

@@ -17,11 +17,11 @@ interface ExpirationInputState {
}
export class ExpirationInput extends React.Component<ExpirationInputProps, ExpirationInputState> {
private earliestPickableMoment: moment.Moment;
private _earliestPickableMoment: moment.Moment;
constructor(props: ExpirationInputProps) {
super(props);
// Set the earliest pickable date to today at 00:00, so users can only pick the current or later dates
this.earliestPickableMoment = moment().startOf('day');
this._earliestPickableMoment = moment().startOf('day');
const expirationMoment = utils.convertToMomentFromUnixTimestamp(props.orderExpiryTimestamp);
const initialOrderExpiryTimestamp = utils.initialOrderExpiryUnixTimestampSec();
const didUserSetExpiry = !initialOrderExpiryTimestamp.eq(props.orderExpiryTimestamp);
@@ -42,8 +42,8 @@ export class ExpirationInput extends React.Component<ExpirationInputProps, Expir
mode="landscape"
autoOk={true}
value={date}
onChange={this.onDateChanged.bind(this)}
shouldDisableDate={this.shouldDisableDate.bind(this)}
onChange={this._onDateChanged.bind(this)}
shouldDisableDate={this._shouldDisableDate.bind(this)}
/>
<div
className="absolute"
@@ -58,7 +58,7 @@ export class ExpirationInput extends React.Component<ExpirationInputProps, Expir
hintText="Time"
autoOk={true}
value={time}
onChange={this.onTimeChanged.bind(this)}
onChange={this._onTimeChanged.bind(this)}
/>
<div
className="absolute"
@@ -68,7 +68,7 @@ export class ExpirationInput extends React.Component<ExpirationInputProps, Expir
</div>
</div>
<div
onClick={this.clearDates.bind(this)}
onClick={this._clearDates.bind(this)}
className="col col-1 pt2"
style={{textAlign: 'right'}}
>
@@ -77,10 +77,10 @@ export class ExpirationInput extends React.Component<ExpirationInputProps, Expir
</div>
);
}
private shouldDisableDate(date: Date): boolean {
return moment(date).startOf('day').isBefore(this.earliestPickableMoment);
private _shouldDisableDate(date: Date): boolean {
return moment(date).startOf('day').isBefore(this._earliestPickableMoment);
}
private clearDates() {
private _clearDates() {
this.setState({
dateMoment: undefined,
timeMoment: undefined,
@@ -88,7 +88,7 @@ export class ExpirationInput extends React.Component<ExpirationInputProps, Expir
const defaultDateTime = utils.initialOrderExpiryUnixTimestampSec();
this.props.updateOrderExpiry(defaultDateTime);
}
private onDateChanged(e: any, date: Date) {
private _onDateChanged(e: any, date: Date) {
const dateMoment = moment(date);
this.setState({
dateMoment,
@@ -96,7 +96,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) {
private _onTimeChanged(e: any, time: Date) {
const timeMoment = moment(time);
this.setState({
timeMoment,

View File

@@ -27,7 +27,7 @@ interface HashInputState {}
export class HashInput extends React.Component<HashInputProps, HashInputState> {
public render() {
const msgHashHex = this.props.blockchainIsLoaded ? this.generateMessageHashHex() : '';
const msgHashHex = this.props.blockchainIsLoaded ? this._generateMessageHashHex() : '';
return (
<div>
<FakeTextField label={this.props.label}>
@@ -43,7 +43,7 @@ export class HashInput extends React.Component<HashInputProps, HashInputState> {
</div>
);
}
private generateMessageHashHex() {
private _generateMessageHashHex() {
const exchangeContractAddress = this.props.blockchain.getExchangeContractAddressIfExists();
const hashData = this.props.hashData;
const order: Order = {

View File

@@ -38,14 +38,14 @@ export class IdenticonAddressInput extends React.Component<IdenticonAddressInput
hintText="e.g 0x75bE4F78AA3699B3A348c84bDB2a96c3Db..."
shouldHideLabel={true}
initialAddress={this.props.initialAddress}
updateAddress={this.updateAddress.bind(this)}
updateAddress={this._updateAddress.bind(this)}
/>
</div>
</div>
</div>
);
}
private updateAddress(address?: string): void {
private _updateAddress(address?: string): void {
this.setState({
address,
});

View File

@@ -33,8 +33,8 @@ export class TokenAmountInput extends React.Component<TokenAmountInputProps, Tok
label={this.props.label}
amount={amount}
balance={ZeroEx.toUnitAmount(this.props.tokenState.balance, this.props.token.decimals)}
onChange={this.onChange.bind(this)}
validate={this.validate.bind(this)}
onChange={this._onChange.bind(this)}
validate={this._validate.bind(this)}
shouldCheckBalance={this.props.shouldCheckBalance}
shouldShowIncompleteErrs={this.props.shouldShowIncompleteErrs}
onVisitBalancesPageClick={this.props.onVisitBalancesPageClick}
@@ -45,14 +45,14 @@ export class TokenAmountInput extends React.Component<TokenAmountInputProps, Tok
</div>
);
}
private onChange(isValid: boolean, amount?: BigNumber) {
private _onChange(isValid: boolean, amount?: BigNumber) {
let baseUnitAmount;
if (!_.isUndefined(amount)) {
baseUnitAmount = ZeroEx.toBaseUnitAmount(amount, this.props.token.decimals);
}
this.props.onChange(isValid, baseUnitAmount);
}
private validate(amount: BigNumber): InputErrMsg {
private _validate(amount: BigNumber): InputErrMsg {
if (this.props.shouldCheckAllowance && amount.gt(this.props.tokenState.allowance)) {
return (
<span>

View File

@@ -52,9 +52,9 @@ export class TokenInput extends React.Component<TokenInputProps, TokenInputState
<Paper
zDepth={1}
style={{cursor: 'pointer'}}
onMouseEnter={this.onToggleHover.bind(this, true)}
onMouseLeave={this.onToggleHover.bind(this, false)}
onClick={this.onAssetClicked.bind(this)}
onMouseEnter={this._onToggleHover.bind(this, true)}
onMouseLeave={this._onToggleHover.bind(this, false)}
onClick={this._onAssetClicked.bind(this)}
>
<div
className="mx-auto pt2"
@@ -73,13 +73,13 @@ export class TokenInput extends React.Component<TokenInputProps, TokenInputState
dispatcher={this.props.dispatcher}
isOpen={this.state.isPickerOpen}
currentTokenAddress={this.props.assetToken.address}
onTokenChosen={this.onTokenChosen.bind(this)}
onTokenChosen={this._onTokenChosen.bind(this)}
tokenByAddress={this.props.tokenByAddress}
/>
</div>
);
}
private onTokenChosen(tokenAddress: string) {
private _onTokenChosen(tokenAddress: string) {
const assetToken: AssetToken = {
address: tokenAddress,
amount: this.props.assetToken.amount,
@@ -89,12 +89,12 @@ export class TokenInput extends React.Component<TokenInputProps, TokenInputState
isPickerOpen: false,
});
}
private onToggleHover(isHoveringIcon: boolean) {
private _onToggleHover(isHoveringIcon: boolean) {
this.setState({
isHoveringIcon,
});
}
private onAssetClicked() {
private _onAssetClicked() {
if (this.props.blockchainErr !== BlockchainErrs.NoError) {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
return;

View File

@@ -36,7 +36,7 @@ export class OrderJSON extends React.Component<OrderJSONProps, OrderJSONState> {
shareLink: '',
};
// tslint:disable-next-line:no-floating-promises
this.setShareLinkAsync();
this._setShareLinkAsync();
}
public render() {
const order = utils.generateOrder(this.props.networkId, this.props.exchangeContractIfExists,
@@ -88,21 +88,21 @@ export class OrderJSON extends React.Component<OrderJSONProps, OrderJSONState> {
<div>
<i
style={{cursor: 'pointer', fontSize: 29}}
onClick={this.shareViaFacebook.bind(this)}
onClick={this._shareViaFacebook.bind(this)}
className="zmdi zmdi-facebook-box"
/>
</div>
<div className="pl1" style={{position: 'relative', width: 28}}>
<i
style={{cursor: 'pointer', fontSize: 32, position: 'absolute', top: -2, left: 8}}
onClick={this.shareViaEmailAsync.bind(this)}
onClick={this._shareViaEmailAsync.bind(this)}
className="zmdi zmdi-email"
/>
</div>
<div className="pl1">
<i
style={{cursor: 'pointer', fontSize: 29}}
onClick={this.shareViaTwitterAsync.bind(this)}
onClick={this._shareViaTwitterAsync.bind(this)}
className="zmdi zmdi-twitter-box"
/>
</div>
@@ -111,32 +111,32 @@ export class OrderJSON extends React.Component<OrderJSONProps, OrderJSONState> {
</div>
);
}
private async shareViaTwitterAsync() {
private async _shareViaTwitterAsync() {
const tweetText = encodeURIComponent(`Fill my order using the 0x protocol: ${this.state.shareLink}`);
window.open(`https://twitter.com/intent/tweet?text=${tweetText}`, 'Share your order', 'width=500,height=400');
}
private async shareViaFacebook() {
private async _shareViaFacebook() {
(window as any).FB.ui({
display: 'popup',
href: this.state.shareLink,
method: 'share',
}, _.noop);
}
private async shareViaEmailAsync() {
private async _shareViaEmailAsync() {
const encodedSubject = encodeURIComponent('Let\'s trade using the 0x protocol');
const encodedBody = encodeURIComponent(`I generated an order with the 0x protocol.
You can see and fill it here: ${this.state.shareLink}`);
const mailToLink = `mailto:mail@example.org?subject=${encodedSubject}&body=${encodedBody}`;
window.open(mailToLink, '_blank');
}
private async setShareLinkAsync() {
const shareLink = await this.generateShareLinkAsync();
private async _setShareLinkAsync() {
const shareLink = await this._generateShareLinkAsync();
this.setState({
shareLink,
});
}
private async generateShareLinkAsync(): Promise<string> {
const longUrl = encodeURIComponent(this.getOrderUrl());
private async _generateShareLinkAsync(): Promise<string> {
const longUrl = encodeURIComponent(this._getOrderUrl());
const bitlyRequestUrl =
`${constants.URL_BITLY_API}/v3/shorten?access_token=${configs.BITLY_ACCESS_TOKEN}&longUrl=${longUrl}`;
const response = await fetch(bitlyRequestUrl);
@@ -150,7 +150,7 @@ You can see and fill it here: ${this.state.shareLink}`);
}
return (bodyObj).data.url;
}
private getOrderUrl() {
private _getOrderUrl() {
const order = utils.generateOrder(this.props.networkId, this.props.exchangeContractIfExists,
this.props.sideToAssetToken, this.props.orderExpiryTimestamp, this.props.orderTakerAddress,
this.props.orderMakerAddress, this.props.orderMakerFee, this.props.orderTakerFee,

View File

@@ -70,9 +70,9 @@ interface PortalAllState {
}
export class Portal extends React.Component<PortalAllProps, PortalAllState> {
private blockchain: Blockchain;
private sharedOrderIfExists: Order;
private throttledScreenWidthUpdate: () => void;
private _blockchain: Blockchain;
private _sharedOrderIfExists: Order;
private _throttledScreenWidthUpdate: () => void;
public static hasAlreadyDismissedWethNotice() {
const didDismissWethNotice = localStorage.getItemIfExists(constants.LOCAL_STORAGE_KEY_DISMISS_WETH_NOTICE);
const hasAlreadyDismissedWethNotice = !_.isUndefined(didDismissWethNotice) &&
@@ -81,8 +81,8 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
}
constructor(props: PortalAllProps) {
super(props);
this.sharedOrderIfExists = this.getSharedOrderIfExists();
this.throttledScreenWidthUpdate = _.throttle(this.updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
this._sharedOrderIfExists = this._getSharedOrderIfExists();
this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
const isViewingBalances = _.includes(props.location.pathname, `${WebsitePaths.Portal}/balances`);
const hasAlreadyDismissedWethNotice = Portal.hasAlreadyDismissedWethNotice();
@@ -100,15 +100,15 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
};
}
public componentDidMount() {
window.addEventListener('resize', this.throttledScreenWidthUpdate);
window.addEventListener('resize', this._throttledScreenWidthUpdate);
window.scrollTo(0, 0);
}
public componentWillMount() {
this.blockchain = new Blockchain(this.props.dispatcher);
this._blockchain = new Blockchain(this.props.dispatcher);
}
public componentWillUnmount() {
this.blockchain.destroy();
window.removeEventListener('resize', this.throttledScreenWidthUpdate);
this._blockchain.destroy();
window.removeEventListener('resize', this._throttledScreenWidthUpdate);
// We re-set the entire redux state when the portal is unmounted so that when it is re-rendered
// the initialization process always occurs from the same base state. This helps avoid
// initialization inconsistencies (i.e While the portal was unrendered, the user might have
@@ -118,19 +118,19 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
public componentWillReceiveProps(nextProps: PortalAllProps) {
if (nextProps.networkId !== this.state.prevNetworkId) {
// tslint:disable-next-line:no-floating-promises
this.blockchain.networkIdUpdatedFireAndForgetAsync(nextProps.networkId);
this._blockchain.networkIdUpdatedFireAndForgetAsync(nextProps.networkId);
this.setState({
prevNetworkId: nextProps.networkId,
});
}
if (nextProps.userAddress !== this.state.prevUserAddress) {
// tslint:disable-next-line:no-floating-promises
this.blockchain.userAddressUpdatedFireAndForgetAsync(nextProps.userAddress);
this._blockchain.userAddressUpdatedFireAndForgetAsync(nextProps.userAddress);
if (!_.isEmpty(nextProps.userAddress) &&
nextProps.blockchainIsLoaded) {
const tokens = _.values(nextProps.tokenByAddress);
// tslint:disable-next-line:no-floating-promises
this.updateBalanceAndAllowanceWithLoadingScreenAsync(tokens);
this._updateBalanceAndAllowanceWithLoadingScreenAsync(tokens);
}
this.setState({
prevUserAddress: nextProps.userAddress,
@@ -138,7 +138,7 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
}
if (nextProps.nodeVersion !== this.state.prevNodeVersion) {
// tslint:disable-next-line:no-floating-promises
this.blockchain.nodeVersionUpdatedFireAndForgetAsync(nextProps.nodeVersion);
this._blockchain.nodeVersionUpdatedFireAndForgetAsync(nextProps.nodeVersion);
}
if (nextProps.location.pathname !== this.state.prevPathname) {
const isViewingBalances = _.includes(nextProps.location.pathname, `${WebsitePaths.Portal}/balances`);
@@ -206,23 +206,23 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
<Switch>
<Route
path={`${WebsitePaths.Portal}/weth`}
render={this.renderEthWrapper.bind(this)}
render={this._renderEthWrapper.bind(this)}
/>
<Route
path={`${WebsitePaths.Portal}/fill`}
render={this.renderFillOrder.bind(this)}
render={this._renderFillOrder.bind(this)}
/>
<Route
path={`${WebsitePaths.Portal}/balances`}
render={this.renderTokenBalances.bind(this)}
render={this._renderTokenBalances.bind(this)}
/>
<Route
path={`${WebsitePaths.Portal}/trades`}
component={this.renderTradeHistory.bind(this)}
component={this._renderTradeHistory.bind(this)}
/>
<Route
path={`${WebsitePaths.Home}`}
render={this.renderGenerateOrderForm.bind(this)}
render={this._renderGenerateOrderForm.bind(this)}
/>
</Switch> :
<Loading />
@@ -233,7 +233,7 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
}
</Paper>
<BlockchainErrDialog
blockchain={this.blockchain}
blockchain={this._blockchain}
blockchainErr={this.props.blockchainErr}
isOpen={this.props.shouldBlockchainErrDialogBeOpen}
userAddress={this.props.userAddress}
@@ -242,11 +242,11 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
/>
<WrappedEthSectionNoticeDialog
isOpen={this.state.isWethNoticeDialogOpen}
onToggleDialog={this.onWethNoticeAccepted.bind(this)}
onToggleDialog={this._onWethNoticeAccepted.bind(this)}
/>
<PortalDisclaimerDialog
isOpen={this.state.isDisclaimerDialogOpen}
onToggleDialog={this.onPortalDisclaimerAccepted.bind(this)}
onToggleDialog={this._onPortalDisclaimerAccepted.bind(this)}
/>
<FlashMessage
dispatcher={this.props.dispatcher}
@@ -257,11 +257,11 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
</div>
);
}
private renderEthWrapper() {
private _renderEthWrapper() {
return (
<EthWrappers
networkId={this.props.networkId}
blockchain={this.blockchain}
blockchain={this._blockchain}
dispatcher={this.props.dispatcher}
tokenByAddress={this.props.tokenByAddress}
tokenStateByAddress={this.props.tokenStateByAddress}
@@ -270,7 +270,7 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
/>
);
}
private renderTradeHistory() {
private _renderTradeHistory() {
return (
<TradeHistory
tokenByAddress={this.props.tokenByAddress}
@@ -279,10 +279,10 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
/>
);
}
private renderTokenBalances() {
private _renderTokenBalances() {
return (
<TokenBalances
blockchain={this.blockchain}
blockchain={this._blockchain}
blockchainErr={this.props.blockchainErr}
blockchainIsLoaded={this.props.blockchainIsLoaded}
dispatcher={this.props.dispatcher}
@@ -295,16 +295,16 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
/>
);
}
private renderFillOrder(match: any, location: Location, history: History) {
private _renderFillOrder(match: any, location: Location, history: History) {
const initialFillOrder = !_.isUndefined(this.props.userSuppliedOrderCache) ?
this.props.userSuppliedOrderCache :
this.sharedOrderIfExists;
this._sharedOrderIfExists;
return (
<FillOrder
blockchain={this.blockchain}
blockchain={this._blockchain}
blockchainErr={this.props.blockchainErr}
initialOrder={initialFillOrder}
isOrderInUrl={!_.isUndefined(this.sharedOrderIfExists)}
isOrderInUrl={!_.isUndefined(this._sharedOrderIfExists)}
orderFillAmount={this.props.orderFillAmount}
networkId={this.props.networkId}
userAddress={this.props.userAddress}
@@ -314,28 +314,28 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
/>
);
}
private renderGenerateOrderForm(match: any, location: Location, history: History) {
private _renderGenerateOrderForm(match: any, location: Location, history: History) {
return (
<GenerateOrderForm
blockchain={this.blockchain}
blockchain={this._blockchain}
hashData={this.props.hashData}
dispatcher={this.props.dispatcher}
/>
);
}
private onPortalDisclaimerAccepted() {
private _onPortalDisclaimerAccepted() {
localStorage.setItem(constants.LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER, 'set');
this.setState({
isDisclaimerDialogOpen: false,
});
}
private onWethNoticeAccepted() {
private _onWethNoticeAccepted() {
localStorage.setItem(constants.LOCAL_STORAGE_KEY_DISMISS_WETH_NOTICE, 'set');
this.setState({
isWethNoticeDialogOpen: false,
});
}
private getSharedOrderIfExists(): Order {
private _getSharedOrderIfExists(): Order {
const queryString = window.location.search;
if (queryString.length === 0) {
return;
@@ -362,13 +362,13 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
}
return order;
}
private updateScreenWidth() {
private _updateScreenWidth() {
const newScreenWidth = utils.getScreenWidth();
this.props.dispatcher.updateScreenWidth(newScreenWidth);
}
private async updateBalanceAndAllowanceWithLoadingScreenAsync(tokens: Token[]) {
private async _updateBalanceAndAllowanceWithLoadingScreenAsync(tokens: Token[]) {
this.props.dispatcher.updateBlockchainIsLoaded(false);
await this.blockchain.updateTokenBalancesAndAllowancesAsync(tokens);
await this._blockchain.updateTokenBalancesAndAllowancesAsync(tokens);
this.props.dispatcher.updateBlockchainIsLoaded(true);
}
}

View File

@@ -23,7 +23,7 @@ export class PortalMenu extends React.Component<PortalMenuProps, PortalMenuState
to={`${WebsitePaths.Portal}`}
onClick={this.props.onClick.bind(this)}
>
{this.renderMenuItemWithIcon('Generate order', 'zmdi-arrow-right-top')}
{this._renderMenuItemWithIcon('Generate order', 'zmdi-arrow-right-top')}
</MenuItem>
<MenuItem
style={this.props.menuItemStyle}
@@ -31,7 +31,7 @@ export class PortalMenu extends React.Component<PortalMenuProps, PortalMenuState
to={`${WebsitePaths.Portal}/fill`}
onClick={this.props.onClick.bind(this)}
>
{this.renderMenuItemWithIcon('Fill order', 'zmdi-arrow-left-bottom')}
{this._renderMenuItemWithIcon('Fill order', 'zmdi-arrow-left-bottom')}
</MenuItem>
<MenuItem
style={this.props.menuItemStyle}
@@ -39,7 +39,7 @@ export class PortalMenu extends React.Component<PortalMenuProps, PortalMenuState
to={`${WebsitePaths.Portal}/balances`}
onClick={this.props.onClick.bind(this)}
>
{this.renderMenuItemWithIcon('Balances', 'zmdi-balance-wallet')}
{this._renderMenuItemWithIcon('Balances', 'zmdi-balance-wallet')}
</MenuItem>
<MenuItem
style={this.props.menuItemStyle}
@@ -47,7 +47,7 @@ export class PortalMenu extends React.Component<PortalMenuProps, PortalMenuState
to={`${WebsitePaths.Portal}/trades`}
onClick={this.props.onClick.bind(this)}
>
{this.renderMenuItemWithIcon('Trade history', 'zmdi-format-list-bulleted')}
{this._renderMenuItemWithIcon('Trade history', 'zmdi-format-list-bulleted')}
</MenuItem>
<MenuItem
style={this.props.menuItemStyle}
@@ -55,12 +55,12 @@ export class PortalMenu extends React.Component<PortalMenuProps, PortalMenuState
to={`${WebsitePaths.Portal}/weth`}
onClick={this.props.onClick.bind(this)}
>
{this.renderMenuItemWithIcon('Wrap ETH', 'zmdi-circle-o')}
{this._renderMenuItemWithIcon('Wrap ETH', 'zmdi-circle-o')}
</MenuItem>
</div>
);
}
private renderMenuItemWithIcon(title: string, iconName: string) {
private _renderMenuItemWithIcon(title: string, iconName: string) {
return (
<div className="flex" style={{fontWeight: 100}}>
<div className="pr1 pl2">

View File

@@ -39,28 +39,28 @@ export class SendButton extends React.Component<SendButtonProps, SendButtonState
labelStyle={labelStyle}
disabled={this.state.isSending}
label={this.state.isSending ? 'Sending...' : 'Send'}
onClick={this.toggleSendDialog.bind(this)}
onClick={this._toggleSendDialog.bind(this)}
/>
<SendDialog
isOpen={this.state.isSendDialogVisible}
onComplete={this.onSendAmountSelectedAsync.bind(this)}
onCancelled={this.toggleSendDialog.bind(this)}
onComplete={this._onSendAmountSelectedAsync.bind(this)}
onCancelled={this._toggleSendDialog.bind(this)}
token={this.props.token}
tokenState={this.props.tokenState}
/>
</div>
);
}
private toggleSendDialog() {
private _toggleSendDialog() {
this.setState({
isSendDialogVisible: !this.state.isSendDialogVisible,
});
}
private async onSendAmountSelectedAsync(recipient: string, value: BigNumber) {
private async _onSendAmountSelectedAsync(recipient: string, value: BigNumber) {
this.setState({
isSending: true,
});
this.toggleSendDialog();
this._toggleSendDialog();
const token = this.props.token;
const tokenState = this.props.tokenState;
let balance = tokenState.balance;

View File

@@ -133,7 +133,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
key="errorOkBtn"
label="Ok"
primary={true}
onTouchTap={this.onErrorDialogToggle.bind(this, false)}
onTouchTap={this._onErrorDialogToggle.bind(this, false)}
/>,
];
const dharmaDialogActions = [
@@ -141,7 +141,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
key="dharmaCloseBtn"
label="Close"
primary={true}
onTouchTap={this.onDharmaDialogToggle.bind(this, false)}
onTouchTap={this._onDharmaDialogToggle.bind(this, false)}
/>,
];
const isTestNetwork = this.props.networkId === constants.NETWORK_ID_TESTNET;
@@ -239,7 +239,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
labelReady="Request"
labelLoading="Sending..."
labelComplete="Sent!"
onClickAsyncFn={this.faucetRequestAsync.bind(this, true)}
onClickAsyncFn={this._faucetRequestAsync.bind(this, true)}
/>
</TableRowColumn>
}
@@ -249,7 +249,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
<RaisedButton
label="Request"
style={{width: '100%'}}
onTouchTap={this.onDharmaDialogToggle.bind(this)}
onTouchTap={this._onDharmaDialogToggle.bind(this)}
/>
</TableRowColumn>
}
@@ -266,7 +266,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
<FloatingActionButton
mini={true}
zDepth={0}
onClick={this.onAddTokenClicked.bind(this)}
onClick={this._onAddTokenClicked.bind(this)}
>
<ContentAdd />
</FloatingActionButton>
@@ -275,7 +275,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
<FloatingActionButton
mini={true}
zDepth={0}
onClick={this.onRemoveTokenClicked.bind(this)}
onClick={this._onRemoveTokenClicked.bind(this)}
>
<ContentRemove />
</FloatingActionButton>
@@ -319,7 +319,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
</TableRow>
</TableHeader>
<TableBody displayRowCheckbox={false}>
{this.renderTokenTableRows()}
{this._renderTokenTableRows()}
</TableBody>
</Table>
<Dialog
@@ -327,9 +327,9 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
titleStyle={{fontWeight: 100}}
actions={errorDialogActions}
open={!_.isUndefined(this.state.errorType)}
onRequestClose={this.onErrorDialogToggle.bind(this, false)}
onRequestClose={this._onErrorDialogToggle.bind(this, false)}
>
{this.renderErrorDialogBody()}
{this._renderErrorDialogBody()}
</Dialog>
<Dialog
title="Request Dharma Loan"
@@ -340,7 +340,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
actions={dharmaDialogActions}
open={this.state.isDharmaDialogVisible}
>
{this.renderDharmaLoanFrame()}
{this._renderDharmaLoanFrame()}
</Dialog>
<AssetPicker
userAddress={this.props.userAddress}
@@ -349,14 +349,14 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
dispatcher={this.props.dispatcher}
isOpen={this.state.isTokenPickerOpen}
currentTokenAddress={''}
onTokenChosen={this.onAssetTokenPicked.bind(this)}
onTokenChosen={this._onAssetTokenPicked.bind(this)}
tokenByAddress={this.props.tokenByAddress}
tokenVisibility={this.state.isAddingToken ? TokenVisibility.UNTRACKED : TokenVisibility.TRACKED}
/>
</div>
);
}
private renderTokenTableRows() {
private _renderTokenTableRows() {
if (!this.props.blockchainIsLoaded || this.props.blockchainErr !== BlockchainErrs.NoError) {
return '';
}
@@ -372,11 +372,11 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
);
const tableRows = _.map(
trackedTokensStartingWithEtherToken,
this.renderTokenRow.bind(this, tokenColSpan, actionPaddingX),
this._renderTokenRow.bind(this, tokenColSpan, actionPaddingX),
);
return tableRows;
}
private renderTokenRow(tokenColSpan: number, actionPaddingX: number, token: Token) {
private _renderTokenRow(tokenColSpan: number, actionPaddingX: number, token: Token) {
const tokenState = this.props.tokenStateByAddress[token.address];
const tokenLink = utils.getEtherScanLinkIfExists(token.address, this.props.networkId,
EtherscanLinkSuffixes.Address);
@@ -388,14 +388,14 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
colSpan={tokenColSpan}
>
{_.isUndefined(tokenLink) ?
this.renderTokenName(token) :
this._renderTokenName(token) :
<a href={tokenLink} target="_blank" style={{textDecoration: 'none'}}>
{this.renderTokenName(token)}
{this._renderTokenName(token)}
</a>
}
</TableRowColumn>
<TableRowColumn style={{paddingRight: 3, paddingLeft: 3}}>
{this.renderAmount(tokenState.balance, token.decimals)} {token.symbol}
{this._renderAmount(tokenState.balance, token.decimals)} {token.symbol}
{this.state.isZRXSpinnerVisible && token.symbol === ZRX_TOKEN_SYMBOL &&
<span className="pl1">
<i className="zmdi zmdi-spinner zmdi-hc-spin" />
@@ -408,7 +408,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
dispatcher={this.props.dispatcher}
token={token}
tokenState={tokenState}
onErrorOccurred={this.onErrorOccurred.bind(this)}
onErrorOccurred={this._onErrorOccurred.bind(this)}
userAddress={this.props.userAddress}
/>
</TableRowColumn>
@@ -420,7 +420,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
labelReady="Mint"
labelLoading={<span style={{fontSize: 12}}>Minting...</span>}
labelComplete="Minted!"
onClickAsyncFn={this.onMintTestTokensAsync.bind(this, token)}
onClickAsyncFn={this._onMintTestTokensAsync.bind(this, token)}
/>
}
{token.symbol === ZRX_TOKEN_SYMBOL && this.props.networkId === constants.NETWORK_ID_TESTNET &&
@@ -428,7 +428,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
labelReady="Request"
labelLoading="Sending..."
labelComplete="Sent!"
onClickAsyncFn={this.faucetRequestAsync.bind(this, false)}
onClickAsyncFn={this._faucetRequestAsync.bind(this, false)}
/>
}
</TableRowColumn>
@@ -441,14 +441,14 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
dispatcher={this.props.dispatcher}
token={token}
tokenState={tokenState}
onError={this.onSendFailed.bind(this)}
onError={this._onSendFailed.bind(this)}
/>
</TableRowColumn>
}
</TableRow>
);
}
private onAssetTokenPicked(tokenAddress: string) {
private _onAssetTokenPicked(tokenAddress: string) {
if (_.isEmpty(tokenAddress)) {
this.setState({
isTokenPickerOpen: false,
@@ -477,16 +477,16 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
isTokenPickerOpen: false,
});
}
private onSendFailed() {
private _onSendFailed() {
this.setState({
errorType: BalanceErrs.sendFailed,
});
}
private renderAmount(amount: BigNumber, decimals: number) {
private _renderAmount(amount: BigNumber, decimals: number) {
const unitAmount = ZeroEx.toUnitAmount(amount, decimals);
return unitAmount.toNumber().toFixed(PRECISION);
}
private renderTokenName(token: Token) {
private _renderTokenName(token: Token) {
const tooltipId = `tooltip-${token.address}`;
return (
<div className="flex">
@@ -502,7 +502,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
</div>
);
}
private renderErrorDialogBody() {
private _renderErrorDialogBody() {
switch (this.state.errorType) {
case BalanceErrs.incorrectNetworkForFaucet:
return (
@@ -550,7 +550,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
throw utils.spawnSwitchErr('errorType', this.state.errorType);
}
}
private renderDharmaLoanFrame() {
private _renderDharmaLoanFrame() {
if (utils.isUserOnMobile()) {
return (
<h4 style={{textAlign: 'center'}}>
@@ -568,12 +568,12 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
);
}
}
private onErrorOccurred(errorType: BalanceErrs) {
private _onErrorOccurred(errorType: BalanceErrs) {
this.setState({
errorType,
});
}
private async onMintTestTokensAsync(token: Token): Promise<boolean> {
private async _onMintTestTokensAsync(token: Token): Promise<boolean> {
try {
await this.props.blockchain.mintTestTokensAsync(token);
const amount = ZeroEx.toUnitAmount(constants.MINT_AMOUNT, token.decimals);
@@ -590,14 +590,14 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
}
utils.consoleLog(`Unexpected error encountered: ${err}`);
utils.consoleLog(err.stack);
await errorReporter.reportAsync(err);
this.setState({
errorType: BalanceErrs.mintingFailed,
});
await errorReporter.reportAsync(err);
return false;
}
}
private async faucetRequestAsync(isEtherRequest: boolean): Promise<boolean> {
private async _faucetRequestAsync(isEtherRequest: boolean): Promise<boolean> {
if (this.props.userAddress === '') {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
return false;
@@ -619,13 +619,13 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
const responseBody = await response.text();
if (response.status !== constants.SUCCESS_STATUS) {
utils.consoleLog(`Unexpected status code: ${response.status} -> ${responseBody}`);
await errorReporter.reportAsync(new Error(`Faucet returned non-200: ${JSON.stringify(response)}`));
const errorType = response.status === constants.UNAVAILABLE_STATUS ?
BalanceErrs.faucetQueueIsFull :
BalanceErrs.faucetRequestFailed;
this.setState({
errorType,
});
await errorReporter.reportAsync(new Error(`Faucet returned non-200: ${JSON.stringify(response)}`));
return false;
}
@@ -646,23 +646,23 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
}
return true;
}
private onErrorDialogToggle(isOpen: boolean) {
private _onErrorDialogToggle(isOpen: boolean) {
this.setState({
errorType: undefined,
});
}
private onDharmaDialogToggle() {
private _onDharmaDialogToggle() {
this.setState({
isDharmaDialogVisible: !this.state.isDharmaDialogVisible,
});
}
private onAddTokenClicked() {
private _onAddTokenClicked() {
this.setState({
isTokenPickerOpen: true,
isAddingToken: true,
});
}
private onRemoveTokenClicked() {
private _onRemoveTokenClicked() {
this.setState({
isTokenPickerOpen: true,
isAddingToken: false,

View File

@@ -127,7 +127,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
<MenuItem style={{fontSize: styles.menuItem.fontSize}} primaryText="Whitepaper" />
</a>,
];
const bottomBorderStyle = this.shouldDisplayBottomBar() ? styles.bottomBar : {};
const bottomBorderStyle = this._shouldDisplayBottomBar() ? styles.bottomBar : {};
const fullWidthClasses = isFullWidthPage ? 'pr4' : '';
const logoUrl = isNightVersion ? '/images/protocol_logo_white.png' : '/images/protocol_logo_black.png';
const menuClasses = `col col-${isFullWidthPage ? '4' : '5'} ${fullWidthClasses} lg-pr0 md-pr2 sm-hide xs-hide`;
@@ -147,7 +147,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
</div>
<div className={`col col-${isFullWidthPage ? '8' : '9'} lg-hide md-hide`} />
<div className={`col col-${isFullWidthPage ? '6' : '5'} sm-hide xs-hide`} />
{!this.isViewingPortal() &&
{!this._isViewingPortal() &&
<div
className={menuClasses}
>
@@ -183,37 +183,37 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
}
{this.props.blockchainIsLoaded && !_.isEmpty(this.props.userAddress) &&
<div className="col col-5">
{this.renderUser()}
{this._renderUser()}
</div>
}
{!this.isViewingPortal() &&
{!this._isViewingPortal() &&
<div
className={`col ${isFullWidthPage ? 'col-2 pl2' : 'col-1'} md-hide lg-hide`}
>
<div style={menuIconStyle}>
<i
className="zmdi zmdi-menu"
onClick={this.onMenuButtonClick.bind(this)}
onClick={this._onMenuButtonClick.bind(this)}
/>
</div>
</div>
}
</div>
{this.renderDrawer()}
{this._renderDrawer()}
</div>
);
}
private renderDrawer() {
private _renderDrawer() {
return (
<Drawer
open={this.state.isDrawerOpen}
docked={false}
openSecondary={true}
onRequestChange={this.onMenuButtonClick.bind(this)}
onRequestChange={this._onMenuButtonClick.bind(this)}
>
{this.renderPortalMenu()}
{this.renderDocsMenu()}
{this.renderWiki()}
{this._renderPortalMenu()}
{this._renderDocsMenu()}
{this._renderWiki()}
<div className="pl1 py1 mt3" style={{backgroundColor: colors.lightGrey}}>Website</div>
<Link to={WebsitePaths.Home} className="text-decoration-none">
<MenuItem className="py2">Home</MenuItem>
@@ -221,22 +221,22 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
<Link to={`${WebsitePaths.Wiki}`} className="text-decoration-none">
<MenuItem className="py2">Wiki</MenuItem>
</Link>
{!this.isViewing0xjsDocs() &&
{!this._isViewing0xjsDocs() &&
<Link to={WebsitePaths.ZeroExJs} className="text-decoration-none">
<MenuItem className="py2">0x.js Docs</MenuItem>
</Link>
}
{!this.isViewingConnectDocs() &&
{!this._isViewingConnectDocs() &&
<Link to={WebsitePaths.Connect} className="text-decoration-none">
<MenuItem className="py2">0x Connect Docs</MenuItem>
</Link>
}
{!this.isViewingSmartContractsDocs() &&
{!this._isViewingSmartContractsDocs() &&
<Link to={WebsitePaths.SmartContracts} className="text-decoration-none">
<MenuItem className="py2">Smart Contract Docs</MenuItem>
</Link>
}
{!this.isViewingPortal() &&
{!this._isViewingPortal() &&
<Link to={`${WebsitePaths.Portal}`} className="text-decoration-none">
<MenuItem className="py2">Portal DApp</MenuItem>
</Link>
@@ -261,7 +261,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
<Link to={`${WebsitePaths.FAQ}`} className="text-decoration-none">
<MenuItem
className="py2"
onTouchTap={this.onMenuButtonClick.bind(this)}
onTouchTap={this._onMenuButtonClick.bind(this)}
>
FAQ
</MenuItem>
@@ -269,8 +269,8 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
</Drawer>
);
}
private renderDocsMenu() {
if (!this.isViewing0xjsDocs() && !this.isViewingSmartContractsDocs() && !this.isViewingConnectDocs()
private _renderDocsMenu() {
if (!this._isViewing0xjsDocs() && !this._isViewingSmartContractsDocs() && !this._isViewingConnectDocs()
|| _.isUndefined(this.props.menu)) {
return;
}
@@ -283,7 +283,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
topLevelMenu={this.props.menu}
menuSubsectionsBySection={this.props.menuSubsectionsBySection}
shouldDisplaySectionHeaders={false}
onMenuItemClick={this.onMenuButtonClick.bind(this)}
onMenuItemClick={this._onMenuButtonClick.bind(this)}
selectedVersion={this.props.docsVersion}
docPath={this.props.docsInfo.websitePath}
versions={this.props.availableDocVersions}
@@ -291,8 +291,8 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
</div>
);
}
private renderWiki() {
if (!this.isViewingWiki()) {
private _renderWiki() {
if (!this._isViewingWiki()) {
return;
}
@@ -303,13 +303,13 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
topLevelMenu={this.props.menuSubsectionsBySection}
menuSubsectionsBySection={this.props.menuSubsectionsBySection}
shouldDisplaySectionHeaders={false}
onMenuItemClick={this.onMenuButtonClick.bind(this)}
onMenuItemClick={this._onMenuButtonClick.bind(this)}
/>
</div>
);
}
private renderPortalMenu() {
if (!this.isViewingPortal()) {
private _renderPortalMenu() {
if (!this._isViewingPortal()) {
return;
}
@@ -318,12 +318,12 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
<div className="pl1 py1" style={{backgroundColor: colors.lightGrey}}>Portal DApp</div>
<PortalMenu
menuItemStyle={{color: 'black'}}
onClick={this.onMenuButtonClick.bind(this)}
onClick={this._onMenuButtonClick.bind(this)}
/>
</div>
);
}
private renderUser() {
private _renderUser() {
const userAddress = this.props.userAddress;
const identiconDiameter = 26;
return (
@@ -345,31 +345,31 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
</div>
);
}
private onMenuButtonClick() {
private _onMenuButtonClick() {
this.setState({
isDrawerOpen: !this.state.isDrawerOpen,
});
}
private isViewingPortal() {
private _isViewingPortal() {
return _.includes(this.props.location.pathname, WebsitePaths.Portal);
}
private isViewingFAQ() {
private _isViewingFAQ() {
return _.includes(this.props.location.pathname, WebsitePaths.FAQ);
}
private isViewing0xjsDocs() {
private _isViewing0xjsDocs() {
return _.includes(this.props.location.pathname, WebsitePaths.ZeroExJs);
}
private isViewingConnectDocs() {
private _isViewingConnectDocs() {
return _.includes(this.props.location.pathname, WebsitePaths.Connect);
}
private isViewingSmartContractsDocs() {
private _isViewingSmartContractsDocs() {
return _.includes(this.props.location.pathname, WebsitePaths.SmartContracts);
}
private isViewingWiki() {
private _isViewingWiki() {
return _.includes(this.props.location.pathname, WebsitePaths.Wiki);
}
private shouldDisplayBottomBar() {
return this.isViewingWiki() || this.isViewing0xjsDocs() || this.isViewingFAQ() ||
this.isViewingSmartContractsDocs() || this.isViewingConnectDocs();
private _shouldDisplayBottomBar() {
return this._isViewingWiki() || this._isViewing0xjsDocs() || this._isViewingFAQ() ||
this._isViewingSmartContractsDocs() || this._isViewingConnectDocs();
}
}

View File

@@ -20,19 +20,19 @@ interface TradeHistoryState {
}
export class TradeHistory extends React.Component<TradeHistoryProps, TradeHistoryState> {
private fillPollingIntervalId: number;
private _fillPollingIntervalId: number;
public constructor(props: TradeHistoryProps) {
super(props);
const sortedFills = this.getSortedFills();
const sortedFills = this._getSortedFills();
this.state = {
sortedFills,
};
}
public componentWillMount() {
this.startPollingForFills();
this._startPollingForFills();
}
public componentWillUnmount() {
this.stopPollingForFills();
this._stopPollingForFills();
}
public componentDidMount() {
window.scrollTo(0, 0);
@@ -43,15 +43,15 @@ export class TradeHistory extends React.Component<TradeHistoryProps, TradeHistor
<h3>Trade history</h3>
<Divider />
<div className="pt2" style={{height: 608, overflow: 'scroll'}}>
{this.renderTrades()}
{this._renderTrades()}
</div>
</div>
);
}
private renderTrades() {
const numNonCustomFills = this.numFillsWithoutCustomERC20Tokens();
private _renderTrades() {
const numNonCustomFills = this._numFillsWithoutCustomERC20Tokens();
if (numNonCustomFills === 0) {
return this.renderEmptyNotice();
return this._renderEmptyNotice();
}
return _.map(this.state.sortedFills, (fill, index) => {
@@ -66,14 +66,14 @@ export class TradeHistory extends React.Component<TradeHistoryProps, TradeHistor
);
});
}
private renderEmptyNotice() {
private _renderEmptyNotice() {
return (
<Paper className="mt1 p2 mx-auto center" style={{width: '80%'}}>
No filled orders yet.
</Paper>
);
}
private numFillsWithoutCustomERC20Tokens() {
private _numFillsWithoutCustomERC20Tokens() {
let numNonCustomFills = 0;
const tokens = _.values(this.props.tokenByAddress);
_.each(this.state.sortedFills, fill => {
@@ -93,9 +93,9 @@ export class TradeHistory extends React.Component<TradeHistoryProps, TradeHistor
});
return numNonCustomFills;
}
private startPollingForFills() {
this.fillPollingIntervalId = window.setInterval(() => {
const sortedFills = this.getSortedFills();
private _startPollingForFills() {
this._fillPollingIntervalId = window.setInterval(() => {
const sortedFills = this._getSortedFills();
if (!utils.deepEqual(sortedFills, this.state.sortedFills)) {
this.setState({
sortedFills,
@@ -103,10 +103,10 @@ export class TradeHistory extends React.Component<TradeHistoryProps, TradeHistor
}
}, FILL_POLLING_INTERVAL);
}
private stopPollingForFills() {
clearInterval(this.fillPollingIntervalId);
private _stopPollingForFills() {
clearInterval(this._fillPollingIntervalId);
}
private getSortedFills() {
private _getSortedFills() {
const fillsByHash = tradeHistoryStorage.getUserFillsByHash(this.props.userAddress, this.props.networkId);
const fills = _.values(fillsByHash);
const sortedFills = _.sortBy(fills, [(fill: Fill) => fill.blockTimestamp * -1]);

View File

@@ -54,7 +54,7 @@ export class TradeHistoryItem extends React.Component<TradeHistoryItemProps, Tra
>
<div className="clearfix">
<div className="col col-12 lg-col-1 md-col-1 pt2 lg-pl3 md-pl3">
{this.renderDate()}
{this._renderDate()}
</div>
<div
className="col col-12 lg-col-6 md-col-6 lg-pl3 md-pl3"
@@ -80,7 +80,7 @@ export class TradeHistoryItem extends React.Component<TradeHistoryItemProps, Tra
className={amountColClassNames}
style={amountColStyle}
>
{this.renderAmounts(makerToken, takerToken)}
{this._renderAmounts(makerToken, takerToken)}
</div>
<div className="col col-12 lg-col-1 md-col-1 lg-pr3 md-pr3 lg-py3 md-py3 sm-pb1 sm-center">
<div className="pt1 lg-right md-right sm-mx-auto" style={{width: 13}}>
@@ -95,7 +95,7 @@ export class TradeHistoryItem extends React.Component<TradeHistoryItemProps, Tra
</Paper>
);
}
private renderAmounts(makerToken: Token, takerToken: Token) {
private _renderAmounts(makerToken: Token, takerToken: Token) {
const fill = this.props.fill;
const filledTakerTokenAmountInUnits = ZeroEx.toUnitAmount(fill.filledTakerTokenAmount, takerToken.decimals);
const filledMakerTokenAmountInUnits = ZeroEx.toUnitAmount(fill.filledMakerTokenAmount, takerToken.decimals);
@@ -133,14 +133,14 @@ export class TradeHistoryItem extends React.Component<TradeHistoryItemProps, Tra
style={{color: colors.green400, fontSize: 16}}
>
<span>+{' '}</span>
{this.renderAmount(receiveAmount, receiveToken.symbol, receiveToken.decimals)}
{this._renderAmount(receiveAmount, receiveToken.symbol, receiveToken.decimals)}
</div>
<div
className="pb1 inline-block"
style={{color: colors.red200, fontSize: 16}}
>
<span>-{' '}</span>
{this.renderAmount(givenAmount, givenToken.symbol, givenToken.decimals)}
{this._renderAmount(givenAmount, givenToken.symbol, givenToken.decimals)}
</div>
<div style={{color: colors.grey400, fontSize: 14}}>
{exchangeRate.toFixed(PRECISION)} {givenToken.symbol}/{receiveToken.symbol}
@@ -148,7 +148,7 @@ export class TradeHistoryItem extends React.Component<TradeHistoryItemProps, Tra
</div>
);
}
private renderDate() {
private _renderDate() {
const blockMoment = moment.unix(this.props.fill.blockTimestamp);
if (!blockMoment.isValid()) {
return null;
@@ -170,7 +170,7 @@ export class TradeHistoryItem extends React.Component<TradeHistoryItemProps, Tra
</div>
);
}
private renderAmount(amount: BigNumber, symbol: string, decimals: number) {
private _renderAmount(amount: BigNumber, symbol: string, decimals: number) {
const unitAmount = ZeroEx.toUnitAmount(amount, decimals);
return (
<span>

View File

@@ -42,14 +42,14 @@ export class Badge extends React.Component<BadgeProps, BadgeState> {
<div
className="p1 center"
style={badgeStyle}
onMouseOver={this.setHoverState.bind(this, true)}
onMouseOut={this.setHoverState.bind(this, false)}
onMouseOver={this._setHoverState.bind(this, true)}
onMouseOut={this._setHoverState.bind(this, false)}
>
{this.props.title}
</div>
);
}
private setHoverState(isHovering: boolean) {
private _setHoverState(isHovering: boolean) {
this.setState({
isHovering,
});

View File

@@ -15,8 +15,8 @@ interface CopyIconState {
}
export class CopyIcon extends React.Component<CopyIconProps, CopyIconState> {
private copyTooltipTimeoutId: number;
private copyable: HTMLInputElement;
private _copyTooltipTimeoutId: number;
private _copyable: HTMLInputElement;
constructor(props: CopyIconProps) {
super(props);
this.state = {
@@ -25,25 +25,25 @@ export class CopyIcon extends React.Component<CopyIconProps, CopyIconState> {
}
public componentDidUpdate() {
// Remove tooltip if hover away
if (!this.state.isHovering && this.copyTooltipTimeoutId) {
clearInterval(this.copyTooltipTimeoutId);
this.hideTooltip();
if (!this.state.isHovering && this._copyTooltipTimeoutId) {
clearInterval(this._copyTooltipTimeoutId);
this._hideTooltip();
}
}
public render() {
return (
<div className="inline-block">
<CopyToClipboard text={this.props.data} onCopy={this.onCopy.bind(this)}>
<CopyToClipboard text={this.props.data} onCopy={this._onCopy.bind(this)}>
<div
className="inline flex"
style={{cursor: 'pointer', color: colors.amber600}}
ref={this.setRefToProperty.bind(this)}
ref={this._setRefToProperty.bind(this)}
data-tip={true}
data-for="copy"
data-event="click"
data-iscapture={true} // This let's the click event continue to propogate
onMouseOver={this.setHoverState.bind(this, true)}
onMouseOut={this.setHoverState.bind(this, false)}
onMouseOver={this._setHoverState.bind(this, true)}
onMouseOut={this._setHoverState.bind(this, false)}
>
<div>
<i style={{fontSize: 15}} className="zmdi zmdi-copy" />
@@ -57,25 +57,25 @@ export class CopyIcon extends React.Component<CopyIconProps, CopyIconState> {
</div>
);
}
private setRefToProperty(el: HTMLInputElement) {
this.copyable = el;
private _setRefToProperty(el: HTMLInputElement) {
this._copyable = el;
}
private setHoverState(isHovering: boolean) {
private _setHoverState(isHovering: boolean) {
this.setState({
isHovering,
});
}
private onCopy() {
if (this.copyTooltipTimeoutId) {
clearInterval(this.copyTooltipTimeoutId);
private _onCopy() {
if (this._copyTooltipTimeoutId) {
clearInterval(this._copyTooltipTimeoutId);
}
const tooltipLifespanMs = 1000;
this.copyTooltipTimeoutId = window.setTimeout(() => {
this.hideTooltip();
this._copyTooltipTimeoutId = window.setTimeout(() => {
this._hideTooltip();
}, tooltipLifespanMs);
}
private hideTooltip() {
ReactTooltip.hide(ReactDOM.findDOMNode(this.copyable));
private _hideTooltip() {
ReactTooltip.hide(ReactDOM.findDOMNode(this._copyable));
}
}

View File

@@ -28,8 +28,8 @@ export class DropDownMenuItem extends React.Component<DropDownMenuItemProps, Dro
menuItemStyle: DEFAULT_STYLE,
isNightVersion: false,
};
private isHovering: boolean;
private popoverCloseCheckIntervalId: number;
private _isHovering: boolean;
private _popoverCloseCheckIntervalId: number;
constructor(props: DropDownMenuItemProps) {
super(props);
this.state = {
@@ -37,20 +37,20 @@ export class DropDownMenuItem extends React.Component<DropDownMenuItemProps, Dro
};
}
public componentDidMount() {
this.popoverCloseCheckIntervalId = window.setInterval(() => {
this.checkIfShouldClosePopover();
this._popoverCloseCheckIntervalId = window.setInterval(() => {
this._checkIfShouldClosePopover();
}, CHECK_CLOSE_POPOVER_INTERVAL_MS);
}
public componentWillUnmount() {
window.clearInterval(this.popoverCloseCheckIntervalId);
window.clearInterval(this._popoverCloseCheckIntervalId);
}
public render() {
const colorStyle = this.props.isNightVersion ? 'white' : this.props.style.color;
return (
<div
style={{...this.props.style, color: colorStyle}}
onMouseEnter={this.onHover.bind(this)}
onMouseLeave={this.onHoverOff.bind(this)}
onMouseEnter={this._onHover.bind(this)}
onMouseLeave={this._onHoverOff.bind(this)}
>
<div className="flex relative">
<div style={{paddingRight: 10}}>
@@ -65,12 +65,12 @@ export class DropDownMenuItem extends React.Component<DropDownMenuItemProps, Dro
anchorEl={this.state.anchorEl}
anchorOrigin={{horizontal: 'middle', vertical: 'bottom'}}
targetOrigin={{horizontal: 'middle', vertical: 'top'}}
onRequestClose={this.closePopover.bind(this)}
onRequestClose={this._closePopover.bind(this)}
useLayerForClickAway={false}
>
<div
onMouseEnter={this.onHover.bind(this)}
onMouseLeave={this.onHoverOff.bind(this)}
onMouseEnter={this._onHover.bind(this)}
onMouseLeave={this._onHoverOff.bind(this)}
>
<Menu style={{color: colors.grey}}>
{this.props.subMenuItems}
@@ -80,11 +80,11 @@ export class DropDownMenuItem extends React.Component<DropDownMenuItemProps, Dro
</div>
);
}
private onHover(event: React.FormEvent<HTMLInputElement>) {
this.isHovering = true;
this.checkIfShouldOpenPopover(event);
private _onHover(event: React.FormEvent<HTMLInputElement>) {
this._isHovering = true;
this._checkIfShouldOpenPopover(event);
}
private checkIfShouldOpenPopover(event: React.FormEvent<HTMLInputElement>) {
private _checkIfShouldOpenPopover(event: React.FormEvent<HTMLInputElement>) {
if (this.state.isDropDownOpen) {
return; // noop
}
@@ -94,16 +94,16 @@ export class DropDownMenuItem extends React.Component<DropDownMenuItemProps, Dro
anchorEl: event.currentTarget,
});
}
private onHoverOff(event: React.FormEvent<HTMLInputElement>) {
this.isHovering = false;
private _onHoverOff(event: React.FormEvent<HTMLInputElement>) {
this._isHovering = false;
}
private checkIfShouldClosePopover() {
if (!this.state.isDropDownOpen || this.isHovering) {
private _checkIfShouldClosePopover() {
if (!this.state.isDropDownOpen || this._isHovering) {
return; // noop
}
this.closePopover();
this._closePopover();
}
private closePopover() {
private _closePopover() {
this.setState({
isDropDownOpen: false,
});

View File

@@ -26,7 +26,7 @@ export class FlashMessage extends React.Component<FlashMessageProps, FlashMessag
open={true}
message={this.props.flashMessage}
autoHideDuration={this.props.showDurationMs}
onRequestClose={this.onClose.bind(this)}
onRequestClose={this._onClose.bind(this)}
bodyStyle={this.props.bodyStyle}
/>
);
@@ -34,7 +34,7 @@ export class FlashMessage extends React.Component<FlashMessageProps, FlashMessag
return null;
}
}
private onClose() {
private _onClose() {
this.props.dispatcher.hideFlashMessage();
}
}

View File

@@ -35,8 +35,8 @@ export class LifeCycleRaisedButton extends
backgroundColor: colors.white,
labelColor: colors.darkGrey,
};
private buttonTimeoutId: number;
private didUnmount: boolean;
private _buttonTimeoutId: number;
private _didUnmount: boolean;
constructor(props: LifeCycleRaisedButtonProps) {
super(props);
this.state = {
@@ -44,8 +44,8 @@ export class LifeCycleRaisedButton extends
};
}
public componentWillUnmount() {
clearTimeout(this.buttonTimeoutId);
this.didUnmount = true;
clearTimeout(this._buttonTimeoutId);
this._didUnmount = true;
}
public render() {
if (this.props.isHidden) {
@@ -83,14 +83,14 @@ export class LifeCycleRaisedButton extends
buttonState: ButtonState.LOADING,
});
const didSucceed = await this.props.onClickAsyncFn();
if (this.didUnmount) {
if (this._didUnmount) {
return; // noop since unmount called before async callback returned.
}
if (didSucceed) {
this.setState({
buttonState: ButtonState.COMPLETE,
});
this.buttonTimeoutId = window.setTimeout(() => {
this._buttonTimeoutId = window.setTimeout(() => {
this.setState({
buttonState: ButtonState.READY,
});

View File

@@ -35,15 +35,15 @@ export class MenuItem extends React.Component<MenuItemProps, MenuItemState> {
onClick={this.props.onClick.bind(this)}
className={`mx-auto ${this.props.className}`}
style={menuItemStyles}
onMouseEnter={this.onToggleHover.bind(this, true)}
onMouseLeave={this.onToggleHover.bind(this, false)}
onMouseEnter={this._onToggleHover.bind(this, true)}
onMouseLeave={this._onToggleHover.bind(this, false)}
>
{this.props.children}
</div>
</Link>
);
}
private onToggleHover(isHovering: boolean) {
private _onToggleHover(isHovering: boolean) {
this.setState({
isHovering,
});

View File

@@ -27,8 +27,8 @@ export class SwapIcon extends React.Component<SwapIconProps, SwapIconState> {
className="mx-auto pt4"
style={{cursor: 'pointer', height: 50, width: 37.5}}
onClick={this.props.swapTokensFn}
onMouseEnter={this.onToggleHover.bind(this, true)}
onMouseLeave={this.onToggleHover.bind(this, false)}
onMouseEnter={this._onToggleHover.bind(this, true)}
onMouseLeave={this._onToggleHover.bind(this, false)}
>
<i
style={swapStyles}
@@ -37,7 +37,7 @@ export class SwapIcon extends React.Component<SwapIconProps, SwapIconState> {
</div>
);
}
private onToggleHover(isHovering: boolean) {
private _onToggleHover(isHovering: boolean) {
this.setState({
isHovering,
});

View File

@@ -42,13 +42,13 @@ export class VisualOrder extends React.Component<VisualOrderProps, VisualOrderSt
</div>
<div className="col col-2 center pt1">
<div className="pb1">
{this.renderAmount(this.props.takerAssetToken, this.props.takerToken)}
{this._renderAmount(this.props.takerAssetToken, this.props.takerToken)}
</div>
<div className="lg-p2 md-p2 sm-p1">
<img src="/images/trade_arrows.png" style={{width: 47}} />
</div>
<div className="pt1">
{this.renderAmount(this.props.makerAssetToken, this.props.makerToken)}
{this._renderAmount(this.props.makerAssetToken, this.props.makerToken)}
</div>
</div>
<div className="col col-5 center">
@@ -65,7 +65,7 @@ export class VisualOrder extends React.Component<VisualOrderProps, VisualOrderSt
</div>
);
}
private renderAmount(assetToken: AssetToken, token: Token) {
private _renderAmount(assetToken: AssetToken, token: Token) {
const unitAmount = ZeroEx.toUnitAmount(assetToken.amount, token.decimals);
return (
<div style={{fontSize: 13}}>

Some files were not shown because too many files have changed in this diff Show More