From 7ebebb5bd9e0b60aab8dfac22bc1663d3fc13285 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 9 Mar 2018 19:02:07 +0100 Subject: Create blockchainWatcher class and refactor Portal such that Ether amounts are always passed around as baseUnits --- packages/website/ts/blockchain.ts | 64 +++++++--- packages/website/ts/blockchain_watcher.ts | 107 +++++++++++++++++ .../dialogs/eth_weth_conversion_dialog.tsx | 7 +- .../ts/components/dialogs/ledger_config_dialog.tsx | 12 +- .../ts/components/eth_weth_conversion_button.tsx | 4 +- packages/website/ts/components/eth_wrappers.tsx | 16 +-- packages/website/ts/components/portal.tsx | 6 +- packages/website/ts/components/token_balances.tsx | 17 ++- packages/website/ts/containers/portal.ts | 4 +- packages/website/ts/redux/dispatcher.ts | 2 +- packages/website/ts/redux/reducer.ts | 6 +- packages/website/ts/web3_wrapper.ts | 129 --------------------- 12 files changed, 197 insertions(+), 177 deletions(-) create mode 100644 packages/website/ts/blockchain_watcher.ts delete mode 100644 packages/website/ts/web3_wrapper.ts (limited to 'packages') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 4a9e16e88..e85c40e59 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -24,9 +24,11 @@ import { RedundantRPCSubprovider, } from '@0xproject/subproviders'; import { BigNumber, intervalUtils, promisify } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import * as React from 'react'; import contract = require('truffle-contract'); +import { BlockchainWatcher } from 'ts/blockchain_watcher'; import { TokenSendCompleted } from 'ts/components/flash_messages/token_send_completed'; import { TransactionSubmitted } from 'ts/components/flash_messages/transaction_submitted'; 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 { errorReporter } from 'ts/utils/error_reporter'; import { utils } from 'ts/utils/utils'; -import { Web3Wrapper } from 'ts/web3_wrapper'; import Web3 = require('web3'); import ProviderEngine = require('web3-provider-engine'); import FilterSubprovider = require('web3-provider-engine/subproviders/filters'); @@ -63,6 +64,7 @@ export class Blockchain { private _zeroEx: ZeroEx; private _dispatcher: Dispatcher; private _web3Wrapper?: Web3Wrapper; + private _blockchainWatcher?: BlockchainWatcher; private _userAddress: string; private _cachedProvider: Web3.Provider; private _cachedProviderNetworkId: number; @@ -188,11 +190,11 @@ export class Blockchain { // Cache injected provider so that we can switch the user back to it easily if (_.isUndefined(this._cachedProvider)) { - this._cachedProvider = this._web3Wrapper.getProviderObj(); + this._cachedProvider = this._web3Wrapper.getProvider(); this._cachedProviderNetworkId = this.networkId; } - this._web3Wrapper.destroy(); + this._blockchainWatcher.destroy(); this._userAddress = ''; this._dispatcher.updateUserAddress(''); // Clear old userAddress @@ -210,9 +212,15 @@ export class Blockchain { this.networkId = networkId; this._dispatcher.updateNetworkId(this.networkId); 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._web3Wrapper.startEmittingNetworkConnectionAndUserBalanceState(); + this._blockchainWatcher.startEmittingNetworkConnectionAndUserBalanceState(); this._dispatcher.updateProviderType(ProviderType.Ledger); } public async updateProviderToInjectedAsync() { @@ -222,20 +230,26 @@ export class Blockchain { return; // Going from injected to injected, so we noop } - this._web3Wrapper.destroy(); + this._blockchainWatcher.destroy(); const provider = this._cachedProvider; this.networkId = this._cachedProviderNetworkId; 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); await this.fetchTokenInformationAsync(); - this._web3Wrapper.startEmittingNetworkConnectionAndUserBalanceState(); + this._blockchainWatcher.startEmittingNetworkConnectionAndUserBalanceState(); this._dispatcher.updateProviderType(ProviderType.Injected); delete this._ledgerSubprovider; delete this._cachedProvider; @@ -428,9 +442,9 @@ export class Blockchain { gasPrice: this._defaultGasPrice, }); } - public async getBalanceInEthAsync(owner: string): Promise { - const balance = await this._web3Wrapper.getBalanceInEthAsync(owner); - return balance; + public async getBalanceInWeiAsync(owner: string): Promise { + const balanceInWei = await this._web3Wrapper.getBalanceInWeiAsync(owner); + return balanceInWei; } public async convertEthToWrappedEthTokensAsync(etherTokenAddress: string, amount: BigNumber): Promise { 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 // manually update it. This should only be called by the LedgerConfigDialog. public updateWeb3WrapperPrevUserAddress(newUserAddress: string) { - this._web3Wrapper.updatePrevUserAddress(newUserAddress); + this._blockchainWatcher.updatePrevUserAddress(newUserAddress); } public destroy() { - this._web3Wrapper.destroy(); + this._blockchainWatcher.destroy(); this._stopWatchingExchangeLogFillEvents(); } public async fetchTokenInformationAsync() { @@ -540,6 +554,13 @@ export class Blockchain { this._dispatcher.updateBlockchainIsLoaded(true); } + public async getFirstAccountIfExistsAsync() { + const addresses = await this._web3Wrapper.getAvailableAddressesAsync(); + if (_.isEmpty(addresses)) { + return ''; + } + return addresses[0]; + } private async _showEtherScanLinkAndAwaitTransactionMinedAsync( txHash: string, ): Promise { @@ -736,11 +757,18 @@ export class Blockchain { this._zeroEx = new ZeroEx(provider, zeroExConfigs); this._updateProviderName(injectedWeb3); const shouldPollUserAddress = true; - this._web3Wrapper = new Web3Wrapper(this._dispatcher, provider, this.networkId, shouldPollUserAddress); - this._userAddress = await this._web3Wrapper.getFirstAccountIfExistsAsync(); + this._web3Wrapper = new Web3Wrapper(provider); + this._blockchainWatcher = new BlockchainWatcher( + this._dispatcher, + this._web3Wrapper, + this.networkId, + shouldPollUserAddress, + ); + + this._userAddress = await this.getFirstAccountIfExistsAsync(); this._dispatcher.updateUserAddress(this._userAddress); await this.fetchTokenInformationAsync(); - this._web3Wrapper.startEmittingNetworkConnectionAndUserBalanceState(); + this._blockchainWatcher.startEmittingNetworkConnectionAndUserBalanceState(); await this._rehydrateStoreWithContractEvents(); } private _updateProviderName(injectedWeb3: Web3) { @@ -752,7 +780,7 @@ export class Blockchain { } private async _instantiateContractIfExistsAsync(artifact: any, address?: string): Promise { const c = await contract(artifact); - const providerObj = this._web3Wrapper.getProviderObj(); + const providerObj = this._web3Wrapper.getProvider(); c.setProvider(providerObj); const artifactNetworkConfigs = artifact.networks[this.networkId]; diff --git a/packages/website/ts/blockchain_watcher.ts b/packages/website/ts/blockchain_watcher.ts new file mode 100644 index 000000000..af5bafc0c --- /dev/null +++ b/packages/website/ts/blockchain_watcher.ts @@ -0,0 +1,107 @@ +import { BigNumber, intervalUtils, promisify } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; +import * as _ from 'lodash'; +import { Dispatcher } from 'ts/redux/dispatcher'; +import { utils } from 'ts/utils/utils'; + +export class BlockchainWatcher { + private _dispatcher: Dispatcher; + private _web3Wrapper: Web3Wrapper; + private _prevNetworkId: number; + private _shouldPollUserAddress: boolean; + private _watchNetworkAndBalanceIntervalId: NodeJS.Timer; + private _prevUserEtherBalanceInWei: BigNumber; + private _prevUserAddress: string; + constructor( + dispatcher: Dispatcher, + web3Wrapper: Web3Wrapper, + networkIdIfExists: number, + shouldPollUserAddress: boolean, + ) { + this._dispatcher = dispatcher; + this._prevNetworkId = networkIdIfExists; + this._shouldPollUserAddress = shouldPollUserAddress; + this._web3Wrapper = web3Wrapper; + } + public destroy() { + this._stopEmittingNetworkConnectionAndUserBalanceStateAsync(); + // HACK: stop() is only available on providerEngine instances + const provider = this._web3Wrapper.getProvider(); + if (!_.isUndefined((provider as any).stop)) { + (provider as any).stop(); + } + } + // This should only be called from the LedgerConfigDialog + public updatePrevUserAddress(userAddress: string) { + this._prevUserAddress = userAddress; + } + public startEmittingNetworkConnectionAndUserBalanceState() { + if (!_.isUndefined(this._watchNetworkAndBalanceIntervalId)) { + return; // we are already emitting the state + } + + let prevNodeVersion: string; + this._prevUserEtherBalanceInWei = new BigNumber(0); + this._dispatcher.updateNetworkId(this._prevNetworkId); + this._watchNetworkAndBalanceIntervalId = intervalUtils.setAsyncExcludingInterval( + async () => { + // Check for network state changes + let currentNetworkId; + try { + currentNetworkId = await this._web3Wrapper.getNetworkIdAsync(); + } catch (err) { + // Noop + } + if (currentNetworkId !== this._prevNetworkId) { + this._prevNetworkId = currentNetworkId; + this._dispatcher.updateNetworkId(currentNetworkId); + } + + // Check for node version changes + const currentNodeVersion = await this._web3Wrapper.getNodeVersionAsync(); + if (currentNodeVersion !== prevNodeVersion) { + prevNodeVersion = currentNodeVersion; + this._dispatcher.updateNodeVersion(currentNodeVersion); + } + + if (this._shouldPollUserAddress) { + const addresses = await this._web3Wrapper.getAvailableAddressesAsync(); + const userAddressIfExists = addresses[0] || ''; + // Update makerAddress on network change + if (this._prevUserAddress !== userAddressIfExists) { + this._prevUserAddress = userAddressIfExists; + this._dispatcher.updateUserAddress(userAddressIfExists); + } + + // Check for user ether balance changes + if (!_.isEmpty(userAddressIfExists)) { + await this._updateUserWeiBalanceAsync(userAddressIfExists); + } + } else { + // 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. + if (!_.isEmpty(this._prevUserAddress)) { + await this._updateUserWeiBalanceAsync(this._prevUserAddress); + } + } + }, + 5000, + (err: Error) => { + utils.consoleLog(`Watching network and balances failed: ${err.stack}`); + this._stopEmittingNetworkConnectionAndUserBalanceStateAsync(); + }, + ); + } + private async _updateUserWeiBalanceAsync(userAddress: string) { + const balanceInWei = await this._web3Wrapper.getBalanceInWeiAsync(userAddress); + if (!balanceInWei.eq(this._prevUserEtherBalanceInWei)) { + this._prevUserEtherBalanceInWei = balanceInWei; + this._dispatcher.updateUserWeiBalance(balanceInWei); + } + } + private _stopEmittingNetworkConnectionAndUserBalanceStateAsync() { + if (!_.isUndefined(this._watchNetworkAndBalanceIntervalId)) { + intervalUtils.clearAsyncExcludingInterval(this._watchNetworkAndBalanceIntervalId); + } + } +} diff --git a/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx b/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx index 5c61f0d57..72ebe1f67 100644 --- a/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx +++ b/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx @@ -1,3 +1,4 @@ +import { ZeroEx } from '0x.js'; import { colors } from '@0xproject/react-shared'; import { BigNumber } from '@0xproject/utils'; 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 { TokenAmountInput } from 'ts/components/inputs/token_amount_input'; import { Side, Token } from 'ts/types'; +import { constants } from 'ts/utils/constants'; interface EthWethConversionDialogProps { blockchain: Blockchain; @@ -17,7 +19,7 @@ interface EthWethConversionDialogProps { onCancelled: () => void; isOpen: boolean; token: Token; - etherBalance: BigNumber; + etherBalanceInWei: BigNumber; lastForceTokenStateRefetch: number; } @@ -75,6 +77,7 @@ export class EthWethConversionDialog extends React.Component< ? 'Convert your Ether into a tokenized, tradable form.' : "Convert your Wrapped Ether back into it's native form."; const isWrappedVersion = this.props.direction === Side.Receive; + const etherBalanceInEth = ZeroEx.toUnitAmount(this.props.etherBalanceInWei, constants.DECIMAL_PLACES_ETH); return (
{explanation}
@@ -103,7 +106,7 @@ export class EthWethConversionDialog extends React.Component< /> ) : ( { - const balance = this.state.addressBalances[i]; + const balanceInWei = this.state.addressBalances[i]; const addressTooltipId = `address-${userAddress}`; const balanceTooltipId = `balance-${userAddress}`; const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId]; // We specifically prefix kovan ETH. // TODO: We should probably add prefixes for all networks 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 ( @@ -204,7 +206,7 @@ export class LedgerConfigDialog extends React.Component void; isDisabled?: boolean; @@ -74,7 +74,7 @@ export class EthWethConversionButton extends React.Component< isOpen={this.state.isEthConversionDialogVisible} onComplete={this._onConversionAmountSelectedAsync.bind(this)} onCancelled={this._toggleConversionDialog.bind(this)} - etherBalance={this.props.userEtherBalance} + etherBalanceInWei={this.props.userEtherBalanceInWei} token={this.props.ethToken} lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} /> diff --git a/packages/website/ts/components/eth_wrappers.tsx b/packages/website/ts/components/eth_wrappers.tsx index 7ac5d5c9c..8aac31917 100644 --- a/packages/website/ts/components/eth_wrappers.tsx +++ b/packages/website/ts/components/eth_wrappers.tsx @@ -34,7 +34,7 @@ interface EthWrappersProps { dispatcher: Dispatcher; tokenByAddress: TokenByAddress; userAddress: string; - userEtherBalance: BigNumber; + userEtherBalanceInWei: BigNumber; lastForceTokenStateRefetch: number; } @@ -98,6 +98,10 @@ export class EthWrappers extends React.Component
@@ -143,9 +147,7 @@ export class EthWrappers extends React.Component
- - {this.props.userEtherBalance.toFixed(PRECISION)} ETH - + {userEtherBalanceInEth.toFixed(PRECISION)} ETH
@@ -184,7 +186,7 @@ export class EthWrappers extends React.Component @@ -304,7 +306,7 @@ export class EthWrappers extends React.Component diff --git a/packages/website/ts/components/portal.tsx b/packages/website/ts/components/portal.tsx index d71e821c6..ad437acdb 100644 --- a/packages/website/ts/components/portal.tsx +++ b/packages/website/ts/components/portal.tsx @@ -46,7 +46,7 @@ export interface PortalAllProps { providerType: ProviderType; screenWidth: ScreenWidths; tokenByAddress: TokenByAddress; - userEtherBalance: BigNumber; + userEtherBalanceInWei: BigNumber; userAddress: string; shouldBlockchainErrDialogBeOpen: boolean; userSuppliedOrderCache: Order; @@ -279,7 +279,7 @@ export class Portal extends React.Component { dispatcher={this.props.dispatcher} tokenByAddress={this.props.tokenByAddress} userAddress={this.props.userAddress} - userEtherBalance={this.props.userEtherBalance} + userEtherBalanceInWei={this.props.userEtherBalanceInWei} lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} /> ); @@ -306,7 +306,7 @@ export class Portal extends React.Component { tokenByAddress={this.props.tokenByAddress} trackedTokens={trackedTokens} userAddress={this.props.userAddress} - userEtherBalance={this.props.userEtherBalance} + userEtherBalanceInWei={this.props.userEtherBalanceInWei} networkId={this.props.networkId} lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} /> diff --git a/packages/website/ts/components/token_balances.tsx b/packages/website/ts/components/token_balances.tsx index 7e7596fd7..3c285803b 100644 --- a/packages/website/ts/components/token_balances.tsx +++ b/packages/website/ts/components/token_balances.tsx @@ -79,7 +79,7 @@ interface TokenBalancesProps { tokenByAddress: TokenByAddress; trackedTokens: Token[]; userAddress: string; - userEtherBalance: BigNumber; + userEtherBalanceInWei: BigNumber; networkId: number; lastForceTokenStateRefetch: number; } @@ -119,11 +119,14 @@ export class TokenBalances extends React.Component \ Toggling sets an allowance for the
\ smart contract so you can start trading that token.'; + const userEtherBalanceInEth = ZeroEx.toUnitAmount( + this.props.userEtherBalanceInWei, + constants.DECIMAL_PLACES_ETH, + ); return (

{isTestNetwork ? 'Test ether' : 'Ether'}

@@ -241,7 +248,7 @@ export class TokenBalances extends React.Component - {this.props.userEtherBalance.toFixed(PRECISION)} ETH + {userEtherBalanceInEth.toFixed(PRECISION)} ETH {this.state.isBalanceSpinnerVisible && ( diff --git a/packages/website/ts/containers/portal.ts b/packages/website/ts/containers/portal.ts index befa16bdb..725564ead 100644 --- a/packages/website/ts/containers/portal.ts +++ b/packages/website/ts/containers/portal.ts @@ -21,7 +21,7 @@ interface ConnectedState { providerType: ProviderType; tokenByAddress: TokenByAddress; lastForceTokenStateRefetch: number; - userEtherBalance: BigNumber; + userEtherBalanceInWei: BigNumber; screenWidth: ScreenWidths; shouldBlockchainErrDialogBeOpen: boolean; userAddress: string; @@ -72,7 +72,7 @@ const mapStateToProps = (state: State, ownProps: PortalComponentAllProps): Conne tokenByAddress: state.tokenByAddress, lastForceTokenStateRefetch: state.lastForceTokenStateRefetch, userAddress: state.userAddress, - userEtherBalance: state.userEtherBalance, + userEtherBalanceInWei: state.userEtherBalanceInWei, userSuppliedOrderCache: state.userSuppliedOrderCache, flashMessage: state.flashMessage, translate: state.translate, diff --git a/packages/website/ts/redux/dispatcher.ts b/packages/website/ts/redux/dispatcher.ts index 5c40ded2c..e40d435e0 100644 --- a/packages/website/ts/redux/dispatcher.ts +++ b/packages/website/ts/redux/dispatcher.ts @@ -155,7 +155,7 @@ export class Dispatcher { type: ActionTypes.UpdateOrderECSignature, }); } - public updateUserEtherBalance(balance: BigNumber) { + public updateUserWeiBalance(balance: BigNumber) { this._dispatch({ data: balance, type: ActionTypes.UpdateUserEtherBalance, diff --git a/packages/website/ts/redux/reducer.ts b/packages/website/ts/redux/reducer.ts index 1f489db85..1d43e4ffb 100644 --- a/packages/website/ts/redux/reducer.ts +++ b/packages/website/ts/redux/reducer.ts @@ -38,7 +38,7 @@ export interface State { tokenByAddress: TokenByAddress; lastForceTokenStateRefetch: number; userAddress: string; - userEtherBalance: BigNumber; + userEtherBalanceInWei: BigNumber; // Note: cache of supplied orderJSON in fill order step. Do not use for anything else. userSuppliedOrderCache: Order; @@ -77,7 +77,7 @@ const INITIAL_STATE: State = { tokenByAddress: {}, lastForceTokenStateRefetch: moment().unix(), userAddress: '', - userEtherBalance: new BigNumber(0), + userEtherBalanceInWei: new BigNumber(0), userSuppliedOrderCache: undefined, // Docs @@ -138,7 +138,7 @@ export function reducer(state: State = INITIAL_STATE, action: Action) { case ActionTypes.UpdateUserEtherBalance: { return { ...state, - userEtherBalance: action.data, + userEtherBalanceInWei: action.data, }; } diff --git a/packages/website/ts/web3_wrapper.ts b/packages/website/ts/web3_wrapper.ts deleted file mode 100644 index fca98ac8f..000000000 --- a/packages/website/ts/web3_wrapper.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { BigNumber, intervalUtils, promisify } from '@0xproject/utils'; -import { Web3Wrapper as Web3WrapperBase } from '@0xproject/web3-wrapper'; -import * as _ from 'lodash'; -import { Dispatcher } from 'ts/redux/dispatcher'; -import { utils } from 'ts/utils/utils'; -import * as Web3 from 'web3'; - -export class Web3Wrapper extends Web3WrapperBase { - private _dispatcher: Dispatcher; - private _web3: Web3; - private _prevNetworkId: number; - private _shouldPollUserAddress: boolean; - private _watchNetworkAndBalanceIntervalId: NodeJS.Timer; - private _prevUserEtherBalanceInEth: BigNumber; - private _prevUserAddress: string; - constructor( - dispatcher: Dispatcher, - provider: Web3.Provider, - networkIdIfExists: number, - shouldPollUserAddress: boolean, - ) { - super(provider); - this._dispatcher = dispatcher; - this._prevNetworkId = networkIdIfExists; - this._shouldPollUserAddress = shouldPollUserAddress; - - 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 { - try { - const networkId = await this.getNetworkIdAsync(); - return Number(networkId); - } catch (err) { - return undefined; - } - } - public async getBalanceInEthAsync(owner: string): Promise { - const balanceInWei = await this.getBalanceInWeiAsync(owner); - const balanceEthOldBigNumber = this._web3.fromWei(balanceInWei, 'ether'); - const balanceEth = new BigNumber(balanceEthOldBigNumber); - return balanceEth; - } - public destroy() { - this._stopEmittingNetworkConnectionAndUserBalanceStateAsync(); - // HACK: stop() is only available on providerEngine instances - const provider = this._web3.currentProvider; - if (!_.isUndefined((provider as any).stop)) { - (provider as any).stop(); - } - } - // This should only be called from the LedgerConfigDialog - public updatePrevUserAddress(userAddress: string) { - this._prevUserAddress = userAddress; - } - public startEmittingNetworkConnectionAndUserBalanceState() { - if (!_.isUndefined(this._watchNetworkAndBalanceIntervalId)) { - return; // we are already emitting the state - } - - let prevNodeVersion: string; - this._prevUserEtherBalanceInEth = new BigNumber(0); - this._dispatcher.updateNetworkId(this._prevNetworkId); - this._watchNetworkAndBalanceIntervalId = intervalUtils.setAsyncExcludingInterval( - async () => { - // Check for network state changes - const currentNetworkId = await this.getNetworkIdIfExistsAsync(); - if (currentNetworkId !== this._prevNetworkId) { - this._prevNetworkId = currentNetworkId; - this._dispatcher.updateNetworkId(currentNetworkId); - } - - // Check for node version changes - const currentNodeVersion = await this.getNodeVersionAsync(); - if (currentNodeVersion !== prevNodeVersion) { - prevNodeVersion = currentNodeVersion; - this._dispatcher.updateNodeVersion(currentNodeVersion); - } - - if (this._shouldPollUserAddress) { - const userAddressIfExists = await this.getFirstAccountIfExistsAsync(); - // Update makerAddress on network change - if (this._prevUserAddress !== userAddressIfExists) { - this._prevUserAddress = userAddressIfExists; - this._dispatcher.updateUserAddress(userAddressIfExists); - } - - // Check for user ether balance changes - if (!_.isEmpty(userAddressIfExists)) { - await this._updateUserEtherBalanceAsync(userAddressIfExists); - } - } else { - // 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. - if (!_.isEmpty(this._prevUserAddress)) { - await this._updateUserEtherBalanceAsync(this._prevUserAddress); - } - } - }, - 5000, - (err: Error) => { - utils.consoleLog(`Watching network and balances failed: ${err.stack}`); - this._stopEmittingNetworkConnectionAndUserBalanceStateAsync(); - }, - ); - } - private async _updateUserEtherBalanceAsync(userAddress: string) { - const balance = await this.getBalanceInEthAsync(userAddress); - if (!balance.eq(this._prevUserEtherBalanceInEth)) { - this._prevUserEtherBalanceInEth = balance; - this._dispatcher.updateUserEtherBalance(balance); - } - } - private _stopEmittingNetworkConnectionAndUserBalanceStateAsync() { - if (!_.isUndefined(this._watchNetworkAndBalanceIntervalId)) { - intervalUtils.clearAsyncExcludingInterval(this._watchNetworkAndBalanceIntervalId); - } - } -} -- cgit v1.2.3