Create blockchainWatcher class and refactor Portal such that Ether amounts are always passed around as baseUnits
This commit is contained in:
@@ -24,9 +24,11 @@ import {
|
|||||||
RedundantRPCSubprovider,
|
RedundantRPCSubprovider,
|
||||||
} from '@0xproject/subproviders';
|
} from '@0xproject/subproviders';
|
||||||
import { BigNumber, intervalUtils, promisify } from '@0xproject/utils';
|
import { BigNumber, intervalUtils, promisify } from '@0xproject/utils';
|
||||||
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import contract = require('truffle-contract');
|
import contract = require('truffle-contract');
|
||||||
|
import { BlockchainWatcher } from 'ts/blockchain_watcher';
|
||||||
import { TokenSendCompleted } from 'ts/components/flash_messages/token_send_completed';
|
import { TokenSendCompleted } from 'ts/components/flash_messages/token_send_completed';
|
||||||
import { TransactionSubmitted } from 'ts/components/flash_messages/transaction_submitted';
|
import { TransactionSubmitted } from 'ts/components/flash_messages/transaction_submitted';
|
||||||
import { trackedTokenStorage } from 'ts/local_storage/tracked_token_storage';
|
import { trackedTokenStorage } from 'ts/local_storage/tracked_token_storage';
|
||||||
@@ -47,7 +49,6 @@ import { configs } from 'ts/utils/configs';
|
|||||||
import { constants } from 'ts/utils/constants';
|
import { constants } from 'ts/utils/constants';
|
||||||
import { errorReporter } from 'ts/utils/error_reporter';
|
import { errorReporter } from 'ts/utils/error_reporter';
|
||||||
import { utils } from 'ts/utils/utils';
|
import { utils } from 'ts/utils/utils';
|
||||||
import { Web3Wrapper } from 'ts/web3_wrapper';
|
|
||||||
import Web3 = require('web3');
|
import Web3 = require('web3');
|
||||||
import ProviderEngine = require('web3-provider-engine');
|
import ProviderEngine = require('web3-provider-engine');
|
||||||
import FilterSubprovider = require('web3-provider-engine/subproviders/filters');
|
import FilterSubprovider = require('web3-provider-engine/subproviders/filters');
|
||||||
@@ -63,6 +64,7 @@ export class Blockchain {
|
|||||||
private _zeroEx: ZeroEx;
|
private _zeroEx: ZeroEx;
|
||||||
private _dispatcher: Dispatcher;
|
private _dispatcher: Dispatcher;
|
||||||
private _web3Wrapper?: Web3Wrapper;
|
private _web3Wrapper?: Web3Wrapper;
|
||||||
|
private _blockchainWatcher?: BlockchainWatcher;
|
||||||
private _userAddress: string;
|
private _userAddress: string;
|
||||||
private _cachedProvider: Web3.Provider;
|
private _cachedProvider: Web3.Provider;
|
||||||
private _cachedProviderNetworkId: number;
|
private _cachedProviderNetworkId: number;
|
||||||
@@ -188,11 +190,11 @@ 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
|
||||||
if (_.isUndefined(this._cachedProvider)) {
|
if (_.isUndefined(this._cachedProvider)) {
|
||||||
this._cachedProvider = this._web3Wrapper.getProviderObj();
|
this._cachedProvider = this._web3Wrapper.getProvider();
|
||||||
this._cachedProviderNetworkId = this.networkId;
|
this._cachedProviderNetworkId = this.networkId;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._web3Wrapper.destroy();
|
this._blockchainWatcher.destroy();
|
||||||
|
|
||||||
this._userAddress = '';
|
this._userAddress = '';
|
||||||
this._dispatcher.updateUserAddress(''); // Clear old userAddress
|
this._dispatcher.updateUserAddress(''); // Clear old userAddress
|
||||||
@@ -210,9 +212,15 @@ export class Blockchain {
|
|||||||
this.networkId = networkId;
|
this.networkId = networkId;
|
||||||
this._dispatcher.updateNetworkId(this.networkId);
|
this._dispatcher.updateNetworkId(this.networkId);
|
||||||
const shouldPollUserAddress = false;
|
const shouldPollUserAddress = false;
|
||||||
this._web3Wrapper = new Web3Wrapper(this._dispatcher, provider, this.networkId, shouldPollUserAddress);
|
this._web3Wrapper = new Web3Wrapper(provider);
|
||||||
|
this._blockchainWatcher = new BlockchainWatcher(
|
||||||
|
this._dispatcher,
|
||||||
|
this._web3Wrapper,
|
||||||
|
this.networkId,
|
||||||
|
shouldPollUserAddress,
|
||||||
|
);
|
||||||
this._zeroEx.setProvider(provider, this.networkId);
|
this._zeroEx.setProvider(provider, this.networkId);
|
||||||
this._web3Wrapper.startEmittingNetworkConnectionAndUserBalanceState();
|
this._blockchainWatcher.startEmittingNetworkConnectionAndUserBalanceState();
|
||||||
this._dispatcher.updateProviderType(ProviderType.Ledger);
|
this._dispatcher.updateProviderType(ProviderType.Ledger);
|
||||||
}
|
}
|
||||||
public async updateProviderToInjectedAsync() {
|
public async updateProviderToInjectedAsync() {
|
||||||
@@ -222,20 +230,26 @@ export class Blockchain {
|
|||||||
return; // Going from injected to injected, so we noop
|
return; // Going from injected to injected, so we noop
|
||||||
}
|
}
|
||||||
|
|
||||||
this._web3Wrapper.destroy();
|
this._blockchainWatcher.destroy();
|
||||||
|
|
||||||
const provider = this._cachedProvider;
|
const provider = this._cachedProvider;
|
||||||
this.networkId = this._cachedProviderNetworkId;
|
this.networkId = this._cachedProviderNetworkId;
|
||||||
|
|
||||||
const shouldPollUserAddress = true;
|
const shouldPollUserAddress = true;
|
||||||
this._web3Wrapper = new Web3Wrapper(this._dispatcher, provider, this.networkId, shouldPollUserAddress);
|
this._web3Wrapper = new Web3Wrapper(provider);
|
||||||
|
this._blockchainWatcher = new BlockchainWatcher(
|
||||||
|
this._dispatcher,
|
||||||
|
this._web3Wrapper,
|
||||||
|
this.networkId,
|
||||||
|
shouldPollUserAddress,
|
||||||
|
);
|
||||||
|
|
||||||
this._userAddress = await this._web3Wrapper.getFirstAccountIfExistsAsync();
|
this._userAddress = await this.getFirstAccountIfExistsAsync();
|
||||||
|
|
||||||
this._zeroEx.setProvider(provider, this.networkId);
|
this._zeroEx.setProvider(provider, this.networkId);
|
||||||
|
|
||||||
await this.fetchTokenInformationAsync();
|
await this.fetchTokenInformationAsync();
|
||||||
this._web3Wrapper.startEmittingNetworkConnectionAndUserBalanceState();
|
this._blockchainWatcher.startEmittingNetworkConnectionAndUserBalanceState();
|
||||||
this._dispatcher.updateProviderType(ProviderType.Injected);
|
this._dispatcher.updateProviderType(ProviderType.Injected);
|
||||||
delete this._ledgerSubprovider;
|
delete this._ledgerSubprovider;
|
||||||
delete this._cachedProvider;
|
delete this._cachedProvider;
|
||||||
@@ -428,9 +442,9 @@ export class Blockchain {
|
|||||||
gasPrice: this._defaultGasPrice,
|
gasPrice: this._defaultGasPrice,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
public async getBalanceInEthAsync(owner: string): Promise<BigNumber> {
|
public async getBalanceInWeiAsync(owner: string): Promise<BigNumber> {
|
||||||
const balance = await this._web3Wrapper.getBalanceInEthAsync(owner);
|
const balanceInWei = await this._web3Wrapper.getBalanceInWeiAsync(owner);
|
||||||
return balance;
|
return balanceInWei;
|
||||||
}
|
}
|
||||||
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.');
|
||||||
@@ -484,10 +498,10 @@ export class Blockchain {
|
|||||||
// 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._blockchainWatcher.updatePrevUserAddress(newUserAddress);
|
||||||
}
|
}
|
||||||
public destroy() {
|
public destroy() {
|
||||||
this._web3Wrapper.destroy();
|
this._blockchainWatcher.destroy();
|
||||||
this._stopWatchingExchangeLogFillEvents();
|
this._stopWatchingExchangeLogFillEvents();
|
||||||
}
|
}
|
||||||
public async fetchTokenInformationAsync() {
|
public async fetchTokenInformationAsync() {
|
||||||
@@ -540,6 +554,13 @@ export class Blockchain {
|
|||||||
|
|
||||||
this._dispatcher.updateBlockchainIsLoaded(true);
|
this._dispatcher.updateBlockchainIsLoaded(true);
|
||||||
}
|
}
|
||||||
|
public async getFirstAccountIfExistsAsync() {
|
||||||
|
const addresses = await this._web3Wrapper.getAvailableAddressesAsync();
|
||||||
|
if (_.isEmpty(addresses)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return addresses[0];
|
||||||
|
}
|
||||||
private async _showEtherScanLinkAndAwaitTransactionMinedAsync(
|
private async _showEtherScanLinkAndAwaitTransactionMinedAsync(
|
||||||
txHash: string,
|
txHash: string,
|
||||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
@@ -736,11 +757,18 @@ export class Blockchain {
|
|||||||
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, this.networkId, shouldPollUserAddress);
|
this._web3Wrapper = new Web3Wrapper(provider);
|
||||||
this._userAddress = await this._web3Wrapper.getFirstAccountIfExistsAsync();
|
this._blockchainWatcher = new BlockchainWatcher(
|
||||||
|
this._dispatcher,
|
||||||
|
this._web3Wrapper,
|
||||||
|
this.networkId,
|
||||||
|
shouldPollUserAddress,
|
||||||
|
);
|
||||||
|
|
||||||
|
this._userAddress = await this.getFirstAccountIfExistsAsync();
|
||||||
this._dispatcher.updateUserAddress(this._userAddress);
|
this._dispatcher.updateUserAddress(this._userAddress);
|
||||||
await this.fetchTokenInformationAsync();
|
await this.fetchTokenInformationAsync();
|
||||||
this._web3Wrapper.startEmittingNetworkConnectionAndUserBalanceState();
|
this._blockchainWatcher.startEmittingNetworkConnectionAndUserBalanceState();
|
||||||
await this._rehydrateStoreWithContractEvents();
|
await this._rehydrateStoreWithContractEvents();
|
||||||
}
|
}
|
||||||
private _updateProviderName(injectedWeb3: Web3) {
|
private _updateProviderName(injectedWeb3: Web3) {
|
||||||
@@ -752,7 +780,7 @@ export class Blockchain {
|
|||||||
}
|
}
|
||||||
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.getProvider();
|
||||||
c.setProvider(providerObj);
|
c.setProvider(providerObj);
|
||||||
|
|
||||||
const artifactNetworkConfigs = artifact.networks[this.networkId];
|
const artifactNetworkConfigs = artifact.networks[this.networkId];
|
||||||
|
|||||||
@@ -1,60 +1,32 @@
|
|||||||
import { BigNumber, intervalUtils, promisify } from '@0xproject/utils';
|
import { BigNumber, intervalUtils, promisify } from '@0xproject/utils';
|
||||||
import { Web3Wrapper as Web3WrapperBase } from '@0xproject/web3-wrapper';
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import { Dispatcher } from 'ts/redux/dispatcher';
|
import { Dispatcher } from 'ts/redux/dispatcher';
|
||||||
import { utils } from 'ts/utils/utils';
|
import { utils } from 'ts/utils/utils';
|
||||||
import * as Web3 from 'web3';
|
|
||||||
|
|
||||||
export class Web3Wrapper extends Web3WrapperBase {
|
export class BlockchainWatcher {
|
||||||
private _dispatcher: Dispatcher;
|
private _dispatcher: Dispatcher;
|
||||||
private _web3: Web3;
|
private _web3Wrapper: Web3Wrapper;
|
||||||
private _prevNetworkId: number;
|
private _prevNetworkId: number;
|
||||||
private _shouldPollUserAddress: boolean;
|
private _shouldPollUserAddress: boolean;
|
||||||
private _watchNetworkAndBalanceIntervalId: NodeJS.Timer;
|
private _watchNetworkAndBalanceIntervalId: NodeJS.Timer;
|
||||||
private _prevUserEtherBalanceInEth: BigNumber;
|
private _prevUserEtherBalanceInWei: BigNumber;
|
||||||
private _prevUserAddress: string;
|
private _prevUserAddress: string;
|
||||||
constructor(
|
constructor(
|
||||||
dispatcher: Dispatcher,
|
dispatcher: Dispatcher,
|
||||||
provider: Web3.Provider,
|
web3Wrapper: Web3Wrapper,
|
||||||
networkIdIfExists: number,
|
networkIdIfExists: number,
|
||||||
shouldPollUserAddress: boolean,
|
shouldPollUserAddress: boolean,
|
||||||
) {
|
) {
|
||||||
super(provider);
|
|
||||||
this._dispatcher = dispatcher;
|
this._dispatcher = dispatcher;
|
||||||
this._prevNetworkId = networkIdIfExists;
|
this._prevNetworkId = networkIdIfExists;
|
||||||
this._shouldPollUserAddress = shouldPollUserAddress;
|
this._shouldPollUserAddress = shouldPollUserAddress;
|
||||||
|
this._web3Wrapper = web3Wrapper;
|
||||||
this._web3 = new Web3();
|
|
||||||
this._web3.setProvider(provider);
|
|
||||||
}
|
|
||||||
public async getFirstAccountIfExistsAsync() {
|
|
||||||
const addresses = await this.getAvailableAddressesAsync();
|
|
||||||
if (_.isEmpty(addresses)) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
return addresses[0];
|
|
||||||
}
|
|
||||||
public getProviderObj() {
|
|
||||||
return this._web3.currentProvider;
|
|
||||||
}
|
|
||||||
public async getNetworkIdIfExistsAsync(): Promise<number | undefined> {
|
|
||||||
try {
|
|
||||||
const networkId = await this.getNetworkIdAsync();
|
|
||||||
return Number(networkId);
|
|
||||||
} catch (err) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public async getBalanceInEthAsync(owner: string): Promise<BigNumber> {
|
|
||||||
const balanceInWei = await this.getBalanceInWeiAsync(owner);
|
|
||||||
const balanceEthOldBigNumber = this._web3.fromWei(balanceInWei, 'ether');
|
|
||||||
const balanceEth = new BigNumber(balanceEthOldBigNumber);
|
|
||||||
return balanceEth;
|
|
||||||
}
|
}
|
||||||
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._web3Wrapper.getProvider();
|
||||||
if (!_.isUndefined((provider as any).stop)) {
|
if (!_.isUndefined((provider as any).stop)) {
|
||||||
(provider as any).stop();
|
(provider as any).stop();
|
||||||
}
|
}
|
||||||
@@ -69,26 +41,32 @@ export class Web3Wrapper extends Web3WrapperBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let prevNodeVersion: string;
|
let prevNodeVersion: string;
|
||||||
this._prevUserEtherBalanceInEth = new BigNumber(0);
|
this._prevUserEtherBalanceInWei = new BigNumber(0);
|
||||||
this._dispatcher.updateNetworkId(this._prevNetworkId);
|
this._dispatcher.updateNetworkId(this._prevNetworkId);
|
||||||
this._watchNetworkAndBalanceIntervalId = intervalUtils.setAsyncExcludingInterval(
|
this._watchNetworkAndBalanceIntervalId = intervalUtils.setAsyncExcludingInterval(
|
||||||
async () => {
|
async () => {
|
||||||
// Check for network state changes
|
// Check for network state changes
|
||||||
const currentNetworkId = await this.getNetworkIdIfExistsAsync();
|
let currentNetworkId;
|
||||||
|
try {
|
||||||
|
currentNetworkId = await this._web3Wrapper.getNetworkIdAsync();
|
||||||
|
} catch (err) {
|
||||||
|
// Noop
|
||||||
|
}
|
||||||
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._web3Wrapper.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 addresses = await this._web3Wrapper.getAvailableAddressesAsync();
|
||||||
|
const userAddressIfExists = addresses[0] || '';
|
||||||
// Update makerAddress on network change
|
// Update makerAddress on network change
|
||||||
if (this._prevUserAddress !== userAddressIfExists) {
|
if (this._prevUserAddress !== userAddressIfExists) {
|
||||||
this._prevUserAddress = userAddressIfExists;
|
this._prevUserAddress = userAddressIfExists;
|
||||||
@@ -97,13 +75,13 @@ export class Web3Wrapper extends Web3WrapperBase {
|
|||||||
|
|
||||||
// Check for user ether balance changes
|
// Check for user ether balance changes
|
||||||
if (!_.isEmpty(userAddressIfExists)) {
|
if (!_.isEmpty(userAddressIfExists)) {
|
||||||
await this._updateUserEtherBalanceAsync(userAddressIfExists);
|
await this._updateUserWeiBalanceAsync(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._updateUserWeiBalanceAsync(this._prevUserAddress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -114,11 +92,11 @@ export class Web3Wrapper extends Web3WrapperBase {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
private async _updateUserEtherBalanceAsync(userAddress: string) {
|
private async _updateUserWeiBalanceAsync(userAddress: string) {
|
||||||
const balance = await this.getBalanceInEthAsync(userAddress);
|
const balanceInWei = await this._web3Wrapper.getBalanceInWeiAsync(userAddress);
|
||||||
if (!balance.eq(this._prevUserEtherBalanceInEth)) {
|
if (!balanceInWei.eq(this._prevUserEtherBalanceInWei)) {
|
||||||
this._prevUserEtherBalanceInEth = balance;
|
this._prevUserEtherBalanceInWei = balanceInWei;
|
||||||
this._dispatcher.updateUserEtherBalance(balance);
|
this._dispatcher.updateUserWeiBalance(balanceInWei);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private _stopEmittingNetworkConnectionAndUserBalanceStateAsync() {
|
private _stopEmittingNetworkConnectionAndUserBalanceStateAsync() {
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { ZeroEx } from '0x.js';
|
||||||
import { colors } from '@0xproject/react-shared';
|
import { colors } from '@0xproject/react-shared';
|
||||||
import { BigNumber } from '@0xproject/utils';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import Dialog from 'material-ui/Dialog';
|
import Dialog from 'material-ui/Dialog';
|
||||||
@@ -7,6 +8,7 @@ import { Blockchain } from 'ts/blockchain';
|
|||||||
import { EthAmountInput } from 'ts/components/inputs/eth_amount_input';
|
import { EthAmountInput } from 'ts/components/inputs/eth_amount_input';
|
||||||
import { TokenAmountInput } from 'ts/components/inputs/token_amount_input';
|
import { TokenAmountInput } from 'ts/components/inputs/token_amount_input';
|
||||||
import { Side, Token } from 'ts/types';
|
import { Side, Token } from 'ts/types';
|
||||||
|
import { constants } from 'ts/utils/constants';
|
||||||
|
|
||||||
interface EthWethConversionDialogProps {
|
interface EthWethConversionDialogProps {
|
||||||
blockchain: Blockchain;
|
blockchain: Blockchain;
|
||||||
@@ -17,7 +19,7 @@ interface EthWethConversionDialogProps {
|
|||||||
onCancelled: () => void;
|
onCancelled: () => void;
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
token: Token;
|
token: Token;
|
||||||
etherBalance: BigNumber;
|
etherBalanceInWei: BigNumber;
|
||||||
lastForceTokenStateRefetch: number;
|
lastForceTokenStateRefetch: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,6 +77,7 @@ export class EthWethConversionDialog extends React.Component<
|
|||||||
? '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.";
|
||||||
const isWrappedVersion = this.props.direction === Side.Receive;
|
const isWrappedVersion = this.props.direction === Side.Receive;
|
||||||
|
const etherBalanceInEth = ZeroEx.toUnitAmount(this.props.etherBalanceInWei, constants.DECIMAL_PLACES_ETH);
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="pb2">{explanation}</div>
|
<div className="pb2">{explanation}</div>
|
||||||
@@ -103,7 +106,7 @@ export class EthWethConversionDialog extends React.Component<
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<EthAmountInput
|
<EthAmountInput
|
||||||
balance={this.props.etherBalance}
|
balance={etherBalanceInEth}
|
||||||
amount={this.state.value}
|
amount={this.state.value}
|
||||||
onChange={this._onValueChange.bind(this)}
|
onChange={this._onValueChange.bind(this)}
|
||||||
shouldCheckBalance={true}
|
shouldCheckBalance={true}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { ZeroEx } from '0x.js';
|
||||||
import { colors, constants as sharedConstants } from '@0xproject/react-shared';
|
import { colors, constants as sharedConstants } from '@0xproject/react-shared';
|
||||||
import { BigNumber } from '@0xproject/utils';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
@@ -160,14 +161,15 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
|
|||||||
}
|
}
|
||||||
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 balanceInWei = this.state.addressBalances[i];
|
||||||
const addressTooltipId = `address-${userAddress}`;
|
const addressTooltipId = `address-${userAddress}`;
|
||||||
const balanceTooltipId = `balance-${userAddress}`;
|
const balanceTooltipId = `balance-${userAddress}`;
|
||||||
const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId];
|
const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId];
|
||||||
// We specifically prefix kovan ETH.
|
// We specifically prefix kovan ETH.
|
||||||
// TODO: We should probably add prefixes for all networks
|
// TODO: We should probably add prefixes for all networks
|
||||||
const isKovanNetwork = networkName === 'Kovan';
|
const isKovanNetwork = networkName === 'Kovan';
|
||||||
const balanceString = `${balance.toString()} ${isKovanNetwork ? 'Kovan ' : ''}ETH`;
|
const balanceInEth = ZeroEx.toUnitAmount(balanceInWei, constants.DECIMAL_PLACES_ETH);
|
||||||
|
const balanceString = `${balanceInEth.toString()} ${isKovanNetwork ? 'Kovan ' : ''}ETH`;
|
||||||
return (
|
return (
|
||||||
<TableRow key={userAddress} style={{ height: 40 }}>
|
<TableRow key={userAddress} style={{ height: 40 }}>
|
||||||
<TableRowColumn colSpan={2}>
|
<TableRowColumn colSpan={2}>
|
||||||
@@ -204,7 +206,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
|
|||||||
this.props.blockchain.updateWeb3WrapperPrevUserAddress(selectedAddress);
|
this.props.blockchain.updateWeb3WrapperPrevUserAddress(selectedAddress);
|
||||||
// tslint:disable-next-line:no-floating-promises
|
// tslint:disable-next-line:no-floating-promises
|
||||||
this.props.blockchain.fetchTokenInformationAsync();
|
this.props.blockchain.fetchTokenInformationAsync();
|
||||||
this.props.dispatcher.updateUserEtherBalance(selectAddressBalance);
|
this.props.dispatcher.updateUserWeiBalance(selectAddressBalance);
|
||||||
this.setState({
|
this.setState({
|
||||||
stepIndex: LedgerSteps.CONNECT,
|
stepIndex: LedgerSteps.CONNECT,
|
||||||
});
|
});
|
||||||
@@ -233,8 +235,8 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
|
|||||||
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 balanceInWei = await this.props.blockchain.getBalanceInWeiAsync(address);
|
||||||
addressBalances.push(balance);
|
addressBalances.push(balanceInWei);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
utils.consoleLog(`Ledger error: ${JSON.stringify(err)}`);
|
utils.consoleLog(`Ledger error: ${JSON.stringify(err)}`);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ interface EthWethConversionButtonProps {
|
|||||||
ethToken: Token;
|
ethToken: Token;
|
||||||
dispatcher: Dispatcher;
|
dispatcher: Dispatcher;
|
||||||
blockchain: Blockchain;
|
blockchain: Blockchain;
|
||||||
userEtherBalance: BigNumber;
|
userEtherBalanceInWei: BigNumber;
|
||||||
isOutdatedWrappedEther: boolean;
|
isOutdatedWrappedEther: boolean;
|
||||||
onConversionSuccessful?: () => void;
|
onConversionSuccessful?: () => void;
|
||||||
isDisabled?: boolean;
|
isDisabled?: boolean;
|
||||||
@@ -74,7 +74,7 @@ export class EthWethConversionButton extends React.Component<
|
|||||||
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}
|
etherBalanceInWei={this.props.userEtherBalanceInWei}
|
||||||
token={this.props.ethToken}
|
token={this.props.ethToken}
|
||||||
lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch}
|
lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ interface EthWrappersProps {
|
|||||||
dispatcher: Dispatcher;
|
dispatcher: Dispatcher;
|
||||||
tokenByAddress: TokenByAddress;
|
tokenByAddress: TokenByAddress;
|
||||||
userAddress: string;
|
userAddress: string;
|
||||||
userEtherBalance: BigNumber;
|
userEtherBalanceInWei: BigNumber;
|
||||||
lastForceTokenStateRefetch: number;
|
lastForceTokenStateRefetch: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,6 +98,10 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
|
|||||||
EtherscanLinkSuffixes.Address,
|
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);
|
||||||
|
const userEtherBalanceInEth = ZeroEx.toUnitAmount(
|
||||||
|
this.props.userEtherBalanceInWei,
|
||||||
|
constants.DECIMAL_PLACES_ETH,
|
||||||
|
);
|
||||||
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">
|
||||||
@@ -143,9 +147,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</TableRowColumn>
|
</TableRowColumn>
|
||||||
<TableRowColumn>
|
<TableRowColumn>{userEtherBalanceInEth.toFixed(PRECISION)} ETH</TableRowColumn>
|
||||||
{this.props.userEtherBalance.toFixed(PRECISION)} ETH
|
|
||||||
</TableRowColumn>
|
|
||||||
<TableRowColumn>
|
<TableRowColumn>
|
||||||
<EthWethConversionButton
|
<EthWethConversionButton
|
||||||
refetchEthTokenStateAsync={this._refetchEthTokenStateAsync.bind(this)}
|
refetchEthTokenStateAsync={this._refetchEthTokenStateAsync.bind(this)}
|
||||||
@@ -157,7 +159,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
|
|||||||
ethToken={etherToken}
|
ethToken={etherToken}
|
||||||
dispatcher={this.props.dispatcher}
|
dispatcher={this.props.dispatcher}
|
||||||
blockchain={this.props.blockchain}
|
blockchain={this.props.blockchain}
|
||||||
userEtherBalance={this.props.userEtherBalance}
|
userEtherBalanceInWei={this.props.userEtherBalanceInWei}
|
||||||
/>
|
/>
|
||||||
</TableRowColumn>
|
</TableRowColumn>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
@@ -184,7 +186,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
|
|||||||
ethToken={etherToken}
|
ethToken={etherToken}
|
||||||
dispatcher={this.props.dispatcher}
|
dispatcher={this.props.dispatcher}
|
||||||
blockchain={this.props.blockchain}
|
blockchain={this.props.blockchain}
|
||||||
userEtherBalance={this.props.userEtherBalance}
|
userEtherBalanceInWei={this.props.userEtherBalanceInWei}
|
||||||
/>
|
/>
|
||||||
</TableRowColumn>
|
</TableRowColumn>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
@@ -304,7 +306,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
|
|||||||
ethToken={outdatedEtherToken}
|
ethToken={outdatedEtherToken}
|
||||||
dispatcher={this.props.dispatcher}
|
dispatcher={this.props.dispatcher}
|
||||||
blockchain={this.props.blockchain}
|
blockchain={this.props.blockchain}
|
||||||
userEtherBalance={this.props.userEtherBalance}
|
userEtherBalanceInWei={this.props.userEtherBalanceInWei}
|
||||||
onConversionSuccessful={onConversionSuccessful}
|
onConversionSuccessful={onConversionSuccessful}
|
||||||
/>
|
/>
|
||||||
</TableRowColumn>
|
</TableRowColumn>
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export interface PortalAllProps {
|
|||||||
providerType: ProviderType;
|
providerType: ProviderType;
|
||||||
screenWidth: ScreenWidths;
|
screenWidth: ScreenWidths;
|
||||||
tokenByAddress: TokenByAddress;
|
tokenByAddress: TokenByAddress;
|
||||||
userEtherBalance: BigNumber;
|
userEtherBalanceInWei: BigNumber;
|
||||||
userAddress: string;
|
userAddress: string;
|
||||||
shouldBlockchainErrDialogBeOpen: boolean;
|
shouldBlockchainErrDialogBeOpen: boolean;
|
||||||
userSuppliedOrderCache: Order;
|
userSuppliedOrderCache: Order;
|
||||||
@@ -279,7 +279,7 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
|
|||||||
dispatcher={this.props.dispatcher}
|
dispatcher={this.props.dispatcher}
|
||||||
tokenByAddress={this.props.tokenByAddress}
|
tokenByAddress={this.props.tokenByAddress}
|
||||||
userAddress={this.props.userAddress}
|
userAddress={this.props.userAddress}
|
||||||
userEtherBalance={this.props.userEtherBalance}
|
userEtherBalanceInWei={this.props.userEtherBalanceInWei}
|
||||||
lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch}
|
lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -306,7 +306,7 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
|
|||||||
tokenByAddress={this.props.tokenByAddress}
|
tokenByAddress={this.props.tokenByAddress}
|
||||||
trackedTokens={trackedTokens}
|
trackedTokens={trackedTokens}
|
||||||
userAddress={this.props.userAddress}
|
userAddress={this.props.userAddress}
|
||||||
userEtherBalance={this.props.userEtherBalance}
|
userEtherBalanceInWei={this.props.userEtherBalanceInWei}
|
||||||
networkId={this.props.networkId}
|
networkId={this.props.networkId}
|
||||||
lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch}
|
lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ interface TokenBalancesProps {
|
|||||||
tokenByAddress: TokenByAddress;
|
tokenByAddress: TokenByAddress;
|
||||||
trackedTokens: Token[];
|
trackedTokens: Token[];
|
||||||
userAddress: string;
|
userAddress: string;
|
||||||
userEtherBalance: BigNumber;
|
userEtherBalanceInWei: BigNumber;
|
||||||
networkId: number;
|
networkId: number;
|
||||||
lastForceTokenStateRefetch: number;
|
lastForceTokenStateRefetch: number;
|
||||||
}
|
}
|
||||||
@@ -119,11 +119,14 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
|
|||||||
this._isUnmounted = true;
|
this._isUnmounted = true;
|
||||||
}
|
}
|
||||||
public componentWillReceiveProps(nextProps: TokenBalancesProps) {
|
public componentWillReceiveProps(nextProps: TokenBalancesProps) {
|
||||||
if (nextProps.userEtherBalance !== this.props.userEtherBalance) {
|
if (nextProps.userEtherBalanceInWei !== this.props.userEtherBalanceInWei) {
|
||||||
if (this.state.isBalanceSpinnerVisible) {
|
if (this.state.isBalanceSpinnerVisible) {
|
||||||
const receivedAmount = nextProps.userEtherBalance.minus(this.props.userEtherBalance);
|
const receivedAmountInWei = nextProps.userEtherBalanceInWei.minus(this.props.userEtherBalanceInWei);
|
||||||
|
const receivedAmountInEth = ZeroEx.toUnitAmount(receivedAmountInWei, constants.DECIMAL_PLACES_ETH);
|
||||||
const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId];
|
const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId];
|
||||||
this.props.dispatcher.showFlashMessage(`Received ${receivedAmount.toString(10)} ${networkName} Ether`);
|
this.props.dispatcher.showFlashMessage(
|
||||||
|
`Received ${receivedAmountInEth.toString(10)} ${networkName} Ether`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
isBalanceSpinnerVisible: false,
|
isBalanceSpinnerVisible: false,
|
||||||
@@ -205,6 +208,10 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
|
|||||||
token balances in order to execute trades.<br> \
|
token balances in order to execute trades.<br> \
|
||||||
Toggling sets an allowance for the<br> \
|
Toggling sets an allowance for the<br> \
|
||||||
smart contract so you can start trading that token.';
|
smart contract so you can start trading that token.';
|
||||||
|
const userEtherBalanceInEth = ZeroEx.toUnitAmount(
|
||||||
|
this.props.userEtherBalanceInWei,
|
||||||
|
constants.DECIMAL_PLACES_ETH,
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<div className="lg-px4 md-px4 sm-px1 pb2">
|
<div className="lg-px4 md-px4 sm-px1 pb2">
|
||||||
<h3>{isTestNetwork ? 'Test ether' : 'Ether'}</h3>
|
<h3>{isTestNetwork ? 'Test ether' : 'Ether'}</h3>
|
||||||
@@ -241,7 +248,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
|
|||||||
<img style={{ width: ICON_DIMENSION, height: ICON_DIMENSION }} src={ETHER_ICON_PATH} />
|
<img style={{ width: ICON_DIMENSION, height: ICON_DIMENSION }} src={ETHER_ICON_PATH} />
|
||||||
</TableRowColumn>
|
</TableRowColumn>
|
||||||
<TableRowColumn>
|
<TableRowColumn>
|
||||||
{this.props.userEtherBalance.toFixed(PRECISION)} ETH
|
{userEtherBalanceInEth.toFixed(PRECISION)} ETH
|
||||||
{this.state.isBalanceSpinnerVisible && (
|
{this.state.isBalanceSpinnerVisible && (
|
||||||
<span className="pl1">
|
<span className="pl1">
|
||||||
<i className="zmdi zmdi-spinner zmdi-hc-spin" />
|
<i className="zmdi zmdi-spinner zmdi-hc-spin" />
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ interface ConnectedState {
|
|||||||
providerType: ProviderType;
|
providerType: ProviderType;
|
||||||
tokenByAddress: TokenByAddress;
|
tokenByAddress: TokenByAddress;
|
||||||
lastForceTokenStateRefetch: number;
|
lastForceTokenStateRefetch: number;
|
||||||
userEtherBalance: BigNumber;
|
userEtherBalanceInWei: BigNumber;
|
||||||
screenWidth: ScreenWidths;
|
screenWidth: ScreenWidths;
|
||||||
shouldBlockchainErrDialogBeOpen: boolean;
|
shouldBlockchainErrDialogBeOpen: boolean;
|
||||||
userAddress: string;
|
userAddress: string;
|
||||||
@@ -72,7 +72,7 @@ const mapStateToProps = (state: State, ownProps: PortalComponentAllProps): Conne
|
|||||||
tokenByAddress: state.tokenByAddress,
|
tokenByAddress: state.tokenByAddress,
|
||||||
lastForceTokenStateRefetch: state.lastForceTokenStateRefetch,
|
lastForceTokenStateRefetch: state.lastForceTokenStateRefetch,
|
||||||
userAddress: state.userAddress,
|
userAddress: state.userAddress,
|
||||||
userEtherBalance: state.userEtherBalance,
|
userEtherBalanceInWei: state.userEtherBalanceInWei,
|
||||||
userSuppliedOrderCache: state.userSuppliedOrderCache,
|
userSuppliedOrderCache: state.userSuppliedOrderCache,
|
||||||
flashMessage: state.flashMessage,
|
flashMessage: state.flashMessage,
|
||||||
translate: state.translate,
|
translate: state.translate,
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ export class Dispatcher {
|
|||||||
type: ActionTypes.UpdateOrderECSignature,
|
type: ActionTypes.UpdateOrderECSignature,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
public updateUserEtherBalance(balance: BigNumber) {
|
public updateUserWeiBalance(balance: BigNumber) {
|
||||||
this._dispatch({
|
this._dispatch({
|
||||||
data: balance,
|
data: balance,
|
||||||
type: ActionTypes.UpdateUserEtherBalance,
|
type: ActionTypes.UpdateUserEtherBalance,
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export interface State {
|
|||||||
tokenByAddress: TokenByAddress;
|
tokenByAddress: TokenByAddress;
|
||||||
lastForceTokenStateRefetch: number;
|
lastForceTokenStateRefetch: number;
|
||||||
userAddress: string;
|
userAddress: string;
|
||||||
userEtherBalance: BigNumber;
|
userEtherBalanceInWei: BigNumber;
|
||||||
// Note: cache of supplied orderJSON in fill order step. Do not use for anything else.
|
// Note: cache of supplied orderJSON in fill order step. Do not use for anything else.
|
||||||
userSuppliedOrderCache: Order;
|
userSuppliedOrderCache: Order;
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ const INITIAL_STATE: State = {
|
|||||||
tokenByAddress: {},
|
tokenByAddress: {},
|
||||||
lastForceTokenStateRefetch: moment().unix(),
|
lastForceTokenStateRefetch: moment().unix(),
|
||||||
userAddress: '',
|
userAddress: '',
|
||||||
userEtherBalance: new BigNumber(0),
|
userEtherBalanceInWei: new BigNumber(0),
|
||||||
userSuppliedOrderCache: undefined,
|
userSuppliedOrderCache: undefined,
|
||||||
|
|
||||||
// Docs
|
// Docs
|
||||||
@@ -138,7 +138,7 @@ export function reducer(state: State = INITIAL_STATE, action: Action) {
|
|||||||
case ActionTypes.UpdateUserEtherBalance: {
|
case ActionTypes.UpdateUserEtherBalance: {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
userEtherBalance: action.data,
|
userEtherBalanceInWei: action.data,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user