Merge branch 'v2-prototype' of https://github.com/0xProject/0x-monorepo into feature/website/portal-onboarding-polish
This commit is contained in:
@@ -4,7 +4,6 @@ import FlatButton from 'material-ui/FlatButton';
|
||||
import * as React from 'react';
|
||||
import { Blockchain } from 'ts/blockchain';
|
||||
import { BlockchainErrs } from 'ts/types';
|
||||
import { configs } from 'ts/utils/configs';
|
||||
import { constants } from 'ts/utils/constants';
|
||||
|
||||
interface BlockchainErrDialogProps {
|
||||
@@ -125,8 +124,7 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp
|
||||
Parity Signer Chrome extension
|
||||
</a>{' '}
|
||||
lets you connect to a locally running Parity node. Make sure you have started your local Parity node
|
||||
with {configs.IS_MAINNET_ENABLED && '`parity ui` or'} `parity --chain kovan ui` in order to connect
|
||||
to {configs.IS_MAINNET_ENABLED ? 'mainnet or Kovan respectively.' : 'Kovan.'}
|
||||
with `parity ui` or `parity --chain kovan ui` in order to connect to mainnet or Kovan respectively.
|
||||
</div>
|
||||
<div className="pt2">
|
||||
<span className="bold">Note:</span> If you have done one of the above steps and are still seeing
|
||||
@@ -142,10 +140,8 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp
|
||||
<div>
|
||||
The 0x smart contracts are not deployed on the Ethereum network you are currently connected to
|
||||
(network Id: {this.props.networkId}). In order to use the 0x portal dApp, please connect to the{' '}
|
||||
{Networks.Kovan} testnet (network Id: {constants.NETWORK_ID_KOVAN})
|
||||
{configs.IS_MAINNET_ENABLED
|
||||
? ` or ${constants.MAINNET_NAME} (network Id: ${constants.NETWORK_ID_MAINNET}).`
|
||||
: `.`}
|
||||
{Networks.Kovan} testnet (network Id: {constants.NETWORK_ID_KOVAN}) or ${constants.MAINNET_NAME}{' '}
|
||||
(network Id: ${constants.NETWORK_ID_MAINNET}).
|
||||
</div>
|
||||
<h4>Metamask</h4>
|
||||
<div>
|
||||
@@ -159,11 +155,8 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp
|
||||
If using the{' '}
|
||||
<a href={constants.URL_PARITY_CHROME_STORE} target="_blank">
|
||||
Parity Signer Chrome extension
|
||||
</a>, make sure to start your local Parity node with{' '}
|
||||
{configs.IS_MAINNET_ENABLED
|
||||
? '`parity ui` or `parity --chain Kovan ui` in order to connect to mainnet \
|
||||
or Kovan respectively.'
|
||||
: '`parity --chain kovan ui` in order to connect to Kovan.'}
|
||||
</a>, make sure to start your local Parity node with `parity ui` or `parity --chain Kovan ui` in
|
||||
order to connect to mainnet \ or Kovan respectively.
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -282,6 +282,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
|
||||
if (didSucceed) {
|
||||
this.setState({
|
||||
stepIndex: LedgerSteps.SELECT_ADDRESS,
|
||||
connectionErrMsg: '',
|
||||
});
|
||||
}
|
||||
return didSucceed;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Dialog from 'material-ui/Dialog';
|
||||
import FlatButton from 'material-ui/FlatButton';
|
||||
import * as moment from 'moment';
|
||||
import * as React from 'react';
|
||||
import { Blockchain } from 'ts/blockchain';
|
||||
import { TrackTokenConfirmation } from 'ts/components/track_token_confirmation';
|
||||
@@ -73,12 +74,13 @@ export class TrackTokenConfirmationDialog extends React.Component<
|
||||
this.setState({
|
||||
isAddingTokenToTracked: true,
|
||||
});
|
||||
const currentTimestamp = moment().unix();
|
||||
for (const token of this.props.tokens) {
|
||||
const newTokenEntry = {
|
||||
...token,
|
||||
trackedTimestamp: currentTimestamp,
|
||||
};
|
||||
|
||||
newTokenEntry.isTracked = true;
|
||||
trackedTokenStorage.addTrackedTokenToUser(this.props.userAddress, this.props.networkId, newTokenEntry);
|
||||
this.props.dispatcher.updateTokenByAddress([newTokenEntry]);
|
||||
}
|
||||
|
||||
@@ -373,26 +373,26 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
|
||||
|
||||
const tokensToTrack: Token[] = [];
|
||||
const isUnseenMakerToken = _.isUndefined(makerTokenIfExists);
|
||||
const isMakerTokenTracked = !_.isUndefined(makerTokenIfExists) && makerTokenIfExists.isTracked;
|
||||
const isMakerTokenTracked = !_.isUndefined(makerTokenIfExists) && utils.isTokenTracked(makerTokenIfExists);
|
||||
if (isUnseenMakerToken) {
|
||||
tokensToTrack.push({
|
||||
...this.state.parsedOrder.metadata.makerToken,
|
||||
address: this.state.parsedOrder.signedOrder.makerTokenAddress,
|
||||
iconUrl: undefined,
|
||||
isTracked: false,
|
||||
trackedTimestamp: undefined,
|
||||
isRegistered: false,
|
||||
});
|
||||
} else if (!isMakerTokenTracked) {
|
||||
tokensToTrack.push(makerTokenIfExists);
|
||||
}
|
||||
const isUnseenTakerToken = _.isUndefined(takerTokenIfExists);
|
||||
const isTakerTokenTracked = !_.isUndefined(takerTokenIfExists) && takerTokenIfExists.isTracked;
|
||||
const isTakerTokenTracked = !_.isUndefined(takerTokenIfExists) && utils.isTokenTracked(takerTokenIfExists);
|
||||
if (isUnseenTakerToken) {
|
||||
tokensToTrack.push({
|
||||
...this.state.parsedOrder.metadata.takerToken,
|
||||
address: this.state.parsedOrder.signedOrder.takerTokenAddress,
|
||||
iconUrl: undefined,
|
||||
isTracked: false,
|
||||
trackedTimestamp: undefined,
|
||||
isRegistered: false,
|
||||
});
|
||||
} else if (!isTakerTokenTracked) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as _ from 'lodash';
|
||||
import Dialog from 'material-ui/Dialog';
|
||||
import FlatButton from 'material-ui/FlatButton';
|
||||
import * as moment from 'moment';
|
||||
import * as React from 'react';
|
||||
import { Blockchain } from 'ts/blockchain';
|
||||
import { NewTokenForm } from 'ts/components/generate_order/new_token_form';
|
||||
@@ -10,6 +11,7 @@ import { trackedTokenStorage } from 'ts/local_storage/tracked_token_storage';
|
||||
import { Dispatcher } from 'ts/redux/dispatcher';
|
||||
import { DialogConfigs, Token, TokenByAddress, TokenVisibility } from 'ts/types';
|
||||
import { constants } from 'ts/utils/constants';
|
||||
import { utils } from 'ts/utils/utils';
|
||||
|
||||
const TOKEN_ICON_DIMENSION = 100;
|
||||
const TILE_DIMENSION = 146;
|
||||
@@ -134,8 +136,8 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
|
||||
let tileStyles;
|
||||
const gridTiles = _.map(this.props.tokenByAddress, (token: Token, address: string) => {
|
||||
if (
|
||||
(this.props.tokenVisibility === TokenVisibility.TRACKED && !token.isTracked) ||
|
||||
(this.props.tokenVisibility === TokenVisibility.UNTRACKED && token.isTracked) ||
|
||||
(this.props.tokenVisibility === TokenVisibility.TRACKED && !utils.isTokenTracked(token)) ||
|
||||
(this.props.tokenVisibility === TokenVisibility.UNTRACKED && utils.isTokenTracked(token)) ||
|
||||
token.symbol === constants.ZRX_TOKEN_SYMBOL ||
|
||||
token.symbol === constants.ETHER_TOKEN_SYMBOL
|
||||
) {
|
||||
@@ -212,7 +214,7 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
|
||||
}
|
||||
private _onChooseToken(tokenAddress: string): void {
|
||||
const token = this.props.tokenByAddress[tokenAddress];
|
||||
if (token.isTracked) {
|
||||
if (utils.isTokenTracked(token)) {
|
||||
this.props.onTokenChosen(tokenAddress);
|
||||
} else {
|
||||
this.setState({
|
||||
@@ -257,9 +259,8 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
|
||||
}
|
||||
const newTokenEntry = {
|
||||
...token,
|
||||
trackedTimestamp: moment().unix(),
|
||||
};
|
||||
|
||||
newTokenEntry.isTracked = true;
|
||||
trackedTokenStorage.addTrackedTokenToUser(this.props.userAddress, this.props.networkId, newTokenEntry);
|
||||
|
||||
this.props.dispatcher.updateTokenByAddress([newTokenEntry]);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { colors } from '@0xproject/react-shared';
|
||||
import * as _ from 'lodash';
|
||||
import TextField from 'material-ui/TextField';
|
||||
import * as moment from 'moment';
|
||||
import * as React from 'react';
|
||||
import { Blockchain } from 'ts/blockchain';
|
||||
import { AddressInput } from 'ts/components/inputs/address_input';
|
||||
@@ -147,7 +148,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
|
||||
iconUrl: undefined,
|
||||
name: this.state.name,
|
||||
symbol: this.state.symbol.toUpperCase(),
|
||||
isTracked: true,
|
||||
trackedTimestamp: moment().unix(),
|
||||
isRegistered: false,
|
||||
};
|
||||
this.props.onNewTokenSubmitted(newToken);
|
||||
|
||||
@@ -23,7 +23,6 @@ import { GenerateOrderForm } from 'ts/containers/generate_order_form';
|
||||
import { localStorage } from 'ts/local_storage/local_storage';
|
||||
import { Dispatcher } from 'ts/redux/dispatcher';
|
||||
import { BlockchainErrs, HashData, Order, ProviderType, ScreenWidths, TokenByAddress, WebsitePaths } from 'ts/types';
|
||||
import { configs } from 'ts/utils/configs';
|
||||
import { constants } from 'ts/utils/constants';
|
||||
import { orderParser } from 'ts/utils/order_parser';
|
||||
import { Translate } from 'ts/utils/translate';
|
||||
@@ -170,67 +169,53 @@ export class LegacyPortal extends React.Component<LegacyPortalProps, LegacyPorta
|
||||
/>
|
||||
<div id="portal" className="mx-auto max-width-4" style={{ width: '100%' }}>
|
||||
<Paper className="mb3 mt2">
|
||||
{!configs.IS_MAINNET_ENABLED && this.props.networkId === constants.NETWORK_ID_MAINNET ? (
|
||||
<div className="p3 center">
|
||||
<div className="h2 py2">Mainnet unavailable</div>
|
||||
<div className="mx-auto pb2 pt2">
|
||||
<img src="/images/zrx_token.png" style={{ width: 150 }} />
|
||||
</div>
|
||||
<div>
|
||||
0x portal is currently unavailable on the Ethereum mainnet.
|
||||
<div>To try it out, switch to the Kovan test network (networkId: 42).</div>
|
||||
<div className="py2">Check back soon!</div>
|
||||
</div>
|
||||
<div className="mx-auto flex">
|
||||
<div className="col col-2 pr2 pt1 sm-hide xs-hide" style={portalMenuContainerStyle}>
|
||||
<LegacyPortalMenu menuItemStyle={{ color: colors.white }} />
|
||||
</div>
|
||||
) : (
|
||||
<div className="mx-auto flex">
|
||||
<div className="col col-2 pr2 pt1 sm-hide xs-hide" style={portalMenuContainerStyle}>
|
||||
<LegacyPortalMenu menuItemStyle={{ color: colors.white }} />
|
||||
</div>
|
||||
<div className="col col-12 lg-col-10 md-col-10 sm-col sm-col-12">
|
||||
<div className="py2" style={{ backgroundColor: colors.grey50 }}>
|
||||
{this.props.blockchainIsLoaded ? (
|
||||
<Switch>
|
||||
<Route
|
||||
path={`${WebsitePaths.Portal}/weth`}
|
||||
render={this._renderEthWrapper.bind(this)}
|
||||
/>
|
||||
<Route
|
||||
path={`${WebsitePaths.Portal}/fill`}
|
||||
render={this._renderFillOrder.bind(this)}
|
||||
/>
|
||||
<Route
|
||||
path={`${WebsitePaths.Portal}/balances`}
|
||||
render={this._renderTokenBalances.bind(this)}
|
||||
/>
|
||||
<Route
|
||||
path={`${WebsitePaths.Portal}/trades`}
|
||||
render={this._renderTradeHistory.bind(this)}
|
||||
/>
|
||||
<Route
|
||||
path={`${WebsitePaths.Home}`}
|
||||
render={this._renderGenerateOrderForm.bind(this)}
|
||||
/>
|
||||
</Switch>
|
||||
) : (
|
||||
<div className="pt4 sm-px2 sm-pt2 sm-m1" style={{ height: 500 }}>
|
||||
<div
|
||||
className="relative sm-px2 sm-pt2 sm-m1"
|
||||
style={{ height: 122, top: '50%', transform: 'translateY(-50%)' }}
|
||||
>
|
||||
<div className="center pb2">
|
||||
<CircularProgress size={40} thickness={5} />
|
||||
</div>
|
||||
<div className="center pt2" style={{ paddingBottom: 11 }}>
|
||||
Loading Portal...
|
||||
</div>
|
||||
<div className="col col-12 lg-col-10 md-col-10 sm-col sm-col-12">
|
||||
<div className="py2" style={{ backgroundColor: colors.grey50 }}>
|
||||
{this.props.blockchainIsLoaded ? (
|
||||
<Switch>
|
||||
<Route
|
||||
path={`${WebsitePaths.Portal}/weth`}
|
||||
render={this._renderEthWrapper.bind(this)}
|
||||
/>
|
||||
<Route
|
||||
path={`${WebsitePaths.Portal}/fill`}
|
||||
render={this._renderFillOrder.bind(this)}
|
||||
/>
|
||||
<Route
|
||||
path={`${WebsitePaths.Portal}/balances`}
|
||||
render={this._renderTokenBalances.bind(this)}
|
||||
/>
|
||||
<Route
|
||||
path={`${WebsitePaths.Portal}/trades`}
|
||||
render={this._renderTradeHistory.bind(this)}
|
||||
/>
|
||||
<Route
|
||||
path={`${WebsitePaths.Home}`}
|
||||
render={this._renderGenerateOrderForm.bind(this)}
|
||||
/>
|
||||
</Switch>
|
||||
) : (
|
||||
<div className="pt4 sm-px2 sm-pt2 sm-m1" style={{ height: 500 }}>
|
||||
<div
|
||||
className="relative sm-px2 sm-pt2 sm-m1"
|
||||
style={{ height: 122, top: '50%', transform: 'translateY(-50%)' }}
|
||||
>
|
||||
<div className="center pb2">
|
||||
<CircularProgress size={40} thickness={5} />
|
||||
</div>
|
||||
<div className="center pt2" style={{ paddingBottom: 11 }}>
|
||||
Loading Portal...
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Paper>
|
||||
<BlockchainErrDialog
|
||||
blockchain={this._blockchain}
|
||||
@@ -249,16 +234,14 @@ export class LegacyPortal extends React.Component<LegacyPortalProps, LegacyPorta
|
||||
onToggleDialog={this._onPortalDisclaimerAccepted.bind(this)}
|
||||
/>
|
||||
<FlashMessage dispatcher={this.props.dispatcher} flashMessage={this.props.flashMessage} />
|
||||
{this.props.blockchainIsLoaded && (
|
||||
<LedgerConfigDialog
|
||||
providerType={this.props.providerType}
|
||||
networkId={this.props.networkId}
|
||||
blockchain={this._blockchain}
|
||||
dispatcher={this.props.dispatcher}
|
||||
toggleDialogFn={this.onToggleLedgerDialog.bind(this)}
|
||||
isOpen={this.state.isLedgerDialogOpen}
|
||||
/>
|
||||
)}
|
||||
<LedgerConfigDialog
|
||||
providerType={this.props.providerType}
|
||||
networkId={this.props.networkId}
|
||||
blockchain={this._blockchain}
|
||||
dispatcher={this.props.dispatcher}
|
||||
toggleDialogFn={this.onToggleLedgerDialog.bind(this)}
|
||||
isOpen={this.state.isLedgerDialogOpen}
|
||||
/>
|
||||
</div>
|
||||
<Footer translate={this.props.translate} dispatcher={this.props.dispatcher} />
|
||||
</div>
|
||||
@@ -292,8 +275,7 @@ export class LegacyPortal extends React.Component<LegacyPortalProps, LegacyPorta
|
||||
);
|
||||
}
|
||||
private _renderTokenBalances(): React.ReactNode {
|
||||
const allTokens = _.values(this.props.tokenByAddress);
|
||||
const trackedTokens = _.filter(allTokens, t => t.isTracked);
|
||||
const trackedTokens = utils.getTrackedTokens(this.props.tokenByAddress);
|
||||
return (
|
||||
<TokenBalances
|
||||
blockchain={this._blockchain}
|
||||
|
||||
@@ -186,9 +186,11 @@ class PlainPortalOnboardingFlow extends React.Component<PortalOnboardingFlowProp
|
||||
const ethToken = utils.getEthToken(this.props.tokenByAddress);
|
||||
const zrxToken = utils.getZrxToken(this.props.tokenByAddress);
|
||||
if (ethToken && zrxToken) {
|
||||
const ethTokenAllowance = this.props.trackedTokenStateByAddress[ethToken.address].allowance;
|
||||
const zrxTokenAllowance = this.props.trackedTokenStateByAddress[zrxToken.address].allowance;
|
||||
return ethTokenAllowance > new BigNumber(0) && zrxTokenAllowance > new BigNumber(0);
|
||||
const ethTokenState = this.props.trackedTokenStateByAddress[ethToken.address];
|
||||
const zrxTokenState = this.props.trackedTokenStateByAddress[zrxToken.address];
|
||||
if (ethTokenState && zrxTokenState) {
|
||||
return ethTokenState.allowance.gt(0) && zrxTokenState.allowance.gt(0);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -251,12 +253,15 @@ class PlainPortalOnboardingFlow extends React.Component<PortalOnboardingFlowProp
|
||||
if (!token) {
|
||||
return null;
|
||||
}
|
||||
const tokenState = this.props.trackedTokenStateByAddress[token.address];
|
||||
const tokenStateIfExists = this.props.trackedTokenStateByAddress[token.address];
|
||||
if (_.isUndefined(tokenStateIfExists)) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<AllowanceToggle
|
||||
token={token}
|
||||
tokenState={tokenState}
|
||||
isDisabled={!tokenState.isLoaded}
|
||||
tokenState={tokenStateIfExists}
|
||||
isDisabled={!tokenStateIfExists.isLoaded}
|
||||
blockchain={this.props.blockchain}
|
||||
// tslint:disable-next-line:jsx-no-lambda
|
||||
refetchTokenStateAsync={async () => this.props.refetchTokenStateAsync(token.address)}
|
||||
|
||||
@@ -152,9 +152,8 @@ export class Portal extends React.Component<PortalProps, PortalState> {
|
||||
}
|
||||
public componentDidUpdate(prevProps: PortalProps): void {
|
||||
if (!prevProps.blockchainIsLoaded && this.props.blockchainIsLoaded) {
|
||||
const trackedTokenAddresses = _.keys(this.state.trackedTokenStateByAddress);
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
this._fetchBalancesAndAllowancesAsync(trackedTokenAddresses);
|
||||
this._fetchBalancesAndAllowancesAsync(this._getCurrentTrackedTokensAddresses());
|
||||
}
|
||||
}
|
||||
public componentWillReceiveProps(nextProps: PortalProps): void {
|
||||
@@ -182,17 +181,17 @@ export class Portal extends React.Component<PortalProps, PortalState> {
|
||||
prevPathname: nextProps.location.pathname,
|
||||
});
|
||||
}
|
||||
|
||||
// If the address changed, but the network did not, we can just refetch the currently tracked tokens.
|
||||
if (
|
||||
nextProps.userAddress !== this.props.userAddress ||
|
||||
nextProps.networkId !== this.props.networkId ||
|
||||
(nextProps.userAddress !== this.props.userAddress && nextProps.networkId === this.props.networkId) ||
|
||||
nextProps.lastForceTokenStateRefetch !== this.props.lastForceTokenStateRefetch
|
||||
) {
|
||||
const trackedTokenAddresses = _.keys(this.state.trackedTokenStateByAddress);
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
this._fetchBalancesAndAllowancesAsync(trackedTokenAddresses);
|
||||
this._fetchBalancesAndAllowancesAsync(this._getCurrentTrackedTokensAddresses());
|
||||
}
|
||||
|
||||
const nextTrackedTokens = this._getTrackedTokens(nextProps.tokenByAddress);
|
||||
const nextTrackedTokens = utils.getTrackedTokens(nextProps.tokenByAddress);
|
||||
const trackedTokens = this._getCurrentTrackedTokens();
|
||||
|
||||
if (!_.isEqual(nextTrackedTokens, trackedTokens)) {
|
||||
@@ -200,7 +199,7 @@ export class Portal extends React.Component<PortalProps, PortalState> {
|
||||
const newTokenAddresses = _.map(newTokens, token => token.address);
|
||||
// Add placeholder entry for this token to the state, since fetching the
|
||||
// balance/allowance is asynchronous
|
||||
const trackedTokenStateByAddress = this.state.trackedTokenStateByAddress;
|
||||
const trackedTokenStateByAddress = { ...this.state.trackedTokenStateByAddress };
|
||||
for (const tokenAddress of newTokenAddresses) {
|
||||
trackedTokenStateByAddress[tokenAddress] = {
|
||||
balance: new BigNumber(0),
|
||||
@@ -265,16 +264,16 @@ export class Portal extends React.Component<PortalProps, PortalState> {
|
||||
networkId={this.props.networkId}
|
||||
/>
|
||||
<FlashMessage dispatcher={this.props.dispatcher} flashMessage={this.props.flashMessage} />
|
||||
{this.props.blockchainIsLoaded && (
|
||||
<LedgerConfigDialog
|
||||
providerType={this.props.providerType}
|
||||
networkId={this.props.networkId}
|
||||
blockchain={this._blockchain}
|
||||
dispatcher={this.props.dispatcher}
|
||||
toggleDialogFn={this._onToggleLedgerDialog.bind(this)}
|
||||
isOpen={this.state.isLedgerDialogOpen}
|
||||
/>
|
||||
)}
|
||||
|
||||
<LedgerConfigDialog
|
||||
providerType={this.props.providerType}
|
||||
networkId={this.props.networkId}
|
||||
blockchain={this._blockchain}
|
||||
dispatcher={this.props.dispatcher}
|
||||
toggleDialogFn={this._onToggleLedgerDialog.bind(this)}
|
||||
isOpen={this.state.isLedgerDialogOpen}
|
||||
/>
|
||||
|
||||
<AssetPicker
|
||||
userAddress={this.props.userAddress}
|
||||
networkId={this.props.networkId}
|
||||
@@ -563,9 +562,9 @@ export class Portal extends React.Component<PortalProps, PortalState> {
|
||||
if (this.state.tokenManagementState === TokenManagementState.Remove && !isDefaultTrackedToken) {
|
||||
if (token.isRegistered) {
|
||||
// Remove the token from tracked tokens
|
||||
const newToken = {
|
||||
const newToken: Token = {
|
||||
...token,
|
||||
isTracked: false,
|
||||
trackedTimestamp: undefined,
|
||||
};
|
||||
this.props.dispatcher.updateTokenByAddress([newToken]);
|
||||
} else {
|
||||
@@ -608,17 +607,12 @@ export class Portal extends React.Component<PortalProps, PortalState> {
|
||||
const isSmallScreen = this.props.screenWidth === ScreenWidths.Sm;
|
||||
return isSmallScreen;
|
||||
}
|
||||
|
||||
private _getCurrentTrackedTokens(): Token[] {
|
||||
return this._getTrackedTokens(this.props.tokenByAddress);
|
||||
return utils.getTrackedTokens(this.props.tokenByAddress);
|
||||
}
|
||||
|
||||
private _getTrackedTokens(tokenByAddress: TokenByAddress): Token[] {
|
||||
const allTokens = _.values(tokenByAddress);
|
||||
const trackedTokens = _.filter(allTokens, t => t.isTracked);
|
||||
return trackedTokens;
|
||||
private _getCurrentTrackedTokensAddresses(): string[] {
|
||||
return _.map(this._getCurrentTrackedTokens(), token => token.address);
|
||||
}
|
||||
|
||||
private _getInitialTrackedTokenStateByAddress(trackedTokens: Token[]): TokenStateByAddress {
|
||||
const trackedTokenStateByAddress: TokenStateByAddress = {};
|
||||
_.each(trackedTokens, token => {
|
||||
|
||||
@@ -308,7 +308,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
|
||||
const trackedTokensStartingWithEtherToken = trackedTokens.sort(
|
||||
firstBy((t: Token) => t.symbol !== ETHER_TOKEN_SYMBOL)
|
||||
.thenBy((t: Token) => t.symbol !== ZRX_TOKEN_SYMBOL)
|
||||
.thenBy('address'),
|
||||
.thenBy('trackedTimestamp'),
|
||||
);
|
||||
const tableRows = _.map(
|
||||
trackedTokensStartingWithEtherToken,
|
||||
@@ -424,9 +424,9 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
|
||||
if (!this.state.isAddingToken && !isDefaultTrackedToken) {
|
||||
if (token.isRegistered) {
|
||||
// Remove the token from tracked tokens
|
||||
const newToken = {
|
||||
const newToken: Token = {
|
||||
...token,
|
||||
isTracked: false,
|
||||
trackedTimestamp: undefined,
|
||||
};
|
||||
this.props.dispatcher.updateTokenByAddress([newToken]);
|
||||
} else {
|
||||
|
||||
@@ -13,7 +13,6 @@ import { ProviderDisplay } from 'ts/components/top_bar/provider_display';
|
||||
import { TopBarMenuItem } from 'ts/components/top_bar/top_bar_menu_item';
|
||||
import { DropDown } from 'ts/components/ui/drop_down';
|
||||
import { Dispatcher } from 'ts/redux/dispatcher';
|
||||
import { zIndex } from 'ts/style/z_index';
|
||||
import { Deco, Key, ProviderType, WebsiteLegacyPaths, WebsitePaths } from 'ts/types';
|
||||
import { constants } from 'ts/utils/constants';
|
||||
import { Translate } from 'ts/utils/translate';
|
||||
@@ -58,7 +57,6 @@ const styles: Styles = {
|
||||
width: '100%',
|
||||
position: 'relative',
|
||||
top: 0,
|
||||
zIndex: zIndex.topBar,
|
||||
paddingBottom: 1,
|
||||
},
|
||||
bottomBar: {
|
||||
|
||||
@@ -156,6 +156,20 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
|
||||
isHoveringSidebar: false,
|
||||
};
|
||||
}
|
||||
public componentDidUpdate(prevProps: WalletProps): void {
|
||||
const currentTrackedTokens = this.props.trackedTokens;
|
||||
const differentTrackedTokens = _.difference(currentTrackedTokens, prevProps.trackedTokens);
|
||||
const firstDifferentTrackedToken = _.head(differentTrackedTokens);
|
||||
// check if there is only one different token, and if that token is a member of the current tracked tokens
|
||||
// this means that the token was added, not removed
|
||||
if (
|
||||
!_.isUndefined(firstDifferentTrackedToken) &&
|
||||
_.size(differentTrackedTokens) === 1 &&
|
||||
_.includes(currentTrackedTokens, firstDifferentTrackedToken)
|
||||
) {
|
||||
document.getElementById(firstDifferentTrackedToken.address).scrollIntoView();
|
||||
}
|
||||
}
|
||||
public render(): React.ReactNode {
|
||||
const isBlockchainLoaded = this.props.blockchainIsLoaded && this.props.blockchainErr === BlockchainErrs.NoError;
|
||||
return (
|
||||
@@ -318,7 +332,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
|
||||
const trackedTokensStartingWithEtherToken = trackedTokens.sort(
|
||||
firstBy((t: Token) => t.symbol !== constants.ETHER_TOKEN_SYMBOL)
|
||||
.thenBy((t: Token) => t.symbol !== constants.ZRX_TOKEN_SYMBOL)
|
||||
.thenBy('address'),
|
||||
.thenBy('trackedTimestamp'),
|
||||
);
|
||||
return _.map(trackedTokensStartingWithEtherToken, this._renderTokenRow.bind(this));
|
||||
}
|
||||
@@ -375,7 +389,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
|
||||
const style = { ...styles.tokenItem, ...additionalStyle };
|
||||
const etherToken = this._getEthToken();
|
||||
return (
|
||||
<div key={key} className={`flex flex-column ${className || ''}`}>
|
||||
<div id={key} key={key} className={`flex flex-column ${className || ''}`}>
|
||||
<StandardIconRow
|
||||
icon={icon}
|
||||
main={
|
||||
|
||||
Reference in New Issue
Block a user