aboutsummaryrefslogtreecommitdiffstats
path: root/packages/website/ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/website/ts')
-rw-r--r--packages/website/ts/artifacts/Exchange.json610
-rw-r--r--packages/website/ts/blockchain.ts39
-rw-r--r--packages/website/ts/components/dialogs/ledger_config_dialog.tsx5
-rw-r--r--packages/website/ts/components/eth_wrappers.tsx7
-rw-r--r--packages/website/ts/components/generate_order/asset_picker.tsx40
-rw-r--r--packages/website/ts/components/onboarding/add_eth_onboarding_step.tsx14
-rw-r--r--packages/website/ts/components/onboarding/onboarding_card.tsx112
-rw-r--r--packages/website/ts/components/onboarding/onboarding_flow.tsx28
-rw-r--r--packages/website/ts/components/onboarding/onboarding_tooltip.tsx13
-rw-r--r--packages/website/ts/components/onboarding/portal_onboarding_flow.tsx26
-rw-r--r--packages/website/ts/components/onboarding/unlock_wallet_onboarding_step.tsx12
-rw-r--r--packages/website/ts/components/onboarding/wrap_eth_onboarding_step.tsx19
-rw-r--r--packages/website/ts/components/ui/balance.tsx27
-rw-r--r--packages/website/ts/components/ui/container.tsx14
-rw-r--r--packages/website/ts/components/wallet/wallet.tsx12
-rw-r--r--packages/website/ts/types.ts7
-rw-r--r--packages/website/ts/utils/configs.ts43
-rw-r--r--packages/website/ts/utils/utils.ts14
18 files changed, 866 insertions, 176 deletions
diff --git a/packages/website/ts/artifacts/Exchange.json b/packages/website/ts/artifacts/Exchange.json
new file mode 100644
index 000000000..af8db7360
--- /dev/null
+++ b/packages/website/ts/artifacts/Exchange.json
@@ -0,0 +1,610 @@
+{
+ "contract_name": "Exchange",
+ "abi": [
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "numerator",
+ "type": "uint256"
+ },
+ {
+ "name": "denominator",
+ "type": "uint256"
+ },
+ {
+ "name": "target",
+ "type": "uint256"
+ }
+ ],
+ "name": "isRoundingError",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "name": "filled",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "name": "cancelled",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "orderAddresses",
+ "type": "address[5][]"
+ },
+ {
+ "name": "orderValues",
+ "type": "uint256[6][]"
+ },
+ {
+ "name": "fillTakerTokenAmount",
+ "type": "uint256"
+ },
+ {
+ "name": "shouldThrowOnInsufficientBalanceOrAllowance",
+ "type": "bool"
+ },
+ {
+ "name": "v",
+ "type": "uint8[]"
+ },
+ {
+ "name": "r",
+ "type": "bytes32[]"
+ },
+ {
+ "name": "s",
+ "type": "bytes32[]"
+ }
+ ],
+ "name": "fillOrdersUpTo",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "orderAddresses",
+ "type": "address[5]"
+ },
+ {
+ "name": "orderValues",
+ "type": "uint256[6]"
+ },
+ {
+ "name": "cancelTakerTokenAmount",
+ "type": "uint256"
+ }
+ ],
+ "name": "cancelOrder",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "ZRX_TOKEN_CONTRACT",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "orderAddresses",
+ "type": "address[5][]"
+ },
+ {
+ "name": "orderValues",
+ "type": "uint256[6][]"
+ },
+ {
+ "name": "fillTakerTokenAmounts",
+ "type": "uint256[]"
+ },
+ {
+ "name": "v",
+ "type": "uint8[]"
+ },
+ {
+ "name": "r",
+ "type": "bytes32[]"
+ },
+ {
+ "name": "s",
+ "type": "bytes32[]"
+ }
+ ],
+ "name": "batchFillOrKillOrders",
+ "outputs": [],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "orderAddresses",
+ "type": "address[5]"
+ },
+ {
+ "name": "orderValues",
+ "type": "uint256[6]"
+ },
+ {
+ "name": "fillTakerTokenAmount",
+ "type": "uint256"
+ },
+ {
+ "name": "v",
+ "type": "uint8"
+ },
+ {
+ "name": "r",
+ "type": "bytes32"
+ },
+ {
+ "name": "s",
+ "type": "bytes32"
+ }
+ ],
+ "name": "fillOrKillOrder",
+ "outputs": [],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "orderHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "getUnavailableTakerTokenAmount",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "signer",
+ "type": "address"
+ },
+ {
+ "name": "hash",
+ "type": "bytes32"
+ },
+ {
+ "name": "v",
+ "type": "uint8"
+ },
+ {
+ "name": "r",
+ "type": "bytes32"
+ },
+ {
+ "name": "s",
+ "type": "bytes32"
+ }
+ ],
+ "name": "isValidSignature",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "numerator",
+ "type": "uint256"
+ },
+ {
+ "name": "denominator",
+ "type": "uint256"
+ },
+ {
+ "name": "target",
+ "type": "uint256"
+ }
+ ],
+ "name": "getPartialAmount",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "TOKEN_TRANSFER_PROXY_CONTRACT",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "orderAddresses",
+ "type": "address[5][]"
+ },
+ {
+ "name": "orderValues",
+ "type": "uint256[6][]"
+ },
+ {
+ "name": "fillTakerTokenAmounts",
+ "type": "uint256[]"
+ },
+ {
+ "name": "shouldThrowOnInsufficientBalanceOrAllowance",
+ "type": "bool"
+ },
+ {
+ "name": "v",
+ "type": "uint8[]"
+ },
+ {
+ "name": "r",
+ "type": "bytes32[]"
+ },
+ {
+ "name": "s",
+ "type": "bytes32[]"
+ }
+ ],
+ "name": "batchFillOrders",
+ "outputs": [],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "orderAddresses",
+ "type": "address[5][]"
+ },
+ {
+ "name": "orderValues",
+ "type": "uint256[6][]"
+ },
+ {
+ "name": "cancelTakerTokenAmounts",
+ "type": "uint256[]"
+ }
+ ],
+ "name": "batchCancelOrders",
+ "outputs": [],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "orderAddresses",
+ "type": "address[5]"
+ },
+ {
+ "name": "orderValues",
+ "type": "uint256[6]"
+ },
+ {
+ "name": "fillTakerTokenAmount",
+ "type": "uint256"
+ },
+ {
+ "name": "shouldThrowOnInsufficientBalanceOrAllowance",
+ "type": "bool"
+ },
+ {
+ "name": "v",
+ "type": "uint8"
+ },
+ {
+ "name": "r",
+ "type": "bytes32"
+ },
+ {
+ "name": "s",
+ "type": "bytes32"
+ }
+ ],
+ "name": "fillOrder",
+ "outputs": [
+ {
+ "name": "filledTakerTokenAmount",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "orderAddresses",
+ "type": "address[5]"
+ },
+ {
+ "name": "orderValues",
+ "type": "uint256[6]"
+ }
+ ],
+ "name": "getOrderHash",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "EXTERNAL_QUERY_GAS_LIMIT",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint16"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "VERSION",
+ "outputs": [
+ {
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "payable": false,
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "name": "_zrxToken",
+ "type": "address"
+ },
+ {
+ "name": "_tokenTransferProxy",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "type": "constructor"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "maker",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "taker",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "feeRecipient",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "makerToken",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "takerToken",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "filledMakerTokenAmount",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "name": "filledTakerTokenAmount",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "name": "paidMakerFee",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "name": "paidTakerFee",
+ "type": "uint256"
+ },
+ {
+ "indexed": true,
+ "name": "tokens",
+ "type": "bytes32"
+ },
+ {
+ "indexed": false,
+ "name": "orderHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "LogFill",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "maker",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "feeRecipient",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "makerToken",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "takerToken",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "cancelledMakerTokenAmount",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "name": "cancelledTakerTokenAmount",
+ "type": "uint256"
+ },
+ {
+ "indexed": true,
+ "name": "tokens",
+ "type": "bytes32"
+ },
+ {
+ "indexed": false,
+ "name": "orderHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "LogCancel",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "errorId",
+ "type": "uint8"
+ },
+ {
+ "indexed": true,
+ "name": "orderHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "LogError",
+ "type": "event"
+ }
+ ],
+ "networks": {
+ "1": {
+ "address": "0x12459c951127e0c374ff9105dda097662a027093"
+ },
+ "3": {
+ "address": "0x479cc461fecd078f766ecc58533d6f69580cf3ac"
+ },
+ "4": {
+ "address": "0x1d16ef40fac01cec8adac2ac49427b9384192c05"
+ },
+ "42": {
+ "address": "0x90fe2af704b34e0224bf2299c838e04d4dcf1364"
+ },
+ "50": {
+ "address": "0x48bacb9266a570d521063ef5dd96e61686dbe788"
+ }
+ }
+}
diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts
index cc2afa28a..fde134b18 100644
--- a/packages/website/ts/blockchain.ts
+++ b/packages/website/ts/blockchain.ts
@@ -66,6 +66,9 @@ import RpcSubprovider = require('web3-provider-engine/subproviders/rpc');
import * as MintableArtifacts from '../contracts/Mintable.json';
+// HACK: remove this hard-coded abi and use @0xproject/contract-wrappers
+import * as Exchange from './artifacts/Exchange.json';
+
const BLOCK_NUMBER_BACK_TRACK = 50;
const GWEI_IN_WEI = 1000000000;
@@ -89,6 +92,7 @@ export class Blockchain {
private _userAddressIfExists: string;
private _ledgerSubprovider: LedgerSubprovider;
private _defaultGasPrice: BigNumber;
+ private _watchGasPriceIntervalId: NodeJS.Timer;
private static _getNameGivenProvider(provider: Provider): string {
const providerType = utils.getProviderType(provider);
const providerNameIfExists = providerToName[providerType];
@@ -196,13 +200,11 @@ export class Blockchain {
}
constructor(dispatcher: Dispatcher) {
this._dispatcher = dispatcher;
- const defaultGasPrice = GWEI_IN_WEI * 30;
+ const defaultGasPrice = GWEI_IN_WEI * 40;
this._defaultGasPrice = new BigNumber(defaultGasPrice);
// We need a unique reference to this function so we can use it to unsubcribe.
this._injectedProviderUpdateHandler = this._handleInjectedProviderUpdateAsync.bind(this);
// tslint:disable-next-line:no-floating-promises
- this._updateDefaultGasPriceAsync();
- // tslint:disable-next-line:no-floating-promises
this._onPageLoadInitFireAndForgetAsync();
}
public async networkIdUpdatedFireAndForgetAsync(newNetworkId: number): Promise<void> {
@@ -537,6 +539,7 @@ export class Blockchain {
this._blockchainWatcher.destroy();
this._injectedProviderObservable.unsubscribe(this._injectedProviderUpdateHandler);
this._stopWatchingExchangeLogFillEvents();
+ this._stopWatchingGasPrice();
}
public async fetchTokenInformationAsync(): Promise<void> {
utils.assert(
@@ -624,7 +627,9 @@ export class Blockchain {
);
const provider = this._contractWrappers.getProvider();
const web3Wrapper = new Web3Wrapper(provider);
- web3Wrapper.abiDecoder.addABI(this._contractWrappers.exchange.abi);
+ // HACK: remove this hard-coded abi and use @0xproject/contract-wrappers
+ const exchangeAbi = _.get(Exchange, 'abi', []);
+ web3Wrapper.abiDecoder.addABI(exchangeAbi);
const receipt = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
return receipt;
}
@@ -769,7 +774,7 @@ export class Blockchain {
_.each(tokenRegistryTokens, (t: ZeroExToken) => {
// HACK: For now we have a hard-coded list of iconUrls for the dummyTokens
// TODO: Refactor this out and pull the iconUrl directly from the TokenRegistry
- const iconUrl = configs.ICON_URL_BY_SYMBOL[t.symbol];
+ const iconUrl = utils.getTokenIconUrl(t.symbol);
const token: Token = {
iconUrl,
address: t.address,
@@ -798,8 +803,30 @@ export class Blockchain {
this._updateProviderName(injectedWeb3IfExists);
const shouldPollUserAddress = true;
const shouldUseLedgerProvider = false;
+ this._startWatchingGasPrice();
await this._resetOrInitializeAsync(this.networkId, shouldPollUserAddress, shouldUseLedgerProvider);
}
+ private _startWatchingGasPrice(): void {
+ if (!_.isUndefined(this._watchGasPriceIntervalId)) {
+ return; // we are already watching
+ }
+ const oneMinuteInMs = 60000;
+ // tslint:disable-next-line:no-floating-promises
+ this._updateDefaultGasPriceAsync();
+ this._watchGasPriceIntervalId = intervalUtils.setAsyncExcludingInterval(
+ this._updateDefaultGasPriceAsync.bind(this),
+ oneMinuteInMs,
+ (err: Error) => {
+ logUtils.log(`Watching gas price failed: ${err.stack}`);
+ this._stopWatchingGasPrice();
+ },
+ );
+ }
+ private _stopWatchingGasPrice(): void {
+ if (!_.isUndefined(this._watchGasPriceIntervalId)) {
+ intervalUtils.clearAsyncExcludingInterval(this._watchGasPriceIntervalId);
+ }
+ }
private async _resetOrInitializeAsync(
networkId: number,
shouldPollUserAddress: boolean = false,
@@ -895,7 +922,7 @@ export class Blockchain {
private async _updateDefaultGasPriceAsync(): Promise<void> {
try {
const gasInfo = await backendClient.getGasInfoAsync();
- const gasPriceInGwei = new BigNumber(gasInfo.average / 10);
+ const gasPriceInGwei = new BigNumber(gasInfo.fast / 10);
const gasPriceInWei = gasPriceInGwei.mul(1000000000);
this._defaultGasPrice = gasPriceInWei;
} catch (err) {
diff --git a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx
index 38e4732a4..d2f373d67 100644
--- a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx
+++ b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx
@@ -29,7 +29,7 @@ interface LedgerConfigDialogProps {
toggleDialogFn: (isOpen: boolean) => void;
dispatcher: Dispatcher;
blockchain: Blockchain;
- networkId: number;
+ networkId?: number;
providerType: ProviderType;
}
@@ -44,6 +44,9 @@ interface LedgerConfigDialogState {
}
export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps, LedgerConfigDialogState> {
+ public static defaultProps = {
+ networkId: 1,
+ };
constructor(props: LedgerConfigDialogProps) {
super(props);
const derivationPathIfExists = props.blockchain.getLedgerDerivationPathIfExists();
diff --git a/packages/website/ts/components/eth_wrappers.tsx b/packages/website/ts/components/eth_wrappers.tsx
index 20b446155..0b282b2a1 100644
--- a/packages/website/ts/components/eth_wrappers.tsx
+++ b/packages/website/ts/components/eth_wrappers.tsx
@@ -20,6 +20,7 @@ import {
} from 'ts/types';
import { configs } from 'ts/utils/configs';
import { constants } from 'ts/utils/constants';
+import { utils } from 'ts/utils/utils';
const DATE_FORMAT = 'D/M/YY';
const ICON_DIMENSION = 40;
@@ -95,7 +96,11 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
this.props.networkId,
EtherscanLinkSuffixes.Address,
);
- const tokenLabel = this._renderToken('Wrapped Ether', etherToken.address, configs.ICON_URL_BY_SYMBOL.WETH);
+ const tokenLabel = this._renderToken(
+ 'Wrapped Ether',
+ etherToken.address,
+ utils.getTokenIconUrl(etherToken.symbol),
+ );
const userEtherBalanceInEth = !_.isUndefined(this.props.userEtherBalanceInWei)
? Web3Wrapper.toUnitAmount(this.props.userEtherBalanceInWei, constants.DECIMAL_PLACES_ETH)
: undefined;
diff --git a/packages/website/ts/components/generate_order/asset_picker.tsx b/packages/website/ts/components/generate_order/asset_picker.tsx
index 3d53a9e7d..5eada37b6 100644
--- a/packages/website/ts/components/generate_order/asset_picker.tsx
+++ b/packages/website/ts/components/generate_order/asset_picker.tsx
@@ -3,6 +3,8 @@ import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton';
import * as moment from 'moment';
import * as React from 'react';
+import firstBy = require('thenby');
+
import { Blockchain } from 'ts/blockchain';
import { NewTokenForm } from 'ts/components/generate_order/new_token_form';
import { TrackTokenConfirmation } from 'ts/components/track_token_confirmation';
@@ -87,10 +89,10 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
return (
<Dialog
title={dialogConfigs.title}
- titleStyle={{ fontWeight: 100 }}
modal={dialogConfigs.isModal}
open={this.props.isOpen}
actions={dialogConfigs.actions}
+ autoScrollBodyContent={true}
onRequestClose={this._onCloseDialog.bind(this)}
>
{this.state.assetView === AssetViews.ASSET_PICKER && this._renderAssetPicker()}
@@ -121,9 +123,8 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
<div
className="flex flex-wrap"
style={{
- overflowY: 'auto',
- maxWidth: 720,
- maxHeight: 356,
+ maxWidth: 1000,
+ maxHeight: 600,
marginBottom: 10,
}}
>
@@ -134,15 +135,28 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
private _renderGridTiles(): React.ReactNode {
let isHovered;
let tileStyles;
- const gridTiles = _.map(this.props.tokenByAddress, (token: Token, address: string) => {
- if (
- (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
- ) {
- return null; // Skip
- }
+ const allTokens = _.values(this.props.tokenByAddress);
+ // filter tokens based on visibility specified in props, do not show ZRX or ETHER as tracked or untracked
+ const filteredTokens =
+ this.props.tokenVisibility === TokenVisibility.ALL
+ ? allTokens
+ : _.filter(allTokens, token => {
+ return (
+ token.symbol !== constants.ZRX_TOKEN_SYMBOL &&
+ token.symbol !== constants.ETHER_TOKEN_SYMBOL &&
+ ((this.props.tokenVisibility === TokenVisibility.TRACKED && utils.isTokenTracked(token)) ||
+ (this.props.tokenVisibility === TokenVisibility.UNTRACKED &&
+ !utils.isTokenTracked(token)))
+ );
+ });
+ // if we are showing tracked tokens, sort by date added, otherwise sort by symbol
+ const sortKey = this.props.tokenVisibility === TokenVisibility.TRACKED ? 'trackedTimestamp' : 'symbol';
+ const sortedTokens = filteredTokens.sort(firstBy(sortKey));
+ if (_.isEmpty(sortedTokens)) {
+ return <div className="mx-auto p4 h2">No tokens to remove.</div>;
+ }
+ const gridTiles = _.map(sortedTokens, token => {
+ const address = token.address;
isHovered = this.state.hoveredAddress === address;
tileStyles = {
cursor: 'pointer',
diff --git a/packages/website/ts/components/onboarding/add_eth_onboarding_step.tsx b/packages/website/ts/components/onboarding/add_eth_onboarding_step.tsx
index bccdc0c18..ca71fcd50 100644
--- a/packages/website/ts/components/onboarding/add_eth_onboarding_step.tsx
+++ b/packages/website/ts/components/onboarding/add_eth_onboarding_step.tsx
@@ -1,10 +1,10 @@
import { BigNumber } from '@0xproject/utils';
import * as React from 'react';
+import { Balance } from 'ts/components/ui/balance';
import { Container } from 'ts/components/ui/container';
import { Image } from 'ts/components/ui/image';
import { Text } from 'ts/components/ui/text';
import { constants } from 'ts/utils/constants';
-import { utils } from 'ts/utils/utils';
export interface AddEthOnboardingStepProps {
userEthBalanceInWei: BigNumber;
@@ -15,13 +15,11 @@ export const AddEthOnboardingStep: React.StatelessComponent<AddEthOnboardingStep
<div className="flex items-center flex-column">
<Text>
Great! Looks like you already have{' '}
- <b>
- {utils.getFormattedAmount(
- props.userEthBalanceInWei,
- constants.DECIMAL_PLACES_ETH,
- constants.ETHER_SYMBOL,
- )}{' '}
- </b>
+ <Balance
+ amount={props.userEthBalanceInWei}
+ decimals={constants.DECIMAL_PLACES_ETH}
+ symbol={constants.ETHER_SYMBOL}
+ />{' '}
in your wallet.
</Text>
<Container marginTop="15px" marginBottom="15px">
diff --git a/packages/website/ts/components/onboarding/onboarding_card.tsx b/packages/website/ts/components/onboarding/onboarding_card.tsx
index ba5b3d6ea..e1b0f304b 100644
--- a/packages/website/ts/components/onboarding/onboarding_card.tsx
+++ b/packages/website/ts/components/onboarding/onboarding_card.tsx
@@ -12,6 +12,7 @@ export type ContinueButtonDisplay = 'enabled' | 'disabled';
export interface OnboardingCardProps {
title?: string;
+ shouldCenterTitle?: boolean;
content: React.ReactNode;
isLastStep: boolean;
onClose: () => void;
@@ -23,10 +24,13 @@ export interface OnboardingCardProps {
shouldHideNextButton?: boolean;
continueButtonText?: string;
borderRadius?: string;
+ // Used for super-custom content.
+ shouldRemoveExtraSpacing?: boolean;
}
export const OnboardingCard: React.StatelessComponent<OnboardingCardProps> = ({
title,
+ shouldCenterTitle,
content,
continueButtonDisplay,
continueButtonText,
@@ -37,55 +41,75 @@ export const OnboardingCard: React.StatelessComponent<OnboardingCardProps> = ({
shouldHideBackButton,
shouldHideNextButton,
borderRadius,
-}) => (
- <Island borderRadius={borderRadius}>
- <Container paddingRight="30px" paddingLeft="30px" paddingTop="15px" paddingBottom="15px">
- <div className="flex flex-column">
- <div className="flex justify-between">
- <Title>{title}</Title>
- <Container position="relative" bottom="20px" left="15px">
- <IconButton color={colors.grey} iconName="zmdi-close" onClick={onClose}>
- Close
- </IconButton>
+ shouldRemoveExtraSpacing,
+}) => {
+ const padding = shouldRemoveExtraSpacing
+ ? {}
+ : {
+ paddingRight: '30px',
+ paddingLeft: '30px',
+ paddingTop: '15px',
+ paddingBottom: '15px',
+ };
+ const closeIconPositioning = shouldRemoveExtraSpacing
+ ? { right: '15px', bottom: '3px' }
+ : { bottom: '20px', left: '15px' };
+ return (
+ <Island borderRadius={borderRadius}>
+ <Container {...padding}>
+ <div className="flex flex-column">
+ <Container className="flex justify-between">
+ <Container width="100%">
+ <Title center={shouldCenterTitle}>{title}</Title>
+ </Container>
+ <Container position="relative" {...closeIconPositioning}>
+ <IconButton color={colors.grey} iconName="zmdi-close" onClick={onClose}>
+ Close
+ </IconButton>
+ </Container>
</Container>
+ <Container marginBottom={shouldRemoveExtraSpacing ? undefined : '15px'}>
+ <Text>{content}</Text>
+ </Container>
+ {continueButtonDisplay && (
+ <Button
+ isDisabled={continueButtonDisplay === 'disabled'}
+ onClick={!_.isUndefined(onContinueButtonClick) ? onContinueButtonClick : onClickNext}
+ fontColor={colors.white}
+ fontSize="15px"
+ backgroundColor={colors.mediumBlue}
+ >
+ {continueButtonText}
+ </Button>
+ )}
+ {!(shouldHideBackButton && shouldHideNextButton) && (
+ <Container className="clearfix" marginTop="15px">
+ <div className="left">
+ {!shouldHideBackButton && (
+ <Text fontColor={colors.grey} onClick={onClickBack}>
+ Back
+ </Text>
+ )}
+ </div>
+ <div className="right">
+ {!shouldHideNextButton && (
+ <Text fontColor={colors.grey} onClick={onClickNext}>
+ Skip
+ </Text>
+ )}
+ </div>
+ </Container>
+ )}
</div>
- <Container marginBottom="15px">
- <Text>{content}</Text>
- </Container>
- {continueButtonDisplay && (
- <Button
- isDisabled={continueButtonDisplay === 'disabled'}
- onClick={!_.isUndefined(onContinueButtonClick) ? onContinueButtonClick : onClickNext}
- fontColor={colors.white}
- fontSize="15px"
- backgroundColor={colors.mediumBlue}
- >
- {continueButtonText}
- </Button>
- )}
- <Container className="clearfix" marginTop="15px">
- <div className="left">
- {!shouldHideBackButton && (
- <Text fontColor={colors.grey} onClick={onClickBack}>
- Back
- </Text>
- )}
- </div>
- <div className="right">
- {!shouldHideNextButton && (
- <Text fontColor={colors.grey} onClick={onClickNext}>
- Skip
- </Text>
- )}
- </div>
- </Container>
- </div>
- </Container>
- </Island>
-);
+ </Container>
+ </Island>
+ );
+};
OnboardingCard.defaultProps = {
continueButtonText: 'Continue',
+ shouldCenterTitle: false,
+ shouldRemoveExtraSpacing: false,
};
OnboardingCard.displayName = 'OnboardingCard';
diff --git a/packages/website/ts/components/onboarding/onboarding_flow.tsx b/packages/website/ts/components/onboarding/onboarding_flow.tsx
index c2b4a4ca7..91d5f2476 100644
--- a/packages/website/ts/components/onboarding/onboarding_flow.tsx
+++ b/packages/website/ts/components/onboarding/onboarding_flow.tsx
@@ -2,11 +2,14 @@ import * as React from 'react';
import { Placement, Popper, PopperChildrenProps } from 'react-popper';
import { OnboardingCard } from 'ts/components/onboarding/onboarding_card';
-import { ContinueButtonDisplay, OnboardingTooltip } from 'ts/components/onboarding/onboarding_tooltip';
+import {
+ ContinueButtonDisplay,
+ OnboardingTooltip,
+ TooltipPointerDisplay,
+} from 'ts/components/onboarding/onboarding_tooltip';
import { Animation } from 'ts/components/ui/animation';
import { Container } from 'ts/components/ui/container';
import { Overlay } from 'ts/components/ui/overlay';
-import { PointerDirection } from 'ts/components/ui/pointer';
import { zIndex } from 'ts/style/z_index';
export interface FixedPositionSettings {
@@ -15,7 +18,7 @@ export interface FixedPositionSettings {
bottom?: string;
left?: string;
right?: string;
- pointerDirection?: PointerDirection;
+ tooltipPointerDisplay?: TooltipPointerDisplay;
}
export interface TargetPositionSettings {
@@ -28,12 +31,15 @@ export interface Step {
// Provide either a CSS selector, or fixed position settings. Only applies to desktop.
position: TargetPositionSettings | FixedPositionSettings;
title?: string;
+ shouldCenterTitle?: boolean;
content: React.ReactNode;
shouldHideBackButton?: boolean;
shouldHideNextButton?: boolean;
continueButtonDisplay?: ContinueButtonDisplay;
continueButtonText?: string;
onContinueButtonClick?: () => void;
+ // Only used for very custom steps.
+ shouldRemoveExtraSpacing?: boolean;
}
export interface OnboardingFlowProps {
@@ -44,12 +50,14 @@ export interface OnboardingFlowProps {
updateOnboardingStep: (stepIndex: number) => void;
disableOverlay?: boolean;
isMobile: boolean;
+ disableCloseOnClickOutside?: boolean;
}
export class OnboardingFlow extends React.Component<OnboardingFlowProps> {
public static defaultProps = {
disableOverlay: false,
isMobile: false,
+ disableCloseOnClickOutside: false,
};
public render(): React.ReactNode {
if (!this.props.isRunning) {
@@ -67,7 +75,7 @@ export class OnboardingFlow extends React.Component<OnboardingFlowProps> {
</Popper>
);
} else if (currentStep.position.type === 'fixed') {
- const { top, right, bottom, left, pointerDirection } = currentStep.position;
+ const { top, right, bottom, left, tooltipPointerDisplay } = currentStep.position;
onboardingElement = (
<Container
position="fixed"
@@ -77,7 +85,7 @@ export class OnboardingFlow extends React.Component<OnboardingFlowProps> {
bottom={bottom}
left={left}
>
- {this._renderToolTip(pointerDirection)}
+ {this._renderToolTip(tooltipPointerDisplay)}
</Container>
);
}
@@ -86,7 +94,7 @@ export class OnboardingFlow extends React.Component<OnboardingFlowProps> {
}
return (
<div>
- <Overlay onClick={this.props.onClose} />
+ <Overlay onClick={this.props.disableCloseOnClickOutside ? undefined : this.props.onClose} />
{onboardingElement}
</div>
);
@@ -101,7 +109,7 @@ export class OnboardingFlow extends React.Component<OnboardingFlowProps> {
</div>
);
}
- private _renderToolTip(pointerDirection?: PointerDirection): React.ReactNode {
+ private _renderToolTip(tooltipPointerDisplay?: TooltipPointerDisplay): React.ReactNode {
const { steps, stepIndex } = this.props;
const step = steps[stepIndex];
const isLastStep = steps.length - 1 === stepIndex;
@@ -109,6 +117,7 @@ export class OnboardingFlow extends React.Component<OnboardingFlowProps> {
<Container marginLeft="30px" width="400px">
<OnboardingTooltip
title={step.title}
+ shouldCenterTitle={step.shouldCenterTitle}
content={step.content}
isLastStep={isLastStep}
shouldHideBackButton={step.shouldHideBackButton}
@@ -119,7 +128,8 @@ export class OnboardingFlow extends React.Component<OnboardingFlowProps> {
continueButtonDisplay={step.continueButtonDisplay}
continueButtonText={step.continueButtonText}
onContinueButtonClick={step.onContinueButtonClick}
- pointerDirection={pointerDirection}
+ pointerDisplay={tooltipPointerDisplay}
+ shouldRemoveExtraSpacing={step.shouldRemoveExtraSpacing}
/>
</Container>
);
@@ -133,6 +143,7 @@ export class OnboardingFlow extends React.Component<OnboardingFlowProps> {
<Container position="relative" zIndex={1}>
<OnboardingCard
title={step.title}
+ shouldCenterTitle={step.shouldCenterTitle}
content={step.content}
isLastStep={isLastStep}
shouldHideBackButton={step.shouldHideBackButton}
@@ -144,6 +155,7 @@ export class OnboardingFlow extends React.Component<OnboardingFlowProps> {
continueButtonText={step.continueButtonText}
onContinueButtonClick={step.onContinueButtonClick}
borderRadius="10px 10px 0px 0px"
+ shouldRemoveExtraSpacing={step.shouldRemoveExtraSpacing}
/>
</Container>
);
diff --git a/packages/website/ts/components/onboarding/onboarding_tooltip.tsx b/packages/website/ts/components/onboarding/onboarding_tooltip.tsx
index d8065625d..15d47908d 100644
--- a/packages/website/ts/components/onboarding/onboarding_tooltip.tsx
+++ b/packages/website/ts/components/onboarding/onboarding_tooltip.tsx
@@ -4,22 +4,27 @@ import { OnboardingCard, OnboardingCardProps } from 'ts/components/onboarding/on
import { Pointer, PointerDirection } from 'ts/components/ui/pointer';
export type ContinueButtonDisplay = 'enabled' | 'disabled';
+export type TooltipPointerDisplay = PointerDirection | 'none';
export interface OnboardingTooltipProps extends OnboardingCardProps {
className?: string;
- pointerDirection?: PointerDirection;
+ pointerDisplay?: TooltipPointerDisplay;
}
export const OnboardingTooltip: React.StatelessComponent<OnboardingTooltipProps> = props => {
- const { pointerDirection, className, ...cardProps } = props;
+ const { pointerDisplay, className, ...cardProps } = props;
+ const card = <OnboardingCard {...cardProps} />;
+ if (pointerDisplay === 'none') {
+ return card;
+ }
return (
- <Pointer className={className} direction={pointerDirection}>
+ <Pointer className={className} direction={pointerDisplay}>
<OnboardingCard {...cardProps} />
</Pointer>
);
};
OnboardingTooltip.defaultProps = {
- pointerDirection: 'left',
+ pointerDisplay: 'left',
};
OnboardingTooltip.displayName = 'OnboardingTooltip';
diff --git a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx
index 1c2c92fd1..20a8f0a32 100644
--- a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx
+++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx
@@ -23,7 +23,7 @@ import {
WrapEthOnboardingStep3,
} from 'ts/components/onboarding/wrap_eth_onboarding_step';
import { AllowanceToggle } from 'ts/containers/inputs/allowance_toggle';
-import { ProviderType, ScreenWidths, Token, TokenByAddress, TokenStateByAddress } from 'ts/types';
+import { BrowserType, ProviderType, ScreenWidths, Token, TokenByAddress, TokenStateByAddress } from 'ts/types';
import { analytics } from 'ts/utils/analytics';
import { utils } from 'ts/utils/utils';
@@ -68,6 +68,7 @@ class PlainPortalOnboardingFlow extends React.Component<PortalOnboardingFlowProp
}
}
public render(): React.ReactNode {
+ const browserType = utils.getBrowserType();
return (
<OnboardingFlow
steps={this._getSteps()}
@@ -77,6 +78,8 @@ class PlainPortalOnboardingFlow extends React.Component<PortalOnboardingFlowProp
updateOnboardingStep={this._updateOnboardingStep.bind(this)}
disableOverlay={this.props.screenWidth === ScreenWidths.Sm}
isMobile={this.props.screenWidth === ScreenWidths.Sm}
+ // This is necessary to ensure onboarding stays open once the user unlocks metamask and clicks away
+ disableCloseOnClickOutside={browserType === BrowserType.Firefox || browserType === BrowserType.Opera}
/>
);
}
@@ -88,9 +91,9 @@ class PlainPortalOnboardingFlow extends React.Component<PortalOnboardingFlowProp
};
const underMetamaskExtension: FixedPositionSettings = {
type: 'fixed',
- top: '30px',
+ top: '10px',
right: '10px',
- pointerDirection: 'top',
+ tooltipPointerDisplay: 'none',
};
const steps: Step[] = [
{
@@ -102,10 +105,12 @@ class PlainPortalOnboardingFlow extends React.Component<PortalOnboardingFlowProp
},
{
position: underMetamaskExtension,
- title: '0x Ecosystem Setup',
+ title: 'Please Unlock Metamask...',
content: <UnlockWalletOnboardingStep />,
shouldHideBackButton: true,
shouldHideNextButton: true,
+ shouldCenterTitle: true,
+ shouldRemoveExtraSpacing: true,
},
{
position: nextToWalletPosition,
@@ -137,13 +142,7 @@ class PlainPortalOnboardingFlow extends React.Component<PortalOnboardingFlowProp
{
position: nextToWalletPosition,
title: 'Step 2: Wrap ETH',
- content: (
- <WrapEthOnboardingStep3
- formattedWethBalanceIfExists={
- this._userHasVisibleWeth() ? this._getFormattedWethBalance() : undefined
- }
- />
- ),
+ content: <WrapEthOnboardingStep3 wethAmount={this._getWethBalance()} />,
continueButtonDisplay: this._userHasVisibleWeth() ? 'enabled' : 'disabled',
},
{
@@ -184,11 +183,6 @@ class PlainPortalOnboardingFlow extends React.Component<PortalOnboardingFlowProp
const ethTokenState = this.props.trackedTokenStateByAddress[ethToken.address];
return ethTokenState.balance;
}
- private _getFormattedWethBalance(): string {
- const ethToken = utils.getEthToken(this.props.tokenByAddress);
- const ethTokenState = this.props.trackedTokenStateByAddress[ethToken.address];
- return utils.getFormattedAmountFromToken(ethToken, ethTokenState);
- }
private _userHasVisibleWeth(): boolean {
return this._getWethBalance() > new BigNumber(0);
}
diff --git a/packages/website/ts/components/onboarding/unlock_wallet_onboarding_step.tsx b/packages/website/ts/components/onboarding/unlock_wallet_onboarding_step.tsx
index 4ed7137d4..358141520 100644
--- a/packages/website/ts/components/onboarding/unlock_wallet_onboarding_step.tsx
+++ b/packages/website/ts/components/onboarding/unlock_wallet_onboarding_step.tsx
@@ -1,16 +1,8 @@
import * as React from 'react';
-import { Container } from 'ts/components/ui/container';
-import { Text } from 'ts/components/ui/text';
+import { Image } from 'ts/components/ui/image';
export interface UnlockWalletOnboardingStepProps {}
export const UnlockWalletOnboardingStep: React.StatelessComponent<UnlockWalletOnboardingStepProps> = () => (
- <div className="flex items-center flex-column">
- <div className="flex items-center flex-column">
- <Container marginTop="15px" marginBottom="15px">
- <img src="/images/metamask_icon.png" height="50px" width="50px" />
- </Container>
- <Text center={true}>Unlock your MetaMask extension to get started.</Text>
- </div>
- </div>
+ <Image src="/images/unlock-mm.png" />
);
diff --git a/packages/website/ts/components/onboarding/wrap_eth_onboarding_step.tsx b/packages/website/ts/components/onboarding/wrap_eth_onboarding_step.tsx
index 4d336c80f..e4332de75 100644
--- a/packages/website/ts/components/onboarding/wrap_eth_onboarding_step.tsx
+++ b/packages/website/ts/components/onboarding/wrap_eth_onboarding_step.tsx
@@ -1,8 +1,11 @@
import { colors } from '@0xproject/react-shared';
+import { BigNumber } from '@0xproject/utils';
import * as React from 'react';
+import { Balance } from 'ts/components/ui/balance';
import { Container } from 'ts/components/ui/container';
import { IconButton } from 'ts/components/ui/icon_button';
import { Text } from 'ts/components/ui/text';
+import { constants } from 'ts/utils/constants';
export interface WrapEthOnboardingStep1Props {}
@@ -51,16 +54,20 @@ export const WrapEthOnboardingStep2: React.StatelessComponent<WrapEthOnboardingS
);
export interface WrapEthOnboardingStep3Props {
- formattedWethBalanceIfExists?: string;
+ wethAmount: BigNumber;
}
-export const WrapEthOnboardingStep3: React.StatelessComponent<WrapEthOnboardingStep3Props> = ({
- formattedWethBalanceIfExists,
-}) => (
+export const WrapEthOnboardingStep3: React.StatelessComponent<WrapEthOnboardingStep3Props> = ({ wethAmount }) => (
<div className="flex items-center flex-column">
<Text>
- You have <b>{formattedWethBalanceIfExists || '0 WETH'}</b> in your wallet.
- {formattedWethBalanceIfExists && ' Great!'}
+ You have{' '}
+ <Balance
+ amount={wethAmount}
+ decimals={constants.DECIMAL_PLACES_ETH}
+ symbol={constants.ETHER_TOKEN_SYMBOL}
+ />{' '}
+ in your wallet.
+ {wethAmount.gt(0) && ' Great!'}
</Text>
<Container width="100%" marginTop="25px" marginBottom="15px" className="flex justify-center">
<div className="flex flex-column items-center">
diff --git a/packages/website/ts/components/ui/balance.tsx b/packages/website/ts/components/ui/balance.tsx
new file mode 100644
index 000000000..9e5a256b6
--- /dev/null
+++ b/packages/website/ts/components/ui/balance.tsx
@@ -0,0 +1,27 @@
+import { BigNumber } from '@0xproject/utils';
+import * as React from 'react';
+import { Container } from 'ts/components/ui/container';
+import { Text } from 'ts/components/ui/text';
+import { utils } from 'ts/utils/utils';
+
+export interface BalanceProps {
+ amount: BigNumber;
+ decimals: number;
+ symbol: string;
+}
+
+export const Balance: React.StatelessComponent<BalanceProps> = ({ amount, decimals, symbol }) => {
+ const formattedAmout = utils.getFormattedAmount(amount, decimals);
+ return (
+ <span>
+ <Text Tag="span" fontSize="16px" fontWeight="700" lineHeight="1em">
+ {formattedAmout}
+ </Text>
+ <Container marginLeft="0.3em" Tag="span">
+ <Text Tag="span" fontSize="12px" fontWeight="700" lineHeight="1em">
+ {symbol}
+ </Text>
+ </Container>
+ </span>
+ );
+};
diff --git a/packages/website/ts/components/ui/container.tsx b/packages/website/ts/components/ui/container.tsx
index edbf8814b..427cc6cc7 100644
--- a/packages/website/ts/components/ui/container.tsx
+++ b/packages/website/ts/components/ui/container.tsx
@@ -2,6 +2,8 @@ import * as React from 'react';
type StringOrNum = string | number;
+export type ContainerTag = 'div' | 'span';
+
export interface ContainerProps {
marginTop?: StringOrNum;
marginBottom?: StringOrNum;
@@ -28,15 +30,21 @@ export interface ContainerProps {
right?: string;
bottom?: string;
zIndex?: number;
+ Tag?: ContainerTag;
}
-export const Container: React.StatelessComponent<ContainerProps> = ({ children, className, isHidden, ...style }) => {
+export const Container: React.StatelessComponent<ContainerProps> = props => {
+ const { children, className, Tag, isHidden, ...style } = props;
const visibility = isHidden ? 'hidden' : undefined;
return (
- <div style={{ ...style, visibility }} className={className}>
+ <Tag style={{ ...style, visibility }} className={className}>
{children}
- </div>
+ </Tag>
);
};
+Container.defaultProps = {
+ Tag: 'div',
+};
+
Container.displayName = 'Container';
diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx
index de3b91ad0..6c1c495d7 100644
--- a/packages/website/ts/components/wallet/wallet.tsx
+++ b/packages/website/ts/components/wallet/wallet.tsx
@@ -8,6 +8,7 @@ import firstBy = require('thenby');
import { Blockchain } from 'ts/blockchain';
import { AccountConnection } from 'ts/components/ui/account_connection';
+import { Balance } from 'ts/components/ui/balance';
import { Container } from 'ts/components/ui/container';
import { DropDown, DropdownMouseEvent } from 'ts/components/ui/drop_down';
import { IconButton } from 'ts/components/ui/icon_button';
@@ -269,8 +270,8 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
position: 'relative',
overflowY: this.state.isHoveringSidebar ? 'scroll' : 'hidden',
marginRight: this.state.isHoveringSidebar ? 0 : 4,
- // TODO: make this completely responsive
- maxHeight: this.props.screenWidth !== ScreenWidths.Sm ? 475 : undefined,
+ minHeight: '250px',
+ maxHeight: !utils.isMobileWidth(this.props.screenWidth) ? 'calc(90vh - 300px)' : undefined,
};
}
private _onSidebarHover(_event: React.FormEvent<HTMLInputElement>): void {
@@ -436,12 +437,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
</PlaceHolder>
);
} else {
- const result = utils.getFormattedAmount(amount, decimals, symbol);
- return (
- <Text fontSize="16px" fontWeight="bold" lineHeight="1em">
- {result}
- </Text>
- );
+ return <Balance amount={amount} decimals={decimals} symbol={symbol} />;
}
}
private _renderValue(
diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts
index f7324e87a..e8dc694f6 100644
--- a/packages/website/ts/types.ts
+++ b/packages/website/ts/types.ts
@@ -243,8 +243,8 @@ export enum BlockchainCallErrs {
}
export enum Environments {
- DEVELOPMENT,
- PRODUCTION,
+ DEVELOPMENT = 'DEVELOPMENT',
+ PRODUCTION = 'PRODUCTION',
}
export type ContractInstance = any; // TODO: add type definition for Contract
@@ -552,7 +552,10 @@ export interface WebsiteBackendTokenInfo {
}
export interface WebsiteBackendGasInfo {
+ safeSlow: number;
average: number;
+ fast: number;
+ fastest: number;
}
export interface WebsiteBackendJobInfo {
diff --git a/packages/website/ts/utils/configs.ts b/packages/website/ts/utils/configs.ts
index e8a486c35..97aabd13d 100644
--- a/packages/website/ts/utils/configs.ts
+++ b/packages/website/ts/utils/configs.ts
@@ -22,50 +22,9 @@ export const configs = {
DOMAIN_DEVELOPMENT: '0xproject.localhost:3572',
DOMAIN_PRODUCTION: '0xproject.com',
ENVIRONMENT: isDevelopment ? Environments.DEVELOPMENT : Environments.PRODUCTION,
- ICON_URL_BY_SYMBOL: {
- REP: '/images/token_icons/augur.png',
- DGD: '/images/token_icons/digixdao.png',
- WETH: '/images/token_icons/ether_erc20.png',
- MLN: '/images/token_icons/melon.png',
- GNT: '/images/token_icons/golem.png',
- MKR: '/images/token_icons/makerdao.png',
- ZRX: '/images/token_icons/zero_ex.png',
- ANT: '/images/token_icons/aragon.png',
- BNT: '/images/token_icons/bancor.png',
- BAT: '/images/token_icons/basicattentiontoken.png',
- CVC: '/images/token_icons/civic.png',
- EOS: '/images/token_icons/eos.png',
- FUN: '/images/token_icons/funfair.png',
- GNO: '/images/token_icons/gnosis.png',
- ICN: '/images/token_icons/iconomi.png',
- OMG: '/images/token_icons/omisego.png',
- SNT: '/images/token_icons/status.png',
- STORJ: '/images/token_icons/storjcoinx.png',
- PAY: '/images/token_icons/tenx.png',
- QTUM: '/images/token_icons/qtum.png',
- DNT: '/images/token_icons/district0x.png',
- SNGLS: '/images/token_icons/singularity.png',
- EDG: '/images/token_icons/edgeless.png',
- '1ST': '/images/token_icons/firstblood.jpg',
- WINGS: '/images/token_icons/wings.png',
- BQX: '/images/token_icons/bitquence.png',
- LUN: '/images/token_icons/lunyr.png',
- RLC: '/images/token_icons/iexec.png',
- MCO: '/images/token_icons/monaco.png',
- ADT: '/images/token_icons/adtoken.png',
- CFI: '/images/token_icons/cofound-it.png',
- ROL: '/images/token_icons/etheroll.png',
- WGNT: '/images/token_icons/golem.png',
- MTL: '/images/token_icons/metal.png',
- NMR: '/images/token_icons/numeraire.png',
- SAN: '/images/token_icons/santiment.png',
- TAAS: '/images/token_icons/taas.png',
- TKN: '/images/token_icons/tokencard.png',
- TRST: '/images/token_icons/trust.png',
- } as { [symbol: string]: string },
GOOGLE_ANALYTICS_ID: 'UA-98720122-1',
LAST_LOCAL_STORAGE_FILL_CLEARANCE_DATE: '2017-11-22',
- LAST_LOCAL_STORAGE_TRACKED_TOKEN_CLEARANCE_DATE: '2018-6-25',
+ LAST_LOCAL_STORAGE_TRACKED_TOKEN_CLEARANCE_DATE: '2018-7-5',
OUTDATED_WRAPPED_ETHERS: [
{
42: {
diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts
index 623819fc9..8c76a7592 100644
--- a/packages/website/ts/utils/utils.ts
+++ b/packages/website/ts/utils/utils.ts
@@ -359,7 +359,9 @@ export const utils = {
},
isDogfood,
shouldShowPortalV2(): boolean {
- return this.isDevelopment() || this.isStaging() || this.isDogfood();
+ // return this.isDevelopment() || this.isStaging() || this.isDogfood();
+ // TODO: Remove this method entirely after launch.
+ return true;
},
shouldShowJobsPage(): boolean {
return this.isDevelopment() || this.isStaging() || this.isDogfood();
@@ -381,9 +383,9 @@ export const utils = {
return trackedTokens;
},
getFormattedAmountFromToken(token: Token, tokenState: TokenState): string {
- return utils.getFormattedAmount(tokenState.balance, token.decimals, token.symbol);
+ return utils.getFormattedAmount(tokenState.balance, token.decimals);
},
- getFormattedAmount(amount: BigNumber, decimals: number, symbol: string): string {
+ getFormattedAmount(amount: BigNumber, decimals: number): string {
const unitAmount = Web3Wrapper.toUnitAmount(amount, decimals);
// if the unit amount is less than 1, show the natural number of decimal places with a max of 4
// if the unit amount is greater than or equal to 1, show only 2 decimal places
@@ -392,7 +394,7 @@ export const utils = {
: 2;
const format = `0,0.${_.repeat('0', precision)}`;
const formattedAmount = numeral(unitAmount).format(format);
- return `${formattedAmount} ${symbol}`;
+ return formattedAmount;
},
getUsdValueFormattedAmount(amount: BigNumber, decimals: number, price: BigNumber): string {
const unitAmount = Web3Wrapper.toUnitAmount(amount, decimals);
@@ -474,4 +476,8 @@ export const utils = {
}
return [downloadLink, isOnMobile];
},
+ getTokenIconUrl(symbol: string): string {
+ const result = `/images/token_icons/${symbol}.png`;
+ return result;
+ },
};