Merge pull request #285 from 0xProject/fix/underscorePrivate

Add new underscore-privates rule to @0xproject/tslint-config and fix …
This commit is contained in:
Brandon Millman
2017-12-21 13:16:25 -05:00
committed by GitHub
94 changed files with 1433 additions and 1366 deletions

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

View File

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

View File

@@ -3,69 +3,69 @@ import {BigNumber} from 'bignumber.js';
import {SignedOrder} from '../types'; import {SignedOrder} from '../types';
export class RemainingFillableCalculator { export class RemainingFillableCalculator {
private signedOrder: SignedOrder; private _signedOrder: SignedOrder;
private isMakerTokenZRX: boolean; private _isMakerTokenZRX: boolean;
// Transferrable Amount is the minimum of Approval and Balance // Transferrable Amount is the minimum of Approval and Balance
private transferrableMakerTokenAmount: BigNumber; private _transferrableMakerTokenAmount: BigNumber;
private transferrableMakerFeeTokenAmount: BigNumber; private _transferrableMakerFeeTokenAmount: BigNumber;
private remainingMakerTokenAmount: BigNumber; private _remainingMakerTokenAmount: BigNumber;
private remainingMakerFeeAmount: BigNumber; private _remainingMakerFeeAmount: BigNumber;
constructor(signedOrder: SignedOrder, constructor(signedOrder: SignedOrder,
isMakerTokenZRX: boolean, isMakerTokenZRX: boolean,
transferrableMakerTokenAmount: BigNumber, transferrableMakerTokenAmount: BigNumber,
transferrableMakerFeeTokenAmount: BigNumber, transferrableMakerFeeTokenAmount: BigNumber,
remainingMakerTokenAmount: BigNumber) { remainingMakerTokenAmount: BigNumber) {
this.signedOrder = signedOrder; this._signedOrder = signedOrder;
this.isMakerTokenZRX = isMakerTokenZRX; this._isMakerTokenZRX = isMakerTokenZRX;
this.transferrableMakerTokenAmount = transferrableMakerTokenAmount; this._transferrableMakerTokenAmount = transferrableMakerTokenAmount;
this.transferrableMakerFeeTokenAmount = transferrableMakerFeeTokenAmount; this._transferrableMakerFeeTokenAmount = transferrableMakerFeeTokenAmount;
this.remainingMakerTokenAmount = remainingMakerTokenAmount; this._remainingMakerTokenAmount = remainingMakerTokenAmount;
this.remainingMakerFeeAmount = remainingMakerTokenAmount.times(signedOrder.makerFee) this._remainingMakerFeeAmount = remainingMakerTokenAmount.times(signedOrder.makerFee)
.dividedToIntegerBy(signedOrder.makerTokenAmount); .dividedToIntegerBy(signedOrder.makerTokenAmount);
} }
public computeRemainingMakerFillable(): BigNumber { public computeRemainingMakerFillable(): BigNumber {
if (this.hasSufficientFundsForFeeAndTransferAmount()) { if (this._hasSufficientFundsForFeeAndTransferAmount()) {
return this.remainingMakerTokenAmount; return this._remainingMakerTokenAmount;
} }
if (this.signedOrder.makerFee.isZero()) { if (this._signedOrder.makerFee.isZero()) {
return BigNumber.min(this.remainingMakerTokenAmount, this.transferrableMakerTokenAmount); return BigNumber.min(this._remainingMakerTokenAmount, this._transferrableMakerTokenAmount);
} }
return this.calculatePartiallyFillableMakerTokenAmount(); return this._calculatePartiallyFillableMakerTokenAmount();
} }
public computeRemainingTakerFillable(): BigNumber { public computeRemainingTakerFillable(): BigNumber {
return this.computeRemainingMakerFillable().times(this.signedOrder.takerTokenAmount) return this.computeRemainingMakerFillable().times(this._signedOrder.takerTokenAmount)
.dividedToIntegerBy(this.signedOrder.makerTokenAmount); .dividedToIntegerBy(this._signedOrder.makerTokenAmount);
} }
private hasSufficientFundsForFeeAndTransferAmount(): boolean { private _hasSufficientFundsForFeeAndTransferAmount(): boolean {
if (this.isMakerTokenZRX) { if (this._isMakerTokenZRX) {
const totalZRXTransferAmountRequired = this.remainingMakerTokenAmount.plus(this.remainingMakerFeeAmount); const totalZRXTransferAmountRequired = this._remainingMakerTokenAmount.plus(this._remainingMakerFeeAmount);
const hasSufficientFunds = this.transferrableMakerTokenAmount.greaterThanOrEqualTo( const hasSufficientFunds = this._transferrableMakerTokenAmount.greaterThanOrEqualTo(
totalZRXTransferAmountRequired); totalZRXTransferAmountRequired);
return hasSufficientFunds; return hasSufficientFunds;
} else { } else {
const hasSufficientFundsForTransferAmount = this.transferrableMakerTokenAmount.greaterThanOrEqualTo( const hasSufficientFundsForTransferAmount = this._transferrableMakerTokenAmount.greaterThanOrEqualTo(
this.remainingMakerTokenAmount); this._remainingMakerTokenAmount);
const hasSufficientFundsForFeeAmount = this.transferrableMakerFeeTokenAmount.greaterThanOrEqualTo( const hasSufficientFundsForFeeAmount = this._transferrableMakerFeeTokenAmount.greaterThanOrEqualTo(
this.remainingMakerFeeAmount); this._remainingMakerFeeAmount);
const hasSufficientFunds = hasSufficientFundsForTransferAmount && hasSufficientFundsForFeeAmount; const hasSufficientFunds = hasSufficientFundsForTransferAmount && hasSufficientFundsForFeeAmount;
return hasSufficientFunds; 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 // 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 // The number of times the maker can fill the order, if each fill only required the transfer of a single
// baseUnit of fee tokens. // baseUnit of fee tokens.
// Given 2 ZRXwei, the maximum amount of times Maker can fill this order, in terms of fees, is 2 // 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, const fillableTimesInFeeTokenBaseUnits = BigNumber.min(this._transferrableMakerFeeTokenAmount,
this.remainingMakerFeeAmount); this._remainingMakerFeeAmount);
// The number of times the Maker can fill the order, given the Maker Token Balance // 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. // 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); let fillableTimesInMakerTokenUnits = this._transferrableMakerTokenAmount.dividedBy(orderToFeeRatio);
if (this.isMakerTokenZRX) { if (this._isMakerTokenZRX) {
// If ZRX is the maker token, the Fee and the Maker amount need to be removed from the same pool; // 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) // 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 // 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 // For every one number of fills, we have to take an extra ZRX out of the pool
fillableTimesInMakerTokenUnits = totalZRXTokenPooled.dividedBy( 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. // 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. // This can result in a RoundingError being thrown by the Exchange Contract.
const partiallyFillableMakerTokenAmount = fillableTimesInMakerTokenUnits const partiallyFillableMakerTokenAmount = fillableTimesInMakerTokenUnits
.times(this.signedOrder.makerTokenAmount) .times(this._signedOrder.makerTokenAmount)
.dividedToIntegerBy(this.signedOrder.makerFee); .dividedToIntegerBy(this._signedOrder.makerFee);
const partiallyFillableFeeTokenAmount = fillableTimesInFeeTokenBaseUnits const partiallyFillableFeeTokenAmount = fillableTimesInFeeTokenBaseUnits
.times(this.signedOrder.makerTokenAmount) .times(this._signedOrder.makerTokenAmount)
.dividedToIntegerBy(this.signedOrder.makerFee); .dividedToIntegerBy(this._signedOrder.makerFee);
const partiallyFillableAmount = BigNumber.min(partiallyFillableMakerTokenAmount, const partiallyFillableAmount = BigNumber.min(partiallyFillableMakerTokenAmount,
partiallyFillableFeeTokenAmount); partiallyFillableFeeTokenAmount);
return partiallyFillableAmount; return partiallyFillableAmount;

View File

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

View File

@@ -8,54 +8,54 @@ import {BlockParamLiteral} from '../types';
* Copy on read store for filled/cancelled taker amounts * Copy on read store for filled/cancelled taker amounts
*/ */
export class OrderFilledCancelledLazyStore { export class OrderFilledCancelledLazyStore {
private exchange: ExchangeWrapper; private _exchange: ExchangeWrapper;
private filledTakerAmount: { private _filledTakerAmount: {
[orderHash: string]: BigNumber; [orderHash: string]: BigNumber;
}; };
private cancelledTakerAmount: { private _cancelledTakerAmount: {
[orderHash: string]: BigNumber; [orderHash: string]: BigNumber;
}; };
constructor(exchange: ExchangeWrapper) { constructor(exchange: ExchangeWrapper) {
this.exchange = exchange; this._exchange = exchange;
this.filledTakerAmount = {}; this._filledTakerAmount = {};
this.cancelledTakerAmount = {}; this._cancelledTakerAmount = {};
} }
public async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber> { public async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber> {
if (_.isUndefined(this.filledTakerAmount[orderHash])) { if (_.isUndefined(this._filledTakerAmount[orderHash])) {
const methodOpts = { const methodOpts = {
defaultBlock: BlockParamLiteral.Pending, defaultBlock: BlockParamLiteral.Pending,
}; };
const filledTakerAmount = await this.exchange.getFilledTakerAmountAsync(orderHash, methodOpts); const filledTakerAmount = await this._exchange.getFilledTakerAmountAsync(orderHash, methodOpts);
this.setFilledTakerAmount(orderHash, filledTakerAmount); this.setFilledTakerAmount(orderHash, filledTakerAmount);
} }
const cachedFilled = this.filledTakerAmount[orderHash]; const cachedFilled = this._filledTakerAmount[orderHash];
return cachedFilled; return cachedFilled;
} }
public setFilledTakerAmount(orderHash: string, filledTakerAmount: BigNumber): void { public setFilledTakerAmount(orderHash: string, filledTakerAmount: BigNumber): void {
this.filledTakerAmount[orderHash] = filledTakerAmount; this._filledTakerAmount[orderHash] = filledTakerAmount;
} }
public deleteFilledTakerAmount(orderHash: string): void { public deleteFilledTakerAmount(orderHash: string): void {
delete this.filledTakerAmount[orderHash]; delete this._filledTakerAmount[orderHash];
} }
public async getCancelledTakerAmountAsync(orderHash: string): Promise<BigNumber> { public async getCancelledTakerAmountAsync(orderHash: string): Promise<BigNumber> {
if (_.isUndefined(this.cancelledTakerAmount[orderHash])) { if (_.isUndefined(this._cancelledTakerAmount[orderHash])) {
const methodOpts = { const methodOpts = {
defaultBlock: BlockParamLiteral.Pending, defaultBlock: BlockParamLiteral.Pending,
}; };
const cancelledTakerAmount = await this.exchange.getCancelledTakerAmountAsync(orderHash, methodOpts); const cancelledTakerAmount = await this._exchange.getCancelledTakerAmountAsync(orderHash, methodOpts);
this.setCancelledTakerAmount(orderHash, cancelledTakerAmount); this.setCancelledTakerAmount(orderHash, cancelledTakerAmount);
} }
const cachedCancelled = this.cancelledTakerAmount[orderHash]; const cachedCancelled = this._cancelledTakerAmount[orderHash];
return cachedCancelled; return cachedCancelled;
} }
public setCancelledTakerAmount(orderHash: string, cancelledTakerAmount: BigNumber): void { public setCancelledTakerAmount(orderHash: string, cancelledTakerAmount: BigNumber): void {
this.cancelledTakerAmount[orderHash] = cancelledTakerAmount; this._cancelledTakerAmount[orderHash] = cancelledTakerAmount;
} }
public deleteCancelledTakerAmount(orderHash: string): void { public deleteCancelledTakerAmount(orderHash: string): void {
delete this.cancelledTakerAmount[orderHash]; delete this._cancelledTakerAmount[orderHash];
} }
public deleteAll(): void { public deleteAll(): void {
this.filledTakerAmount = {}; this._filledTakerAmount = {};
this.cancelledTakerAmount = {}; 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'; import {AbiType, ContractEventArgs, DecodedLogArgs, LogWithDecodedArgs, RawLog, SolidityTypes} from '../types';
export class AbiDecoder { export class AbiDecoder {
private savedABIs: Web3.AbiDefinition[] = []; private _savedABIs: Web3.AbiDefinition[] = [];
private methodIds: {[signatureHash: string]: Web3.EventAbi} = {}; private _methodIds: {[signatureHash: string]: Web3.EventAbi} = {};
private static padZeros(address: string) { private static _padZeros(address: string) {
let formatted = address; let formatted = address;
if (_.startsWith(formatted, '0x')) { if (_.startsWith(formatted, '0x')) {
formatted = formatted.slice(2); formatted = formatted.slice(2);
@@ -18,13 +18,13 @@ export class AbiDecoder {
return `0x${formatted}`; return `0x${formatted}`;
} }
constructor(abiArrays: Web3.AbiDefinition[][]) { 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 // This method can only decode logs from the 0x & ERC20 smart contracts
public tryToDecodeLogOrNoop<ArgsType extends ContractEventArgs>( public tryToDecodeLogOrNoop<ArgsType extends ContractEventArgs>(
log: Web3.LogEntry): LogWithDecodedArgs<ArgsType>|RawLog { log: Web3.LogEntry): LogWithDecodedArgs<ArgsType>|RawLog {
const methodId = log.topics[0]; const methodId = log.topics[0];
const event = this.methodIds[methodId]; const event = this._methodIds[methodId];
if (_.isUndefined(event)) { if (_.isUndefined(event)) {
return log; return log;
} }
@@ -41,7 +41,7 @@ export class AbiDecoder {
// Indexed parameters are stored in topics. Non-indexed ones in decodedData // Indexed parameters are stored in topics. Non-indexed ones in decodedData
let value = param.indexed ? log.topics[topicsIndex++] : decodedData[dataIndex++]; let value = param.indexed ? log.topics[topicsIndex++] : decodedData[dataIndex++];
if (param.type === SolidityTypes.Address) { 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 || } else if (param.type === SolidityTypes.Uint256 ||
param.type === SolidityTypes.Uint8 || param.type === SolidityTypes.Uint8 ||
param.type === SolidityTypes.Uint) { param.type === SolidityTypes.Uint) {
@@ -56,14 +56,14 @@ export class AbiDecoder {
args: decodedParams, args: decodedParams,
}; };
} }
private addABI(abiArray: Web3.AbiDefinition[]): void { private _addABI(abiArray: Web3.AbiDefinition[]): void {
_.map(abiArray, (abi: Web3.AbiDefinition) => { _.map(abiArray, (abi: Web3.AbiDefinition) => {
if (abi.type === AbiType.Event) { if (abi.type === AbiType.Event) {
const signature = `${abi.name}(${_.map(abi.inputs, input => input.type).join(',')})`; const signature = `${abi.name}(${_.map(abi.inputs, input => input.type).join(',')})`;
const signatureHash = new Web3().sha3(signature); 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 { export class ExchangeTransferSimulator {
private store: BalanceAndProxyAllowanceLazyStore; private _store: BalanceAndProxyAllowanceLazyStore;
private UNLIMITED_ALLOWANCE_IN_BASE_UNITS: BigNumber; private _UNLIMITED_ALLOWANCE_IN_BASE_UNITS: BigNumber;
private static throwValidationError(failureReason: FailureReason, tradeSide: TradeSide, private static _throwValidationError(failureReason: FailureReason, tradeSide: TradeSide,
transferType: TransferType): never { transferType: TransferType): never {
const errMsg = ERR_MSG_MAPPING[failureReason][tradeSide][transferType]; const errMsg = ERR_MSG_MAPPING[failureReason][tradeSide][transferType];
throw new Error(errMsg); throw new Error(errMsg);
} }
constructor(token: TokenWrapper, defaultBlock: BlockParamLiteral) { constructor(token: TokenWrapper, defaultBlock: BlockParamLiteral) {
this.store = new BalanceAndProxyAllowanceLazyStore(token, defaultBlock); this._store = new BalanceAndProxyAllowanceLazyStore(token, defaultBlock);
this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS = token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; this._UNLIMITED_ALLOWANCE_IN_BASE_UNITS = token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
} }
/** /**
* Simulates transferFrom call performed by a proxy * Simulates transferFrom call performed by a proxy
@@ -57,33 +57,33 @@ export class ExchangeTransferSimulator {
public async transferFromAsync(tokenAddress: string, from: string, to: string, public async transferFromAsync(tokenAddress: string, from: string, to: string,
amountInBaseUnits: BigNumber, tradeSide: TradeSide, amountInBaseUnits: BigNumber, tradeSide: TradeSide,
transferType: TransferType): Promise<void> { transferType: TransferType): Promise<void> {
const balance = await this.store.getBalanceAsync(tokenAddress, from); const balance = await this._store.getBalanceAsync(tokenAddress, from);
const proxyAllowance = await this.store.getProxyAllowanceAsync(tokenAddress, from); const proxyAllowance = await this._store.getProxyAllowanceAsync(tokenAddress, from);
if (proxyAllowance.lessThan(amountInBaseUnits)) { if (proxyAllowance.lessThan(amountInBaseUnits)) {
ExchangeTransferSimulator.throwValidationError(FailureReason.ProxyAllowance, tradeSide, transferType); ExchangeTransferSimulator._throwValidationError(FailureReason.ProxyAllowance, tradeSide, transferType);
} }
if (balance.lessThan(amountInBaseUnits)) { if (balance.lessThan(amountInBaseUnits)) {
ExchangeTransferSimulator.throwValidationError(FailureReason.Balance, tradeSide, transferType); ExchangeTransferSimulator._throwValidationError(FailureReason.Balance, tradeSide, transferType);
} }
await this.decreaseProxyAllowanceAsync(tokenAddress, from, amountInBaseUnits); await this._decreaseProxyAllowanceAsync(tokenAddress, from, amountInBaseUnits);
await this.decreaseBalanceAsync(tokenAddress, from, amountInBaseUnits); await this._decreaseBalanceAsync(tokenAddress, from, amountInBaseUnits);
await this.increaseBalanceAsync(tokenAddress, to, amountInBaseUnits); await this._increaseBalanceAsync(tokenAddress, to, amountInBaseUnits);
} }
private async decreaseProxyAllowanceAsync(tokenAddress: string, userAddress: string, private async _decreaseProxyAllowanceAsync(tokenAddress: string, userAddress: string,
amountInBaseUnits: BigNumber): Promise<void> { amountInBaseUnits: BigNumber): Promise<void> {
const proxyAllowance = await this.store.getProxyAllowanceAsync(tokenAddress, userAddress); const proxyAllowance = await this._store.getProxyAllowanceAsync(tokenAddress, userAddress);
if (!proxyAllowance.eq(this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS)) { if (!proxyAllowance.eq(this._UNLIMITED_ALLOWANCE_IN_BASE_UNITS)) {
this.store.setProxyAllowance(tokenAddress, userAddress, proxyAllowance.minus(amountInBaseUnits)); this._store.setProxyAllowance(tokenAddress, userAddress, proxyAllowance.minus(amountInBaseUnits));
} }
} }
private async increaseBalanceAsync(tokenAddress: string, userAddress: string, private async _increaseBalanceAsync(tokenAddress: string, userAddress: string,
amountInBaseUnits: BigNumber): Promise<void> { amountInBaseUnits: BigNumber): Promise<void> {
const balance = await this.store.getBalanceAsync(tokenAddress, userAddress); const balance = await this._store.getBalanceAsync(tokenAddress, userAddress);
this.store.setBalance(tokenAddress, userAddress, balance.plus(amountInBaseUnits)); this._store.setBalance(tokenAddress, userAddress, balance.plus(amountInBaseUnits));
} }
private async decreaseBalanceAsync(tokenAddress: string, userAddress: string, private async _decreaseBalanceAsync(tokenAddress: string, userAddress: string,
amountInBaseUnits: BigNumber): Promise<void> { amountInBaseUnits: BigNumber): Promise<void> {
const balance = await this.store.getBalanceAsync(tokenAddress, userAddress); const balance = await this._store.getBalanceAsync(tokenAddress, userAddress);
this.store.setBalance(tokenAddress, userAddress, balance.minus(amountInBaseUnits)); this._store.setBalance(tokenAddress, userAddress, balance.minus(amountInBaseUnits));
} }
} }

View File

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

View File

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

View File

@@ -65,7 +65,7 @@ describe('ExchangeTransferSimulator', () => {
await exchangeTransferSimulator.transferFromAsync( await exchangeTransferSimulator.transferFromAsync(
exampleTokenAddress, sender, recipient, transferAmount, TradeSide.Taker, TransferType.Trade, 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 senderBalance = await store.getBalanceAsync(exampleTokenAddress, sender);
const recipientBalance = await store.getBalanceAsync(exampleTokenAddress, recipient); const recipientBalance = await store.getBalanceAsync(exampleTokenAddress, recipient);
const senderProxyAllowance = await store.getProxyAllowanceAsync(exampleTokenAddress, sender); const senderProxyAllowance = await store.getProxyAllowanceAsync(exampleTokenAddress, sender);
@@ -81,7 +81,7 @@ describe('ExchangeTransferSimulator', () => {
await exchangeTransferSimulator.transferFromAsync( await exchangeTransferSimulator.transferFromAsync(
exampleTokenAddress, sender, recipient, transferAmount, TradeSide.Taker, TransferType.Trade, 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 senderBalance = await store.getBalanceAsync(exampleTokenAddress, sender);
const recipientBalance = await store.getBalanceAsync(exampleTokenAddress, recipient); const recipientBalance = await store.getBalanceAsync(exampleTokenAddress, recipient);
const senderProxyAllowance = await store.getProxyAllowanceAsync(exampleTokenAddress, sender); 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); const INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS = new BigNumber(100);
export class FillScenarios { export class FillScenarios {
private zeroEx: ZeroEx; private _zeroEx: ZeroEx;
private userAddresses: string[]; private _userAddresses: string[];
private tokens: Token[]; private _tokens: Token[];
private coinbase: string; private _coinbase: string;
private zrxTokenAddress: string; private _zrxTokenAddress: string;
private exchangeContractAddress: string; private _exchangeContractAddress: string;
constructor(zeroEx: ZeroEx, userAddresses: string[], constructor(zeroEx: ZeroEx, userAddresses: string[],
tokens: Token[], zrxTokenAddress: string, exchangeContractAddress: string) { tokens: Token[], zrxTokenAddress: string, exchangeContractAddress: string) {
this.zeroEx = zeroEx; this._zeroEx = zeroEx;
this.userAddresses = userAddresses; this._userAddresses = userAddresses;
this.tokens = tokens; this._tokens = tokens;
this.coinbase = userAddresses[0]; this._coinbase = userAddresses[0];
this.zrxTokenAddress = zrxTokenAddress; this._zrxTokenAddress = zrxTokenAddress;
this.exchangeContractAddress = exchangeContractAddress; this._exchangeContractAddress = exchangeContractAddress;
} }
public async initTokenBalancesAsync() { public async initTokenBalancesAsync() {
const web3Wrapper = (this.zeroEx as any)._web3Wrapper as Web3Wrapper; const web3Wrapper = (this._zeroEx as any)._web3Wrapper as Web3Wrapper;
for (const token of this.tokens) { for (const token of this._tokens) {
if (token.symbol !== 'ZRX' && token.symbol !== 'WETH') { if (token.symbol !== 'ZRX' && token.symbol !== 'WETH') {
const contractInstance = web3Wrapper.getContractInstance( const contractInstance = web3Wrapper.getContractInstance(
artifacts.DummyTokenArtifact.abi, token.address, artifacts.DummyTokenArtifact.abi, token.address,
@@ -36,10 +36,10 @@ export class FillScenarios {
const defaults = {}; const defaults = {};
const dummyToken = new DummyTokenContract(contractInstance, defaults); const dummyToken = new DummyTokenContract(contractInstance, defaults);
const tokenSupply = ZeroEx.toBaseUnitAmount(INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS, token.decimals); const tokenSupply = ZeroEx.toBaseUnitAmount(INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS, token.decimals);
const txHash = await dummyToken.setBalance.sendTransactionAsync(this.coinbase, tokenSupply, { const txHash = await dummyToken.setBalance.sendTransactionAsync(this._coinbase, tokenSupply, {
from: this.coinbase, from: this._coinbase,
}); });
await this.zeroEx.awaitTransactionMinedAsync(txHash); await this._zeroEx.awaitTransactionMinedAsync(txHash);
} }
} }
} }
@@ -60,7 +60,7 @@ export class FillScenarios {
fillableAmount: BigNumber, fillableAmount: BigNumber,
feeRecepient: string, expirationUnixTimestampSec?: BigNumber, feeRecepient: string, expirationUnixTimestampSec?: BigNumber,
): Promise<SignedOrder> { ): Promise<SignedOrder> {
return this.createAsymmetricFillableSignedOrderWithFeesAsync( return this._createAsymmetricFillableSignedOrderWithFeesAsync(
makerTokenAddress, takerTokenAddress, makerFee, takerFee, makerAddress, takerAddress, makerTokenAddress, takerTokenAddress, makerFee, takerFee, makerAddress, takerAddress,
fillableAmount, fillableAmount, feeRecepient, expirationUnixTimestampSec, fillableAmount, fillableAmount, feeRecepient, expirationUnixTimestampSec,
); );
@@ -72,7 +72,7 @@ export class FillScenarios {
const makerFee = new BigNumber(0); const makerFee = new BigNumber(0);
const takerFee = new BigNumber(0); const takerFee = new BigNumber(0);
const feeRecepient = constants.NULL_ADDRESS; const feeRecepient = constants.NULL_ADDRESS;
return this.createAsymmetricFillableSignedOrderWithFeesAsync( return this._createAsymmetricFillableSignedOrderWithFeesAsync(
makerTokenAddress, takerTokenAddress, makerFee, takerFee, makerAddress, takerAddress, makerTokenAddress, takerTokenAddress, makerFee, takerFee, makerAddress, takerAddress,
makerFillableAmount, takerFillableAmount, feeRecepient, expirationUnixTimestampSec, makerFillableAmount, takerFillableAmount, feeRecepient, expirationUnixTimestampSec,
); );
@@ -80,18 +80,18 @@ export class FillScenarios {
public async createPartiallyFilledSignedOrderAsync(makerTokenAddress: string, takerTokenAddress: string, public async createPartiallyFilledSignedOrderAsync(makerTokenAddress: string, takerTokenAddress: string,
takerAddress: string, fillableAmount: BigNumber, takerAddress: string, fillableAmount: BigNumber,
partialFillAmount: BigNumber) { partialFillAmount: BigNumber) {
const [makerAddress] = this.userAddresses; const [makerAddress] = this._userAddresses;
const signedOrder = await this.createAsymmetricFillableSignedOrderAsync( const signedOrder = await this.createAsymmetricFillableSignedOrderAsync(
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
fillableAmount, fillableAmount, fillableAmount, fillableAmount,
); );
const shouldThrowOnInsufficientBalanceOrAllowance = false; const shouldThrowOnInsufficientBalanceOrAllowance = false;
await this.zeroEx.exchange.fillOrderAsync( await this._zeroEx.exchange.fillOrderAsync(
signedOrder, partialFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, signedOrder, partialFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
); );
return signedOrder; return signedOrder;
} }
private async createAsymmetricFillableSignedOrderWithFeesAsync( private async _createAsymmetricFillableSignedOrderWithFeesAsync(
makerTokenAddress: string, takerTokenAddress: string, makerTokenAddress: string, takerTokenAddress: string,
makerFee: BigNumber, takerFee: BigNumber, makerFee: BigNumber, takerFee: BigNumber,
makerAddress: string, takerAddress: string, makerAddress: string, takerAddress: string,
@@ -99,39 +99,39 @@ export class FillScenarios {
feeRecepient: string, expirationUnixTimestampSec?: BigNumber): Promise<SignedOrder> { feeRecepient: string, expirationUnixTimestampSec?: BigNumber): Promise<SignedOrder> {
await Promise.all([ await Promise.all([
this.increaseBalanceAndAllowanceAsync(makerTokenAddress, makerAddress, makerFillableAmount), this._increaseBalanceAndAllowanceAsync(makerTokenAddress, makerAddress, makerFillableAmount),
this.increaseBalanceAndAllowanceAsync(takerTokenAddress, takerAddress, takerFillableAmount), this._increaseBalanceAndAllowanceAsync(takerTokenAddress, takerAddress, takerFillableAmount),
]); ]);
await Promise.all([ await Promise.all([
this.increaseBalanceAndAllowanceAsync(this.zrxTokenAddress, makerAddress, makerFee), this._increaseBalanceAndAllowanceAsync(this._zrxTokenAddress, makerAddress, makerFee),
this.increaseBalanceAndAllowanceAsync(this.zrxTokenAddress, takerAddress, takerFee), this._increaseBalanceAndAllowanceAsync(this._zrxTokenAddress, takerAddress, takerFee),
]); ]);
const signedOrder = await orderFactory.createSignedOrderAsync(this.zeroEx, const signedOrder = await orderFactory.createSignedOrderAsync(this._zeroEx,
makerAddress, takerAddress, makerFee, takerFee, makerAddress, takerAddress, makerFee, takerFee,
makerFillableAmount, makerTokenAddress, takerFillableAmount, takerTokenAddress, makerFillableAmount, makerTokenAddress, takerFillableAmount, takerTokenAddress,
this.exchangeContractAddress, feeRecepient, expirationUnixTimestampSec); this._exchangeContractAddress, feeRecepient, expirationUnixTimestampSec);
return signedOrder; return signedOrder;
} }
private async increaseBalanceAndAllowanceAsync( private async _increaseBalanceAndAllowanceAsync(
tokenAddress: string, address: string, amount: BigNumber): Promise<void> { tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
if (amount.isZero() || address === ZeroEx.NULL_ADDRESS) { if (amount.isZero() || address === ZeroEx.NULL_ADDRESS) {
return; // noop return; // noop
} }
await Promise.all([ await Promise.all([
this.increaseBalanceAsync(tokenAddress, address, amount), this._increaseBalanceAsync(tokenAddress, address, amount),
this.increaseAllowanceAsync(tokenAddress, address, amount), this._increaseAllowanceAsync(tokenAddress, address, amount),
]); ]);
} }
private async increaseBalanceAsync( private async _increaseBalanceAsync(
tokenAddress: string, address: string, amount: BigNumber): Promise<void> { 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> { 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); const newMakerAllowance = oldMakerAllowance.plus(amount);
await this.zeroEx.token.setProxyAllowanceAsync( await this._zeroEx.token.setProxyAllowanceAsync(
tokenAddress, address, newMakerAllowance, 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 * Source: https://github.com/MetaMask/provider-engine/blob/master/subproviders/subprovider.js
*/ */
export class FakeGasEstimateSubprovider { export class FakeGasEstimateSubprovider {
private constantGasAmount: number; private _constantGasAmount: number;
constructor(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. // 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 // tslint:disable-next-line:prefer-function-over-method
public handleRequest(payload: JSONRPCPayload, next: () => void, end: (err: Error|null, result: any) => void) { public handleRequest(payload: JSONRPCPayload, next: () => void, end: (err: Error|null, result: any) => void) {
switch (payload.method) { switch (payload.method) {
case 'eth_estimateGas': case 'eth_estimateGas':
end(null, this.constantGasAmount); end(null, this._constantGasAmount);
return; return;
default: default:

View File

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

View File

@@ -31,7 +31,7 @@ BigNumber.config({
* that implement the standard relayer API v0 * that implement the standard relayer API v0
*/ */
export class HttpClient implements Client { export class HttpClient implements Client {
private apiEndpointUrl: string; private _apiEndpointUrl: string;
/** /**
* Instantiates a new HttpClient instance * Instantiates a new HttpClient instance
* @param url The relayer API base HTTP url you would like to interact with * @param url The relayer API base HTTP url you would like to interact with
@@ -39,7 +39,7 @@ export class HttpClient implements Client {
*/ */
constructor(url: string) { constructor(url: string) {
assert.isHttpUrl('url', url); assert.isHttpUrl('url', url);
this.apiEndpointUrl = url; this._apiEndpointUrl = url;
} }
/** /**
* Retrieve token pair info from the API * Retrieve token pair info from the API
@@ -152,7 +152,7 @@ export class HttpClient implements Client {
const stringifiedParams = queryString.stringify(params); const stringifiedParams = queryString.stringify(params);
query = `?${stringifiedParams}`; query = `?${stringifiedParams}`;
} }
const url = `${this.apiEndpointUrl}/v0${path}${query}`; const url = `${this._apiEndpointUrl}/v0${path}${query}`;
const headers = new Headers({ const headers = new Headers({
'content-type': 'application/json', 'content-type': 'application/json',
}); });

View File

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

View File

@@ -19,18 +19,18 @@ import {utils} from './utils/utils';
const SOLIDITY_FILE_EXTENSION = '.sol'; const SOLIDITY_FILE_EXTENSION = '.sol';
export class Compiler { export class Compiler {
private contractsDir: string; private _contractsDir: string;
private networkId: number; private _networkId: number;
private optimizerEnabled: number; private _optimizerEnabled: number;
private artifactsDir: string; private _artifactsDir: string;
private contractSourcesIfExists?: ContractSources; private _contractSourcesIfExists?: ContractSources;
private solcErrors: Set<string>; private _solcErrors: Set<string>;
/** /**
* Recursively retrieves Solidity source code from directory. * Recursively retrieves Solidity source code from directory.
* @param dirPath Directory to search. * @param dirPath Directory to search.
* @return Mapping of contract name to contract source. * @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[] = []; let dirContents: string[] = [];
try { try {
dirContents = await fsWrapper.readdirAsync(dirPath); dirContents = await fsWrapper.readdirAsync(dirPath);
@@ -52,7 +52,7 @@ export class Compiler {
} }
} else { } else {
try { try {
const nestedSources = await Compiler.getContractSourcesAsync(contentPath); const nestedSources = await Compiler._getContractSourcesAsync(contentPath);
sources = { sources = {
...sources, ...sources,
...nestedSources, ...nestedSources,
@@ -69,7 +69,7 @@ export class Compiler {
* @param source Source code of contract. * @param source Source code of contract.
* @return Solc compiler version. * @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})/); const solcVersionMatch = source.match(/(?:solidity\s\^?)([0-9]{1,2}[.][0-9]{1,2}[.][0-9]{1,2})/);
if (_.isNull(solcVersionMatch)) { if (_.isNull(solcVersionMatch)) {
throw new Error('Could not find Solidity version in source'); 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. * @param errMsg An error message from the compiled output.
* @return The error message with directories truncated from the contract path. * @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)/); const errPathMatch = errMsg.match(/(.*\.sol)/);
if (_.isNull(errPathMatch)) { if (_.isNull(errPathMatch)) {
throw new Error('Could not find a path in error message'); 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. * @return An instance of the Compiler class.
*/ */
constructor(opts: CompilerOptions) { constructor(opts: CompilerOptions) {
this.contractsDir = opts.contractsDir; this._contractsDir = opts.contractsDir;
this.networkId = opts.networkId; this._networkId = opts.networkId;
this.optimizerEnabled = opts.optimizerEnabled; this._optimizerEnabled = opts.optimizerEnabled;
this.artifactsDir = opts.artifactsDir; this._artifactsDir = opts.artifactsDir;
this.solcErrors = new Set(); this._solcErrors = new Set();
} }
/** /**
* Compiles all Solidity files found in contractsDir and writes JSON artifacts to artifactsDir. * Compiles all Solidity files found in contractsDir and writes JSON artifacts to artifactsDir.
*/ */
public async compileAllAsync(): Promise<void> { public async compileAllAsync(): Promise<void> {
await this.createArtifactsDirIfDoesNotExistAsync(); await this._createArtifactsDirIfDoesNotExistAsync();
this.contractSourcesIfExists = await Compiler.getContractSourcesAsync(this.contractsDir); 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> => { const compiledContractPromises = _.map(contractBaseNames, async (contractBaseName: string): Promise<void> => {
return this.compileContractAsync(contractBaseName); return this._compileContractAsync(contractBaseName);
}); });
await Promise.all(compiledContractPromises); await Promise.all(compiledContractPromises);
this.solcErrors.forEach(errMsg => { this._solcErrors.forEach(errMsg => {
utils.consoleLog(errMsg); utils.consoleLog(errMsg);
}); });
} }
@@ -128,14 +128,14 @@ export class Compiler {
* Compiles contract and saves artifact to artifactsDir. * Compiles contract and saves artifact to artifactsDir.
* @param contractBaseName Name of contract with '.sol' extension. * @param contractBaseName Name of contract with '.sol' extension.
*/ */
private async compileContractAsync(contractBaseName: string): Promise<void> { private async _compileContractAsync(contractBaseName: string): Promise<void> {
if (_.isUndefined(this.contractSourcesIfExists)) { if (_.isUndefined(this._contractSourcesIfExists)) {
throw new Error('Contract sources not yet initialized'); 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 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')}`; const sourceHash = `0x${ethUtil.sha3(source).toString('hex')}`;
let currentArtifactString: string; let currentArtifactString: string;
@@ -149,10 +149,10 @@ export class Compiler {
currentArtifactString = await fsWrapper.readFileAsync(currentArtifactPath, opts); currentArtifactString = await fsWrapper.readFileAsync(currentArtifactPath, opts);
currentArtifact = JSON.parse(currentArtifactString); currentArtifact = JSON.parse(currentArtifactString);
oldNetworks = currentArtifact.networks; oldNetworks = currentArtifact.networks;
const oldNetwork: ContractData = oldNetworks[this.networkId]; const oldNetwork: ContractData = oldNetworks[this._networkId];
shouldCompile = _.isUndefined(oldNetwork) || shouldCompile = _.isUndefined(oldNetwork) ||
oldNetwork.keccak256 !== sourceHash || oldNetwork.keccak256 !== sourceHash ||
oldNetwork.optimizer_enabled !== this.optimizerEnabled; oldNetwork.optimizer_enabled !== this._optimizerEnabled;
} catch (err) { } catch (err) {
shouldCompile = true; shouldCompile = true;
} }
@@ -164,7 +164,7 @@ export class Compiler {
const input = { const input = {
[contractBaseName]: source, [contractBaseName]: source,
}; };
const solcVersion = Compiler.parseSolidityVersion(source); const solcVersion = Compiler._parseSolidityVersion(source);
const fullSolcVersion = binPaths[solcVersion]; const fullSolcVersion = binPaths[solcVersion];
const solcBinPath = `./../solc/solc_bin/${fullSolcVersion}`; const solcBinPath = `./../solc/solc_bin/${fullSolcVersion}`;
const solcBin = require(solcBinPath); const solcBin = require(solcBinPath);
@@ -175,13 +175,13 @@ export class Compiler {
sources: input, sources: input,
}; };
const compiled = solcInstance.compile(sourcesToCompile, const compiled = solcInstance.compile(sourcesToCompile,
this.optimizerEnabled, this._optimizerEnabled,
this.findImportsIfSourcesExist.bind(this)); this._findImportsIfSourcesExist.bind(this));
if (!_.isUndefined(compiled.errors)) { if (!_.isUndefined(compiled.errors)) {
_.each(compiled.errors, errMsg => { _.each(compiled.errors, errMsg => {
const normalizedErrMsg = Compiler.getNormalizedErrMsg(errMsg); const normalizedErrMsg = Compiler._getNormalizedErrMsg(errMsg);
this.solcErrors.add(normalizedErrMsg); this._solcErrors.add(normalizedErrMsg);
}); });
} }
@@ -192,7 +192,7 @@ export class Compiler {
const contractData: ContractData = { const contractData: ContractData = {
solc_version: solcVersion, solc_version: solcVersion,
keccak256: sourceHash, keccak256: sourceHash,
optimizer_enabled: this.optimizerEnabled, optimizer_enabled: this._optimizerEnabled,
abi, abi,
unlinked_binary, unlinked_binary,
updated_at, updated_at,
@@ -204,14 +204,14 @@ export class Compiler {
...currentArtifact, ...currentArtifact,
networks: { networks: {
...oldNetworks, ...oldNetworks,
[this.networkId]: contractData, [this._networkId]: contractData,
}, },
}; };
} else { } else {
newArtifact = { newArtifact = {
contract_name: contractName, contract_name: contractName,
networks: { networks: {
[this.networkId]: contractData, [this._networkId]: contractData,
}, },
}; };
} }
@@ -226,12 +226,12 @@ export class Compiler {
* @param importPath Path to an imported dependency. * @param importPath Path to an imported dependency.
* @return Import contents object containing source code of dependency. * @return Import contents object containing source code of dependency.
*/ */
private findImportsIfSourcesExist(importPath: string): ImportContents { private _findImportsIfSourcesExist(importPath: string): ImportContents {
if (_.isUndefined(this.contractSourcesIfExists)) { if (_.isUndefined(this._contractSourcesIfExists)) {
throw new Error('Contract sources not yet initialized'); throw new Error('Contract sources not yet initialized');
} }
const contractBaseName = path.basename(importPath); const contractBaseName = path.basename(importPath);
const source = this.contractSourcesIfExists[contractBaseName]; const source = this._contractSourcesIfExists[contractBaseName];
const importContents: ImportContents = { const importContents: ImportContents = {
contents: source, contents: source,
}; };
@@ -240,10 +240,10 @@ export class Compiler {
/** /**
* Creates the artifacts directory if it does not already exist. * Creates the artifacts directory if it does not already exist.
*/ */
private async createArtifactsDirIfDoesNotExistAsync(): Promise<void> { private async _createArtifactsDirIfDoesNotExistAsync(): Promise<void> {
if (!fsWrapper.doesPathExistSync(this.artifactsDir)) { if (!fsWrapper.doesPathExistSync(this._artifactsDir)) {
utils.consoleLog('Creating artifacts directory...'); 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 { export class Deployer {
public web3Wrapper: Web3Wrapper; public web3Wrapper: Web3Wrapper;
private artifactsDir: string; private _artifactsDir: string;
private jsonrpcPort: number; private _jsonrpcPort: number;
private networkId: number; private _networkId: number;
private defaults: Partial<TxData>; private _defaults: Partial<TxData>;
constructor(opts: DeployerOptions) { constructor(opts: DeployerOptions) {
this.artifactsDir = opts.artifactsDir; this._artifactsDir = opts.artifactsDir;
this.jsonrpcPort = opts.jsonrpcPort; this._jsonrpcPort = opts.jsonrpcPort;
this.networkId = opts.networkId; this._networkId = opts.networkId;
const jsonrpcUrl = `http://localhost:${this.jsonrpcPort}`; const jsonrpcUrl = `http://localhost:${this._jsonrpcPort}`;
const web3Provider = new Web3.providers.HttpProvider(jsonrpcUrl); const web3Provider = new Web3.providers.HttpProvider(jsonrpcUrl);
this.defaults = opts.defaults; this._defaults = opts.defaults;
this.web3Wrapper = new Web3Wrapper(web3Provider, this.defaults); this.web3Wrapper = new Web3Wrapper(web3Provider, this._defaults);
} }
/** /**
* Loads contract artifact and deploys contract with given arguments. * Loads contract artifact and deploys contract with given arguments.
@@ -39,21 +39,21 @@ export class Deployer {
* @return Deployed contract instance. * @return Deployed contract instance.
*/ */
public async deployAsync(contractName: string, args: any[] = []): Promise<Web3.ContractInstance> { public async deployAsync(contractName: string, args: any[] = []): Promise<Web3.ContractInstance> {
const contractArtifact: ContractArtifact = this.loadContractArtifactIfExists(contractName); const contractArtifact: ContractArtifact = this._loadContractArtifactIfExists(contractName);
const contractData: ContractData = this.getContractDataFromArtifactIfExists(contractArtifact); const contractData: ContractData = this._getContractDataFromArtifactIfExists(contractArtifact);
const data = contractData.unlinked_binary; const data = contractData.unlinked_binary;
const from = await this.getFromAddressAsync(); const from = await this._getFromAddressAsync();
const gas = await this.getAllowableGasEstimateAsync(data); const gas = await this._getAllowableGasEstimateAsync(data);
const txData = { const txData = {
gasPrice: this.defaults.gasPrice, gasPrice: this._defaults.gasPrice,
from, from,
data, data,
gas, gas,
}; };
const abi = contractData.abi; 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}`); 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; return contractInstance;
} }
/** /**
@@ -64,7 +64,7 @@ export class Deployer {
*/ */
public async deployAndSaveAsync(contractName: string, args: any[] = []): Promise<Web3.ContractInstance> { public async deployAndSaveAsync(contractName: string, args: any[] = []): Promise<Web3.ContractInstance> {
const contractInstance = await this.deployAsync(contractName, args); const contractInstance = await this.deployAsync(contractName, args);
await this.saveContractDataToArtifactAsync(contractName, contractInstance.address, args); await this._saveContractDataToArtifactAsync(contractName, contractInstance.address, args);
return contractInstance; return contractInstance;
} }
/** /**
@@ -74,7 +74,7 @@ export class Deployer {
* @param txData Tx options used for deployment. * @param txData Tx options used for deployment.
* @return Promise that resolves to a web3 contract instance. * @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 contract: Web3.Contract<Web3.ContractInstance> = this.web3Wrapper.getContractFromAbi(abi);
const deployPromise = new Promise((resolve, reject) => { const deployPromise = new Promise((resolve, reject) => {
/** /**
@@ -99,10 +99,10 @@ export class Deployer {
* @param contractAddress Contract address to save to artifact. * @param contractAddress Contract address to save to artifact.
* @param args Contract constructor arguments that will be encoded and saved to artifact. * @param args Contract constructor arguments that will be encoded and saved to artifact.
*/ */
private async saveContractDataToArtifactAsync(contractName: string, private async _saveContractDataToArtifactAsync(contractName: string,
contractAddress: string, args: any[]): Promise<void> { contractAddress: string, args: any[]): Promise<void> {
const contractArtifact: ContractArtifact = this.loadContractArtifactIfExists(contractName); const contractArtifact: ContractArtifact = this._loadContractArtifactIfExists(contractName);
const contractData: ContractData = this.getContractDataFromArtifactIfExists(contractArtifact); const contractData: ContractData = this._getContractDataFromArtifactIfExists(contractArtifact);
const abi = contractData.abi; const abi = contractData.abi;
const encodedConstructorArgs = encoder.encodeConstructorArgsFromAbi(args, abi); const encodedConstructorArgs = encoder.encodeConstructorArgsFromAbi(args, abi);
const newContractData = { const newContractData = {
@@ -114,11 +114,11 @@ export class Deployer {
...contractArtifact, ...contractArtifact,
networks: { networks: {
...contractArtifact.networks, ...contractArtifact.networks,
[this.networkId]: newContractData, [this._networkId]: newContractData,
}, },
}; };
const artifactString = utils.stringifyWithFormatting(newArtifact); const artifactString = utils.stringifyWithFormatting(newArtifact);
const artifactPath = `${this.artifactsDir}/${contractName}.json`; const artifactPath = `${this._artifactsDir}/${contractName}.json`;
await fsWrapper.writeFileAsync(artifactPath, artifactString); await fsWrapper.writeFileAsync(artifactPath, artifactString);
} }
/** /**
@@ -126,8 +126,8 @@ export class Deployer {
* @param contractName Name of the contract, without the extension. * @param contractName Name of the contract, without the extension.
* @return The contract artifact. * @return The contract artifact.
*/ */
private loadContractArtifactIfExists(contractName: string): ContractArtifact { private _loadContractArtifactIfExists(contractName: string): ContractArtifact {
const artifactPath = `${this.artifactsDir}/${contractName}.json`; const artifactPath = `${this._artifactsDir}/${contractName}.json`;
try { try {
const contractArtifact: ContractArtifact = require(artifactPath); const contractArtifact: ContractArtifact = require(artifactPath);
return contractArtifact; return contractArtifact;
@@ -140,8 +140,8 @@ export class Deployer {
* @param contractArtifact The contract artifact. * @param contractArtifact The contract artifact.
* @return Network specific contract data. * @return Network specific contract data.
*/ */
private getContractDataFromArtifactIfExists(contractArtifact: ContractArtifact): ContractData { private _getContractDataFromArtifactIfExists(contractArtifact: ContractArtifact): ContractData {
const contractData = contractArtifact.networks[this.networkId]; const contractData = contractArtifact.networks[this._networkId];
if (_.isUndefined(contractData)) { if (_.isUndefined(contractData)) {
throw new Error(`Data not found in artifact for contract: ${contractArtifact.contract_name}`); 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. * Gets the address to use for sending a transaction.
* @return The default from address. If not specified, returns the first address accessible by web3. * @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; let from: string;
if (_.isUndefined(this.defaults.from)) { if (_.isUndefined(this._defaults.from)) {
const accounts = await this.web3Wrapper.getAvailableAddressesAsync(); const accounts = await this.web3Wrapper.getAvailableAddressesAsync();
from = accounts[0]; from = accounts[0];
} else { } else {
from = this.defaults.from; from = this._defaults.from;
} }
return from; return from;
} }
@@ -167,7 +167,7 @@ export class Deployer {
* @param data Bytecode to estimate gas for. * @param data Bytecode to estimate gas for.
* @return Gas estimate for transaction data. * @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'); const block = await this.web3Wrapper.getBlockAsync('latest');
let gas: number; let gas: number;
try { try {

View File

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

View File

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

View File

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

View File

@@ -6,7 +6,7 @@ import * as Web3 from 'web3';
import {ContractInstance, TransactionDataParams} from './types'; import {ContractInstance, TransactionDataParams} from './types';
export class MultiSigWrapper { export class MultiSigWrapper {
private multiSig: ContractInstance; private _multiSig: ContractInstance;
public static encodeFnArgs(name: string, abi: Web3.AbiDefinition[], args: any[]) { public static encodeFnArgs(name: string, abi: Web3.AbiDefinition[], args: any[]) {
const abiEntity = _.find(abi, {name}) as Web3.MethodAbi; const abiEntity = _.find(abi, {name}) as Web3.MethodAbi;
if (_.isUndefined(abiEntity)) { if (_.isUndefined(abiEntity)) {
@@ -22,13 +22,13 @@ export class MultiSigWrapper {
return funcSig + argsData.join(''); return funcSig + argsData.join('');
} }
constructor(multiSigContractInstance: ContractInstance) { constructor(multiSigContractInstance: ContractInstance) {
this.multiSig = multiSigContractInstance; this._multiSig = multiSigContractInstance;
} }
public async submitTransactionAsync(destination: string, from: string, public async submitTransactionAsync(destination: string, from: string,
dataParams: TransactionDataParams, dataParams: TransactionDataParams,
value: number = 0) { value: number = 0) {
const {name, abi, args = []} = dataParams; const {name, abi, args = []} = dataParams;
const encoded = MultiSigWrapper.encodeFnArgs(name, abi, args); 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)) { if (_.isUndefined(v) || _.isUndefined(r) || _.isUndefined(s)) {
throw new Error('Cannot call isValidSignature on unsigned order'); throw new Error('Cannot call isValidSignature on unsigned order');
} }
const orderHash = this.getOrderHash(); const orderHash = this._getOrderHash();
const msgHash = ethUtil.hashPersonalMessage(ethUtil.toBuffer(orderHash)); const msgHash = ethUtil.hashPersonalMessage(ethUtil.toBuffer(orderHash));
try { try {
const pubKey = ethUtil.ecrecover(msgHash, v, ethUtil.toBuffer(r), ethUtil.toBuffer(s)); const pubKey = ethUtil.ecrecover(msgHash, v, ethUtil.toBuffer(r), ethUtil.toBuffer(s));
@@ -32,7 +32,7 @@ export class Order {
} }
} }
public async signAsync() { public async signAsync() {
const orderHash = this.getOrderHash(); const orderHash = this._getOrderHash();
const signature = await promisify<string>(web3.eth.sign)(this.params.maker, orderHash); const signature = await promisify<string>(web3.eth.sign)(this.params.maker, orderHash);
const {v, r, s} = ethUtil.fromRpcSig(signature); const {v, r, s} = ethUtil.fromRpcSig(signature);
this.params = _.assign(this.params, { this.params = _.assign(this.params, {
@@ -88,7 +88,7 @@ export class Order {
}; };
return cancel; return cancel;
} }
private getOrderHash(): string { private _getOrderHash(): string {
const orderHash = crypto.solSHA3([ const orderHash = crypto.solSHA3([
this.params.exchangeContractAddress, this.params.exchangeContractAddress,
this.params.maker, this.params.maker,

View File

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

View File

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

View File

@@ -1,21 +1,21 @@
import {RPC} from './rpc'; import {RPC} from './rpc';
export class BlockchainLifecycle { export class BlockchainLifecycle {
private rpc: RPC; private _rpc: RPC;
private snapshotIdsStack: number[]; private _snapshotIdsStack: number[];
constructor(url: string) { constructor(url: string) {
this.rpc = new RPC(url); this._rpc = new RPC(url);
this.snapshotIdsStack = []; this._snapshotIdsStack = [];
} }
// TODO: In order to run these tests on an actual node, we should check if we are running against // 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 // TestRPC, if so, use snapshots, otherwise re-deploy contracts before every test
public async startAsync(): Promise<void> { public async startAsync(): Promise<void> {
const snapshotId = await this.rpc.takeSnapshotAsync(); const snapshotId = await this._rpc.takeSnapshotAsync();
this.snapshotIdsStack.push(snapshotId); this._snapshotIdsStack.push(snapshotId);
} }
public async revertAsync(): Promise<void> { public async revertAsync(): Promise<void> {
const snapshotId = this.snapshotIdsStack.pop() as number; const snapshotId = this._snapshotIdsStack.pop() as number;
const didRevert = await this.rpc.revertSnapshotAsync(snapshotId); const didRevert = await this._rpc.revertSnapshotAsync(snapshotId);
if (!didRevert) { if (!didRevert) {
throw new Error(`Snapshot with id #${snapshotId} failed to revert`); 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'; import * as request from 'request-promise-native';
export class RPC { export class RPC {
private url: string; private _url: string;
private id: number; private _id: number;
constructor(url: string) { constructor(url: string) {
this.url = url; this._url = url;
this.id = 0; this._id = 0;
} }
public async takeSnapshotAsync(): Promise<number> { public async takeSnapshotAsync(): Promise<number> {
const method = 'evm_snapshot'; const method = 'evm_snapshot';
const params: any[] = []; const params: any[] = [];
const payload = this.toPayload(method, params); const payload = this._toPayload(method, params);
const snapshotIdHex = await this.sendAsync(payload); const snapshotIdHex = await this._sendAsync(payload);
const snapshotId = ethUtil.bufferToInt(ethUtil.toBuffer(snapshotIdHex)); const snapshotId = ethUtil.bufferToInt(ethUtil.toBuffer(snapshotIdHex));
return snapshotId; return snapshotId;
} }
public async revertSnapshotAsync(snapshotId: number): Promise<boolean> { public async revertSnapshotAsync(snapshotId: number): Promise<boolean> {
const method = 'evm_revert'; const method = 'evm_revert';
const params = [snapshotId]; const params = [snapshotId];
const payload = this.toPayload(method, params); const payload = this._toPayload(method, params);
const didRevert = await this.sendAsync(payload); const didRevert = await this._sendAsync(payload);
return didRevert; return didRevert;
} }
public async increaseTimeAsync(time: number) { public async increaseTimeAsync(time: number) {
const method = 'evm_increaseTime'; const method = 'evm_increaseTime';
const params = [time]; const params = [time];
const payload = this.toPayload(method, params); const payload = this._toPayload(method, params);
return this.sendAsync(payload); return this._sendAsync(payload);
} }
public async mineBlockAsync(): Promise<void> { public async mineBlockAsync(): Promise<void> {
const method = 'evm_mine'; const method = 'evm_mine';
const params: any[] = []; const params: any[] = [];
const payload = this.toPayload(method, params); const payload = this._toPayload(method, params);
await this.sendAsync(payload); await this._sendAsync(payload);
} }
private toPayload(method: string, params: any[] = []): string { private _toPayload(method: string, params: any[] = []): string {
const payload = JSON.stringify({ const payload = JSON.stringify({
id: this.id, id: this._id,
method, method,
params, params,
}); });
this.id += 1; this._url += 1;
return payload; return payload;
} }
private async sendAsync(payload: string): Promise<any> { private async _sendAsync(payload: string): Promise<any> {
const opts = { const opts = {
method: 'POST', method: 'POST',
uri: this.url, uri: this._url,
body: payload, body: payload,
headers: { headers: {
'content-type': 'application/json', 'content-type': 'application/json',

View File

@@ -4,15 +4,15 @@ import values = require('lodash.values');
import {schemas} from './schemas'; import {schemas} from './schemas';
export class SchemaValidator { export class SchemaValidator {
private validator: Validator; private _validator: Validator;
constructor() { constructor() {
this.validator = new Validator(); this._validator = new Validator();
for (const schema of values(schemas)) { for (const schema of values(schemas)) {
this.validator.addSchema(schema, schema.id); this._validator.addSchema(schema, schema.id);
} }
} }
public addSchema(schema: Schema) { 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 // 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 // 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. // then parse it. The resultant object can then be checked using jsonschema.
public validate(instance: any, schema: Schema): ValidatorResult { public validate(instance: any, schema: Schema): ValidatorResult {
const jsonSchemaCompatibleObject = JSON.parse(JSON.stringify(instance)); 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 { public isValid(instance: any, schema: Schema): boolean {
const isValid = this.validate(instance, schema).errors.length === 0; const isValid = this.validate(instance, schema).errors.length === 0;

View File

@@ -18,25 +18,25 @@ import {ZRXRequestQueue} from './zrx_request_queue';
import * as Web3 from 'web3'; import * as Web3 from 'web3';
export class Handler { export class Handler {
private etherRequestQueue: EtherRequestQueue; private _etherRequestQueue: EtherRequestQueue;
private zrxRequestQueue: ZRXRequestQueue; private _zrxRequestQueue: ZRXRequestQueue;
private web3: Web3; private _web3: Web3;
constructor() { constructor() {
// Setup provider engine to talk with RPC node // Setup provider engine to talk with RPC node
const providerObj = this.createProviderEngine(configs.RPC_URL); const providerObj = this._createProviderEngine(configs.RPC_URL);
this.web3 = new Web3(providerObj); this._web3 = new Web3(providerObj);
this.etherRequestQueue = new EtherRequestQueue(this.web3); this._etherRequestQueue = new EtherRequestQueue(this._web3);
this.zrxRequestQueue = new ZRXRequestQueue(this.web3); this._zrxRequestQueue = new ZRXRequestQueue(this._web3);
} }
public dispenseEther(req: express.Request, res: express.Response) { public dispenseEther(req: express.Request, res: express.Response) {
const recipientAddress = req.params.recipient; const recipientAddress = req.params.recipient;
if (_.isUndefined(recipientAddress) || !this.isValidEthereumAddress(recipientAddress)) { if (_.isUndefined(recipientAddress) || !this._isValidEthereumAddress(recipientAddress)) {
res.status(400).send('INVALID_REQUEST'); res.status(400).send('INVALID_REQUEST');
return; return;
} }
const lowerCaseRecipientAddress = recipientAddress.toLowerCase(); const lowerCaseRecipientAddress = recipientAddress.toLowerCase();
const didAddToQueue = this.etherRequestQueue.add(lowerCaseRecipientAddress); const didAddToQueue = this._etherRequestQueue.add(lowerCaseRecipientAddress);
if (!didAddToQueue) { if (!didAddToQueue) {
res.status(503).send('QUEUE_IS_FULL'); res.status(503).send('QUEUE_IS_FULL');
return; return;
@@ -46,12 +46,12 @@ export class Handler {
} }
public dispenseZRX(req: express.Request, res: express.Response) { public dispenseZRX(req: express.Request, res: express.Response) {
const recipientAddress = req.params.recipient; const recipientAddress = req.params.recipient;
if (_.isUndefined(recipientAddress) || !this.isValidEthereumAddress(recipientAddress)) { if (_.isUndefined(recipientAddress) || !this._isValidEthereumAddress(recipientAddress)) {
res.status(400).send('INVALID_REQUEST'); res.status(400).send('INVALID_REQUEST');
return; return;
} }
const lowerCaseRecipientAddress = recipientAddress.toLowerCase(); const lowerCaseRecipientAddress = recipientAddress.toLowerCase();
const didAddToQueue = this.zrxRequestQueue.add(lowerCaseRecipientAddress); const didAddToQueue = this._zrxRequestQueue.add(lowerCaseRecipientAddress);
if (!didAddToQueue) { if (!didAddToQueue) {
res.status(503).send('QUEUE_IS_FULL'); res.status(503).send('QUEUE_IS_FULL');
return; return;
@@ -63,18 +63,18 @@ export class Handler {
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
const payload = JSON.stringify({ const payload = JSON.stringify({
ether: { ether: {
full: this.etherRequestQueue.isFull(), full: this._etherRequestQueue.isFull(),
size: this.etherRequestQueue.size(), size: this._etherRequestQueue.size(),
}, },
zrx: { zrx: {
full: this.zrxRequestQueue.isFull(), full: this._zrxRequestQueue.isFull(),
size: this.zrxRequestQueue.size(), size: this._zrxRequestQueue.size(),
}, },
}); });
res.status(200).send(payload); res.status(200).send(payload);
} }
// tslint:disable-next-line:prefer-function-over-method // tslint:disable-next-line:prefer-function-over-method
private createProviderEngine(rpcUrl: string) { private _createProviderEngine(rpcUrl: string) {
const engine = new ProviderEngine(); const engine = new ProviderEngine();
engine.addProvider(new NonceSubprovider()); engine.addProvider(new NonceSubprovider());
engine.addProvider(new HookedWalletSubprovider(idManagement)); engine.addProvider(new HookedWalletSubprovider(idManagement));
@@ -84,8 +84,8 @@ export class Handler {
engine.start(); engine.start();
return engine; return engine;
} }
private isValidEthereumAddress(address: string): boolean { private _isValidEthereumAddress(address: string): boolean {
const lowercaseAddress = address.toLowerCase(); 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; const QUEUE_INTERVAL_MS = 5000;
export class ZRXRequestQueue extends RequestQueue { export class ZRXRequestQueue extends RequestQueue {
private zeroEx: ZeroEx; private _zeroEx: ZeroEx;
constructor(web3: Web3) { constructor(web3: Web3) {
super(web3); super(web3);
this.queueIntervalMs = QUEUE_INTERVAL_MS; this.queueIntervalMs = QUEUE_INTERVAL_MS;
const zeroExConfig = { const zeroExConfig = {
networkId: configs.KOVAN_NETWORK_ID, networkId: configs.KOVAN_NETWORK_ID,
}; };
this.zeroEx = new ZeroEx(web3.currentProvider, zeroExConfig); this._zeroEx = new ZeroEx(web3.currentProvider, zeroExConfig);
} }
protected async processNextRequestFireAndForgetAsync(recipientAddress: string) { protected async processNextRequestFireAndForgetAsync(recipientAddress: string) {
utils.consoleLog(`Processing ZRX ${recipientAddress}`); utils.consoleLog(`Processing ZRX ${recipientAddress}`);
const baseUnitAmount = ZeroEx.toBaseUnitAmount(DISPENSE_AMOUNT_ZRX, 18); const baseUnitAmount = ZeroEx.toBaseUnitAmount(DISPENSE_AMOUNT_ZRX, 18);
try { try {
await this.zeroEx.token.transferAsync( await this._zeroEx.token.transferAsync(
configs.ZRX_TOKEN_ADDRESS, configs.DISPENSER_ADDRESS, recipientAddress, baseUnitAmount, configs.ZRX_TOKEN_ADDRESS, configs.DISPENSER_ADDRESS, recipientAddress, baseUnitAmount,
); );
utils.consoleLog(`Sent ${DISPENSE_AMOUNT_ZRX} ZRX to ${recipientAddress}`); utils.consoleLog(`Sent ${DISPENSE_AMOUNT_ZRX} ZRX to ${recipientAddress}`);

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,10 @@
# CHANGELOG # CHANGELOG
v0.x.x - TBD
------------------------
* 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_ v0.3.0 - _December 20, 2017_
------------------------ ------------------------
* Added rules for unused imports, variables and Async suffixes (#265) * Added rules for unused imports, variables and Async suffixes (#265)

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, "space-within-parens": false,
"type-literal-delimiter": true, "type-literal-delimiter": true,
"underscore-privates": true,
"variable-name": [true, "variable-name": [true,
"ban-keywords", "ban-keywords",
"allow-pascal-case" "allow-pascal-case"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -59,13 +59,13 @@ export class EthWethConversionButton extends
labelStyle={labelStyle} labelStyle={labelStyle}
disabled={this.props.isDisabled || this.state.isEthConversionHappening} disabled={this.props.isDisabled || this.state.isEthConversionHappening}
label={this.state.isEthConversionHappening ? inProgressLabel : callToActionLabel} label={this.state.isEthConversionHappening ? inProgressLabel : callToActionLabel}
onClick={this.toggleConversionDialog.bind(this)} onClick={this._toggleConversionDialog.bind(this)}
/> />
<EthWethConversionDialog <EthWethConversionDialog
direction={this.props.direction} direction={this.props.direction}
isOpen={this.state.isEthConversionDialogVisible} isOpen={this.state.isEthConversionDialogVisible}
onComplete={this.onConversionAmountSelectedAsync.bind(this)} onComplete={this._onConversionAmountSelectedAsync.bind(this)}
onCancelled={this.toggleConversionDialog.bind(this)} onCancelled={this._toggleConversionDialog.bind(this)}
etherBalance={this.props.userEtherBalance} etherBalance={this.props.userEtherBalance}
token={this.props.ethToken} token={this.props.ethToken}
tokenState={this.props.ethTokenState} tokenState={this.props.ethTokenState}
@@ -73,16 +73,16 @@ export class EthWethConversionButton extends
</div> </div>
); );
} }
private toggleConversionDialog() { private _toggleConversionDialog() {
this.setState({ this.setState({
isEthConversionDialogVisible: !this.state.isEthConversionDialogVisible, isEthConversionDialogVisible: !this.state.isEthConversionDialogVisible,
}); });
} }
private async onConversionAmountSelectedAsync(direction: Side, value: BigNumber) { private async _onConversionAmountSelectedAsync(direction: Side, value: BigNumber) {
this.setState({ this.setState({
isEthConversionHappening: true, isEthConversionHappening: true,
}); });
this.toggleConversionDialog(); this._toggleConversionDialog();
const token = this.props.ethToken; const token = this.props.ethToken;
const tokenState = this.props.ethTokenState; const tokenState = this.props.ethTokenState;
let balance = tokenState.balance; let balance = tokenState.balance;

View File

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

View File

@@ -66,7 +66,7 @@ interface FillOrderState {
} }
export class FillOrder extends React.Component<FillOrderProps, FillOrderState> { export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
private validator: SchemaValidator; private _validator: SchemaValidator;
constructor(props: FillOrderProps) { constructor(props: FillOrderProps) {
super(props); super(props);
this.state = { this.state = {
@@ -87,12 +87,12 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
isConfirmingTokenTracking: false, isConfirmingTokenTracking: false,
tokensToTrack: [], tokensToTrack: [],
}; };
this.validator = new SchemaValidator(); this._validator = new SchemaValidator();
} }
public componentWillMount() { public componentWillMount() {
if (!_.isEmpty(this.state.orderJSON)) { if (!_.isEmpty(this.state.orderJSON)) {
// tslint:disable-next-line:no-floating-promises // tslint:disable-next-line:no-floating-promises
this.validateFillOrderFireAndForgetAsync(this.state.orderJSON); this._validateFillOrderFireAndForgetAsync(this.state.orderJSON);
} }
} }
public componentDidMount() { public componentDidMount() {
@@ -115,15 +115,15 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
tokenByAddress={this.props.tokenByAddress} tokenByAddress={this.props.tokenByAddress}
networkId={this.props.networkId} networkId={this.props.networkId}
orderJSON={this.state.orderJSON} orderJSON={this.state.orderJSON}
onFillOrderJSONChanged={this.onFillOrderJSONChanged.bind(this)} onFillOrderJSONChanged={this._onFillOrderJSONChanged.bind(this)}
/> />
{this.renderOrderJsonNotices()} {this._renderOrderJsonNotices()}
</div> </div>
} }
<div> <div>
{!_.isUndefined(this.state.parsedOrder) && this.state.didOrderValidationRun {!_.isUndefined(this.state.parsedOrder) && this.state.didOrderValidationRun
&& this.state.areAllInvolvedTokensTracked && && this.state.areAllInvolvedTokensTracked &&
this.renderVisualOrder() this._renderVisualOrder()
} }
</div> </div>
{this.props.isOrderInUrl && {this.props.isOrderInUrl &&
@@ -140,17 +140,17 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
tokenByAddress={this.props.tokenByAddress} tokenByAddress={this.props.tokenByAddress}
networkId={this.props.networkId} networkId={this.props.networkId}
orderJSON={this.state.orderJSON} orderJSON={this.state.orderJSON}
onFillOrderJSONChanged={this.onFillOrderJSONChanged.bind(this)} onFillOrderJSONChanged={this._onFillOrderJSONChanged.bind(this)}
/> />
</CardText> </CardText>
</Card> </Card>
{this.renderOrderJsonNotices()} {this._renderOrderJsonNotices()}
</div> </div>
} }
</div> </div>
<FillWarningDialog <FillWarningDialog
isOpen={this.state.isFillWarningDialogOpen} isOpen={this.state.isFillWarningDialogOpen}
onToggleDialog={this.onFillWarningClosed.bind(this)} onToggleDialog={this._onFillWarningClosed.bind(this)}
/> />
<TrackTokenConfirmationDialog <TrackTokenConfirmationDialog
userAddress={this.props.userAddress} userAddress={this.props.userAddress}
@@ -160,12 +160,12 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
dispatcher={this.props.dispatcher} dispatcher={this.props.dispatcher}
tokens={this.state.tokensToTrack} tokens={this.state.tokensToTrack}
isOpen={this.state.isConfirmingTokenTracking} isOpen={this.state.isConfirmingTokenTracking}
onToggleDialog={this.onToggleTrackConfirmDialog.bind(this)} onToggleDialog={this._onToggleTrackConfirmDialog.bind(this)}
/> />
</div> </div>
); );
} }
private renderOrderJsonNotices() { private _renderOrderJsonNotices() {
return ( return (
<div> <div>
{!_.isUndefined(this.props.initialOrder) && !this.state.didOrderValidationRun && {!_.isUndefined(this.props.initialOrder) && !this.state.didOrderValidationRun &&
@@ -182,7 +182,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
</div> </div>
); );
} }
private renderVisualOrder() { private _renderVisualOrder() {
const takerTokenAddress = this.state.parsedOrder.taker.token.address; const takerTokenAddress = this.state.parsedOrder.taker.token.address;
const takerToken = this.props.tokenByAddress[takerTokenAddress]; const takerToken = this.props.tokenByAddress[takerTokenAddress];
const orderTakerAmount = new BigNumber(this.state.parsedOrder.taker.amount); const orderTakerAmount = new BigNumber(this.state.parsedOrder.taker.amount);
@@ -211,7 +211,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
let orderReceiveAmount = 0; let orderReceiveAmount = 0;
if (!_.isUndefined(this.props.orderFillAmount)) { if (!_.isUndefined(this.props.orderFillAmount)) {
const orderReceiveAmountBigNumber = exchangeRate.mul(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) && const isUserMaker = !_.isUndefined(this.state.parsedOrder) &&
this.state.parsedOrder.maker.address === this.props.userAddress; 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}}> <div className="clearfix mx-auto relative" style={{width: 235, height: 108}}>
<TokenAmountInput <TokenAmountInput
label="Fill amount" label="Fill amount"
onChange={this.onFillAmountChange.bind(this)} onChange={this._onFillAmountChange.bind(this)}
shouldShowIncompleteErrs={false} shouldShowIncompleteErrs={false}
token={fillToken} token={fillToken}
tokenState={fillTokenState} tokenState={fillTokenState}
@@ -284,12 +284,12 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
style={{width: '100%'}} style={{width: '100%'}}
disabled={this.state.isCancelling} disabled={this.state.isCancelling}
label={this.state.isCancelling ? 'Cancelling order...' : 'Cancel order'} label={this.state.isCancelling ? 'Cancelling order...' : 'Cancel order'}
onClick={this.onCancelOrderClickFireAndForgetAsync.bind(this)} onClick={this._onCancelOrderClickFireAndForgetAsync.bind(this)}
/> />
{this.state.didCancelOrderSucceed && {this.state.didCancelOrderSucceed &&
<Alert <Alert
type={AlertTypes.SUCCESS} type={AlertTypes.SUCCESS}
message={this.renderCancelSuccessMsg()} message={this._renderCancelSuccessMsg()}
/> />
} }
</div> : </div> :
@@ -298,7 +298,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
style={{width: '100%'}} style={{width: '100%'}}
disabled={this.state.isFilling} disabled={this.state.isFilling}
label={this.state.isFilling ? 'Filling order...' : 'Fill order'} label={this.state.isFilling ? 'Filling order...' : 'Fill order'}
onClick={this.onFillOrderClick.bind(this)} onClick={this._onFillOrderClick.bind(this)}
/> />
{!_.isEmpty(this.state.globalErrMsg) && {!_.isEmpty(this.state.globalErrMsg) &&
<Alert type={AlertTypes.ERROR} message={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 && {this.state.didFillOrderSucceed &&
<Alert <Alert
type={AlertTypes.SUCCESS} type={AlertTypes.SUCCESS}
message={this.renderFillSuccessMsg()} message={this._renderFillSuccessMsg()}
/> />
} }
</div> </div>
@@ -315,7 +315,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
</div> </div>
); );
} }
private renderFillSuccessMsg() { private _renderFillSuccessMsg() {
return ( return (
<div> <div>
Order successfully filled. See the trade details in your{' '} Order successfully filled. See the trade details in your{' '}
@@ -328,45 +328,45 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
</div> </div>
); );
} }
private renderCancelSuccessMsg() { private _renderCancelSuccessMsg() {
return ( return (
<div> <div>
Order successfully cancelled. Order successfully cancelled.
</div> </div>
); );
} }
private onFillOrderClick() { private _onFillOrderClick() {
if (!this.state.isMakerTokenAddressInRegistry || !this.state.isTakerTokenAddressInRegistry) { if (!this.state.isMakerTokenAddressInRegistry || !this.state.isTakerTokenAddressInRegistry) {
this.setState({ this.setState({
isFillWarningDialogOpen: true, isFillWarningDialogOpen: true,
}); });
} else { } else {
// tslint:disable-next-line:no-floating-promises // tslint:disable-next-line:no-floating-promises
this.onFillOrderClickFireAndForgetAsync(); this._onFillOrderClickFireAndForgetAsync();
} }
} }
private onFillWarningClosed(didUserCancel: boolean) { private _onFillWarningClosed(didUserCancel: boolean) {
this.setState({ this.setState({
isFillWarningDialogOpen: false, isFillWarningDialogOpen: false,
}); });
if (!didUserCancel) { if (!didUserCancel) {
// tslint:disable-next-line:no-floating-promises // 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); this.props.dispatcher.updateOrderFillAmount(amount);
} }
private onFillOrderJSONChanged(event: any) { private _onFillOrderJSONChanged(event: any) {
const orderJSON = event.target.value; const orderJSON = event.target.value;
this.setState({ this.setState({
didOrderValidationRun: _.isEmpty(orderJSON) && _.isEmpty(this.state.orderJSONErrMsg), didOrderValidationRun: _.isEmpty(orderJSON) && _.isEmpty(this.state.orderJSONErrMsg),
didFillOrderSucceed: false, didFillOrderSucceed: false,
}); });
// tslint:disable-next-line:no-floating-promises // tslint:disable-next-line:no-floating-promises
this.validateFillOrderFireAndForgetAsync(orderJSON); this._validateFillOrderFireAndForgetAsync(orderJSON);
} }
private async checkForUntrackedTokensAndAskToAdd() { private async _checkForUntrackedTokensAndAskToAdd() {
if (!_.isEmpty(this.state.orderJSONErrMsg)) { if (!_.isEmpty(this.state.orderJSONErrMsg)) {
return; 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 orderJSONErrMsg = '';
let parsedOrder: Order; let parsedOrder: Order;
try { try {
const order = JSON.parse(orderJSON); const order = JSON.parse(orderJSON);
const validationResult = this.validator.validate(order, orderSchema); const validationResult = this._validator.validate(order, orderSchema);
if (validationResult.errors.length > 0) { if (validationResult.errors.length > 0) {
orderJSONErrMsg = 'Submitted order JSON is not a valid order'; orderJSONErrMsg = 'Submitted order JSON is not a valid order';
utils.consoleLog(`Unexpected order JSON validation error: ${validationResult.errors.join(', ')}`); utils.consoleLog(`Unexpected order JSON validation error: ${validationResult.errors.join(', ')}`);
@@ -508,9 +508,9 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
unavailableTakerAmount, 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)) { if (!_.isEmpty(this.props.blockchainErr) || _.isEmpty(this.props.userAddress)) {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
return; return;
@@ -601,7 +601,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
return; return;
} }
} }
private async onCancelOrderClickFireAndForgetAsync(): Promise<void> { private async _onCancelOrderClickFireAndForgetAsync(): Promise<void> {
if (!_.isEmpty(this.props.blockchainErr) || _.isEmpty(this.props.userAddress)) { if (!_.isEmpty(this.props.blockchainErr) || _.isEmpty(this.props.userAddress)) {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
return; return;
@@ -684,12 +684,12 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
return; return;
} }
} }
private formatCurrencyAmount(amount: BigNumber, decimals: number): number { private _formatCurrencyAmount(amount: BigNumber, decimals: number): number {
const unitAmount = ZeroEx.toUnitAmount(amount, decimals); const unitAmount = ZeroEx.toUnitAmount(amount, decimals);
const roundedUnitAmount = Math.round(unitAmount.toNumber() * 100000) / 100000; const roundedUnitAmount = Math.round(unitAmount.toNumber() * 100000) / 100000;
return roundedUnitAmount; return roundedUnitAmount;
} }
private onToggleTrackConfirmDialog(didConfirmTokenTracking: boolean) { private _onToggleTrackConfirmDialog(didConfirmTokenTracking: boolean) {
if (!didConfirmTokenTracking) { if (!didConfirmTokenTracking) {
this.setState({ this.setState({
orderJSON: '', 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-8 md-col-8 col-12 lg-pl4 md-pl4">
<div className="col lg-col-4 md-col-4 col-12"> <div className="col lg-col-4 md-col-4 col-12">
<div className="lg-right md-right sm-center"> <div className="lg-right md-right sm-center">
{this.renderHeader(Sections.Documentation)} {this._renderHeader(Sections.Documentation)}
{_.map(menuItemsBySection[Sections.Documentation], this.renderMenuItem.bind(this))} {_.map(menuItemsBySection[Sections.Documentation], this._renderMenuItem.bind(this))}
</div> </div>
</div> </div>
<div className="col lg-col-4 md-col-4 col-12 lg-pr2 md-pr2"> <div className="col lg-col-4 md-col-4 col-12 lg-pr2 md-pr2">
<div className="lg-right md-right sm-center"> <div className="lg-right md-right sm-center">
{this.renderHeader(Sections.Community)} {this._renderHeader(Sections.Community)}
{_.map(menuItemsBySection[Sections.Community], this.renderMenuItem.bind(this))} {_.map(menuItemsBySection[Sections.Community], this._renderMenuItem.bind(this))}
</div> </div>
</div> </div>
<div className="col lg-col-4 md-col-4 col-12"> <div className="col lg-col-4 md-col-4 col-12">
<div className="lg-right md-right sm-center"> <div className="lg-right md-right sm-center">
{this.renderHeader(Sections.Organization)} {this._renderHeader(Sections.Organization)}
{_.map(menuItemsBySection[Sections.Organization], this.renderMenuItem.bind(this))} {_.map(menuItemsBySection[Sections.Organization], this._renderMenuItem.bind(this))}
</div> </div>
</div> </div>
</div> </div>
@@ -154,14 +154,14 @@ export class Footer extends React.Component<FooterProps, FooterState> {
</div> </div>
); );
} }
private renderIcon(fileName: string) { private _renderIcon(fileName: string) {
return ( return (
<div style={{height: ICON_DIMENSION, width: ICON_DIMENSION}}> <div style={{height: ICON_DIMENSION, width: ICON_DIMENSION}}>
<img src={`/images/social/${fileName}`} style={{width: ICON_DIMENSION}} /> <img src={`/images/social/${fileName}`} style={{width: ICON_DIMENSION}} />
</div> </div>
); );
} }
private renderMenuItem(item: FooterMenuItem) { private _renderMenuItem(item: FooterMenuItem) {
const iconIfExists = titleToIcon[item.title]; const iconIfExists = titleToIcon[item.title];
return ( return (
<div <div
@@ -180,7 +180,7 @@ export class Footer extends React.Component<FooterProps, FooterState> {
<div className="sm-mx-auto" style={{width: 65}}> <div className="sm-mx-auto" style={{width: 65}}>
<div className="flex"> <div className="flex">
<div className="pr1"> <div className="pr1">
{this.renderIcon(iconIfExists)} {this._renderIcon(iconIfExists)}
</div> </div>
<div>{item.title}</div> <div>{item.title}</div>
</div> </div>
@@ -196,7 +196,7 @@ export class Footer extends React.Component<FooterProps, FooterState> {
<div> <div>
{!_.isUndefined(iconIfExists) && {!_.isUndefined(iconIfExists) &&
<div className="pr1"> <div className="pr1">
{this.renderIcon(iconIfExists)} {this._renderIcon(iconIfExists)}
</div> </div>
} }
{item.title} {item.title}
@@ -206,7 +206,7 @@ export class Footer extends React.Component<FooterProps, FooterState> {
</div> </div>
); );
} }
private renderHeader(title: string) { private _renderHeader(title: string) {
const headerStyle = { const headerStyle = {
textTransform: 'uppercase', textTransform: 'uppercase',
color: colors.grey400, color: colors.grey400,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -36,7 +36,7 @@ export class OrderJSON extends React.Component<OrderJSONProps, OrderJSONState> {
shareLink: '', shareLink: '',
}; };
// tslint:disable-next-line:no-floating-promises // tslint:disable-next-line:no-floating-promises
this.setShareLinkAsync(); this._setShareLinkAsync();
} }
public render() { public render() {
const order = utils.generateOrder(this.props.networkId, this.props.exchangeContractIfExists, const order = utils.generateOrder(this.props.networkId, this.props.exchangeContractIfExists,
@@ -88,21 +88,21 @@ export class OrderJSON extends React.Component<OrderJSONProps, OrderJSONState> {
<div> <div>
<i <i
style={{cursor: 'pointer', fontSize: 29}} style={{cursor: 'pointer', fontSize: 29}}
onClick={this.shareViaFacebook.bind(this)} onClick={this._shareViaFacebook.bind(this)}
className="zmdi zmdi-facebook-box" className="zmdi zmdi-facebook-box"
/> />
</div> </div>
<div className="pl1" style={{position: 'relative', width: 28}}> <div className="pl1" style={{position: 'relative', width: 28}}>
<i <i
style={{cursor: 'pointer', fontSize: 32, position: 'absolute', top: -2, left: 8}} 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" className="zmdi zmdi-email"
/> />
</div> </div>
<div className="pl1"> <div className="pl1">
<i <i
style={{cursor: 'pointer', fontSize: 29}} style={{cursor: 'pointer', fontSize: 29}}
onClick={this.shareViaTwitterAsync.bind(this)} onClick={this._shareViaTwitterAsync.bind(this)}
className="zmdi zmdi-twitter-box" className="zmdi zmdi-twitter-box"
/> />
</div> </div>
@@ -111,32 +111,32 @@ export class OrderJSON extends React.Component<OrderJSONProps, OrderJSONState> {
</div> </div>
); );
} }
private async shareViaTwitterAsync() { private async _shareViaTwitterAsync() {
const tweetText = encodeURIComponent(`Fill my order using the 0x protocol: ${this.state.shareLink}`); 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'); 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({ (window as any).FB.ui({
display: 'popup', display: 'popup',
href: this.state.shareLink, href: this.state.shareLink,
method: 'share', method: 'share',
}, _.noop); }, _.noop);
} }
private async shareViaEmailAsync() { private async _shareViaEmailAsync() {
const encodedSubject = encodeURIComponent('Let\'s trade using the 0x protocol'); const encodedSubject = encodeURIComponent('Let\'s trade using the 0x protocol');
const encodedBody = encodeURIComponent(`I generated an order with the 0x protocol. const encodedBody = encodeURIComponent(`I generated an order with the 0x protocol.
You can see and fill it here: ${this.state.shareLink}`); You can see and fill it here: ${this.state.shareLink}`);
const mailToLink = `mailto:mail@example.org?subject=${encodedSubject}&body=${encodedBody}`; const mailToLink = `mailto:mail@example.org?subject=${encodedSubject}&body=${encodedBody}`;
window.open(mailToLink, '_blank'); window.open(mailToLink, '_blank');
} }
private async setShareLinkAsync() { private async _setShareLinkAsync() {
const shareLink = await this.generateShareLinkAsync(); const shareLink = await this._generateShareLinkAsync();
this.setState({ this.setState({
shareLink, shareLink,
}); });
} }
private async generateShareLinkAsync(): Promise<string> { private async _generateShareLinkAsync(): Promise<string> {
const longUrl = encodeURIComponent(this.getOrderUrl()); const longUrl = encodeURIComponent(this._getOrderUrl());
const bitlyRequestUrl = const bitlyRequestUrl =
`${constants.URL_BITLY_API}/v3/shorten?access_token=${configs.BITLY_ACCESS_TOKEN}&longUrl=${longUrl}`; `${constants.URL_BITLY_API}/v3/shorten?access_token=${configs.BITLY_ACCESS_TOKEN}&longUrl=${longUrl}`;
const response = await fetch(bitlyRequestUrl); const response = await fetch(bitlyRequestUrl);
@@ -150,7 +150,7 @@ You can see and fill it here: ${this.state.shareLink}`);
} }
return (bodyObj).data.url; return (bodyObj).data.url;
} }
private getOrderUrl() { private _getOrderUrl() {
const order = utils.generateOrder(this.props.networkId, this.props.exchangeContractIfExists, const order = utils.generateOrder(this.props.networkId, this.props.exchangeContractIfExists,
this.props.sideToAssetToken, this.props.orderExpiryTimestamp, this.props.orderTakerAddress, this.props.sideToAssetToken, this.props.orderExpiryTimestamp, this.props.orderTakerAddress,
this.props.orderMakerAddress, this.props.orderMakerFee, this.props.orderTakerFee, 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> { export class Portal extends React.Component<PortalAllProps, PortalAllState> {
private blockchain: Blockchain; private _blockchain: Blockchain;
private sharedOrderIfExists: Order; private _sharedOrderIfExists: Order;
private throttledScreenWidthUpdate: () => void; private _throttledScreenWidthUpdate: () => void;
public static hasAlreadyDismissedWethNotice() { public static hasAlreadyDismissedWethNotice() {
const didDismissWethNotice = localStorage.getItemIfExists(constants.LOCAL_STORAGE_KEY_DISMISS_WETH_NOTICE); const didDismissWethNotice = localStorage.getItemIfExists(constants.LOCAL_STORAGE_KEY_DISMISS_WETH_NOTICE);
const hasAlreadyDismissedWethNotice = !_.isUndefined(didDismissWethNotice) && const hasAlreadyDismissedWethNotice = !_.isUndefined(didDismissWethNotice) &&
@@ -81,8 +81,8 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
} }
constructor(props: PortalAllProps) { constructor(props: PortalAllProps) {
super(props); super(props);
this.sharedOrderIfExists = this.getSharedOrderIfExists(); this._sharedOrderIfExists = this._getSharedOrderIfExists();
this.throttledScreenWidthUpdate = _.throttle(this.updateScreenWidth.bind(this), THROTTLE_TIMEOUT); this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
const isViewingBalances = _.includes(props.location.pathname, `${WebsitePaths.Portal}/balances`); const isViewingBalances = _.includes(props.location.pathname, `${WebsitePaths.Portal}/balances`);
const hasAlreadyDismissedWethNotice = Portal.hasAlreadyDismissedWethNotice(); const hasAlreadyDismissedWethNotice = Portal.hasAlreadyDismissedWethNotice();
@@ -100,15 +100,15 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
}; };
} }
public componentDidMount() { public componentDidMount() {
window.addEventListener('resize', this.throttledScreenWidthUpdate); window.addEventListener('resize', this._throttledScreenWidthUpdate);
window.scrollTo(0, 0); window.scrollTo(0, 0);
} }
public componentWillMount() { public componentWillMount() {
this.blockchain = new Blockchain(this.props.dispatcher); this._blockchain = new Blockchain(this.props.dispatcher);
} }
public componentWillUnmount() { public componentWillUnmount() {
this.blockchain.destroy(); this._blockchain.destroy();
window.removeEventListener('resize', this.throttledScreenWidthUpdate); window.removeEventListener('resize', this._throttledScreenWidthUpdate);
// We re-set the entire redux state when the portal is unmounted so that when it is re-rendered // 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 // 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 // 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) { public componentWillReceiveProps(nextProps: PortalAllProps) {
if (nextProps.networkId !== this.state.prevNetworkId) { if (nextProps.networkId !== this.state.prevNetworkId) {
// tslint:disable-next-line:no-floating-promises // tslint:disable-next-line:no-floating-promises
this.blockchain.networkIdUpdatedFireAndForgetAsync(nextProps.networkId); this._blockchain.networkIdUpdatedFireAndForgetAsync(nextProps.networkId);
this.setState({ this.setState({
prevNetworkId: nextProps.networkId, prevNetworkId: nextProps.networkId,
}); });
} }
if (nextProps.userAddress !== this.state.prevUserAddress) { if (nextProps.userAddress !== this.state.prevUserAddress) {
// tslint:disable-next-line:no-floating-promises // tslint:disable-next-line:no-floating-promises
this.blockchain.userAddressUpdatedFireAndForgetAsync(nextProps.userAddress); this._blockchain.userAddressUpdatedFireAndForgetAsync(nextProps.userAddress);
if (!_.isEmpty(nextProps.userAddress) && if (!_.isEmpty(nextProps.userAddress) &&
nextProps.blockchainIsLoaded) { nextProps.blockchainIsLoaded) {
const tokens = _.values(nextProps.tokenByAddress); const tokens = _.values(nextProps.tokenByAddress);
// tslint:disable-next-line:no-floating-promises // tslint:disable-next-line:no-floating-promises
this.updateBalanceAndAllowanceWithLoadingScreenAsync(tokens); this._updateBalanceAndAllowanceWithLoadingScreenAsync(tokens);
} }
this.setState({ this.setState({
prevUserAddress: nextProps.userAddress, prevUserAddress: nextProps.userAddress,
@@ -138,7 +138,7 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
} }
if (nextProps.nodeVersion !== this.state.prevNodeVersion) { if (nextProps.nodeVersion !== this.state.prevNodeVersion) {
// tslint:disable-next-line:no-floating-promises // tslint:disable-next-line:no-floating-promises
this.blockchain.nodeVersionUpdatedFireAndForgetAsync(nextProps.nodeVersion); this._blockchain.nodeVersionUpdatedFireAndForgetAsync(nextProps.nodeVersion);
} }
if (nextProps.location.pathname !== this.state.prevPathname) { if (nextProps.location.pathname !== this.state.prevPathname) {
const isViewingBalances = _.includes(nextProps.location.pathname, `${WebsitePaths.Portal}/balances`); const isViewingBalances = _.includes(nextProps.location.pathname, `${WebsitePaths.Portal}/balances`);
@@ -206,23 +206,23 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
<Switch> <Switch>
<Route <Route
path={`${WebsitePaths.Portal}/weth`} path={`${WebsitePaths.Portal}/weth`}
render={this.renderEthWrapper.bind(this)} render={this._renderEthWrapper.bind(this)}
/> />
<Route <Route
path={`${WebsitePaths.Portal}/fill`} path={`${WebsitePaths.Portal}/fill`}
render={this.renderFillOrder.bind(this)} render={this._renderFillOrder.bind(this)}
/> />
<Route <Route
path={`${WebsitePaths.Portal}/balances`} path={`${WebsitePaths.Portal}/balances`}
render={this.renderTokenBalances.bind(this)} render={this._renderTokenBalances.bind(this)}
/> />
<Route <Route
path={`${WebsitePaths.Portal}/trades`} path={`${WebsitePaths.Portal}/trades`}
component={this.renderTradeHistory.bind(this)} component={this._renderTradeHistory.bind(this)}
/> />
<Route <Route
path={`${WebsitePaths.Home}`} path={`${WebsitePaths.Home}`}
render={this.renderGenerateOrderForm.bind(this)} render={this._renderGenerateOrderForm.bind(this)}
/> />
</Switch> : </Switch> :
<Loading /> <Loading />
@@ -233,7 +233,7 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
} }
</Paper> </Paper>
<BlockchainErrDialog <BlockchainErrDialog
blockchain={this.blockchain} blockchain={this._blockchain}
blockchainErr={this.props.blockchainErr} blockchainErr={this.props.blockchainErr}
isOpen={this.props.shouldBlockchainErrDialogBeOpen} isOpen={this.props.shouldBlockchainErrDialogBeOpen}
userAddress={this.props.userAddress} userAddress={this.props.userAddress}
@@ -242,11 +242,11 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
/> />
<WrappedEthSectionNoticeDialog <WrappedEthSectionNoticeDialog
isOpen={this.state.isWethNoticeDialogOpen} isOpen={this.state.isWethNoticeDialogOpen}
onToggleDialog={this.onWethNoticeAccepted.bind(this)} onToggleDialog={this._onWethNoticeAccepted.bind(this)}
/> />
<PortalDisclaimerDialog <PortalDisclaimerDialog
isOpen={this.state.isDisclaimerDialogOpen} isOpen={this.state.isDisclaimerDialogOpen}
onToggleDialog={this.onPortalDisclaimerAccepted.bind(this)} onToggleDialog={this._onPortalDisclaimerAccepted.bind(this)}
/> />
<FlashMessage <FlashMessage
dispatcher={this.props.dispatcher} dispatcher={this.props.dispatcher}
@@ -257,11 +257,11 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
</div> </div>
); );
} }
private renderEthWrapper() { private _renderEthWrapper() {
return ( return (
<EthWrappers <EthWrappers
networkId={this.props.networkId} networkId={this.props.networkId}
blockchain={this.blockchain} blockchain={this._blockchain}
dispatcher={this.props.dispatcher} dispatcher={this.props.dispatcher}
tokenByAddress={this.props.tokenByAddress} tokenByAddress={this.props.tokenByAddress}
tokenStateByAddress={this.props.tokenStateByAddress} tokenStateByAddress={this.props.tokenStateByAddress}
@@ -270,7 +270,7 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
/> />
); );
} }
private renderTradeHistory() { private _renderTradeHistory() {
return ( return (
<TradeHistory <TradeHistory
tokenByAddress={this.props.tokenByAddress} tokenByAddress={this.props.tokenByAddress}
@@ -279,10 +279,10 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
/> />
); );
} }
private renderTokenBalances() { private _renderTokenBalances() {
return ( return (
<TokenBalances <TokenBalances
blockchain={this.blockchain} blockchain={this._blockchain}
blockchainErr={this.props.blockchainErr} blockchainErr={this.props.blockchainErr}
blockchainIsLoaded={this.props.blockchainIsLoaded} blockchainIsLoaded={this.props.blockchainIsLoaded}
dispatcher={this.props.dispatcher} 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) ? const initialFillOrder = !_.isUndefined(this.props.userSuppliedOrderCache) ?
this.props.userSuppliedOrderCache : this.props.userSuppliedOrderCache :
this.sharedOrderIfExists; this._sharedOrderIfExists;
return ( return (
<FillOrder <FillOrder
blockchain={this.blockchain} blockchain={this._blockchain}
blockchainErr={this.props.blockchainErr} blockchainErr={this.props.blockchainErr}
initialOrder={initialFillOrder} initialOrder={initialFillOrder}
isOrderInUrl={!_.isUndefined(this.sharedOrderIfExists)} isOrderInUrl={!_.isUndefined(this._sharedOrderIfExists)}
orderFillAmount={this.props.orderFillAmount} orderFillAmount={this.props.orderFillAmount}
networkId={this.props.networkId} networkId={this.props.networkId}
userAddress={this.props.userAddress} 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 ( return (
<GenerateOrderForm <GenerateOrderForm
blockchain={this.blockchain} blockchain={this._blockchain}
hashData={this.props.hashData} hashData={this.props.hashData}
dispatcher={this.props.dispatcher} dispatcher={this.props.dispatcher}
/> />
); );
} }
private onPortalDisclaimerAccepted() { private _onPortalDisclaimerAccepted() {
localStorage.setItem(constants.LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER, 'set'); localStorage.setItem(constants.LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER, 'set');
this.setState({ this.setState({
isDisclaimerDialogOpen: false, isDisclaimerDialogOpen: false,
}); });
} }
private onWethNoticeAccepted() { private _onWethNoticeAccepted() {
localStorage.setItem(constants.LOCAL_STORAGE_KEY_DISMISS_WETH_NOTICE, 'set'); localStorage.setItem(constants.LOCAL_STORAGE_KEY_DISMISS_WETH_NOTICE, 'set');
this.setState({ this.setState({
isWethNoticeDialogOpen: false, isWethNoticeDialogOpen: false,
}); });
} }
private getSharedOrderIfExists(): Order { private _getSharedOrderIfExists(): Order {
const queryString = window.location.search; const queryString = window.location.search;
if (queryString.length === 0) { if (queryString.length === 0) {
return; return;
@@ -362,13 +362,13 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
} }
return order; return order;
} }
private updateScreenWidth() { private _updateScreenWidth() {
const newScreenWidth = utils.getScreenWidth(); const newScreenWidth = utils.getScreenWidth();
this.props.dispatcher.updateScreenWidth(newScreenWidth); this.props.dispatcher.updateScreenWidth(newScreenWidth);
} }
private async updateBalanceAndAllowanceWithLoadingScreenAsync(tokens: Token[]) { private async _updateBalanceAndAllowanceWithLoadingScreenAsync(tokens: Token[]) {
this.props.dispatcher.updateBlockchainIsLoaded(false); this.props.dispatcher.updateBlockchainIsLoaded(false);
await this.blockchain.updateTokenBalancesAndAllowancesAsync(tokens); await this._blockchain.updateTokenBalancesAndAllowancesAsync(tokens);
this.props.dispatcher.updateBlockchainIsLoaded(true); this.props.dispatcher.updateBlockchainIsLoaded(true);
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

@@ -20,19 +20,19 @@ interface TradeHistoryState {
} }
export class TradeHistory extends React.Component<TradeHistoryProps, TradeHistoryState> { export class TradeHistory extends React.Component<TradeHistoryProps, TradeHistoryState> {
private fillPollingIntervalId: number; private _fillPollingIntervalId: number;
public constructor(props: TradeHistoryProps) { public constructor(props: TradeHistoryProps) {
super(props); super(props);
const sortedFills = this.getSortedFills(); const sortedFills = this._getSortedFills();
this.state = { this.state = {
sortedFills, sortedFills,
}; };
} }
public componentWillMount() { public componentWillMount() {
this.startPollingForFills(); this._startPollingForFills();
} }
public componentWillUnmount() { public componentWillUnmount() {
this.stopPollingForFills(); this._stopPollingForFills();
} }
public componentDidMount() { public componentDidMount() {
window.scrollTo(0, 0); window.scrollTo(0, 0);
@@ -43,15 +43,15 @@ export class TradeHistory extends React.Component<TradeHistoryProps, TradeHistor
<h3>Trade history</h3> <h3>Trade history</h3>
<Divider /> <Divider />
<div className="pt2" style={{height: 608, overflow: 'scroll'}}> <div className="pt2" style={{height: 608, overflow: 'scroll'}}>
{this.renderTrades()} {this._renderTrades()}
</div> </div>
</div> </div>
); );
} }
private renderTrades() { private _renderTrades() {
const numNonCustomFills = this.numFillsWithoutCustomERC20Tokens(); const numNonCustomFills = this._numFillsWithoutCustomERC20Tokens();
if (numNonCustomFills === 0) { if (numNonCustomFills === 0) {
return this.renderEmptyNotice(); return this._renderEmptyNotice();
} }
return _.map(this.state.sortedFills, (fill, index) => { return _.map(this.state.sortedFills, (fill, index) => {
@@ -66,14 +66,14 @@ export class TradeHistory extends React.Component<TradeHistoryProps, TradeHistor
); );
}); });
} }
private renderEmptyNotice() { private _renderEmptyNotice() {
return ( return (
<Paper className="mt1 p2 mx-auto center" style={{width: '80%'}}> <Paper className="mt1 p2 mx-auto center" style={{width: '80%'}}>
No filled orders yet. No filled orders yet.
</Paper> </Paper>
); );
} }
private numFillsWithoutCustomERC20Tokens() { private _numFillsWithoutCustomERC20Tokens() {
let numNonCustomFills = 0; let numNonCustomFills = 0;
const tokens = _.values(this.props.tokenByAddress); const tokens = _.values(this.props.tokenByAddress);
_.each(this.state.sortedFills, fill => { _.each(this.state.sortedFills, fill => {
@@ -93,9 +93,9 @@ export class TradeHistory extends React.Component<TradeHistoryProps, TradeHistor
}); });
return numNonCustomFills; return numNonCustomFills;
} }
private startPollingForFills() { private _startPollingForFills() {
this.fillPollingIntervalId = window.setInterval(() => { this._fillPollingIntervalId = window.setInterval(() => {
const sortedFills = this.getSortedFills(); const sortedFills = this._getSortedFills();
if (!utils.deepEqual(sortedFills, this.state.sortedFills)) { if (!utils.deepEqual(sortedFills, this.state.sortedFills)) {
this.setState({ this.setState({
sortedFills, sortedFills,
@@ -103,10 +103,10 @@ export class TradeHistory extends React.Component<TradeHistoryProps, TradeHistor
} }
}, FILL_POLLING_INTERVAL); }, FILL_POLLING_INTERVAL);
} }
private stopPollingForFills() { private _stopPollingForFills() {
clearInterval(this.fillPollingIntervalId); clearInterval(this._fillPollingIntervalId);
} }
private getSortedFills() { private _getSortedFills() {
const fillsByHash = tradeHistoryStorage.getUserFillsByHash(this.props.userAddress, this.props.networkId); const fillsByHash = tradeHistoryStorage.getUserFillsByHash(this.props.userAddress, this.props.networkId);
const fills = _.values(fillsByHash); const fills = _.values(fillsByHash);
const sortedFills = _.sortBy(fills, [(fill: Fill) => fill.blockTimestamp * -1]); 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="clearfix">
<div className="col col-12 lg-col-1 md-col-1 pt2 lg-pl3 md-pl3"> <div className="col col-12 lg-col-1 md-col-1 pt2 lg-pl3 md-pl3">
{this.renderDate()} {this._renderDate()}
</div> </div>
<div <div
className="col col-12 lg-col-6 md-col-6 lg-pl3 md-pl3" 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} className={amountColClassNames}
style={amountColStyle} style={amountColStyle}
> >
{this.renderAmounts(makerToken, takerToken)} {this._renderAmounts(makerToken, takerToken)}
</div> </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="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}}> <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> </Paper>
); );
} }
private renderAmounts(makerToken: Token, takerToken: Token) { private _renderAmounts(makerToken: Token, takerToken: Token) {
const fill = this.props.fill; const fill = this.props.fill;
const filledTakerTokenAmountInUnits = ZeroEx.toUnitAmount(fill.filledTakerTokenAmount, takerToken.decimals); const filledTakerTokenAmountInUnits = ZeroEx.toUnitAmount(fill.filledTakerTokenAmount, takerToken.decimals);
const filledMakerTokenAmountInUnits = ZeroEx.toUnitAmount(fill.filledMakerTokenAmount, 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}} style={{color: colors.green400, fontSize: 16}}
> >
<span>+{' '}</span> <span>+{' '}</span>
{this.renderAmount(receiveAmount, receiveToken.symbol, receiveToken.decimals)} {this._renderAmount(receiveAmount, receiveToken.symbol, receiveToken.decimals)}
</div> </div>
<div <div
className="pb1 inline-block" className="pb1 inline-block"
style={{color: colors.red200, fontSize: 16}} style={{color: colors.red200, fontSize: 16}}
> >
<span>-{' '}</span> <span>-{' '}</span>
{this.renderAmount(givenAmount, givenToken.symbol, givenToken.decimals)} {this._renderAmount(givenAmount, givenToken.symbol, givenToken.decimals)}
</div> </div>
<div style={{color: colors.grey400, fontSize: 14}}> <div style={{color: colors.grey400, fontSize: 14}}>
{exchangeRate.toFixed(PRECISION)} {givenToken.symbol}/{receiveToken.symbol} {exchangeRate.toFixed(PRECISION)} {givenToken.symbol}/{receiveToken.symbol}
@@ -148,7 +148,7 @@ export class TradeHistoryItem extends React.Component<TradeHistoryItemProps, Tra
</div> </div>
); );
} }
private renderDate() { private _renderDate() {
const blockMoment = moment.unix(this.props.fill.blockTimestamp); const blockMoment = moment.unix(this.props.fill.blockTimestamp);
if (!blockMoment.isValid()) { if (!blockMoment.isValid()) {
return null; return null;
@@ -170,7 +170,7 @@ export class TradeHistoryItem extends React.Component<TradeHistoryItemProps, Tra
</div> </div>
); );
} }
private renderAmount(amount: BigNumber, symbol: string, decimals: number) { private _renderAmount(amount: BigNumber, symbol: string, decimals: number) {
const unitAmount = ZeroEx.toUnitAmount(amount, decimals); const unitAmount = ZeroEx.toUnitAmount(amount, decimals);
return ( return (
<span> <span>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -23,12 +23,12 @@ export class LazyComponent extends React.Component<LazyComponentProps, LazyCompo
} }
public componentWillMount() { public componentWillMount() {
// tslint:disable-next-line:no-floating-promises // tslint:disable-next-line:no-floating-promises
this.loadComponentFireAndForgetAsync(this.props); this._loadComponentFireAndForgetAsync(this.props);
} }
public componentWillReceiveProps(nextProps: LazyComponentProps) { public componentWillReceiveProps(nextProps: LazyComponentProps) {
if (nextProps.reactComponentPromise !== this.props.reactComponentPromise) { if (nextProps.reactComponentPromise !== this.props.reactComponentPromise) {
// tslint:disable-next-line:no-floating-promises // tslint:disable-next-line:no-floating-promises
this.loadComponentFireAndForgetAsync(nextProps); this._loadComponentFireAndForgetAsync(nextProps);
} }
} }
public render() { public render() {
@@ -36,7 +36,7 @@ export class LazyComponent extends React.Component<LazyComponentProps, LazyCompo
null : null :
React.createElement(this.state.component, this.props.reactComponentProps); React.createElement(this.state.component, this.props.reactComponentProps);
} }
private async loadComponentFireAndForgetAsync(props: LazyComponentProps) { private async _loadComponentFireAndForgetAsync(props: LazyComponentProps) {
const component = await props.reactComponentPromise; const component = await props.reactComponentPromise;
this.setState({ this.setState({
component, component,

View File

@@ -188,10 +188,10 @@ export class About extends React.Component<AboutProps, AboutState> {
</div> </div>
<div className="pt3 md-px4 lg-px0"> <div className="pt3 md-px4 lg-px0">
<div className="clearfix pb3"> <div className="clearfix pb3">
{this.renderProfiles(teamRow1)} {this._renderProfiles(teamRow1)}
</div> </div>
<div className="clearfix"> <div className="clearfix">
{this.renderProfiles(teamRow2)} {this._renderProfiles(teamRow2)}
</div> </div>
</div> </div>
<div className="pt3 pb2"> <div className="pt3 pb2">
@@ -202,7 +202,7 @@ export class About extends React.Component<AboutProps, AboutState> {
Advisors: Advisors:
</div> </div>
<div className="clearfix"> <div className="clearfix">
{this.renderProfiles(advisors)} {this._renderProfiles(advisors)}
</div> </div>
</div> </div>
<div className="mx-auto py4 sm-px3" style={{maxWidth: 308}}> <div className="mx-auto py4 sm-px3" style={{maxWidth: 308}}>
@@ -232,7 +232,7 @@ export class About extends React.Component<AboutProps, AboutState> {
</div> </div>
); );
} }
private renderProfiles(profiles: ProfileInfo[]) { private _renderProfiles(profiles: ProfileInfo[]) {
const numIndiv = profiles.length; const numIndiv = profiles.length;
const colSize = utils.getColSize(numIndiv); const colSize = utils.getColSize(numIndiv);
return _.map(profiles, profile => { return _.map(profiles, profile => {

View File

@@ -19,7 +19,7 @@ export class DocsInfo {
public menu: DocsMenu; public menu: DocsMenu;
public sections: SectionsMap; public sections: SectionsMap;
public sectionNameToMarkdown: {[sectionName: string]: string}; public sectionNameToMarkdown: {[sectionName: string]: string};
private docsInfo: DocsInfoConfig; private _docsInfo: DocsInfoConfig;
constructor(config: DocsInfoConfig) { constructor(config: DocsInfoConfig) {
this.displayName = config.displayName; this.displayName = config.displayName;
this.packageUrl = config.packageUrl; this.packageUrl = config.packageUrl;
@@ -28,32 +28,32 @@ export class DocsInfo {
this.docsJsonRoot = config.docsJsonRoot; this.docsJsonRoot = config.docsJsonRoot;
this.sections = config.sections; this.sections = config.sections;
this.sectionNameToMarkdown = config.sectionNameToMarkdown; this.sectionNameToMarkdown = config.sectionNameToMarkdown;
this.docsInfo = config; this._docsInfo = config;
} }
public isPublicType(typeName: string): boolean { public isPublicType(typeName: string): boolean {
if (_.isUndefined(this.docsInfo.publicTypes)) { if (_.isUndefined(this._docsInfo.publicTypes)) {
return false; return false;
} }
const isPublic = _.includes(this.docsInfo.publicTypes, typeName); const isPublic = _.includes(this._docsInfo.publicTypes, typeName);
return isPublic; return isPublic;
} }
public getModulePathsIfExists(sectionName: string): string[] { public getModulePathsIfExists(sectionName: string): string[] {
const modulePathsIfExists = this.docsInfo.sectionNameToModulePath[sectionName]; const modulePathsIfExists = this._docsInfo.sectionNameToModulePath[sectionName];
return modulePathsIfExists; return modulePathsIfExists;
} }
public getMenu(selectedVersion?: string): {[section: string]: string[]} { public getMenu(selectedVersion?: string): {[section: string]: string[]} {
if (_.isUndefined(selectedVersion) || _.isUndefined(this.docsInfo.menuSubsectionToVersionWhenIntroduced)) { if (_.isUndefined(selectedVersion) || _.isUndefined(this._docsInfo.menuSubsectionToVersionWhenIntroduced)) {
return this.docsInfo.menu; return this._docsInfo.menu;
} }
const finalMenu = _.cloneDeep(this.docsInfo.menu); const finalMenu = _.cloneDeep(this._docsInfo.menu);
if (_.isUndefined(finalMenu.contracts)) { if (_.isUndefined(finalMenu.contracts)) {
return finalMenu; return finalMenu;
} }
// TODO: refactor to include more sections then simply the `contracts` section // TODO: refactor to include more sections then simply the `contracts` section
finalMenu.contracts = _.filter(finalMenu.contracts, (contractName: string) => { finalMenu.contracts = _.filter(finalMenu.contracts, (contractName: string) => {
const versionIntroducedIfExists = this.docsInfo.menuSubsectionToVersionWhenIntroduced[contractName]; const versionIntroducedIfExists = this._docsInfo.menuSubsectionToVersionWhenIntroduced[contractName];
if (!_.isUndefined(versionIntroducedIfExists)) { if (!_.isUndefined(versionIntroducedIfExists)) {
const existsInSelectedVersion = compareVersions(selectedVersion, const existsInSelectedVersion = compareVersions(selectedVersion,
versionIntroducedIfExists) >= 0; versionIntroducedIfExists) >= 0;
@@ -104,9 +104,9 @@ export class DocsInfo {
return typeDefinitionByName; return typeDefinitionByName;
} }
public isVisibleConstructor(sectionName: string): boolean { public isVisibleConstructor(sectionName: string): boolean {
return _.includes(this.docsInfo.visibleConstructors, sectionName); return _.includes(this._docsInfo.visibleConstructors, sectionName);
} }
public convertToDocAgnosticFormat(docObj: DoxityDocObj|TypeDocNode): DocAgnosticFormat { public convertToDocAgnosticFormat(docObj: DoxityDocObj|TypeDocNode): DocAgnosticFormat {
return this.docsInfo.convertToDocAgnosticFormatFn(docObj, this); return this._docsInfo.convertToDocAgnosticFormatFn(docObj, this);
} }
} }

View File

@@ -93,7 +93,7 @@ export class Documentation extends
const versions = findVersions(lastSegment); const versions = findVersions(lastSegment);
const preferredVersionIfExists = versions.length > 0 ? versions[0] : undefined; const preferredVersionIfExists = versions.length > 0 ? versions[0] : undefined;
// tslint:disable-next-line:no-floating-promises // tslint:disable-next-line:no-floating-promises
this.fetchJSONDocsFireAndForgetAsync(preferredVersionIfExists); this._fetchJSONDocsFireAndForgetAsync(preferredVersionIfExists);
} }
public render() { public render() {
const menuSubsectionsBySection = _.isUndefined(this.state.docAgnosticFormat) ? const menuSubsectionsBySection = _.isUndefined(this.state.docAgnosticFormat) ?
@@ -157,7 +157,7 @@ export class Documentation extends
{this.props.docsInfo.displayName} {this.props.docsInfo.displayName}
</a> </a>
</h1> </h1>
{this.renderDocumentation()} {this._renderDocumentation()}
</div> </div>
</div> </div>
</div> </div>
@@ -165,16 +165,16 @@ export class Documentation extends
</div> </div>
); );
} }
private renderDocumentation(): React.ReactNode { private _renderDocumentation(): React.ReactNode {
const subMenus = _.values(this.props.docsInfo.getMenu()); const subMenus = _.values(this.props.docsInfo.getMenu());
const orderedSectionNames = _.flatten(subMenus); const orderedSectionNames = _.flatten(subMenus);
const typeDefinitionByName = this.props.docsInfo.getTypeDefinitionsByName(this.state.docAgnosticFormat); const typeDefinitionByName = this.props.docsInfo.getTypeDefinitionsByName(this.state.docAgnosticFormat);
const renderedSections = _.map(orderedSectionNames, this.renderSection.bind(this, typeDefinitionByName)); const renderedSections = _.map(orderedSectionNames, this._renderSection.bind(this, typeDefinitionByName));
return renderedSections; return renderedSections;
} }
private renderSection(typeDefinitionByName: TypeDefinitionByName, sectionName: string): React.ReactNode { private _renderSection(typeDefinitionByName: TypeDefinitionByName, sectionName: string): React.ReactNode {
const markdownFileIfExists = this.props.docsInfo.sectionNameToMarkdown[sectionName]; const markdownFileIfExists = this.props.docsInfo.sectionNameToMarkdown[sectionName];
if (!_.isUndefined(markdownFileIfExists)) { if (!_.isUndefined(markdownFileIfExists)) {
return ( return (
@@ -203,12 +203,12 @@ export class Documentation extends
}); });
const sortedProperties = _.sortBy(docSection.properties, 'name'); const sortedProperties = _.sortBy(docSection.properties, 'name');
const propertyDefs = _.map(sortedProperties, this.renderProperty.bind(this)); const propertyDefs = _.map(sortedProperties, this._renderProperty.bind(this));
const sortedMethods = _.sortBy(docSection.methods, 'name'); const sortedMethods = _.sortBy(docSection.methods, 'name');
const methodDefs = _.map(sortedMethods, method => { const methodDefs = _.map(sortedMethods, method => {
const isConstructor = false; const isConstructor = false;
return this.renderMethodBlocks(method, sectionName, isConstructor, typeDefinitionByName); return this._renderMethodBlocks(method, sectionName, isConstructor, typeDefinitionByName);
}); });
const sortedEvents = _.sortBy(docSection.events, 'name'); const sortedEvents = _.sortBy(docSection.events, 'name');
@@ -230,7 +230,7 @@ export class Documentation extends
<div style={{marginRight: 7}}> <div style={{marginRight: 7}}>
<SectionHeader sectionName={sectionName} /> <SectionHeader sectionName={sectionName} />
</div> </div>
{this.renderNetworkBadgesIfExists(sectionName)} {this._renderNetworkBadgesIfExists(sectionName)}
</div> </div>
{docSection.comment && {docSection.comment &&
<Comment <Comment
@@ -241,7 +241,7 @@ export class Documentation extends
this.props.docsInfo.isVisibleConstructor(sectionName) && this.props.docsInfo.isVisibleConstructor(sectionName) &&
<div> <div>
<h2 className="thin">Constructor</h2> <h2 className="thin">Constructor</h2>
{this.renderConstructors(docSection.constructors, sectionName, typeDefinitionByName)} {this._renderConstructors(docSection.constructors, sectionName, typeDefinitionByName)}
</div> </div>
} }
{docSection.properties.length > 0 && {docSection.properties.length > 0 &&
@@ -270,7 +270,7 @@ export class Documentation extends
</div> </div>
); );
} }
private renderNetworkBadgesIfExists(sectionName: string) { private _renderNetworkBadgesIfExists(sectionName: string) {
const networkToAddressByContractName = configs.CONTRACT_ADDRESS[this.props.docsVersion]; const networkToAddressByContractName = configs.CONTRACT_ADDRESS[this.props.docsVersion];
const badges = _.map(networkToAddressByContractName, const badges = _.map(networkToAddressByContractName,
(addressByContractName: AddressByContractName, networkName: string) => { (addressByContractName: AddressByContractName, networkName: string) => {
@@ -297,11 +297,11 @@ export class Documentation extends
}); });
return badges; return badges;
} }
private renderConstructors(constructors: SolidityMethod[]|TypescriptMethod[], private _renderConstructors(constructors: SolidityMethod[]|TypescriptMethod[],
sectionName: string, sectionName: string,
typeDefinitionByName: TypeDefinitionByName): React.ReactNode { typeDefinitionByName: TypeDefinitionByName): React.ReactNode {
const constructorDefs = _.map(constructors, constructor => { const constructorDefs = _.map(constructors, constructor => {
return this.renderMethodBlocks( return this._renderMethodBlocks(
constructor, sectionName, constructor.isConstructor, typeDefinitionByName, constructor, sectionName, constructor.isConstructor, typeDefinitionByName,
); );
}); });
@@ -311,7 +311,7 @@ export class Documentation extends
</div> </div>
); );
} }
private renderProperty(property: Property): React.ReactNode { private _renderProperty(property: Property): React.ReactNode {
return ( return (
<div <div
key={`property-${property.name}-${property.type.name}`} key={`property-${property.name}-${property.type.name}`}
@@ -337,7 +337,7 @@ export class Documentation extends
</div> </div>
); );
} }
private renderMethodBlocks(method: SolidityMethod|TypescriptMethod, sectionName: string, private _renderMethodBlocks(method: SolidityMethod|TypescriptMethod, sectionName: string,
isConstructor: boolean, typeDefinitionByName: TypeDefinitionByName): React.ReactNode { isConstructor: boolean, typeDefinitionByName: TypeDefinitionByName): React.ReactNode {
return ( return (
<MethodBlock <MethodBlock
@@ -349,7 +349,7 @@ export class Documentation extends
/> />
); );
} }
private scrollToHash(): void { private _scrollToHash(): void {
const hashWithPrefix = this.props.location.hash; const hashWithPrefix = this.props.location.hash;
let hash = hashWithPrefix.slice(1); let hash = hashWithPrefix.slice(1);
if (_.isEmpty(hash)) { if (_.isEmpty(hash)) {
@@ -358,7 +358,7 @@ export class Documentation extends
scroller.scrollTo(hash, {duration: 0, offset: 0, containerId: 'documentation'}); scroller.scrollTo(hash, {duration: 0, offset: 0, containerId: 'documentation'});
} }
private async fetchJSONDocsFireAndForgetAsync(preferredVersionIfExists?: string): Promise<void> { private async _fetchJSONDocsFireAndForgetAsync(preferredVersionIfExists?: string): Promise<void> {
const versionToFileName = await docUtils.getVersionToFileNameAsync(this.props.docsInfo.docsJsonRoot); const versionToFileName = await docUtils.getVersionToFileNameAsync(this.props.docsInfo.docsJsonRoot);
const versions = _.keys(versionToFileName); const versions = _.keys(versionToFileName);
this.props.dispatcher.updateAvailableDocVersions(versions); this.props.dispatcher.updateAvailableDocVersions(versions);
@@ -383,7 +383,7 @@ export class Documentation extends
this.setState({ this.setState({
docAgnosticFormat, docAgnosticFormat,
}, () => { }, () => {
this.scrollToHash(); this._scrollToHash();
}); });
} }
} }

View File

@@ -29,8 +29,8 @@ export class EventDefinition extends React.Component<EventDefinitionProps, Event
id={event.name} id={event.name}
className="pb2" className="pb2"
style={{overflow: 'hidden', width: '100%'}} style={{overflow: 'hidden', width: '100%'}}
onMouseOver={this.setAnchorVisibility.bind(this, true)} onMouseOver={this._setAnchorVisibility.bind(this, true)}
onMouseOut={this.setAnchorVisibility.bind(this, false)} onMouseOut={this._setAnchorVisibility.bind(this, false)}
> >
<AnchorTitle <AnchorTitle
headerSize={HeaderSizes.H3} headerSize={HeaderSizes.H3}
@@ -41,14 +41,14 @@ export class EventDefinition extends React.Component<EventDefinitionProps, Event
<div style={{fontSize: 16}}> <div style={{fontSize: 16}}>
<pre> <pre>
<code className="hljs"> <code className="hljs">
{this.renderEventCode()} {this._renderEventCode()}
</code> </code>
</pre> </pre>
</div> </div>
</div> </div>
); );
} }
private renderEventCode() { private _renderEventCode() {
const indexed = <span style={{color: colors.green}}> indexed</span>; const indexed = <span style={{color: colors.green}}> indexed</span>;
const eventArgs = _.map(this.props.event.eventArgs, (eventArg: EventArg) => { const eventArgs = _.map(this.props.event.eventArgs, (eventArg: EventArg) => {
const type = ( const type = (
@@ -76,7 +76,7 @@ export class EventDefinition extends React.Component<EventDefinitionProps, Event
</span> </span>
); );
} }
private setAnchorVisibility(shouldShowAnchor: boolean) { private _setAnchorVisibility(shouldShowAnchor: boolean) {
this.setState({ this.setState({
shouldShowAnchor, shouldShowAnchor,
}); });

View File

@@ -57,19 +57,19 @@ export class MethodBlock extends React.Component<MethodBlockProps, MethodBlockSt
id={method.name} id={method.name}
style={{overflow: 'hidden', width: '100%'}} style={{overflow: 'hidden', width: '100%'}}
className="pb4" className="pb4"
onMouseOver={this.setAnchorVisibility.bind(this, true)} onMouseOver={this._setAnchorVisibility.bind(this, true)}
onMouseOut={this.setAnchorVisibility.bind(this, false)} onMouseOut={this._setAnchorVisibility.bind(this, false)}
> >
{!method.isConstructor && {!method.isConstructor &&
<div className="flex"> <div className="flex">
{(method as TypescriptMethod).isStatic && {(method as TypescriptMethod).isStatic &&
this.renderChip('Static') this._renderChip('Static')
} }
{(method as SolidityMethod).isConstant && {(method as SolidityMethod).isConstant &&
this.renderChip('Constant') this._renderChip('Constant')
} }
{(method as SolidityMethod).isPayable && {(method as SolidityMethod).isPayable &&
this.renderChip('Payable') this._renderChip('Payable')
} }
<AnchorTitle <AnchorTitle
headerSize={HeaderSizes.H3} headerSize={HeaderSizes.H3}
@@ -108,7 +108,7 @@ export class MethodBlock extends React.Component<MethodBlockProps, MethodBlockSt
> >
ARGUMENTS ARGUMENTS
</h4> </h4>
{this.renderParameterDescriptions(method.parameters)} {this._renderParameterDescriptions(method.parameters)}
</div> </div>
} }
{method.returnComment && {method.returnComment &&
@@ -127,7 +127,7 @@ export class MethodBlock extends React.Component<MethodBlockProps, MethodBlockSt
</div> </div>
); );
} }
private renderChip(text: string) { private _renderChip(text: string) {
return ( return (
<div <div
className="p1 mr1" className="p1 mr1"
@@ -137,7 +137,7 @@ export class MethodBlock extends React.Component<MethodBlockProps, MethodBlockSt
</div> </div>
); );
} }
private renderParameterDescriptions(parameters: Parameter[]) { private _renderParameterDescriptions(parameters: Parameter[]) {
const descriptions = _.map(parameters, parameter => { const descriptions = _.map(parameters, parameter => {
const isOptional = parameter.isOptional; const isOptional = parameter.isOptional;
return ( return (
@@ -166,7 +166,7 @@ export class MethodBlock extends React.Component<MethodBlockProps, MethodBlockSt
}); });
return descriptions; return descriptions;
} }
private setAnchorVisibility(shouldShowAnchor: boolean) { private _setAnchorVisibility(shouldShowAnchor: boolean) {
this.setState({ this.setState({
shouldShowAnchor, shouldShowAnchor,
}); });

View File

@@ -107,8 +107,8 @@ export class TypeDefinition extends React.Component<TypeDefinitionProps, TypeDef
id={this.props.shouldAddId ? typeDefinitionAnchorId : ''} id={this.props.shouldAddId ? typeDefinitionAnchorId : ''}
className="pb2" className="pb2"
style={{overflow: 'hidden', width: '100%'}} style={{overflow: 'hidden', width: '100%'}}
onMouseOver={this.setAnchorVisibility.bind(this, true)} onMouseOver={this._setAnchorVisibility.bind(this, true)}
onMouseOut={this.setAnchorVisibility.bind(this, false)} onMouseOut={this._setAnchorVisibility.bind(this, false)}
> >
<AnchorTitle <AnchorTitle
headerSize={HeaderSizes.H3} headerSize={HeaderSizes.H3}
@@ -132,7 +132,7 @@ export class TypeDefinition extends React.Component<TypeDefinitionProps, TypeDef
</div> </div>
); );
} }
private setAnchorVisibility(shouldShowAnchor: boolean) { private _setAnchorVisibility(shouldShowAnchor: boolean) {
this.setState({ this.setState({
shouldShowAnchor, shouldShowAnchor,
}); });

View File

@@ -459,26 +459,26 @@ export class FAQ extends React.Component<FAQProps, FAQState> {
> >
<h1 className="center" style={{...styles.thin}}>0x FAQ</h1> <h1 className="center" style={{...styles.thin}}>0x FAQ</h1>
<div className="sm-px2 md-px2 lg-px0 pb4"> <div className="sm-px2 md-px2 lg-px0 pb4">
{this.renderSections()} {this._renderSections()}
</div> </div>
</div> </div>
<Footer /> <Footer />
</div> </div>
); );
} }
private renderSections() { private _renderSections() {
const renderedSections = _.map(sections, (section: FAQSection, i: number) => { const renderedSections = _.map(sections, (section: FAQSection, i: number) => {
const isFirstSection = i === 0; const isFirstSection = i === 0;
return ( return (
<div key={section.name}> <div key={section.name}>
<h3>{section.name}</h3> <h3>{section.name}</h3>
{this.renderQuestions(section.questions, isFirstSection)} {this._renderQuestions(section.questions, isFirstSection)}
</div> </div>
); );
}); });
return renderedSections; return renderedSections;
} }
private renderQuestions(questions: FAQQuestion[], isFirstSection: boolean) { private _renderQuestions(questions: FAQQuestion[], isFirstSection: boolean) {
const renderedQuestions = _.map(questions, (question: FAQQuestion, i: number) => { const renderedQuestions = _.map(questions, (question: FAQQuestion, i: number) => {
const isFirstQuestion = i === 0; const isFirstQuestion = i === 0;
return ( return (

View File

@@ -27,7 +27,7 @@ export class Question extends React.Component<QuestionProps, QuestionState> {
> >
<Card <Card
initiallyExpanded={this.props.shouldDisplayExpanded} initiallyExpanded={this.props.shouldDisplayExpanded}
onExpandChange={this.onExchangeChange.bind(this)} onExpandChange={this._onExchangeChange.bind(this)}
> >
<CardHeader <CardHeader
title={this.props.prompt} title={this.props.prompt}
@@ -45,7 +45,7 @@ export class Question extends React.Component<QuestionProps, QuestionState> {
</div> </div>
); );
} }
private onExchangeChange() { private _onExchangeChange() {
this.setState({ this.setState({
isExpanded: !this.state.isExpanded, isExpanded: !this.state.isExpanded,
}); });

View File

@@ -138,20 +138,20 @@ interface LandingState {
} }
export class Landing extends React.Component<LandingProps, LandingState> { export class Landing extends React.Component<LandingProps, LandingState> {
private throttledScreenWidthUpdate: () => void; private _throttledScreenWidthUpdate: () => void;
constructor(props: LandingProps) { constructor(props: LandingProps) {
super(props); super(props);
this.state = { this.state = {
screenWidth: utils.getScreenWidth(), screenWidth: utils.getScreenWidth(),
}; };
this.throttledScreenWidthUpdate = _.throttle(this.updateScreenWidth.bind(this), THROTTLE_TIMEOUT); this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
} }
public componentDidMount() { public componentDidMount() {
window.addEventListener('resize', this.throttledScreenWidthUpdate); window.addEventListener('resize', this._throttledScreenWidthUpdate);
window.scrollTo(0, 0); window.scrollTo(0, 0);
} }
public componentWillUnmount() { public componentWillUnmount() {
window.removeEventListener('resize', this.throttledScreenWidthUpdate); window.removeEventListener('resize', this._throttledScreenWidthUpdate);
} }
public render() { public render() {
return ( return (
@@ -163,19 +163,19 @@ export class Landing extends React.Component<LandingProps, LandingState> {
isNightVersion={true} isNightVersion={true}
style={{backgroundColor: colors.heroGrey, position: 'relative'}} style={{backgroundColor: colors.heroGrey, position: 'relative'}}
/> />
{this.renderHero()} {this._renderHero()}
{this.renderProjects()} {this._renderProjects()}
{this.renderTokenizationSection()} {this._renderTokenizationSection()}
{this.renderProtocolSection()} {this._renderProtocolSection()}
{this.renderInfoBoxes()} {this._renderInfoBoxes()}
{this.renderBuildingBlocksSection()} {this._renderBuildingBlocksSection()}
{this.renderUseCases()} {this._renderUseCases()}
{this.renderCallToAction()} {this._renderCallToAction()}
<Footer /> <Footer />
</div> </div>
); );
} }
private renderHero() { private _renderHero() {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const buttonLabelStyle: React.CSSProperties = { const buttonLabelStyle: React.CSSProperties = {
textTransform: 'none', textTransform: 'none',
@@ -259,7 +259,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div> </div>
); );
} }
private renderProjects() { private _renderProjects() {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const isMediumScreen = this.state.screenWidth === ScreenWidths.Md; const isMediumScreen = this.state.screenWidth === ScreenWidths.Md;
const projectList = _.map(projects, (project: Project, i: number) => { const projectList = _.map(projects, (project: Project, i: number) => {
@@ -323,7 +323,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div> </div>
); );
} }
private renderTokenizationSection() { private _renderTokenizationSection() {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
return ( return (
<div <div
@@ -332,7 +332,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
> >
<div className="mx-auto max-width-4 py4 clearfix"> <div className="mx-auto max-width-4 py4 clearfix">
{isSmallScreen && {isSmallScreen &&
this.renderTokenCloud() this._renderTokenCloud()
} }
<div className="col lg-col-6 md-col-6 col-12"> <div className="col lg-col-6 md-col-6 col-12">
<div className="mx-auto" style={{maxWidth: 385, paddingTop: 7}}> <div className="mx-auto" style={{maxWidth: 385, paddingTop: 7}}>
@@ -365,18 +365,18 @@ export class Landing extends React.Component<LandingProps, LandingState> {
} }
</div> </div>
<div className="flex pt1 sm-px3"> <div className="flex pt1 sm-px3">
{this.renderAssetTypes()} {this._renderAssetTypes()}
</div> </div>
</div> </div>
</div> </div>
{!isSmallScreen && {!isSmallScreen &&
this.renderTokenCloud() this._renderTokenCloud()
} }
</div> </div>
</div> </div>
); );
} }
private renderProtocolSection() { private _renderProtocolSection() {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
return ( return (
<div <div
@@ -462,7 +462,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div> </div>
); );
} }
private renderBuildingBlocksSection() { private _renderBuildingBlocksSection() {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const descriptionStyle: React.CSSProperties = { const descriptionStyle: React.CSSProperties = {
fontFamily: 'Roboto Mono', fontFamily: 'Roboto Mono',
@@ -484,7 +484,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
> >
<div className="mx-auto max-width-4 lg-pt4 md-pt4 lg-mb4 md-mb4 sm-mb2 clearfix"> <div className="mx-auto max-width-4 lg-pt4 md-pt4 lg-mb4 md-mb4 sm-mb2 clearfix">
{isSmallScreen && {isSmallScreen &&
this.renderBlockChipImage() this._renderBlockChipImage()
} }
<div <div
className="col lg-col-6 md-col-6 col-12 lg-pr3 md-pr3 sm-px3" className="col lg-col-6 md-col-6 col-12 lg-pr3 md-pr3 sm-px3"
@@ -528,13 +528,13 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div> </div>
</div> </div>
{!isSmallScreen && {!isSmallScreen &&
this.renderBlockChipImage() this._renderBlockChipImage()
} }
</div> </div>
</div> </div>
); );
} }
private renderBlockChipImage() { private _renderBlockChipImage() {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
return ( return (
<div className="col lg-col-6 md-col-6 col-12 sm-center"> <div className="col lg-col-6 md-col-6 col-12 sm-center">
@@ -545,7 +545,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div> </div>
); );
} }
private renderTokenCloud() { private _renderTokenCloud() {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
return ( return (
<div className="col lg-col-6 md-col-6 col-12 center"> <div className="col lg-col-6 md-col-6 col-12 center">
@@ -556,7 +556,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div> </div>
); );
} }
private renderAssetTypes() { private _renderAssetTypes() {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const assetTypes: AssetType[] = [ const assetTypes: AssetType[] = [
{ {
@@ -595,7 +595,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
}); });
return assets; return assets;
} }
private renderInfoBoxes() { private _renderInfoBoxes() {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const boxStyle: React.CSSProperties = { const boxStyle: React.CSSProperties = {
maxWidth: 252, maxWidth: 252,
@@ -648,7 +648,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div> </div>
); );
} }
private renderUseCases() { private _renderUseCases() {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const useCases: UseCase[] = [ const useCases: UseCase[] = [
@@ -759,7 +759,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div> </div>
); );
} }
private renderCallToAction() { private _renderCallToAction() {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const buttonLabelStyle: React.CSSProperties = { const buttonLabelStyle: React.CSSProperties = {
textTransform: 'none', textTransform: 'none',
@@ -805,7 +805,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div> </div>
); );
} }
private updateScreenWidth() { private _updateScreenWidth() {
const newScreenWidth = utils.getScreenWidth(); const newScreenWidth = utils.getScreenWidth();
if (newScreenWidth !== this.state.screenWidth) { if (newScreenWidth !== this.state.screenWidth) {
this.setState({ this.setState({

View File

@@ -79,14 +79,14 @@ export class AnchorTitle extends React.Component<AnchorTitleProps, AnchorTitleSt
className="zmdi zmdi-link" className="zmdi zmdi-link"
onClick={utils.setUrlHash.bind(utils, this.props.id)} onClick={utils.setUrlHash.bind(utils, this.props.id)}
style={{...styles.anchor, opacity}} style={{...styles.anchor, opacity}}
onMouseOver={this.setHoverState.bind(this, true)} onMouseOver={this._setHoverState.bind(this, true)}
onMouseOut={this.setHoverState.bind(this, false)} onMouseOut={this._setHoverState.bind(this, false)}
/> />
</ScrollLink> </ScrollLink>
</div> </div>
); );
} }
private setHoverState(isHovering: boolean) { private _setHoverState(isHovering: boolean) {
this.setState({ this.setState({
isHovering, isHovering,
}); });

View File

@@ -35,8 +35,8 @@ export class MarkdownSection extends React.Component<MarkdownSectionProps, Markd
return ( return (
<div <div
className="pt2 pr3 md-pl2 sm-pl3 overflow-hidden" className="pt2 pr3 md-pl2 sm-pl3 overflow-hidden"
onMouseOver={this.setAnchorVisibility.bind(this, true)} onMouseOver={this._setAnchorVisibility.bind(this, true)}
onMouseOut={this.setAnchorVisibility.bind(this, false)} onMouseOut={this._setAnchorVisibility.bind(this, false)}
> >
<ScrollElement name={id}> <ScrollElement name={id}>
<div className="clearfix"> <div className="clearfix">
@@ -69,7 +69,7 @@ export class MarkdownSection extends React.Component<MarkdownSectionProps, Markd
</div> </div>
); );
} }
private setAnchorVisibility(shouldShowAnchor: boolean) { private _setAnchorVisibility(shouldShowAnchor: boolean) {
this.setState({ this.setState({
shouldShowAnchor, shouldShowAnchor,
}); });

View File

@@ -61,13 +61,13 @@ export class NestedSidebarMenu extends React.Component<NestedSidebarMenuProps, N
{finalSectionName.toUpperCase()} {finalSectionName.toUpperCase()}
</div> </div>
</ScrollLink> </ScrollLink>
{this.renderMenuItems(menuItems)} {this._renderMenuItems(menuItems)}
</div> </div>
); );
} else { } else {
return ( return (
<div key={`section-${sectionName}`} > <div key={`section-${sectionName}`} >
{this.renderMenuItems(menuItems)} {this._renderMenuItems(menuItems)}
</div> </div>
); );
} }
@@ -87,7 +87,7 @@ export class NestedSidebarMenu extends React.Component<NestedSidebarMenuProps, N
</div> </div>
); );
} }
private renderMenuItems(menuItemNames: string[]): React.ReactNode[] { private _renderMenuItems(menuItemNames: string[]): React.ReactNode[] {
const menuItemStyles = this.props.shouldDisplaySectionHeaders ? const menuItemStyles = this.props.shouldDisplaySectionHeaders ?
styles.menuItemWithHeaders : styles.menuItemWithHeaders :
styles.menuItemWithoutHeaders; styles.menuItemWithoutHeaders;
@@ -105,7 +105,7 @@ export class NestedSidebarMenu extends React.Component<NestedSidebarMenuProps, N
containerId={constants.DOCS_CONTAINER_ID} containerId={constants.DOCS_CONTAINER_ID}
> >
<MenuItem <MenuItem
onTouchTap={this.onMenuItemClick.bind(this, menuItemName)} onTouchTap={this._onMenuItemClick.bind(this, menuItemName)}
style={menuItemStyles} style={menuItemStyles}
innerDivStyle={menuItemInnerDivStyles} innerDivStyle={menuItemInnerDivStyles}
> >
@@ -114,19 +114,19 @@ export class NestedSidebarMenu extends React.Component<NestedSidebarMenuProps, N
</span> </span>
</MenuItem> </MenuItem>
</ScrollLink> </ScrollLink>
{this.renderMenuItemSubsections(menuItemName)} {this._renderMenuItemSubsections(menuItemName)}
</div> </div>
); );
}); });
return menuItems; return menuItems;
} }
private renderMenuItemSubsections(menuItemName: string): React.ReactNode { private _renderMenuItemSubsections(menuItemName: string): React.ReactNode {
if (_.isUndefined(this.props.menuSubsectionsBySection[menuItemName])) { if (_.isUndefined(this.props.menuSubsectionsBySection[menuItemName])) {
return null; return null;
} }
return this.renderMenuSubsectionsBySection(menuItemName, this.props.menuSubsectionsBySection[menuItemName]); return this._renderMenuSubsectionsBySection(menuItemName, this.props.menuSubsectionsBySection[menuItemName]);
} }
private renderMenuSubsectionsBySection(menuItemName: string, entityNames: string[]): React.ReactNode { private _renderMenuSubsectionsBySection(menuItemName: string, entityNames: string[]): React.ReactNode {
return ( return (
<ul style={{margin: 0, listStyleType: 'none', paddingLeft: 0}} key={menuItemName}> <ul style={{margin: 0, listStyleType: 'none', paddingLeft: 0}} key={menuItemName}>
{_.map(entityNames, entityName => { {_.map(entityNames, entityName => {
@@ -138,10 +138,10 @@ export class NestedSidebarMenu extends React.Component<NestedSidebarMenuProps, N
offset={0} offset={0}
duration={constants.DOCS_SCROLL_DURATION_MS} duration={constants.DOCS_SCROLL_DURATION_MS}
containerId={constants.DOCS_CONTAINER_ID} containerId={constants.DOCS_CONTAINER_ID}
onTouchTap={this.onMenuItemClick.bind(this, entityName)} onTouchTap={this._onMenuItemClick.bind(this, entityName)}
> >
<MenuItem <MenuItem
onTouchTap={this.onMenuItemClick.bind(this, menuItemName)} onTouchTap={this._onMenuItemClick.bind(this, menuItemName)}
style={{minHeight: 35}} style={{minHeight: 35}}
innerDivStyle={{paddingLeft: 36, fontSize: 14, lineHeight: '35px'}} innerDivStyle={{paddingLeft: 36, fontSize: 14, lineHeight: '35px'}}
> >
@@ -154,7 +154,7 @@ export class NestedSidebarMenu extends React.Component<NestedSidebarMenuProps, N
</ul> </ul>
); );
} }
private onMenuItemClick(menuItemName: string): void { private _onMenuItemClick(menuItemName: string): void {
const id = utils.getIdFromName(menuItemName); const id = utils.getIdFromName(menuItemName);
utils.setUrlHash(id); utils.setUrlHash(id);
this.props.onMenuItemClick(); this.props.onMenuItemClick();

View File

@@ -28,8 +28,8 @@ export class SectionHeader extends React.Component<SectionHeaderProps, SectionHe
const id = utils.getIdFromName(sectionName); const id = utils.getIdFromName(sectionName);
return ( return (
<div <div
onMouseOver={this.setAnchorVisibility.bind(this, true)} onMouseOver={this._setAnchorVisibility.bind(this, true)}
onMouseOut={this.setAnchorVisibility.bind(this, false)} onMouseOut={this._setAnchorVisibility.bind(this, false)}
> >
<ScrollElement name={id}> <ScrollElement name={id}>
<AnchorTitle <AnchorTitle
@@ -42,7 +42,7 @@ export class SectionHeader extends React.Component<SectionHeaderProps, SectionHe
</div> </div>
); );
} }
private setAnchorVisibility(shouldShowAnchor: boolean) { private _setAnchorVisibility(shouldShowAnchor: boolean) {
this.setState({ this.setState({
shouldShowAnchor, shouldShowAnchor,
}); });

View File

@@ -18,14 +18,14 @@ export class VersionDropDown extends React.Component<VersionDropDownProps, Versi
<DropDownMenu <DropDownMenu
maxHeight={300} maxHeight={300}
value={this.props.selectedVersion} value={this.props.selectedVersion}
onChange={this.updateSelectedVersion.bind(this)} onChange={this._updateSelectedVersion.bind(this)}
> >
{this.renderDropDownItems()} {this._renderDropDownItems()}
</DropDownMenu> </DropDownMenu>
</div> </div>
); );
} }
private renderDropDownItems() { private _renderDropDownItems() {
const items = _.map(this.props.versions, version => { const items = _.map(this.props.versions, version => {
return ( return (
<MenuItem <MenuItem
@@ -37,7 +37,7 @@ export class VersionDropDown extends React.Component<VersionDropDownProps, Versi
}); });
return items; return items;
} }
private updateSelectedVersion(e: any, index: number, value: string) { private _updateSelectedVersion(e: any, index: number, value: string) {
window.location.href = `${this.props.docPath}/${value}${window.location.hash}`; window.location.href = `${this.props.docPath}/${value}${window.location.hash}`;
} }
} }

View File

@@ -46,7 +46,7 @@ const styles: Styles = {
}; };
export class Wiki extends React.Component<WikiProps, WikiState> { export class Wiki extends React.Component<WikiProps, WikiState> {
private wikiBackoffTimeoutId: number; private _wikiBackoffTimeoutId: number;
constructor(props: WikiProps) { constructor(props: WikiProps) {
super(props); super(props);
this.state = { this.state = {
@@ -55,15 +55,15 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
} }
public componentWillMount() { public componentWillMount() {
// tslint:disable-next-line:no-floating-promises // tslint:disable-next-line:no-floating-promises
this.fetchArticlesBySectionAsync(); this._fetchArticlesBySectionAsync();
} }
public componentWillUnmount() { public componentWillUnmount() {
clearTimeout(this.wikiBackoffTimeoutId); clearTimeout(this._wikiBackoffTimeoutId);
} }
public render() { public render() {
const menuSubsectionsBySection = _.isUndefined(this.state.articlesBySection) const menuSubsectionsBySection = _.isUndefined(this.state.articlesBySection)
? {} ? {}
: this.getMenuSubsectionsBySection(this.state.articlesBySection); : this._getMenuSubsectionsBySection(this.state.articlesBySection);
return ( return (
<div> <div>
<DocumentTitle title="0x Protocol Wiki"/> <DocumentTitle title="0x Protocol Wiki"/>
@@ -117,7 +117,7 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
</a> </a>
</h1> </h1>
<div id="wiki"> <div id="wiki">
{this.renderWikiArticles()} {this._renderWikiArticles()}
</div> </div>
</div> </div>
</div> </div>
@@ -126,12 +126,12 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
</div> </div>
); );
} }
private renderWikiArticles(): React.ReactNode { private _renderWikiArticles(): React.ReactNode {
const sectionNames = _.keys(this.state.articlesBySection); const sectionNames = _.keys(this.state.articlesBySection);
const sections = _.map(sectionNames, sectionName => this.renderSection(sectionName)); const sections = _.map(sectionNames, sectionName => this._renderSection(sectionName));
return sections; return sections;
} }
private renderSection(sectionName: string) { private _renderSection(sectionName: string) {
const articles = this.state.articlesBySection[sectionName]; const articles = this.state.articlesBySection[sectionName];
const renderedArticles = _.map(articles, (article: Article) => { const renderedArticles = _.map(articles, (article: Article) => {
const githubLink = `${constants.URL_GITHUB_WIKI}/edit/master/${sectionName}/${article.fileName}`; const githubLink = `${constants.URL_GITHUB_WIKI}/edit/master/${sectionName}/${article.fileName}`;
@@ -165,7 +165,7 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
</div> </div>
); );
} }
private scrollToHash(): void { private _scrollToHash(): void {
const hashWithPrefix = this.props.location.hash; const hashWithPrefix = this.props.location.hash;
let hash = hashWithPrefix.slice(1); let hash = hashWithPrefix.slice(1);
if (_.isEmpty(hash)) { if (_.isEmpty(hash)) {
@@ -174,14 +174,14 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
scroller.scrollTo(hash, {duration: 0, offset: 0, containerId: 'documentation'}); scroller.scrollTo(hash, {duration: 0, offset: 0, containerId: 'documentation'});
} }
private async fetchArticlesBySectionAsync(): Promise<void> { private async _fetchArticlesBySectionAsync(): Promise<void> {
const endpoint = `${configs.BACKEND_BASE_URL}${WebsitePaths.Wiki}`; const endpoint = `${configs.BACKEND_BASE_URL}${WebsitePaths.Wiki}`;
const response = await fetch(endpoint); const response = await fetch(endpoint);
if (response.status === constants.HTTP_NO_CONTENT_STATUS_CODE) { if (response.status === constants.HTTP_NO_CONTENT_STATUS_CODE) {
// We need to backoff and try fetching again later // We need to backoff and try fetching again later
this.wikiBackoffTimeoutId = window.setTimeout(() => { this._wikiBackoffTimeoutId = window.setTimeout(() => {
// tslint:disable-next-line:no-floating-promises // tslint:disable-next-line:no-floating-promises
this.fetchArticlesBySectionAsync(); this._fetchArticlesBySectionAsync();
}, WIKI_NOT_READY_BACKOUT_TIMEOUT_MS); }, WIKI_NOT_READY_BACKOUT_TIMEOUT_MS);
return; return;
} }
@@ -195,10 +195,10 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
this.setState({ this.setState({
articlesBySection, articlesBySection,
}, () => { }, () => {
this.scrollToHash(); this._scrollToHash();
}); });
} }
private getMenuSubsectionsBySection(articlesBySection: ArticlesBySection) { private _getMenuSubsectionsBySection(articlesBySection: ArticlesBySection) {
const sectionNames = _.keys(articlesBySection); const sectionNames = _.keys(articlesBySection);
const menuSubsectionsBySection: {[section: string]: string[]} = {}; const menuSubsectionsBySection: {[section: string]: string[]} = {};
for (const sectionName of sectionNames) { for (const sectionName of sectionNames) {

View File

@@ -15,53 +15,53 @@ import {
} from 'ts/types'; } from 'ts/types';
export class Dispatcher { export class Dispatcher {
private dispatch: Dispatch<State>; private _dispatch: Dispatch<State>;
constructor(dispatch: Dispatch<State>) { constructor(dispatch: Dispatch<State>) {
this.dispatch = dispatch; this._dispatch = dispatch;
} }
// Portal // Portal
public resetState() { public resetState() {
this.dispatch({ this._dispatch({
type: ActionTypes.ResetState, type: ActionTypes.ResetState,
}); });
} }
public updateNodeVersion(nodeVersion: string) { public updateNodeVersion(nodeVersion: string) {
this.dispatch({ this._dispatch({
data: nodeVersion, data: nodeVersion,
type: ActionTypes.UpdateNodeVersion, type: ActionTypes.UpdateNodeVersion,
}); });
} }
public updateScreenWidth(screenWidth: ScreenWidths) { public updateScreenWidth(screenWidth: ScreenWidths) {
this.dispatch({ this._dispatch({
data: screenWidth, data: screenWidth,
type: ActionTypes.UpdateScreenWidth, type: ActionTypes.UpdateScreenWidth,
}); });
} }
public swapAssetTokenSymbols() { public swapAssetTokenSymbols() {
this.dispatch({ this._dispatch({
type: ActionTypes.SwapAssetTokens, type: ActionTypes.SwapAssetTokens,
}); });
} }
public updateOrderSalt(salt: BigNumber) { public updateOrderSalt(salt: BigNumber) {
this.dispatch({ this._dispatch({
data: salt, data: salt,
type: ActionTypes.UpdateOrderSalt, type: ActionTypes.UpdateOrderSalt,
}); });
} }
public updateUserSuppliedOrderCache(order: Order) { public updateUserSuppliedOrderCache(order: Order) {
this.dispatch({ this._dispatch({
data: order, data: order,
type: ActionTypes.UpdateUserSuppliedOrderCache, type: ActionTypes.UpdateUserSuppliedOrderCache,
}); });
} }
public updateShouldBlockchainErrDialogBeOpen(shouldBeOpen: boolean) { public updateShouldBlockchainErrDialogBeOpen(shouldBeOpen: boolean) {
this.dispatch({ this._dispatch({
data: shouldBeOpen, data: shouldBeOpen,
type: ActionTypes.UpdateShouldBlockchainErrDialogBeOpen, type: ActionTypes.UpdateShouldBlockchainErrDialogBeOpen,
}); });
} }
public updateChosenAssetToken(side: Side, token: AssetToken) { public updateChosenAssetToken(side: Side, token: AssetToken) {
this.dispatch({ this._dispatch({
data: { data: {
side, side,
token, token,
@@ -70,7 +70,7 @@ export class Dispatcher {
}); });
} }
public updateChosenAssetTokenAddress(side: Side, address: string) { public updateChosenAssetTokenAddress(side: Side, address: string) {
this.dispatch({ this._dispatch({
data: { data: {
address, address,
side, side,
@@ -79,72 +79,72 @@ export class Dispatcher {
}); });
} }
public updateOrderTakerAddress(address: string) { public updateOrderTakerAddress(address: string) {
this.dispatch({ this._dispatch({
data: address, data: address,
type: ActionTypes.UpdateOrderTakerAddress, type: ActionTypes.UpdateOrderTakerAddress,
}); });
} }
public updateUserAddress(address: string) { public updateUserAddress(address: string) {
this.dispatch({ this._dispatch({
data: address, data: address,
type: ActionTypes.UpdateUserAddress, type: ActionTypes.UpdateUserAddress,
}); });
} }
public updateOrderExpiry(unixTimestampSec: BigNumber) { public updateOrderExpiry(unixTimestampSec: BigNumber) {
this.dispatch({ this._dispatch({
data: unixTimestampSec, data: unixTimestampSec,
type: ActionTypes.UpdateOrderExpiry, type: ActionTypes.UpdateOrderExpiry,
}); });
} }
public encounteredBlockchainError(err: BlockchainErrs) { public encounteredBlockchainError(err: BlockchainErrs) {
this.dispatch({ this._dispatch({
data: err, data: err,
type: ActionTypes.BlockchainErrEncountered, type: ActionTypes.BlockchainErrEncountered,
}); });
} }
public updateBlockchainIsLoaded(isLoaded: boolean) { public updateBlockchainIsLoaded(isLoaded: boolean) {
this.dispatch({ this._dispatch({
data: isLoaded, data: isLoaded,
type: ActionTypes.UpdateBlockchainIsLoaded, type: ActionTypes.UpdateBlockchainIsLoaded,
}); });
} }
public addTokenToTokenByAddress(token: Token) { public addTokenToTokenByAddress(token: Token) {
this.dispatch({ this._dispatch({
data: token, data: token,
type: ActionTypes.AddTokenToTokenByAddress, type: ActionTypes.AddTokenToTokenByAddress,
}); });
} }
public removeTokenToTokenByAddress(token: Token) { public removeTokenToTokenByAddress(token: Token) {
this.dispatch({ this._dispatch({
data: token, data: token,
type: ActionTypes.RemoveTokenFromTokenByAddress, type: ActionTypes.RemoveTokenFromTokenByAddress,
}); });
} }
public clearTokenByAddress() { public clearTokenByAddress() {
this.dispatch({ this._dispatch({
type: ActionTypes.ClearTokenByAddress, type: ActionTypes.ClearTokenByAddress,
}); });
} }
public updateTokenByAddress(tokens: Token[]) { public updateTokenByAddress(tokens: Token[]) {
this.dispatch({ this._dispatch({
data: tokens, data: tokens,
type: ActionTypes.UpdateTokenByAddress, type: ActionTypes.UpdateTokenByAddress,
}); });
} }
public updateTokenStateByAddress(tokenStateByAddress: TokenStateByAddress) { public updateTokenStateByAddress(tokenStateByAddress: TokenStateByAddress) {
this.dispatch({ this._dispatch({
data: tokenStateByAddress, data: tokenStateByAddress,
type: ActionTypes.UpdateTokenStateByAddress, type: ActionTypes.UpdateTokenStateByAddress,
}); });
} }
public removeFromTokenStateByAddress(tokenAddress: string) { public removeFromTokenStateByAddress(tokenAddress: string) {
this.dispatch({ this._dispatch({
data: tokenAddress, data: tokenAddress,
type: ActionTypes.RemoveFromTokenStateByAddress, type: ActionTypes.RemoveFromTokenStateByAddress,
}); });
} }
public replaceTokenAllowanceByAddress(address: string, allowance: BigNumber) { public replaceTokenAllowanceByAddress(address: string, allowance: BigNumber) {
this.dispatch({ this._dispatch({
data: { data: {
address, address,
allowance, allowance,
@@ -153,7 +153,7 @@ export class Dispatcher {
}); });
} }
public replaceTokenBalanceByAddress(address: string, balance: BigNumber) { public replaceTokenBalanceByAddress(address: string, balance: BigNumber) {
this.dispatch({ this._dispatch({
data: { data: {
address, address,
balance, balance,
@@ -162,7 +162,7 @@ export class Dispatcher {
}); });
} }
public updateTokenBalanceByAddress(address: string, balanceDelta: BigNumber) { public updateTokenBalanceByAddress(address: string, balanceDelta: BigNumber) {
this.dispatch({ this._dispatch({
data: { data: {
address, address,
balanceDelta, balanceDelta,
@@ -171,25 +171,25 @@ export class Dispatcher {
}); });
} }
public updateSignatureData(signatureData: SignatureData) { public updateSignatureData(signatureData: SignatureData) {
this.dispatch({ this._dispatch({
data: signatureData, data: signatureData,
type: ActionTypes.UpdateOrderSignatureData, type: ActionTypes.UpdateOrderSignatureData,
}); });
} }
public updateUserEtherBalance(balance: BigNumber) { public updateUserEtherBalance(balance: BigNumber) {
this.dispatch({ this._dispatch({
data: balance, data: balance,
type: ActionTypes.UpdateUserEtherBalance, type: ActionTypes.UpdateUserEtherBalance,
}); });
} }
public updateNetworkId(networkId: number) { public updateNetworkId(networkId: number) {
this.dispatch({ this._dispatch({
data: networkId, data: networkId,
type: ActionTypes.UpdateNetworkId, type: ActionTypes.UpdateNetworkId,
}); });
} }
public updateOrderFillAmount(amount: BigNumber) { public updateOrderFillAmount(amount: BigNumber) {
this.dispatch({ this._dispatch({
data: amount, data: amount,
type: ActionTypes.UpdateOrderFillAmount, type: ActionTypes.UpdateOrderFillAmount,
}); });
@@ -197,13 +197,13 @@ export class Dispatcher {
// Docs // Docs
public updateCurrentDocsVersion(version: string) { public updateCurrentDocsVersion(version: string) {
this.dispatch({ this._dispatch({
data: version, data: version,
type: ActionTypes.UpdateLibraryVersion, type: ActionTypes.UpdateLibraryVersion,
}); });
} }
public updateAvailableDocVersions(versions: string[]) { public updateAvailableDocVersions(versions: string[]) {
this.dispatch({ this._dispatch({
data: versions, data: versions,
type: ActionTypes.UpdateAvailableLibraryVersions, type: ActionTypes.UpdateAvailableLibraryVersions,
}); });
@@ -211,24 +211,24 @@ export class Dispatcher {
// Shared // Shared
public showFlashMessage(msg: string|React.ReactNode) { public showFlashMessage(msg: string|React.ReactNode) {
this.dispatch({ this._dispatch({
data: msg, data: msg,
type: ActionTypes.ShowFlashMessage, type: ActionTypes.ShowFlashMessage,
}); });
} }
public hideFlashMessage() { public hideFlashMessage() {
this.dispatch({ this._dispatch({
type: ActionTypes.HideFlashMessage, type: ActionTypes.HideFlashMessage,
}); });
} }
public updateProviderType(providerType: ProviderType) { public updateProviderType(providerType: ProviderType) {
this.dispatch({ this._dispatch({
type: ActionTypes.UpdateProviderType, type: ActionTypes.UpdateProviderType,
data: providerType, data: providerType,
}); });
} }
public updateInjectedProviderName(injectedProviderName: string) { public updateInjectedProviderName(injectedProviderName: string) {
this.dispatch({ this._dispatch({
type: ActionTypes.UpdateInjectedProviderName, type: ActionTypes.UpdateInjectedProviderName,
data: injectedProviderName, data: injectedProviderName,
}); });

View File

@@ -5,15 +5,15 @@ import {signatureDataSchema} from 'ts/schemas/signature_data_schema';
import {tokenSchema} from 'ts/schemas/token_schema'; import {tokenSchema} from 'ts/schemas/token_schema';
export class SchemaValidator { export class SchemaValidator {
private validator: Validator; private _validator: Validator;
constructor() { constructor() {
this.validator = new Validator(); this._validator = new Validator();
this.validator.addSchema(signatureDataSchema as JSONSchema, signatureDataSchema.id); this._validator.addSchema(signatureDataSchema as JSONSchema, signatureDataSchema.id);
this.validator.addSchema(tokenSchema as JSONSchema, tokenSchema.id); this._validator.addSchema(tokenSchema as JSONSchema, tokenSchema.id);
this.validator.addSchema(orderTakerSchema as JSONSchema, orderTakerSchema.id); this._validator.addSchema(orderTakerSchema as JSONSchema, orderTakerSchema.id);
this.validator.addSchema(orderSchema as JSONSchema, orderSchema.id); this._validator.addSchema(orderSchema as JSONSchema, orderSchema.id);
} }
public validate(instance: object, schema: Schema) { public validate(instance: object, schema: Schema) {
return this.validator.validate(instance, schema); return this._validator.validate(instance, schema);
} }
} }

View File

@@ -5,30 +5,30 @@ import {Dispatcher} from 'ts/redux/dispatcher';
import * as Web3 from 'web3'; import * as Web3 from 'web3';
export class Web3Wrapper { export class Web3Wrapper {
private dispatcher: Dispatcher; private _dispatcher: Dispatcher;
private web3: Web3; private _web3: Web3;
private prevNetworkId: number; private _prevNetworkId: number;
private shouldPollUserAddress: boolean; private _shouldPollUserAddress: boolean;
private watchNetworkAndBalanceIntervalId: NodeJS.Timer; private _watchNetworkAndBalanceIntervalId: NodeJS.Timer;
private prevUserEtherBalanceInEth: BigNumber; private _prevUserEtherBalanceInEth: BigNumber;
private prevUserAddress: string; private _prevUserAddress: string;
constructor(dispatcher: Dispatcher, provider: Web3.Provider, networkIdIfExists: number, constructor(dispatcher: Dispatcher, provider: Web3.Provider, networkIdIfExists: number,
shouldPollUserAddress: boolean) { shouldPollUserAddress: boolean) {
this.dispatcher = dispatcher; this._dispatcher = dispatcher;
this.prevNetworkId = networkIdIfExists; this._prevNetworkId = networkIdIfExists;
this.shouldPollUserAddress = shouldPollUserAddress; this._shouldPollUserAddress = shouldPollUserAddress;
this.web3 = new Web3(); this._web3 = new Web3();
this.web3.setProvider(provider); this._web3.setProvider(provider);
// tslint:disable-next-line:no-floating-promises // tslint:disable-next-line:no-floating-promises
this.startEmittingNetworkConnectionAndUserBalanceStateAsync(); this._startEmittingNetworkConnectionAndUserBalanceStateAsync();
} }
public isAddress(address: string) { public isAddress(address: string) {
return this.web3.isAddress(address); return this._web3.isAddress(address);
} }
public async getAccountsAsync(): Promise<string[]> { public async getAccountsAsync(): Promise<string[]> {
const addresses = await promisify<string[]>(this.web3.eth.getAccounts)(); const addresses = await promisify<string[]>(this._web3.eth.getAccounts)();
return addresses; return addresses;
} }
public async getFirstAccountIfExistsAsync() { public async getFirstAccountIfExistsAsync() {
@@ -39,109 +39,109 @@ export class Web3Wrapper {
return (addresses)[0]; return (addresses)[0];
} }
public async getNodeVersionAsync(): Promise<string> { 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; return nodeVersion;
} }
public getProviderObj() { public getProviderObj() {
return this.web3.currentProvider; return this._web3.currentProvider;
} }
public async getNetworkIdIfExists() { public async getNetworkIdIfExists() {
try { try {
const networkId = await this.getNetworkAsync(); const networkId = await this._getNetworkAsync();
return Number(networkId); return Number(networkId);
} catch (err) { } catch (err) {
return undefined; return undefined;
} }
} }
public async getBalanceInEthAsync(owner: string): Promise<BigNumber> { public async getBalanceInEthAsync(owner: string): Promise<BigNumber> {
const balanceInWei: BigNumber = await promisify<BigNumber>(this.web3.eth.getBalance)(owner); const balanceInWei: BigNumber = await promisify<BigNumber>(this._web3.eth.getBalance)(owner);
const balanceEthOldBigNumber = this.web3.fromWei(balanceInWei, 'ether'); const balanceEthOldBigNumber = this._web3.fromWei(balanceInWei, 'ether');
const balanceEth = new BigNumber(balanceEthOldBigNumber); const balanceEth = new BigNumber(balanceEthOldBigNumber);
return balanceEth; return balanceEth;
} }
public async doesContractExistAtAddressAsync(address: string): Promise<boolean> { 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 accomodate poorly implemented clients // Regex matches 0x0, 0x00, 0x in order to accomodate poorly implemented clients
const zeroHexAddressRegex = /^0[xX][0]*$/; const zeroHexAddressRegex = /^0[xX][0]*$/;
const didFindCode = _.isNull(code.match(zeroHexAddressRegex)); const didFindCode = _.isNull(code.match(zeroHexAddressRegex));
return didFindCode; return didFindCode;
} }
public async signTransactionAsync(address: string, message: string): Promise<string> { 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; return signData;
} }
public async getBlockTimestampAsync(blockHash: string): Promise<number> { public async getBlockTimestampAsync(blockHash: string): Promise<number> {
const {timestamp} = await promisify<Web3.BlockWithoutTransactionData>(this.web3.eth.getBlock)(blockHash); const {timestamp} = await promisify<Web3.BlockWithoutTransactionData>(this._web3.eth.getBlock)(blockHash);
return timestamp; return timestamp;
} }
public destroy() { public destroy() {
this.stopEmittingNetworkConnectionAndUserBalanceStateAsync(); this._stopEmittingNetworkConnectionAndUserBalanceStateAsync();
// HACK: stop() is only available on providerEngine instances // HACK: stop() is only available on providerEngine instances
const provider = this.web3.currentProvider; const provider = this._web3.currentProvider;
if (!_.isUndefined((provider as any).stop)) { if (!_.isUndefined((provider as any).stop)) {
(provider as any).stop(); (provider as any).stop();
} }
} }
// This should only be called from the LedgerConfigDialog // This should only be called from the LedgerConfigDialog
public updatePrevUserAddress(userAddress: string) { public updatePrevUserAddress(userAddress: string) {
this.prevUserAddress = userAddress; this._prevUserAddress = userAddress;
} }
private async getNetworkAsync() { private async _getNetworkAsync() {
const networkId = await promisify(this.web3.version.getNetwork)(); const networkId = await promisify(this._web3.version.getNetwork)();
return networkId; return networkId;
} }
private async startEmittingNetworkConnectionAndUserBalanceStateAsync() { private async _startEmittingNetworkConnectionAndUserBalanceStateAsync() {
if (!_.isUndefined(this.watchNetworkAndBalanceIntervalId)) { if (!_.isUndefined(this._watchNetworkAndBalanceIntervalId)) {
return; // we are already emitting the state return; // we are already emitting the state
} }
let prevNodeVersion: string; let prevNodeVersion: string;
this.prevUserEtherBalanceInEth = new BigNumber(0); this._prevUserEtherBalanceInEth = new BigNumber(0);
this.dispatcher.updateNetworkId(this.prevNetworkId); this._dispatcher.updateNetworkId(this._prevNetworkId);
this.watchNetworkAndBalanceIntervalId = intervalUtils.setAsyncExcludingInterval(async () => { this._watchNetworkAndBalanceIntervalId = intervalUtils.setAsyncExcludingInterval(async () => {
// Check for network state changes // Check for network state changes
const currentNetworkId = await this.getNetworkIdIfExists(); const currentNetworkId = await this.getNetworkIdIfExists();
if (currentNetworkId !== this.prevNetworkId) { if (currentNetworkId !== this._prevNetworkId) {
this.prevNetworkId = currentNetworkId; this._prevNetworkId = currentNetworkId;
this.dispatcher.updateNetworkId(currentNetworkId); this._dispatcher.updateNetworkId(currentNetworkId);
} }
// Check for node version changes // Check for node version changes
const currentNodeVersion = await this.getNodeVersionAsync(); const currentNodeVersion = await this.getNodeVersionAsync();
if (currentNodeVersion !== prevNodeVersion) { if (currentNodeVersion !== prevNodeVersion) {
prevNodeVersion = currentNodeVersion; prevNodeVersion = currentNodeVersion;
this.dispatcher.updateNodeVersion(currentNodeVersion); this._dispatcher.updateNodeVersion(currentNodeVersion);
} }
if (this.shouldPollUserAddress) { if (this._shouldPollUserAddress) {
const userAddressIfExists = await this.getFirstAccountIfExistsAsync(); const userAddressIfExists = await this.getFirstAccountIfExistsAsync();
// Update makerAddress on network change // Update makerAddress on network change
if (this.prevUserAddress !== userAddressIfExists) { if (this._prevUserAddress !== userAddressIfExists) {
this.prevUserAddress = userAddressIfExists; this._prevUserAddress = userAddressIfExists;
this.dispatcher.updateUserAddress(userAddressIfExists); this._dispatcher.updateUserAddress(userAddressIfExists);
} }
// Check for user ether balance changes // Check for user ether balance changes
if (userAddressIfExists !== '') { if (userAddressIfExists !== '') {
await this.updateUserEtherBalanceAsync(userAddressIfExists); await this._updateUserEtherBalanceAsync(userAddressIfExists);
} }
} else { } else {
// This logic is primarily for the Ledger, since we don't regularly poll for the address // This logic is primarily for the Ledger, since we don't regularly poll for the address
// we simply update the balance for the last fetched address. // we simply update the balance for the last fetched address.
if (!_.isEmpty(this.prevUserAddress)) { if (!_.isEmpty(this._prevUserAddress)) {
await this.updateUserEtherBalanceAsync(this.prevUserAddress); await this._updateUserEtherBalanceAsync(this._prevUserAddress);
} }
} }
}, 5000); }, 5000);
} }
private async updateUserEtherBalanceAsync(userAddress: string) { private async _updateUserEtherBalanceAsync(userAddress: string) {
const balance = await this.getBalanceInEthAsync(userAddress); const balance = await this.getBalanceInEthAsync(userAddress);
if (!balance.eq(this.prevUserEtherBalanceInEth)) { if (!balance.eq(this._prevUserEtherBalanceInEth)) {
this.prevUserEtherBalanceInEth = balance; this._prevUserEtherBalanceInEth = balance;
this.dispatcher.updateUserEtherBalance(balance); this._dispatcher.updateUserEtherBalance(balance);
} }
} }
private stopEmittingNetworkConnectionAndUserBalanceStateAsync() { private _stopEmittingNetworkConnectionAndUserBalanceStateAsync() {
clearInterval(this.watchNetworkAndBalanceIntervalId); clearInterval(this._watchNetworkAndBalanceIntervalId);
} }
} }