From 7b82a8669d7a7c69d879349a083424d5dcdf79ec Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 9 Mar 2018 15:07:39 +0100 Subject: Fix comment --- packages/web3-wrapper/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages') diff --git a/packages/web3-wrapper/src/index.ts b/packages/web3-wrapper/src/index.ts index 64a19f531..9be4280b3 100644 --- a/packages/web3-wrapper/src/index.ts +++ b/packages/web3-wrapper/src/index.ts @@ -11,7 +11,7 @@ export class Web3Wrapper { if (_.isUndefined((provider as any).sendAsync)) { // Web3@1.0 provider doesn't support synchronous http requests, // so it only has an async `send` method, instead of a `send` and `sendAsync` in web3@0.x.x` - // 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 @0xproject/web3-wrapper (provider as any).sendAsync = (provider as any).send; } this._web3 = new Web3(); -- cgit v1.2.3 From 918f3cde948592e9cb83342c051b71378821f3c5 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 9 Mar 2018 15:08:02 +0100 Subject: Remove duplicitous methods from website's webWrapper --- packages/website/package.json | 1 + packages/website/ts/web3_wrapper.ts | 44 +++++++------------------------------ 2 files changed, 9 insertions(+), 36 deletions(-) (limited to 'packages') diff --git a/packages/website/package.json b/packages/website/package.json index db3035642..a7fc1fe26 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -22,6 +22,7 @@ "@0xproject/react-docs": "^0.0.1", "@0xproject/react-shared": "^0.0.1", "@0xproject/subproviders": "^0.7.0", + "@0xproject/web3-wrapper": "^0.2.1", "@0xproject/utils": "^0.4.1", "accounting": "^0.4.1", "basscss": "^8.0.3", diff --git a/packages/website/ts/web3_wrapper.ts b/packages/website/ts/web3_wrapper.ts index 9d8d771af..fca98ac8f 100644 --- a/packages/website/ts/web3_wrapper.ts +++ b/packages/website/ts/web3_wrapper.ts @@ -1,10 +1,11 @@ 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 { +export class Web3Wrapper extends Web3WrapperBase { private _dispatcher: Dispatcher; private _web3: Web3; private _prevNetworkId: number; @@ -18,6 +19,7 @@ export class Web3Wrapper { networkIdIfExists: number, shouldPollUserAddress: boolean, ) { + super(provider); this._dispatcher = dispatcher; this._prevNetworkId = networkIdIfExists; this._shouldPollUserAddress = shouldPollUserAddress; @@ -25,56 +27,30 @@ export class Web3Wrapper { this._web3 = new Web3(); this._web3.setProvider(provider); } - public isAddress(address: string) { - return this._web3.isAddress(address); - } - public async getAccountsAsync(): Promise { - const addresses = await promisify(this._web3.eth.getAccounts)(); - return addresses; - } public async getFirstAccountIfExistsAsync() { - const addresses = await this.getAccountsAsync(); + const addresses = await this.getAvailableAddressesAsync(); if (_.isEmpty(addresses)) { return ''; } return addresses[0]; } - public async getNodeVersionAsync(): Promise { - const nodeVersion = await promisify(this._web3.version.getNode)(); - return nodeVersion; - } public getProviderObj() { return this._web3.currentProvider; } - public async getNetworkIdIfExists() { + public async getNetworkIdIfExistsAsync(): Promise { try { - const networkId = await this._getNetworkAsync(); + const networkId = await this.getNetworkIdAsync(); return Number(networkId); } catch (err) { return undefined; } } public async getBalanceInEthAsync(owner: string): Promise { - const balanceInWei: BigNumber = await promisify(this._web3.eth.getBalance)(owner); + const balanceInWei = await this.getBalanceInWeiAsync(owner); const balanceEthOldBigNumber = this._web3.fromWei(balanceInWei, 'ether'); const balanceEth = new BigNumber(balanceEthOldBigNumber); return balanceEth; } - public async doesContractExistAtAddressAsync(address: string): Promise { - const code = await promisify(this._web3.eth.getCode)(address); - // Regex matches 0x0, 0x00, 0x in order to accomodate poorly implemented clients - const zeroHexAddressRegex = /^0[xX][0]*$/; - const didFindCode = _.isNull(code.match(zeroHexAddressRegex)); - return didFindCode; - } - public async signTransactionAsync(address: string, message: string): Promise { - const signData = await promisify(this._web3.eth.sign)(address, message); - return signData; - } - public async getBlockTimestampAsync(blockHash: string): Promise { - const { timestamp } = await promisify(this._web3.eth.getBlock)(blockHash); - return timestamp; - } public destroy() { this._stopEmittingNetworkConnectionAndUserBalanceStateAsync(); // HACK: stop() is only available on providerEngine instances @@ -98,7 +74,7 @@ export class Web3Wrapper { this._watchNetworkAndBalanceIntervalId = intervalUtils.setAsyncExcludingInterval( async () => { // Check for network state changes - const currentNetworkId = await this.getNetworkIdIfExists(); + const currentNetworkId = await this.getNetworkIdIfExistsAsync(); if (currentNetworkId !== this._prevNetworkId) { this._prevNetworkId = currentNetworkId; this._dispatcher.updateNetworkId(currentNetworkId); @@ -138,10 +114,6 @@ export class Web3Wrapper { }, ); } - private async _getNetworkAsync() { - const networkId = await promisify(this._web3.version.getNetwork)(); - return networkId; - } private async _updateUserEtherBalanceAsync(userAddress: string) { const balance = await this.getBalanceInEthAsync(userAddress); if (!balance.eq(this._prevUserEtherBalanceInEth)) { -- cgit v1.2.3 From 342a697e42a7209d9454fcd38321e64c7fca3fd0 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 9 Mar 2018 15:08:22 +0100 Subject: Remove _exchangeAddress instance var from blockchain class --- packages/website/ts/blockchain.ts | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'packages') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index fca9504d7..db8a56899 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -213,7 +213,6 @@ export class Blockchain { const shouldPollUserAddress = false; this._web3Wrapper = new Web3Wrapper(this._dispatcher, provider, this.networkId, shouldPollUserAddress); this._zeroEx.setProvider(provider, this.networkId); - await this._postInstantiationOrUpdatingProviderZeroExAsync(); this._web3Wrapper.startEmittingNetworkConnectionAndUserBalanceState(); this._dispatcher.updateProviderType(ProviderType.Ledger); } @@ -235,7 +234,6 @@ export class Blockchain { this._userAddress = await this._web3Wrapper.getFirstAccountIfExistsAsync(); this._zeroEx.setProvider(provider, this.networkId); - await this._postInstantiationOrUpdatingProviderZeroExAsync(); await this.fetchTokenInformationAsync(); this._web3Wrapper.startEmittingNetworkConnectionAndUserBalanceState(); @@ -347,7 +345,7 @@ export class Blockchain { return unavailableTakerAmount; } public getExchangeContractAddressIfExists() { - return this._exchangeAddress; + return this._zeroEx.exchange.getContractAddress(); } public async validateFillOrderThrowIfInvalidAsync( signedOrder: SignedOrder, @@ -740,19 +738,12 @@ export class Blockchain { this._updateProviderName(injectedWeb3); const shouldPollUserAddress = true; this._web3Wrapper = new Web3Wrapper(this._dispatcher, provider, this.networkId, shouldPollUserAddress); - await this._postInstantiationOrUpdatingProviderZeroExAsync(); this._userAddress = await this._web3Wrapper.getFirstAccountIfExistsAsync(); this._dispatcher.updateUserAddress(this._userAddress); await this.fetchTokenInformationAsync(); this._web3Wrapper.startEmittingNetworkConnectionAndUserBalanceState(); await this._rehydrateStoreWithContractEvents(); } - // This method should always be run after instantiating or updating the provider - // of the ZeroEx instance. - private async _postInstantiationOrUpdatingProviderZeroExAsync() { - utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.'); - this._exchangeAddress = this._zeroEx.exchange.getContractAddress(); - } private _updateProviderName(injectedWeb3: Web3) { const doesInjectedWeb3Exist = !_.isUndefined(injectedWeb3); const providerName = doesInjectedWeb3Exist -- cgit v1.2.3 From cfd734d84fadef5c5a7238f092e9a7721e004ef1 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 9 Mar 2018 15:09:25 +0100 Subject: remove remaining declaration --- packages/website/ts/blockchain.ts | 1 - 1 file changed, 1 deletion(-) (limited to 'packages') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index db8a56899..4a9e16e88 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -63,7 +63,6 @@ export class Blockchain { private _zeroEx: ZeroEx; private _dispatcher: Dispatcher; private _web3Wrapper?: Web3Wrapper; - private _exchangeAddress: string; private _userAddress: string; private _cachedProvider: Web3.Provider; private _cachedProviderNetworkId: number; -- cgit v1.2.3 From 8f921a61da6b9976ea680df4fd51147bb78040d9 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 9 Mar 2018 18:52:02 +0100 Subject: Add getProvider method to web3Wrapper --- packages/web3-wrapper/CHANGELOG.md | 4 ++++ packages/web3-wrapper/src/index.ts | 3 +++ 2 files changed, 7 insertions(+) (limited to 'packages') diff --git a/packages/web3-wrapper/CHANGELOG.md b/packages/web3-wrapper/CHANGELOG.md index ac0f5ff0b..9d21f79b2 100644 --- a/packages/web3-wrapper/CHANGELOG.md +++ b/packages/web3-wrapper/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## v0.2.1 _TBD_ + + * Add a `getProvider` method + ## v0.2.0 _March 4, 2018_ * Ensure all returned user addresses are lowercase (#373) diff --git a/packages/web3-wrapper/src/index.ts b/packages/web3-wrapper/src/index.ts index 9be4280b3..e14eb2914 100644 --- a/packages/web3-wrapper/src/index.ts +++ b/packages/web3-wrapper/src/index.ts @@ -22,6 +22,9 @@ export class Web3Wrapper { public getContractDefaults(): Partial { return this._defaults; } + public getProvider(): Web3.Provider { + return this._web3.currentProvider; + } public setProvider(provider: Web3.Provider) { this._web3.setProvider(provider); } -- cgit v1.2.3 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 From 5160e0ba1831d4796f7a03c1e28a356edc395ae7 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Sat, 10 Mar 2018 22:24:13 +0100 Subject: Add pr number to changelog --- packages/web3-wrapper/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages') diff --git a/packages/web3-wrapper/CHANGELOG.md b/packages/web3-wrapper/CHANGELOG.md index 9d21f79b2..6dabc7eb4 100644 --- a/packages/web3-wrapper/CHANGELOG.md +++ b/packages/web3-wrapper/CHANGELOG.md @@ -2,7 +2,7 @@ ## v0.2.1 _TBD_ - * Add a `getProvider` method + * Add a `getProvider` method (#444) ## v0.2.0 _March 4, 2018_ -- cgit v1.2.3 From 63f2606863b9dc3b01fbdc52e232103d07f35c45 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Sat, 10 Mar 2018 22:31:19 +0100 Subject: Refactor blockchain to store userAddress as address or undefined --- packages/website/ts/blockchain.ts | 97 +++++++++++++++++++++------------ packages/website/ts/redux/dispatcher.ts | 6 +- packages/website/ts/redux/reducer.ts | 4 +- 3 files changed, 68 insertions(+), 39 deletions(-) (limited to 'packages') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index e85c40e59..30adf680e 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -65,7 +65,7 @@ export class Blockchain { private _dispatcher: Dispatcher; private _web3Wrapper?: Web3Wrapper; private _blockchainWatcher?: BlockchainWatcher; - private _userAddress: string; + private _userAddressIfExists: string; private _cachedProvider: Web3.Provider; private _cachedProviderNetworkId: number; private _ledgerSubprovider: LedgerWalletSubprovider; @@ -116,7 +116,6 @@ export class Blockchain { } constructor(dispatcher: Dispatcher, isSalePage: boolean = false) { this._dispatcher = dispatcher; - this._userAddress = ''; const defaultGasPrice = GWEI_IN_WEI * 30; this._defaultGasPrice = new BigNumber(defaultGasPrice); // tslint:disable-next-line:no-floating-promises @@ -138,8 +137,8 @@ export class Blockchain { } } public async userAddressUpdatedFireAndForgetAsync(newUserAddress: string) { - if (this._userAddress !== newUserAddress) { - this._userAddress = newUserAddress; + if (this._userAddressIfExists !== newUserAddress) { + this._userAddressIfExists = newUserAddress; await this.fetchTokenInformationAsync(); await this._rehydrateStoreWithContractEvents(); } @@ -196,8 +195,8 @@ export class Blockchain { this._blockchainWatcher.destroy(); - this._userAddress = ''; - this._dispatcher.updateUserAddress(''); // Clear old userAddress + delete this._userAddressIfExists; + this._dispatcher.updateUserAddress(undefined); // Clear old userAddress const provider = new ProviderEngine(); const ledgerWalletConfigs = { @@ -244,7 +243,7 @@ export class Blockchain { shouldPollUserAddress, ); - this._userAddress = await this.getFirstAccountIfExistsAsync(); + this._userAddressIfExists = await this.getFirstAccountIfExistsAsync(); this._zeroEx.setProvider(provider, this.networkId); @@ -262,7 +261,7 @@ export class Blockchain { this._showFlashMessageIfLedger(); const txHash = await this._zeroEx.token.setProxyAllowanceAsync( token.address, - this._userAddress, + this._userAddressIfExists, amountInBaseUnits, { gasPrice: this._defaultGasPrice, @@ -271,10 +270,13 @@ export class Blockchain { await this._showEtherScanLinkAndAwaitTransactionMinedAsync(txHash); } public async transferAsync(token: Token, toAddress: string, amountInBaseUnits: BigNumber): Promise { + utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.'); + utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses); + this._showFlashMessageIfLedger(); const txHash = await this._zeroEx.token.transferAsync( token.address, - this._userAddress, + this._userAddressIfExists, toAddress, amountInBaseUnits, { @@ -316,6 +318,7 @@ export class Blockchain { return zeroExSignedOrder; } public async fillOrderAsync(signedOrder: SignedOrder, fillTakerTokenAmount: BigNumber): Promise { + utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.'); utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses); const shouldThrowOnInsufficientBalanceOrAllowance = true; @@ -325,7 +328,7 @@ export class Blockchain { signedOrder, fillTakerTokenAmount, shouldThrowOnInsufficientBalanceOrAllowance, - this._userAddress, + this._userAddressIfExists, { gasPrice: this._defaultGasPrice, }, @@ -384,12 +387,15 @@ export class Blockchain { public async pollTokenBalanceAsync(token: Token) { utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses); - const [currBalance] = await this.getTokenBalanceAndAllowanceAsync(this._userAddress, token.address); + const [currBalance] = await this.getTokenBalanceAndAllowanceAsync(this._userAddressIfExists, token.address); const newTokenBalancePromise = new Promise((resolve: (balance: BigNumber) => void, reject) => { const tokenPollInterval = intervalUtils.setAsyncExcludingInterval( async () => { - const [balance] = await this.getTokenBalanceAndAllowanceAsync(this._userAddress, token.address); + const [balance] = await this.getTokenBalanceAndAllowanceAsync( + this._userAddressIfExists, + token.address, + ); if (!balance.eq(currBalance)) { intervalUtils.clearAsyncExcludingInterval(tokenPollInterval); resolve(balance); @@ -408,7 +414,7 @@ export class Blockchain { } public async signOrderHashAsync(orderHash: string): Promise { utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.'); - const makerAddress = this._userAddress; + const makerAddress = this._userAddressIfExists; // If makerAddress is undefined, this means they have a web3 instance injected into their browser // but no account addresses associated with it. if (_.isUndefined(makerAddress)) { @@ -438,7 +444,7 @@ export class Blockchain { const mintableContract = await this._instantiateContractIfExistsAsync(MintableArtifacts, token.address); this._showFlashMessageIfLedger(); await mintableContract.mint(constants.MINT_AMOUNT, { - from: this._userAddress, + from: this._userAddressIfExists, gasPrice: this._defaultGasPrice, }); } @@ -451,9 +457,14 @@ export class Blockchain { utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses); this._showFlashMessageIfLedger(); - const txHash = await this._zeroEx.etherToken.depositAsync(etherTokenAddress, amount, this._userAddress, { - gasPrice: this._defaultGasPrice, - }); + const txHash = await this._zeroEx.etherToken.depositAsync( + etherTokenAddress, + amount, + this._userAddressIfExists, + { + gasPrice: this._defaultGasPrice, + }, + ); await this._showEtherScanLinkAndAwaitTransactionMinedAsync(txHash); } public async convertWrappedEthTokensToEthAsync(etherTokenAddress: string, amount: BigNumber): Promise { @@ -461,9 +472,14 @@ export class Blockchain { utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses); this._showFlashMessageIfLedger(); - const txHash = await this._zeroEx.etherToken.withdrawAsync(etherTokenAddress, amount, this._userAddress, { - gasPrice: this._defaultGasPrice, - }); + const txHash = await this._zeroEx.etherToken.withdrawAsync( + etherTokenAddress, + amount, + this._userAddressIfExists, + { + gasPrice: this._defaultGasPrice, + }, + ); await this._showEtherScanLinkAndAwaitTransactionMinedAsync(txHash); } public async doesContractExistAtAddressAsync(address: string) { @@ -471,7 +487,12 @@ export class Blockchain { return doesContractExist; } public async getCurrentUserTokenBalanceAndAllowanceAsync(tokenAddress: string): Promise { - const tokenBalanceAndAllowance = await this.getTokenBalanceAndAllowanceAsync(this._userAddress, tokenAddress); + utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses); + + const tokenBalanceAndAllowance = await this.getTokenBalanceAndAllowanceAsync( + this._userAddressIfExists, + tokenAddress, + ); return tokenBalanceAndAllowance; } public async getTokenBalanceAndAllowanceAsync(ownerAddress: string, tokenAddress: string): Promise { @@ -509,12 +530,16 @@ export class Blockchain { !_.isUndefined(this.networkId), 'Cannot call fetchTokenInformationAsync if disconnected from Ethereum node', ); + utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses); this._dispatcher.updateBlockchainIsLoaded(false); const tokenRegistryTokensByAddress = await this._getTokenRegistryTokensByAddressAsync(); - const trackedTokensByAddress = trackedTokenStorage.getTrackedTokensByAddress(this._userAddress, this.networkId); + const trackedTokensByAddress = trackedTokenStorage.getTrackedTokensByAddress( + this._userAddressIfExists, + this.networkId, + ); const tokenRegistryTokens = _.values(tokenRegistryTokensByAddress); if (_.isEmpty(trackedTokensByAddress)) { _.each(configs.DEFAULT_TRACKED_TOKEN_SYMBOLS, symbol => { @@ -523,7 +548,7 @@ export class Blockchain { trackedTokensByAddress[token.address] = token; }); _.each(trackedTokensByAddress, (token: Token, address: string) => { - trackedTokenStorage.addTrackedTokenToUser(this._userAddress, this.networkId, token); + trackedTokenStorage.addTrackedTokenToUser(this._userAddressIfExists, this.networkId, token); }); } else { // Properly set all tokenRegistry tokens `isTracked` to true if they are in the existing trackedTokens array @@ -550,14 +575,14 @@ export class Blockchain { address: mostPopularTradingPairTokens[1].address, }, }; - this._dispatcher.batchDispatch(allTokensByAddress, this.networkId, this._userAddress, sideToAssetToken); + this._dispatcher.batchDispatch(allTokensByAddress, this.networkId, this._userAddressIfExists, sideToAssetToken); this._dispatcher.updateBlockchainIsLoaded(true); } public async getFirstAccountIfExistsAsync() { const addresses = await this._web3Wrapper.getAvailableAddressesAsync(); if (_.isEmpty(addresses)) { - return ''; + return undefined; } return addresses[0]; } @@ -578,7 +603,7 @@ export class Blockchain { return receipt; } private _doesUserAddressExist(): boolean { - return this._userAddress !== ''; + return !_.isUndefined(this._userAddressIfExists); } private async _rehydrateStoreWithContractEvents() { // Ensure we are only ever listening to one set of events @@ -623,16 +648,18 @@ export class Blockchain { this._updateLatestFillsBlockIfNeeded(decodedLog.blockNumber); const fill = await this._convertDecodedLogToFillAsync(decodedLog); if (decodedLogEvent.isRemoved) { - tradeHistoryStorage.removeFillFromUser(this._userAddress, this.networkId, fill); + tradeHistoryStorage.removeFillFromUser(this._userAddressIfExists, this.networkId, fill); } else { - tradeHistoryStorage.addFillToUser(this._userAddress, this.networkId, fill); + tradeHistoryStorage.addFillToUser(this._userAddressIfExists, this.networkId, fill); } } }, ); } private async _fetchHistoricalExchangeLogFillEventsAsync(indexFilterValues: IndexedFilterValues) { - const fromBlock = tradeHistoryStorage.getFillsLatestBlock(this._userAddress, this.networkId); + utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses); + + const fromBlock = tradeHistoryStorage.getFillsLatestBlock(this._userAddressIfExists, this.networkId); const blockRange: BlockRange = { fromBlock, toBlock: 'latest' as BlockParam, @@ -648,7 +675,7 @@ export class Blockchain { } this._updateLatestFillsBlockIfNeeded(decodedLog.blockNumber); const fill = await this._convertDecodedLogToFillAsync(decodedLog); - tradeHistoryStorage.addFillToUser(this._userAddress, this.networkId, fill); + tradeHistoryStorage.addFillToUser(this._userAddressIfExists, this.networkId, fill); } } private async _convertDecodedLogToFillAsync(decodedLog: LogWithDecodedArgs) { @@ -672,10 +699,12 @@ export class Blockchain { } private _doesLogEventInvolveUser(decodedLog: LogWithDecodedArgs) { const args = decodedLog.args; - const isUserMakerOrTaker = args.maker === this._userAddress || args.taker === this._userAddress; + const isUserMakerOrTaker = args.maker === this._userAddressIfExists || args.taker === this._userAddressIfExists; return isUserMakerOrTaker; } private _updateLatestFillsBlockIfNeeded(blockNumber: number) { + utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses); + const isBlockPending = _.isNull(blockNumber); if (!isBlockPending) { // Hack: I've observed the behavior where a client won't register certain fill events @@ -686,7 +715,7 @@ export class Blockchain { // TODO: Debug if this is a race condition, and apply a more precise fix const blockNumberToSet = blockNumber - BLOCK_NUMBER_BACK_TRACK < 0 ? 0 : blockNumber - BLOCK_NUMBER_BACK_TRACK; - tradeHistoryStorage.setFillsLatestBlock(this._userAddress, this.networkId, blockNumberToSet); + tradeHistoryStorage.setFillsLatestBlock(this._userAddressIfExists, this.networkId, blockNumberToSet); } } private _stopWatchingExchangeLogFillEvents(): void { @@ -765,8 +794,8 @@ export class Blockchain { shouldPollUserAddress, ); - this._userAddress = await this.getFirstAccountIfExistsAsync(); - this._dispatcher.updateUserAddress(this._userAddress); + this._userAddressIfExists = await this.getFirstAccountIfExistsAsync(); + this._dispatcher.updateUserAddress(this._userAddressIfExists); await this.fetchTokenInformationAsync(); this._blockchainWatcher.startEmittingNetworkConnectionAndUserBalanceState(); await this._rehydrateStoreWithContractEvents(); diff --git a/packages/website/ts/redux/dispatcher.ts b/packages/website/ts/redux/dispatcher.ts index e40d435e0..13e9a10cc 100644 --- a/packages/website/ts/redux/dispatcher.ts +++ b/packages/website/ts/redux/dispatcher.ts @@ -86,7 +86,7 @@ export class Dispatcher { type: ActionTypes.UpdateOrderTakerAddress, }); } - public updateUserAddress(address: string) { + public updateUserAddress(address?: string) { this._dispatch({ data: address, type: ActionTypes.UpdateUserAddress, @@ -125,14 +125,14 @@ export class Dispatcher { public batchDispatch( tokenByAddress: TokenByAddress, networkId: number, - userAddress: string, + userAddressIfExists: string | undefined, sideToAssetToken: SideToAssetToken, ) { this._dispatch({ data: { tokenByAddress, networkId, - userAddress, + userAddressIfExists, sideToAssetToken, }, type: ActionTypes.BatchDispatch, diff --git a/packages/website/ts/redux/reducer.ts b/packages/website/ts/redux/reducer.ts index 1d43e4ffb..2f3150f92 100644 --- a/packages/website/ts/redux/reducer.ts +++ b/packages/website/ts/redux/reducer.ts @@ -187,7 +187,7 @@ export function reducer(state: State = INITIAL_STATE, action: Action) { return { ...state, networkId: action.data.networkId, - userAddress: action.data.userAddress, + userAddress: _.isUndefined(action.data.userAddress) ? '' : action.data.userAddress, sideToAssetToken: action.data.sideToAssetToken, tokenByAddress: action.data.tokenByAddress, }; @@ -286,7 +286,7 @@ export function reducer(state: State = INITIAL_STATE, action: Action) { case ActionTypes.UpdateUserAddress: { return { ...state, - userAddress: action.data, + userAddress: _.isUndefined(action.data) ? '' : action.data, }; } -- cgit v1.2.3 From c050186014e4bc060ccbfb3e15ea39d86e59f0c4 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Sat, 10 Mar 2018 22:36:54 +0100 Subject: Use undefined rather then an empty string in blockchainWatcher --- packages/website/ts/blockchain_watcher.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'packages') diff --git a/packages/website/ts/blockchain_watcher.ts b/packages/website/ts/blockchain_watcher.ts index af5bafc0c..d3801cef4 100644 --- a/packages/website/ts/blockchain_watcher.ts +++ b/packages/website/ts/blockchain_watcher.ts @@ -11,7 +11,7 @@ export class BlockchainWatcher { private _shouldPollUserAddress: boolean; private _watchNetworkAndBalanceIntervalId: NodeJS.Timer; private _prevUserEtherBalanceInWei: BigNumber; - private _prevUserAddress: string; + private _prevUserAddressIfExists: string; constructor( dispatcher: Dispatcher, web3Wrapper: Web3Wrapper, @@ -33,7 +33,7 @@ export class BlockchainWatcher { } // This should only be called from the LedgerConfigDialog public updatePrevUserAddress(userAddress: string) { - this._prevUserAddress = userAddress; + this._prevUserAddressIfExists = userAddress; } public startEmittingNetworkConnectionAndUserBalanceState() { if (!_.isUndefined(this._watchNetworkAndBalanceIntervalId)) { @@ -66,22 +66,22 @@ export class BlockchainWatcher { if (this._shouldPollUserAddress) { const addresses = await this._web3Wrapper.getAvailableAddressesAsync(); - const userAddressIfExists = addresses[0] || ''; + const userAddressIfExists = addresses[0]; // Update makerAddress on network change - if (this._prevUserAddress !== userAddressIfExists) { - this._prevUserAddress = userAddressIfExists; + if (this._prevUserAddressIfExists !== userAddressIfExists) { + this._prevUserAddressIfExists = userAddressIfExists; this._dispatcher.updateUserAddress(userAddressIfExists); } // Check for user ether balance changes - if (!_.isEmpty(userAddressIfExists)) { + if (!_.isUndefined(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); + if (!_.isUndefined(this._prevUserAddressIfExists)) { + await this._updateUserWeiBalanceAsync(this._prevUserAddressIfExists); } } }, -- cgit v1.2.3 From 4ac6b6828c30f2ec78bbea66b324c505641f24c3 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Sat, 10 Mar 2018 22:38:31 +0100 Subject: Get rid of getFirstAccountIfExistsAsync since no longer needed --- packages/website/ts/blockchain.ts | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'packages') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 30adf680e..0cb36230b 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -243,7 +243,8 @@ export class Blockchain { shouldPollUserAddress, ); - this._userAddressIfExists = await this.getFirstAccountIfExistsAsync(); + const userAddresses = await this._web3Wrapper.getAvailableAddressesAsync(); + this._userAddressIfExists = userAddresses[0]; this._zeroEx.setProvider(provider, this.networkId); @@ -579,13 +580,6 @@ export class Blockchain { this._dispatcher.updateBlockchainIsLoaded(true); } - public async getFirstAccountIfExistsAsync() { - const addresses = await this._web3Wrapper.getAvailableAddressesAsync(); - if (_.isEmpty(addresses)) { - return undefined; - } - return addresses[0]; - } private async _showEtherScanLinkAndAwaitTransactionMinedAsync( txHash: string, ): Promise { @@ -794,7 +788,8 @@ export class Blockchain { shouldPollUserAddress, ); - this._userAddressIfExists = await this.getFirstAccountIfExistsAsync(); + const userAddresses = await this._web3Wrapper.getAvailableAddressesAsync(); + this._userAddressIfExists = userAddresses[0]; this._dispatcher.updateUserAddress(this._userAddressIfExists); await this.fetchTokenInformationAsync(); this._blockchainWatcher.startEmittingNetworkConnectionAndUserBalanceState(); -- cgit v1.2.3 From 4c08667a078ac9ca1ed5dc62d87a8cfe3b903741 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Sat, 10 Mar 2018 22:43:13 +0100 Subject: Replace local PRECISION constants with global config.AMOUNT_DISPLAY_PRECISION --- packages/website/ts/components/eth_wrappers.tsx | 9 +++++---- packages/website/ts/components/token_balances.tsx | 5 ++--- .../website/ts/components/trade_history/trade_history_item.tsx | 6 +++--- packages/website/ts/components/visual_order.tsx | 5 ++--- packages/website/ts/utils/configs.ts | 1 + 5 files changed, 13 insertions(+), 13 deletions(-) (limited to 'packages') diff --git a/packages/website/ts/components/eth_wrappers.tsx b/packages/website/ts/components/eth_wrappers.tsx index 8aac31917..327d7bd7f 100644 --- a/packages/website/ts/components/eth_wrappers.tsx +++ b/packages/website/ts/components/eth_wrappers.tsx @@ -15,7 +15,6 @@ import { configs } from 'ts/utils/configs'; import { constants } from 'ts/utils/constants'; import { utils } from 'ts/utils/utils'; -const PRECISION = 5; const DATE_FORMAT = 'D/M/YY'; const ICON_DIMENSION = 40; const ETHER_ICON_PATH = '/images/ether.png'; @@ -147,7 +146,9 @@ export class EthWrappers extends React.Component
- {userEtherBalanceInEth.toFixed(PRECISION)} ETH + + {userEtherBalanceInEth.toFixed(configs.AMOUNT_DISPLAY_PRECSION)} ETH + {this.state.isWethStateLoaded ? ( - `${wethBalance.toFixed(PRECISION)} WETH` + `${wethBalance.toFixed(configs.AMOUNT_DISPLAY_PRECSION)} WETH` ) : ( )} @@ -269,7 +270,7 @@ export class EthWrappers extends React.Component - {userEtherBalanceInEth.toFixed(PRECISION)} ETH + {userEtherBalanceInEth.toFixed(configs.AMOUNT_DISPLAY_PRECSION)} ETH {this.state.isBalanceSpinnerVisible && ( @@ -500,7 +499,7 @@ export class TokenBalances extends React.Component
- {exchangeRate.toFixed(PRECISION)} {givenToken.symbol}/{receiveToken.symbol} + {exchangeRate.toFixed(configs.AMOUNT_DISPLAY_PRECSION)} {givenToken.symbol}/{receiveToken.symbol}
); @@ -163,7 +163,7 @@ export class TradeHistoryItem extends React.Component - {unitAmount.toFixed(PRECISION)} {symbol} + {unitAmount.toFixed(configs.AMOUNT_DISPLAY_PRECSION)} {symbol} ); } diff --git a/packages/website/ts/components/visual_order.tsx b/packages/website/ts/components/visual_order.tsx index ec2d47f39..3bf464e92 100644 --- a/packages/website/ts/components/visual_order.tsx +++ b/packages/website/ts/components/visual_order.tsx @@ -3,10 +3,9 @@ import * as _ from 'lodash'; import * as React from 'react'; import { Party } from 'ts/components/ui/party'; import { AssetToken, Token, TokenByAddress } from 'ts/types'; +import { configs } from 'ts/utils/configs'; import { utils } from 'ts/utils/utils'; -const PRECISION = 5; - interface VisualOrderProps { makerAssetToken: AssetToken; takerAssetToken: AssetToken; @@ -67,7 +66,7 @@ export class VisualOrder extends React.Component - {unitAmount.toNumber().toFixed(PRECISION)} {token.symbol} + {unitAmount.toNumber().toFixed(configs.AMOUNT_DISPLAY_PRECSION)} {token.symbol} ); } diff --git a/packages/website/ts/utils/configs.ts b/packages/website/ts/utils/configs.ts index f33b06c0a..f966cedbe 100644 --- a/packages/website/ts/utils/configs.ts +++ b/packages/website/ts/utils/configs.ts @@ -9,6 +9,7 @@ const isDevelopment = _.includes( const INFURA_API_KEY = 'T5WSC8cautR4KXyYgsRs'; export const configs = { + AMOUNT_DISPLAY_PRECSION: 5, BACKEND_BASE_URL: 'https://website-api.0xproject.com', BASE_URL, BITLY_ACCESS_TOKEN: 'ffc4c1a31e5143848fb7c523b39f91b9b213d208', -- cgit v1.2.3 From 56a8e0a09a61ca2c399c676da695bf4cd4ed63a6 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Sun, 11 Mar 2018 12:04:46 +0100 Subject: Fix userAddress bugs --- packages/website/ts/blockchain.ts | 16 ++++++++-------- .../website/ts/components/inputs/allowance_toggle.tsx | 1 + packages/website/ts/components/portal.tsx | 3 ++- packages/website/ts/redux/reducer.ts | 6 ++++-- 4 files changed, 15 insertions(+), 11 deletions(-) (limited to 'packages') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 0cb36230b..3e19cb715 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -531,16 +531,14 @@ export class Blockchain { !_.isUndefined(this.networkId), 'Cannot call fetchTokenInformationAsync if disconnected from Ethereum node', ); - utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses); this._dispatcher.updateBlockchainIsLoaded(false); const tokenRegistryTokensByAddress = await this._getTokenRegistryTokensByAddressAsync(); - const trackedTokensByAddress = trackedTokenStorage.getTrackedTokensByAddress( - this._userAddressIfExists, - this.networkId, - ); + const trackedTokensByAddress = _.isUndefined(this._userAddressIfExists) + ? {} + : trackedTokenStorage.getTrackedTokensByAddress(this._userAddressIfExists, this.networkId); const tokenRegistryTokens = _.values(tokenRegistryTokensByAddress); if (_.isEmpty(trackedTokensByAddress)) { _.each(configs.DEFAULT_TRACKED_TOKEN_SYMBOLS, symbol => { @@ -548,9 +546,11 @@ export class Blockchain { token.isTracked = true; trackedTokensByAddress[token.address] = token; }); - _.each(trackedTokensByAddress, (token: Token, address: string) => { - trackedTokenStorage.addTrackedTokenToUser(this._userAddressIfExists, this.networkId, token); - }); + if (!_.isUndefined(this._userAddressIfExists)) { + _.each(trackedTokensByAddress, (token: Token, address: string) => { + trackedTokenStorage.addTrackedTokenToUser(this._userAddressIfExists, this.networkId, token); + }); + } } else { // Properly set all tokenRegistry tokens `isTracked` to true if they are in the existing trackedTokens array _.each(trackedTokensByAddress, (trackedToken: Token, address: string) => { diff --git a/packages/website/ts/components/inputs/allowance_toggle.tsx b/packages/website/ts/components/inputs/allowance_toggle.tsx index 7fe303cf4..3d353d87c 100644 --- a/packages/website/ts/components/inputs/allowance_toggle.tsx +++ b/packages/website/ts/components/inputs/allowance_toggle.tsx @@ -67,6 +67,7 @@ export class AllowanceToggle extends React.Component { if (this.props.userAddress === '') { this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); + return; } this.setState({ diff --git a/packages/website/ts/components/portal.tsx b/packages/website/ts/components/portal.tsx index ad437acdb..7df340f45 100644 --- a/packages/website/ts/components/portal.tsx +++ b/packages/website/ts/components/portal.tsx @@ -121,8 +121,9 @@ export class Portal extends React.Component { }); } if (nextProps.userAddress !== this.state.prevUserAddress) { + const newUserAddress = _.isEmpty(nextProps.userAddress) ? undefined : nextProps.userAddress; // tslint:disable-next-line:no-floating-promises - this._blockchain.userAddressUpdatedFireAndForgetAsync(nextProps.userAddress); + this._blockchain.userAddressUpdatedFireAndForgetAsync(newUserAddress); this.setState({ prevUserAddress: nextProps.userAddress, }); diff --git a/packages/website/ts/redux/reducer.ts b/packages/website/ts/redux/reducer.ts index 2f3150f92..a628f65c2 100644 --- a/packages/website/ts/redux/reducer.ts +++ b/packages/website/ts/redux/reducer.ts @@ -184,10 +184,11 @@ export function reducer(state: State = INITIAL_STATE, action: Action) { } case ActionTypes.BatchDispatch: { + const userAddress = _.isUndefined(action.data.userAddressIfExists) ? '' : action.data.userAddressIfExists; return { ...state, networkId: action.data.networkId, - userAddress: _.isUndefined(action.data.userAddress) ? '' : action.data.userAddress, + userAddress, sideToAssetToken: action.data.sideToAssetToken, tokenByAddress: action.data.tokenByAddress, }; @@ -284,9 +285,10 @@ export function reducer(state: State = INITIAL_STATE, action: Action) { } case ActionTypes.UpdateUserAddress: { + const userAddress = _.isUndefined(action.data) ? '' : action.data; return { ...state, - userAddress: _.isUndefined(action.data) ? '' : action.data, + userAddress, }; } -- cgit v1.2.3 From caaa70f6302b0d84d43ca93ab014e0cf37886c0a Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Sun, 11 Mar 2018 12:33:34 +0100 Subject: Fix getTokenBalanceAndAllowanceAsync to take ownerAddressIfExists so that we don't sometimes pass an empty string and sometimes undefined --- packages/website/ts/blockchain.ts | 11 +++++++---- .../ts/components/dialogs/eth_weth_conversion_dialog.tsx | 4 +++- packages/website/ts/components/eth_wrappers.tsx | 11 +++++++---- .../ts/components/generate_order/generate_order_form.tsx | 3 ++- packages/website/ts/components/inputs/token_amount_input.tsx | 3 ++- packages/website/ts/components/token_balances.tsx | 6 ++++-- 6 files changed, 25 insertions(+), 13 deletions(-) (limited to 'packages') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 3e19cb715..14582eae9 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -496,18 +496,21 @@ export class Blockchain { ); return tokenBalanceAndAllowance; } - public async getTokenBalanceAndAllowanceAsync(ownerAddress: string, tokenAddress: string): Promise { + public async getTokenBalanceAndAllowanceAsync( + ownerAddressIfExists: string, + tokenAddress: string, + ): Promise { utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.'); - if (_.isEmpty(ownerAddress)) { + if (_.isUndefined(ownerAddressIfExists)) { const zero = new BigNumber(0); return [zero, zero]; } let balance = new BigNumber(0); let allowance = new BigNumber(0); if (this._doesUserAddressExist()) { - balance = await this._zeroEx.token.getBalanceAsync(tokenAddress, ownerAddress); - allowance = await this._zeroEx.token.getProxyAllowanceAsync(tokenAddress, ownerAddress); + balance = await this._zeroEx.token.getBalanceAsync(tokenAddress, ownerAddressIfExists); + allowance = await this._zeroEx.token.getProxyAllowanceAsync(tokenAddress, ownerAddressIfExists); } return [balance, allowance]; } 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 72ebe1f67..d1bdb447f 100644 --- a/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx +++ b/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx @@ -1,6 +1,7 @@ import { ZeroEx } from '0x.js'; import { colors } from '@0xproject/react-shared'; import { BigNumber } from '@0xproject/utils'; +import * as _ from 'lodash'; import Dialog from 'material-ui/Dialog'; import FlatButton from 'material-ui/FlatButton'; import * as React from 'react'; @@ -185,8 +186,9 @@ export class EthWethConversionDialog extends React.Component< this.props.onCancelled(); } private async _fetchEthTokenBalanceAsync() { + const userAddressIfExists = _.isEmpty(this.props.userAddress) ? undefined : this.props.userAddress; const [balance] = await this.props.blockchain.getTokenBalanceAndAllowanceAsync( - this.props.userAddress, + userAddressIfExists, this.props.token.address, ); if (!this._isUnmounted) { diff --git a/packages/website/ts/components/eth_wrappers.tsx b/packages/website/ts/components/eth_wrappers.tsx index 327d7bd7f..b12c637e5 100644 --- a/packages/website/ts/components/eth_wrappers.tsx +++ b/packages/website/ts/components/eth_wrappers.tsx @@ -351,8 +351,9 @@ export class EthWrappers extends React.Component token.symbol === 'WETH'); + const userAddressIfExists = _.isEmpty(this.props.userAddress) ? undefined : this.props.userAddress; const [wethBalance, wethAllowance] = await this.props.blockchain.getTokenBalanceAndAllowanceAsync( - this.props.userAddress, + userAddressIfExists, wethToken.address, ); @@ -382,7 +384,7 @@ export class EthWrappers extends React.Component