diff options
author | Brandon Millman <brandon.millman@gmail.com> | 2017-12-20 06:51:09 +0800 |
---|---|---|
committer | Brandon Millman <brandon.millman@gmail.com> | 2017-12-20 06:51:09 +0800 |
commit | c531d734d442a9ff52346a289e9bbb5fbf32a54e (patch) | |
tree | 979df1281c1107d767634b0477a427a48e0cdd81 /packages/website/ts/components | |
parent | f239522a19b046b2eb3e6961ac2829dfa5d611e8 (diff) | |
parent | d1c36f50d5849e70e16b785f5fff8f58435536d7 (diff) | |
download | dexon-sol-tools-c531d734d442a9ff52346a289e9bbb5fbf32a54e.tar dexon-sol-tools-c531d734d442a9ff52346a289e9bbb5fbf32a54e.tar.gz dexon-sol-tools-c531d734d442a9ff52346a289e9bbb5fbf32a54e.tar.bz2 dexon-sol-tools-c531d734d442a9ff52346a289e9bbb5fbf32a54e.tar.lz dexon-sol-tools-c531d734d442a9ff52346a289e9bbb5fbf32a54e.tar.xz dexon-sol-tools-c531d734d442a9ff52346a289e9bbb5fbf32a54e.tar.zst dexon-sol-tools-c531d734d442a9ff52346a289e9bbb5fbf32a54e.zip |
Merge branch 'development' into feature/updateReadmes
* development: (35 commits)
Remove etherToken from smart contract docs
Update new WETH addresses and localStorage clearance key
Fix merge
Remove re-assignment
Fix scrolling topBar on Portal
Fix overflow issue on calculated fillAmount
Fix faulty import
Refactor remaining _.assign to spread operator
Move muiTheme into it's own module
Add WETH
remove extra space
Remove binding on prop passed callbacks
Add airtable tasks to TODO's
Refactor configs and constants, standardize on uppercase/snakecase, alphebetize, rename for logical grouping
Sort colors into color spectrum
remove unused style
standarize on `grey` over `gray` spelling and other color related fixes
Standardize colors to always be in uppercase hex and consolidate material-ui greys
Consolidate all custom colors and material-ui colors into a colors module
Remove unused `location` prop
...
Diffstat (limited to 'packages/website/ts/components')
42 files changed, 378 insertions, 325 deletions
diff --git a/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx b/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx index 963bd4388..9a5cd90d7 100644 --- a/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx +++ b/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx @@ -1,10 +1,10 @@ import * as _ from 'lodash'; import Dialog from 'material-ui/Dialog'; import FlatButton from 'material-ui/FlatButton'; -import {colors} from 'material-ui/styles'; import * as React from 'react'; import {Blockchain} from 'ts/blockchain'; import {BlockchainErrs} from 'ts/types'; +import {colors} from 'ts/utils/colors'; import {configs} from 'ts/utils/configs'; import {constants} from 'ts/utils/constants'; @@ -46,22 +46,22 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp ); } private getTitle(hasWalletAddress: boolean) { - if (this.props.blockchainErr === BlockchainErrs.A_CONTRACT_NOT_DEPLOYED_ON_NETWORK) { + if (this.props.blockchainErr === BlockchainErrs.AContractNotDeployedOnNetwork) { return '0x smart contracts not found'; } else if (!hasWalletAddress) { return 'Enable wallet communication'; - } else if (this.props.blockchainErr === BlockchainErrs.DISCONNECTED_FROM_ETHEREUM_NODE) { + } else if (this.props.blockchainErr === BlockchainErrs.DisconnectedFromEthereumNode) { return 'Disconnected from Ethereum network'; } else { return 'Unexpected error'; } } private renderExplanation(hasWalletAddress: boolean) { - if (this.props.blockchainErr === BlockchainErrs.A_CONTRACT_NOT_DEPLOYED_ON_NETWORK) { + if (this.props.blockchainErr === BlockchainErrs.AContractNotDeployedOnNetwork) { return this.renderContractsNotDeployedExplanation(); } else if (!hasWalletAddress) { return this.renderNoWalletFoundExplanation(); - } else if (this.props.blockchainErr === BlockchainErrs.DISCONNECTED_FROM_ETHEREUM_NODE) { + } else if (this.props.blockchainErr === BlockchainErrs.DisconnectedFromEthereumNode) { return this.renderDisconnectedFromNode(); } else { return this.renderUnexpectedErrorExplanation(); @@ -71,9 +71,9 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp return ( <div> You were disconnected from the backing Ethereum node. - {' '}If using <a href={constants.METAMASK_CHROME_STORE_URL} target="_blank"> + {' '}If using <a href={constants.URL_METAMASK_CHROME_STORE} target="_blank"> Metamask - </a> or <a href={constants.MIST_DOWNLOAD_URL} target="_blank">Mist</a> try refreshing + </a> or <a href={constants.URL_MIST_DOWNLOAD} target="_blank">Mist</a> try refreshing {' '}the page. If using a locally hosted Ethereum node, make sure it's still running. </div> ); @@ -97,7 +97,7 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp <h4>1. Metamask chrome extension</h4> <div> You can install the{' '} - <a href={constants.METAMASK_CHROME_STORE_URL} target="_blank"> + <a href={constants.URL_METAMASK_CHROME_STORE} target="_blank"> Metamask </a> Chrome extension Ethereum wallet. Once installed and set up, refresh this page. <div className="pt1"> @@ -107,11 +107,11 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp </div> <h4>Parity Signer</h4> <div> - The <a href={constants.PARITY_CHROME_STORE_URL} target="_blank">Parity Signer + The <a href={constants.URL_PARITY_CHROME_STORE} target="_blank">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.isMainnetEnabled && '`parity ui` or'} `parity --chain kovan ui`{' '} - in order to connect to {configs.isMainnetEnabled ? 'mainnet or Kovan respectively.' : 'Kovan.'} + {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.'} </div> <div className="pt2"> <span className="bold">Note:</span> @@ -130,24 +130,24 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp {' '}currently connected to (network Id: {this.props.networkId}). {' '}In order to use the 0x portal dApp, {' '}please connect to the - {' '}{constants.TESTNET_NAME} testnet (network Id: {constants.TESTNET_NETWORK_ID}) - {configs.isMainnetEnabled ? - ` or ${constants.MAINNET_NAME} (network Id: ${constants.MAINNET_NETWORK_ID}).` : + {' '}{constants.TESTNET_NAME} testnet (network Id: {constants.NETWORK_ID_TESTNET}) + {configs.IS_MAINNET_ENABLED ? + ` or ${constants.MAINNET_NAME} (network Id: ${constants.NETWORK_ID_MAINNET}).` : `.` } </div> <h4>Metamask</h4> <div> If you are using{' '} - <a href={constants.METAMASK_CHROME_STORE_URL} target="_blank"> + <a href={constants.URL_METAMASK_CHROME_STORE} target="_blank"> Metamask </a>, you can switch networks in the top left corner of the extension popover. </div> <h4>Parity Signer</h4> <div> - If using the <a href={constants.PARITY_CHROME_STORE_URL} target="_blank">Parity Signer + 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.isMainnetEnabled ? + {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.' 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 c8bdced9b..700255163 100644 --- a/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx +++ b/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx @@ -5,8 +5,7 @@ import * as React from 'react'; import {EthAmountInput} from 'ts/components/inputs/eth_amount_input'; import {TokenAmountInput} from 'ts/components/inputs/token_amount_input'; import {Side, Token, TokenState} from 'ts/types'; - -const DARK_BLUE = '#4D5481'; +import {colors} from 'ts/utils/colors'; interface EthWethConversionDialogProps { direction: Side; @@ -47,7 +46,7 @@ export class EthWethConversionDialog extends onTouchTap={this.onConvertClick.bind(this)} />, ]; - const title = this.props.direction === Side.deposit ? 'Wrap ETH' : 'Unwrap WETH'; + const title = this.props.direction === Side.Deposit ? 'Wrap ETH' : 'Unwrap WETH'; return ( <Dialog title={title} @@ -61,10 +60,10 @@ export class EthWethConversionDialog extends ); } private renderConversionDialogBody() { - const explanation = this.props.direction === Side.deposit ? + const explanation = this.props.direction === Side.Deposit ? '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 isWrappedVersion = this.props.direction === Side.Receive; return ( <div> <div className="pb2"> @@ -75,7 +74,7 @@ export class EthWethConversionDialog extends {this.renderCurrency(isWrappedVersion)} <div style={{paddingTop: 68}}> <i - style={{fontSize: 28, color: DARK_BLUE}} + style={{fontSize: 28, color: colors.darkBlue}} className="zmdi zmdi-arrow-right" /> </div> @@ -85,7 +84,7 @@ export class EthWethConversionDialog extends className="pt2 mx-auto" style={{width: 245}} > - {this.props.direction === Side.receive ? + {this.props.direction === Side.Receive ? <TokenAmountInput token={this.props.token} tokenState={this.props.tokenState} @@ -109,7 +108,16 @@ export class EthWethConversionDialog extends className="pt1" style={{fontSize: 12}} > - 1 ETH = 1 WETH + <div className="left">1 ETH = 1 WETH</div> + {this.props.direction === Side.Receive && + <div + className="right" + onClick={this.onMaxClick.bind(this)} + style={{color: colors.darkBlue, textDecoration: 'underline', cursor: 'pointer'}} + > + Max + </div> + } </div> </div> </div> @@ -124,7 +132,7 @@ export class EthWethConversionDialog extends <div className="mx-auto pt2"> <div className="center" - style={{color: DARK_BLUE}} + style={{color: colors.darkBlue}} > {name} </div> @@ -137,6 +145,11 @@ export class EthWethConversionDialog extends </div> ); } + private onMaxClick() { + this.setState({ + value: this.props.tokenState.balance, + }); + } private onValueChange(isValid: boolean, amount?: BigNumber) { this.setState({ value: amount, diff --git a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx index d3c95a011..ddd1f2cf2 100644 --- a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx +++ b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx @@ -2,7 +2,6 @@ import BigNumber from 'bignumber.js'; import * as _ from 'lodash'; import Dialog from 'material-ui/Dialog'; import FlatButton from 'material-ui/FlatButton'; -import {colors} from 'material-ui/styles'; import { Table, TableBody, @@ -17,6 +16,8 @@ import ReactTooltip = require('react-tooltip'); import {Blockchain} from 'ts/blockchain'; import {LifeCycleRaisedButton} from 'ts/components/ui/lifecycle_raised_button'; import {Dispatcher} from 'ts/redux/dispatcher'; +import {colors} from 'ts/utils/colors'; +import {configs} from 'ts/utils/configs'; import {constants} from 'ts/utils/constants'; import {utils} from 'ts/utils/utils'; @@ -52,7 +53,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps, stepIndex: LedgerSteps.CONNECT, userAddresses: [], addressBalances: [], - derivationPath: constants.DEFAULT_DERIVATION_PATH, + derivationPath: configs.DEFAULT_DERIVATION_PATH, derivationErrMsg: '', }; } @@ -146,7 +147,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps, <div className="overflow-hidden" style={{width: 180}}> <TextField floatingLabelFixed={true} - floatingLabelStyle={{color: colors.grey500}} + floatingLabelStyle={{color: colors.grey}} floatingLabelText="Update path derivation (advanced)" value={this.state.derivationPath} errorText={this.state.derivationErrMsg} @@ -170,7 +171,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps, const balance = this.state.addressBalances[i]; const addressTooltipId = `address-${userAddress}`; const balanceTooltipId = `balance-${userAddress}`; - const networkName = constants.networkNameById[this.props.networkId]; + const networkName = constants.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'; diff --git a/packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx b/packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx index bfff7fbb5..ffe55794f 100644 --- a/packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx +++ b/packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx @@ -1,7 +1,7 @@ import Dialog from 'material-ui/Dialog'; import FlatButton from 'material-ui/FlatButton'; -import {colors} from 'material-ui/styles'; import * as React from 'react'; +import {colors} from 'ts/utils/colors'; interface PortalDisclaimerDialogProps { isOpen: boolean; @@ -17,11 +17,11 @@ export function PortalDisclaimerDialog(props: PortalDisclaimerDialogProps) { <FlatButton key="portalAgree" label="I Agree" - onTouchTap={props.onToggleDialog.bind(this)} + onTouchTap={props.onToggleDialog} />, ]} open={props.isOpen} - onRequestClose={props.onToggleDialog.bind(this)} + onRequestClose={props.onToggleDialog} autoScrollBodyContent={true} modal={true} > diff --git a/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx b/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx index 2d45009d5..f17893a83 100644 --- a/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx +++ b/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx @@ -73,7 +73,9 @@ export class TrackTokenConfirmationDialog extends isAddingTokenToTracked: true, }); for (const token of this.props.tokens) { - const newTokenEntry = _.assign({}, token); + const newTokenEntry = { + ...token, + }; newTokenEntry.isTracked = true; trackedTokenStorage.addTrackedTokenToUser(this.props.userAddress, this.props.networkId, newTokenEntry); diff --git a/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx b/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx index 09c32c997..ff884a94e 100644 --- a/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx +++ b/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx @@ -1,7 +1,7 @@ import Dialog from 'material-ui/Dialog'; import FlatButton from 'material-ui/FlatButton'; -import {colors} from 'material-ui/styles'; import * as React from 'react'; +import {colors} from 'ts/utils/colors'; import {constants} from 'ts/utils/constants'; interface U2fNotSupportedDialogProps { @@ -39,7 +39,7 @@ export function U2fNotSupportedDialog(props: U2fNotSupportedDialogProps) { <li> Firefox with{' '} <a - href={constants.FIREFOX_U2F_ADDON} + href={constants.URL_FIREFOX_U2F_ADDON} target="_blank" style={{textDecoration: 'underline'}} > diff --git a/packages/website/ts/components/dialogs/wrapped_eth_section_notice_dialog.tsx b/packages/website/ts/components/dialogs/wrapped_eth_section_notice_dialog.tsx new file mode 100644 index 000000000..3f485ce4f --- /dev/null +++ b/packages/website/ts/components/dialogs/wrapped_eth_section_notice_dialog.tsx @@ -0,0 +1,38 @@ +import Dialog from 'material-ui/Dialog'; +import FlatButton from 'material-ui/FlatButton'; +import {colors} from 'material-ui/styles'; +import * as React from 'react'; + +interface WrappedEthSectionNoticeDialogProps { + isOpen: boolean; + onToggleDialog: () => void; +} + +export function WrappedEthSectionNoticeDialog(props: WrappedEthSectionNoticeDialogProps) { + return ( + <Dialog + title="Dedicated Wrapped Ether Section" + titleStyle={{fontWeight: 100}} + actions={[ + <FlatButton + key="acknowledgeWrapEthSection" + label="Sounds good" + onTouchTap={props.onToggleDialog} + />, + ]} + open={props.isOpen} + onRequestClose={props.onToggleDialog} + autoScrollBodyContent={true} + modal={true} + > + <div className="pt2" style={{color: colors.grey700}}> + <div> + We have recently updated the Wrapped Ether token (WETH) used by 0x Portal. + Don't worry, unwrapping Ether tied to the old Wrapped Ether token can + be done at any time by clicking on the "Wrap ETH" section in the menu + to the left. + </div> + </div> + </Dialog> + ); +} diff --git a/packages/website/ts/components/eth_weth_conversion_button.tsx b/packages/website/ts/components/eth_weth_conversion_button.tsx index c8a279de9..e802b8782 100644 --- a/packages/website/ts/components/eth_weth_conversion_button.tsx +++ b/packages/website/ts/components/eth_weth_conversion_button.tsx @@ -45,7 +45,7 @@ export class EthWethConversionButton extends const labelStyle = this.state.isEthConversionHappening ? {fontSize: 10} : {}; let callToActionLabel; let inProgressLabel; - if (this.props.direction === Side.deposit) { + if (this.props.direction === Side.Deposit) { callToActionLabel = 'Wrap'; inProgressLabel = 'Wrapping...'; } else { @@ -87,9 +87,9 @@ export class EthWethConversionButton extends const tokenState = this.props.ethTokenState; let balance = tokenState.balance; try { - if (direction === Side.deposit) { + if (direction === Side.Deposit) { await this.props.blockchain.convertEthToWrappedEthTokensAsync(token.address, value); - const ethAmount = ZeroEx.toUnitAmount(value, constants.ETH_DECIMAL_PLACES); + const ethAmount = ZeroEx.toUnitAmount(value, constants.DECIMAL_PLACES_ETH); this.props.dispatcher.showFlashMessage(`Successfully wrapped ${ethAmount.toString()} ETH to WETH`); balance = balance.plus(value); } else { @@ -104,13 +104,13 @@ export class EthWethConversionButton extends this.props.onConversionSuccessful(); } catch (err) { const errMsg = '' + err; - if (_.includes(errMsg, BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES)) { + if (_.includes(errMsg, BlockchainCallErrs.UserHasNoAssociatedAddresses)) { this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); } else if (!_.includes(errMsg, 'User denied transaction')) { utils.consoleLog(`Unexpected error encountered: ${err}`); utils.consoleLog(err.stack); await errorReporter.reportAsync(err); - const errorMsg = direction === Side.deposit ? + const errorMsg = direction === Side.Deposit ? 'Failed to wrap your ETH. Please try again.' : 'Failed to unwrap your WETH. Please try again.'; this.props.dispatcher.showFlashMessage(errorMsg); diff --git a/packages/website/ts/components/eth_wrappers.tsx b/packages/website/ts/components/eth_wrappers.tsx index 58b73b11c..bdd4664e8 100644 --- a/packages/website/ts/components/eth_wrappers.tsx +++ b/packages/website/ts/components/eth_wrappers.tsx @@ -2,7 +2,6 @@ import {ZeroEx} from '0x.js'; import BigNumber from 'bignumber.js'; import * as _ from 'lodash'; import Divider from 'material-ui/Divider'; -import {colors} from 'material-ui/styles'; import { Table, TableBody, @@ -13,10 +12,12 @@ import { } from 'material-ui/Table'; import * as moment from 'moment'; import * as React from 'react'; +import ReactTooltip = require('react-tooltip'); import {Blockchain} from 'ts/blockchain'; import {EthWethConversionButton} from 'ts/components/eth_weth_conversion_button'; import {Dispatcher} from 'ts/redux/dispatcher'; import { + EtherscanLinkSuffixes, OutdatedWrappedEtherByNetworkId, Side, Token, @@ -24,12 +25,13 @@ import { TokenState, TokenStateByAddress, } from 'ts/types'; +import {colors} from 'ts/utils/colors'; 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 LIGHT_GRAY = '#A5A5A5'; const ICON_DIMENSION = 40; const ETHER_ICON_PATH = '/images/ether.png'; const OUTDATED_WETH_ICON_PATH = '/images/wrapped_eth_gray.png'; @@ -83,8 +85,12 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt const tokens = _.values(this.props.tokenByAddress); const etherToken = _.find(tokens, {symbol: 'WETH'}); const etherTokenState = this.props.tokenStateByAddress[etherToken.address]; - const wethBalance = ZeroEx.toUnitAmount(etherTokenState.balance, 18); + const wethBalance = ZeroEx.toUnitAmount(etherTokenState.balance, constants.DECIMAL_PLACES_ETH); const isBidirectional = true; + const etherscanUrl = utils.getEtherScanLinkIfExists( + etherToken.address, this.props.networkId, EtherscanLinkSuffixes.Address, + ); + const tokenLabel = this.renderToken('Wrapped Ether', etherToken.address, configs.ICON_URL_BY_SYMBOL.WETH); return ( <div className="clearfix lg-px4 md-px4 sm-px2" style={{minHeight: 600}}> <div className="relative"> @@ -92,8 +98,8 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt <div className="absolute" style={{top: 0, right: 0}}> <a target="_blank" - href="https://weth.io/" - style={{color: LIGHT_GRAY}} + href={constants.URL_WETH_IO} + style={{color: colors.grey}} > <div className="flex"> <div>About Wrapped ETH</div> @@ -131,8 +137,11 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt style={{width: ICON_DIMENSION, height: ICON_DIMENSION}} src={ETHER_ICON_PATH} /> - <div className="mt2 ml2 sm-hide xs-hide"> - Ether + <div + className="ml2 sm-hide xs-hide" + style={{marginTop: 12}} + > + ETH </div> </div> </TableRowColumn> @@ -142,7 +151,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt <TableRowColumn> <EthWethConversionButton isOutdatedWrappedEther={false} - direction={Side.deposit} + direction={Side.Deposit} ethToken={etherToken} ethTokenState={etherTokenState} dispatcher={this.props.dispatcher} @@ -153,15 +162,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt </TableRow> <TableRow key="WETH"> <TableRowColumn className="py1"> - <div className="flex"> - <img - style={{width: ICON_DIMENSION, height: ICON_DIMENSION}} - src={constants.iconUrlBySymbol.WETH} - /> - <div className="mt2 ml2 sm-hide xs-hide"> - Wrapped Ether - </div> - </div> + {this.renderTokenLink(tokenLabel, etherscanUrl)} </TableRowColumn> <TableRowColumn> {wethBalance.toFixed(PRECISION)} WETH @@ -169,7 +170,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt <TableRowColumn> <EthWethConversionButton isOutdatedWrappedEther={false} - direction={Side.receive} + direction={Side.Receive} ethToken={etherToken} ethTokenState={etherTokenState} dispatcher={this.props.dispatcher} @@ -242,10 +243,13 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt ); } private renderOutdatedWeths(etherToken: Token, etherTokenState: TokenState) { - const rows = _.map(configs.outdatedWrappedEthers, + const rows = _.map(configs.OUTDATED_WRAPPED_ETHERS, (outdatedWETHByNetworkId: OutdatedWrappedEtherByNetworkId) => { - const outdatedWETH = outdatedWETHByNetworkId[this.props.networkId]; - const timestampMsRange = outdatedWETH.timestampMsRange; + const outdatedWETHIfExists = outdatedWETHByNetworkId[this.props.networkId]; + if (_.isUndefined(outdatedWETHIfExists)) { + return null; // noop + } + const timestampMsRange = outdatedWETHIfExists.timestampMsRange; let dateRange: string; if (!_.isUndefined(timestampMsRange)) { const startMoment = moment(timestampMsRange.startTimestampMs); @@ -256,26 +260,26 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt } const outdatedEtherToken = { ...etherToken, - address: outdatedWETH.address, + address: outdatedWETHIfExists.address, }; - const isStateLoaded = this.state.outdatedWETHAddressToIsStateLoaded[outdatedWETH.address]; - const outdatedEtherTokenState = this.state.outdatedWETHStateByAddress[outdatedWETH.address]; + const isStateLoaded = this.state.outdatedWETHAddressToIsStateLoaded[outdatedWETHIfExists.address]; + const outdatedEtherTokenState = this.state.outdatedWETHStateByAddress[outdatedWETHIfExists.address]; const balanceInEthIfExists = isStateLoaded ? - ZeroEx.toUnitAmount(outdatedEtherTokenState.balance, 18).toFixed(PRECISION) : + ZeroEx.toUnitAmount( + outdatedEtherTokenState.balance, constants.DECIMAL_PLACES_ETH, + ).toFixed(PRECISION) : undefined; - const onConversionSuccessful = this.onOutdatedConversionSuccessfulAsync.bind(this, outdatedWETH.address); + const onConversionSuccessful = this.onOutdatedConversionSuccessfulAsync.bind( + this, outdatedWETHIfExists.address, + ); + const etherscanUrl = utils.getEtherScanLinkIfExists( + outdatedWETHIfExists.address, this.props.networkId, EtherscanLinkSuffixes.Address, + ); + const tokenLabel = this.renderToken(dateRange, outdatedEtherToken.address, OUTDATED_WETH_ICON_PATH); return ( - <TableRow key={`weth-${outdatedWETH.address}`}> + <TableRow key={`weth-${outdatedWETHIfExists.address}`}> <TableRowColumn className="py1"> - <div className="flex"> - <img - style={{width: ICON_DIMENSION, height: ICON_DIMENSION}} - src={OUTDATED_WETH_ICON_PATH} - /> - <div className="mt2 ml2 sm-hide xs-hide"> - {dateRange} - </div> - </div> + {this.renderTokenLink(tokenLabel, etherscanUrl)} </TableRowColumn> <TableRowColumn> {isStateLoaded ? @@ -287,7 +291,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt <EthWethConversionButton isDisabled={!isStateLoaded} isOutdatedWrappedEther={true} - direction={Side.receive} + direction={Side.Receive} ethToken={outdatedEtherToken} ethTokenState={outdatedEtherTokenState} dispatcher={this.props.dispatcher} @@ -301,6 +305,41 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt }); return rows; } + private renderTokenLink(tokenLabel: React.ReactNode, etherscanUrl: string) { + return ( + <span> + {_.isUndefined(etherscanUrl) ? + tokenLabel : + <a href={etherscanUrl} target="_blank" style={{textDecoration: 'none'}}> + {tokenLabel} + </a> + } + </span> + ); + } + private renderToken(name: string, address: string, imgPath: string) { + const tooltipId = `tooltip-${address}`; + return ( + <div className="flex"> + <img + style={{width: ICON_DIMENSION, height: ICON_DIMENSION}} + src={imgPath} + /> + <div + className="ml2 sm-hide xs-hide" + style={{marginTop: 12}} + > + <span + data-tip={true} + data-for={tooltipId} + > + {name} + </span> + <ReactTooltip id={tooltipId}>{address}</ReactTooltip> + </div> + </div> + ); + } private async onOutdatedConversionSuccessfulAsync(outdatedWETHAddress: string) { this.setState({ outdatedWETHAddressToIsStateLoaded: { @@ -345,9 +384,15 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt }); } private getOutdatedWETHAddresses(): string[] { - const outdatedWETHAddresses = _.map(configs.outdatedWrappedEthers, outdatedWrappedEther => { - return outdatedWrappedEther[this.props.networkId].address; - }); + const outdatedWETHAddresses = _.compact(_.map(configs.OUTDATED_WRAPPED_ETHERS, + outdatedWrappedEtherByNetwork => { + const outdatedWrappedEtherIfExists = outdatedWrappedEtherByNetwork[this.props.networkId]; + if (_.isUndefined(outdatedWrappedEtherIfExists)) { + return undefined; + } + const address = outdatedWrappedEtherIfExists.address; + return address; + })); return outdatedWETHAddresses; } } // tslint:disable:max-file-line-count diff --git a/packages/website/ts/components/fill_order.tsx b/packages/website/ts/components/fill_order.tsx index 40a9b87d6..ac826fdf6 100644 --- a/packages/website/ts/components/fill_order.tsx +++ b/packages/website/ts/components/fill_order.tsx @@ -28,12 +28,11 @@ import { TokenStateByAddress, WebsitePaths, } from 'ts/types'; +import {colors} from 'ts/utils/colors'; import {constants} from 'ts/utils/constants'; import {errorReporter} from 'ts/utils/error_reporter'; import {utils} from 'ts/utils/utils'; -const CUSTOM_LIGHT_GRAY = '#BBBBBB'; - interface FillOrderProps { blockchain: Blockchain; blockchainErr: BlockchainErrs; @@ -222,7 +221,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> { <div className="clearfix pb2" style={{width: '100%'}}> <div className="inline left">Order details</div> <div className="inline right" style={{minWidth: 208}}> - <div className="col col-4 pl2" style={{color: '#BEBEBE'}}> + <div className="col col-4 pl2" style={{color: colors.grey}}> Maker: </div> <div className="col col-2 pr1"> @@ -259,22 +258,20 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> { </div> </div> {!isUserMaker && - <div className="clearfix mx-auto" style={{width: 315, height: 108}}> - <div className="col col-7" style={{maxWidth: 235}}> - <TokenAmountInput - label="Fill amount" - onChange={this.onFillAmountChange.bind(this)} - shouldShowIncompleteErrs={false} - token={fillToken} - tokenState={fillTokenState} - amount={fillAssetToken.amount} - shouldCheckBalance={true} - shouldCheckAllowance={true} - /> - </div> + <div className="clearfix mx-auto relative" style={{width: 235, height: 108}}> + <TokenAmountInput + label="Fill amount" + onChange={this.onFillAmountChange.bind(this)} + shouldShowIncompleteErrs={false} + token={fillToken} + tokenState={fillTokenState} + amount={fillAssetToken.amount} + shouldCheckBalance={true} + shouldCheckAllowance={true} + /> <div - className="col col-5 pl1" - style={{color: CUSTOM_LIGHT_GRAY, paddingTop: 39}} + className="absolute sm-hide xs-hide" + style={{color: colors.grey400, right: -247, top: 39, width: 242}} > = {accounting.formatNumber(orderReceiveAmount, 6)} {makerToken.symbol} </div> @@ -324,7 +321,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> { Order successfully filled. See the trade details in your{' '} <Link to={`${WebsitePaths.Portal}/trades`} - style={{color: 'white'}} + style={{color: colors.white}} > trade history </Link> @@ -381,22 +378,24 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> { const isUnseenMakerToken = _.isUndefined(makerTokenIfExists); const isMakerTokenTracked = !_.isUndefined(makerTokenIfExists) && makerTokenIfExists.isTracked; if (isUnseenMakerToken) { - tokensToTrack.push(_.assign({}, this.state.parsedOrder.maker.token, { + tokensToTrack.push({ + ...this.state.parsedOrder.maker.token, iconUrl: undefined, isTracked: false, isRegistered: false, - })); + }); } else if (!isMakerTokenTracked) { tokensToTrack.push(makerTokenIfExists); } const isUnseenTakerToken = _.isUndefined(takerTokenIfExists); const isTakerTokenTracked = !_.isUndefined(takerTokenIfExists) && takerTokenIfExists.isTracked; if (isUnseenTakerToken) { - tokensToTrack.push(_.assign({}, this.state.parsedOrder.taker.token, { + tokensToTrack.push({ + ...this.state.parsedOrder.taker.token, iconUrl: undefined, isTracked: false, isRegistered: false, - })); + }); } else if (!isTakerTokenTracked) { tokensToTrack.push(takerTokenIfExists); } diff --git a/packages/website/ts/components/fill_order_json.tsx b/packages/website/ts/components/fill_order_json.tsx index f4db1f74e..4a4bdac9f 100644 --- a/packages/website/ts/components/fill_order_json.tsx +++ b/packages/website/ts/components/fill_order_json.tsx @@ -24,11 +24,11 @@ export class FillOrderJSON extends React.Component<FillOrderJSONProps, FillOrder const tokenAddresses = _.keys(this.props.tokenByAddress); const exchangeContract = this.props.blockchain.getExchangeContractAddressIfExists(); const hintSideToAssetToken = { - [Side.deposit]: { + [Side.Deposit]: { amount: new BigNumber(35), address: tokenAddresses[0], }, - [Side.receive]: { + [Side.Receive]: { amount: new BigNumber(89), address: tokenAddresses[1], }, @@ -41,9 +41,10 @@ export class FillOrderJSON extends React.Component<FillOrderJSONProps, FillOrder v: 27, }; const hintSalt = ZeroEx.generatePseudoRandomSalt(); + const feeRecipient = constants.NULL_ADDRESS; const hintOrder = utils.generateOrder(this.props.networkId, exchangeContract, hintSideToAssetToken, hintOrderExpiryTimestamp, '', '', constants.MAKER_FEE, - constants.TAKER_FEE, constants.FEE_RECIPIENT_ADDRESS, + constants.TAKER_FEE, feeRecipient, hintSignatureData, this.props.tokenByAddress, hintSalt); const hintOrderJSON = `${JSON.stringify(hintOrder, null, '\t').substring(0, 500)}...`; return ( diff --git a/packages/website/ts/components/fill_warning_dialog.tsx b/packages/website/ts/components/fill_warning_dialog.tsx index 83e46cc8f..7370ee2d8 100644 --- a/packages/website/ts/components/fill_warning_dialog.tsx +++ b/packages/website/ts/components/fill_warning_dialog.tsx @@ -1,7 +1,7 @@ import Dialog from 'material-ui/Dialog'; import FlatButton from 'material-ui/FlatButton'; -import {colors} from 'material-ui/styles'; import * as React from 'react'; +import {colors} from 'ts/utils/colors'; interface FillWarningDialogProps { isOpen: boolean; diff --git a/packages/website/ts/components/flash_messages/token_send_completed.tsx b/packages/website/ts/components/flash_messages/token_send_completed.tsx index fef7520f6..26619c54f 100644 --- a/packages/website/ts/components/flash_messages/token_send_completed.tsx +++ b/packages/website/ts/components/flash_messages/token_send_completed.tsx @@ -3,6 +3,7 @@ import BigNumber from 'bignumber.js'; import * as _ from 'lodash'; import * as React from 'react'; import {Token} from 'ts/types'; +import {colors} from 'ts/utils/colors'; import {utils} from 'ts/utils/utils'; interface TokenSendCompletedProps { @@ -19,7 +20,7 @@ export class TokenSendCompleted extends React.Component<TokenSendCompletedProps, const etherScanLink = !_.isUndefined(this.props.etherScanLinkIfExists) && ( <a - style={{color: 'white'}} + style={{color: colors.white}} href={`${this.props.etherScanLinkIfExists}`} target="_blank" > diff --git a/packages/website/ts/components/flash_messages/transaction_submitted.tsx b/packages/website/ts/components/flash_messages/transaction_submitted.tsx index cef3e2b1e..64f460e20 100644 --- a/packages/website/ts/components/flash_messages/transaction_submitted.tsx +++ b/packages/website/ts/components/flash_messages/transaction_submitted.tsx @@ -1,5 +1,6 @@ import * as _ from 'lodash'; import * as React from 'react'; +import {colors} from 'ts/utils/colors'; interface TransactionSubmittedProps { etherScanLinkIfExists?: string; @@ -16,7 +17,7 @@ export class TransactionSubmitted extends React.Component<TransactionSubmittedPr <div> Transaction submitted to the network:{' '} <a - style={{color: 'white'}} + style={{color: colors.white}} href={`${this.props.etherScanLinkIfExists}`} target="_blank" > diff --git a/packages/website/ts/components/footer.tsx b/packages/website/ts/components/footer.tsx index b26523094..0f65405d9 100644 --- a/packages/website/ts/components/footer.tsx +++ b/packages/website/ts/components/footer.tsx @@ -4,6 +4,7 @@ import { Link, } from 'react-router-dom'; import {WebsitePaths} from 'ts/types'; +import {colors} from 'ts/utils/colors'; import {constants} from 'ts/utils/constants'; interface MenuItemsBySection { @@ -24,9 +25,6 @@ enum Sections { } const ICON_DIMENSION = 16; -const CUSTOM_DARK_GRAY = '#393939'; -const CUSTOM_LIGHT_GRAY = '#CACACA'; -const CUSTOM_LIGHTEST_GRAY = '#9E9E9E'; const menuItemsBySection: MenuItemsBySection = { Documentation: [ { @@ -59,25 +57,25 @@ const menuItemsBySection: MenuItemsBySection = { { title: 'Rocket.chat', isExternal: true, - path: constants.ZEROEX_CHAT_URL, + path: constants.URL_ZEROEX_CHAT, fileName: 'rocketchat.png', }, { title: 'Blog', isExternal: true, - path: constants.BLOG_URL, + path: constants.URL_BLOG, fileName: 'medium.png', }, { title: 'Twitter', isExternal: true, - path: constants.TWITTER_URL, + path: constants.URL_TWITTER, fileName: 'twitter.png', }, { title: 'Reddit', isExternal: true, - path: constants.REDDIT_URL, + path: constants.URL_REDDIT, fileName: 'reddit.png', }, ], @@ -90,7 +88,7 @@ const menuItemsBySection: MenuItemsBySection = { { title: 'Careers', isExternal: true, - path: constants.ANGELLIST_URL, + path: constants.URL_ANGELLIST, }, { title: 'Contact', @@ -100,7 +98,7 @@ const menuItemsBySection: MenuItemsBySection = { ], }; const linkStyle = { - color: 'white', + color: colors.white, cursor: 'pointer', }; @@ -111,23 +109,23 @@ const titleToIcon: {[title: string]: string} = { 'Reddit': 'reddit.png', }; -export interface FooterProps { - location: Location; -} +export interface FooterProps {} interface FooterState {} export class Footer extends React.Component<FooterProps, FooterState> { public render() { return ( - <div className="relative pb4 pt2" style={{backgroundColor: CUSTOM_DARK_GRAY}}> - <div className="mx-auto max-width-4 md-px2 lg-px0 py4 clearfix" style={{color: 'white'}}> + <div className="relative pb4 pt2" style={{backgroundColor: colors.darkerGrey}}> + <div className="mx-auto max-width-4 md-px2 lg-px0 py4 clearfix" style={{color: colors.white}}> <div className="col lg-col-4 md-col-4 col-12 left"> <div className="sm-mx-auto" style={{width: 148}}> <div> <img src="/images/protocol_logo_white.png" height="30" /> </div> - <div style={{fontSize: 11, color: CUSTOM_LIGHTEST_GRAY, paddingLeft: 37, paddingTop: 2}}> + <div + style={{fontSize: 11, color: colors.grey, paddingLeft: 37, paddingTop: 2}} + > © ZeroEx, Intl. </div> </div> @@ -211,7 +209,7 @@ export class Footer extends React.Component<FooterProps, FooterState> { private renderHeader(title: string) { const headerStyle = { textTransform: 'uppercase', - color: CUSTOM_LIGHT_GRAY, + color: colors.grey400, letterSpacing: 2, fontFamily: 'Roboto Mono', fontSize: 13, diff --git a/packages/website/ts/components/generate_order/asset_picker.tsx b/packages/website/ts/components/generate_order/asset_picker.tsx index 08b4a909e..51edd2308 100644 --- a/packages/website/ts/components/generate_order/asset_picker.tsx +++ b/packages/website/ts/components/generate_order/asset_picker.tsx @@ -244,7 +244,9 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt }); const tokenAddress = this.state.chosenTrackTokenAddress; const token = this.props.tokenByAddress[tokenAddress]; - const newTokenEntry = _.assign({}, token); + const newTokenEntry = { + ...token, + }; newTokenEntry.isTracked = true; trackedTokenStorage.addTrackedTokenToUser(this.props.userAddress, this.props.networkId, newTokenEntry); diff --git a/packages/website/ts/components/generate_order/generate_order_form.tsx b/packages/website/ts/components/generate_order/generate_order_form.tsx index 59970b10c..5479f0f83 100644 --- a/packages/website/ts/components/generate_order/generate_order_form.tsx +++ b/packages/website/ts/components/generate_order/generate_order_form.tsx @@ -3,7 +3,6 @@ import BigNumber from 'bignumber.js'; import * as _ from 'lodash'; import Dialog from 'material-ui/Dialog'; import Divider from 'material-ui/Divider'; -import {colors} from 'material-ui/styles'; import * as React from 'react'; import {Blockchain} from 'ts/blockchain'; import {ExpirationInput} from 'ts/components/inputs/expiration_input'; @@ -30,6 +29,7 @@ import { TokenByAddress, TokenStateByAddress, } from 'ts/types'; +import {colors} from 'ts/utils/colors'; import {errorReporter} from 'ts/utils/error_reporter'; import {utils} from 'ts/utils/utils'; @@ -78,10 +78,10 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G } public render() { const dispatcher = this.props.dispatcher; - const depositTokenAddress = this.props.sideToAssetToken[Side.deposit].address; + const depositTokenAddress = this.props.sideToAssetToken[Side.Deposit].address; const depositToken = this.props.tokenByAddress[depositTokenAddress]; const depositTokenState = this.props.tokenStateByAddress[depositTokenAddress]; - const receiveTokenAddress = this.props.sideToAssetToken[Side.receive].address; + const receiveTokenAddress = this.props.sideToAssetToken[Side.Receive].address; const receiveToken = this.props.tokenByAddress[receiveTokenAddress]; const receiveTokenState = this.props.tokenStateByAddress[receiveTokenAddress]; const takerExplanation = 'If a taker is specified, only they are<br> \ @@ -102,9 +102,9 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G blockchainErr={this.props.blockchainErr} dispatcher={this.props.dispatcher} label="Selling" - side={Side.deposit} + side={Side.Deposit} networkId={this.props.networkId} - assetToken={this.props.sideToAssetToken[Side.deposit]} + assetToken={this.props.sideToAssetToken[Side.Deposit]} updateChosenAssetToken={dispatcher.updateChosenAssetToken.bind(dispatcher)} tokenByAddress={this.props.tokenByAddress} /> @@ -112,8 +112,8 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G label="Sell amount" token={depositToken} tokenState={depositTokenState} - amount={this.props.sideToAssetToken[Side.deposit].amount} - onChange={this.onTokenAmountChange.bind(this, depositToken, Side.deposit)} + amount={this.props.sideToAssetToken[Side.Deposit].amount} + onChange={this.onTokenAmountChange.bind(this, depositToken, Side.Deposit)} shouldShowIncompleteErrs={this.state.shouldShowIncompleteErrs} shouldCheckBalance={true} shouldCheckAllowance={true} @@ -133,9 +133,9 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G blockchainErr={this.props.blockchainErr} dispatcher={this.props.dispatcher} label="Buying" - side={Side.receive} + side={Side.Receive} networkId={this.props.networkId} - assetToken={this.props.sideToAssetToken[Side.receive]} + assetToken={this.props.sideToAssetToken[Side.Receive]} updateChosenAssetToken={dispatcher.updateChosenAssetToken.bind(dispatcher)} tokenByAddress={this.props.tokenByAddress} /> @@ -143,8 +143,8 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G label="Receive amount" token={receiveToken} tokenState={receiveTokenState} - amount={this.props.sideToAssetToken[Side.receive].amount} - onChange={this.onTokenAmountChange.bind(this, receiveToken, Side.receive)} + amount={this.props.sideToAssetToken[Side.Receive].amount} + onChange={this.onTokenAmountChange.bind(this, receiveToken, Side.Receive)} shouldShowIncompleteErrs={this.state.shouldShowIncompleteErrs} shouldCheckBalance={false} shouldCheckAllowance={false} @@ -154,7 +154,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G </div> <div className="pt1 sm-pb2 lg-px4 md-px4"> <div className="lg-px3 md-px3"> - <div style={{fontSize: 12, color: colors.grey500}}>Expiration</div> + <div style={{fontSize: 12, color: colors.grey}}>Expiration</div> <ExpirationInput orderExpiryTimestamp={this.props.orderExpiryTimestamp} updateOrderExpiry={dispatcher.updateOrderExpiry.bind(dispatcher)} @@ -235,16 +235,16 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G }); } private async onSignClickedAsync(): Promise<boolean> { - if (this.props.blockchainErr !== '') { + if (this.props.blockchainErr !== BlockchainErrs.NoError) { this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); return false; } // Check if all required inputs were supplied - const debitToken = this.props.sideToAssetToken[Side.deposit]; + const debitToken = this.props.sideToAssetToken[Side.Deposit]; const debitBalance = this.props.tokenStateByAddress[debitToken.address].balance; const debitAllowance = this.props.tokenStateByAddress[debitToken.address].allowance; - const receiveAmount = this.props.sideToAssetToken[Side.receive].amount; + const receiveAmount = this.props.sideToAssetToken[Side.Receive].amount; if (!_.isUndefined(debitToken.amount) && !_.isUndefined(receiveAmount) && debitToken.amount.gt(0) && receiveAmount.gt(0) && this.props.userAddress !== '' && diff --git a/packages/website/ts/components/generate_order/new_token_form.tsx b/packages/website/ts/components/generate_order/new_token_form.tsx index 1be9f5ece..6c3c01d0d 100644 --- a/packages/website/ts/components/generate_order/new_token_form.tsx +++ b/packages/website/ts/components/generate_order/new_token_form.tsx @@ -1,6 +1,5 @@ import BigNumber from 'bignumber.js'; import * as _ from 'lodash'; -import {colors} from 'material-ui/styles'; import TextField from 'material-ui/TextField'; import * as React from 'react'; import {Blockchain} from 'ts/blockchain'; @@ -9,6 +8,7 @@ import {Alert} from 'ts/components/ui/alert'; import {LifeCycleRaisedButton} from 'ts/components/ui/lifecycle_raised_button'; import {RequiredLabel} from 'ts/components/ui/required_label'; import {AlertTypes, Token, TokenByAddress, TokenState} from 'ts/types'; +import {colors} from 'ts/utils/colors'; interface NewTokenFormProps { blockchain: Blockchain; @@ -49,7 +49,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor <div> <TextField floatingLabelFixed={true} - floatingLabelStyle={{color: colors.grey500}} + floatingLabelStyle={{color: colors.grey}} floatingLabelText={<RequiredLabel label="Name" />} value={this.state.name} errorText={this.state.nameErrText} @@ -59,7 +59,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor <div> <TextField floatingLabelFixed={true} - floatingLabelStyle={{color: colors.grey500}} + floatingLabelStyle={{color: colors.grey}} floatingLabelText={<RequiredLabel label="Symbol" />} value={this.state.symbol} errorText={this.state.symbolErrText} @@ -78,7 +78,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor <div> <TextField floatingLabelFixed={true} - floatingLabelStyle={{color: colors.grey500}} + floatingLabelStyle={{color: colors.grey}} floatingLabelText={<RequiredLabel label="Decimals" />} value={this.state.decimals} errorText={this.state.decimalsErrText} diff --git a/packages/website/ts/components/inputs/address_input.tsx b/packages/website/ts/components/inputs/address_input.tsx index bd9e24c80..a17b6e3f5 100644 --- a/packages/website/ts/components/inputs/address_input.tsx +++ b/packages/website/ts/components/inputs/address_input.tsx @@ -1,9 +1,9 @@ import {addressUtils} from '@0xproject/utils'; import * as _ from 'lodash'; -import {colors} from 'material-ui/styles'; import TextField from 'material-ui/TextField'; import * as React from 'react'; import {RequiredLabel} from 'ts/components/ui/required_label'; +import {colors} from 'ts/utils/colors'; interface AddressInputProps { disabled?: boolean; @@ -50,7 +50,7 @@ export class AddressInput extends React.Component<AddressInputProps, AddressInpu fullWidth={true} hintText={hintText} floatingLabelFixed={true} - floatingLabelStyle={{color: colors.grey500, display: labelDisplay}} + floatingLabelStyle={{color: colors.grey, display: labelDisplay}} floatingLabelText={label} errorText={this.state.errMsg} value={this.state.address} diff --git a/packages/website/ts/components/inputs/balance_bounded_input.tsx b/packages/website/ts/components/inputs/balance_bounded_input.tsx index 7ddefc3b9..61ab34f25 100644 --- a/packages/website/ts/components/inputs/balance_bounded_input.tsx +++ b/packages/website/ts/components/inputs/balance_bounded_input.tsx @@ -1,11 +1,11 @@ import BigNumber from 'bignumber.js'; import * as _ from 'lodash'; -import {colors} from 'material-ui/styles'; import TextField from 'material-ui/TextField'; import * as React from 'react'; import {Link} from 'react-router-dom'; import {RequiredLabel} from 'ts/components/ui/required_label'; import {InputErrMsg, ValidatedBigNumberCallback, WebsitePaths} from 'ts/types'; +import {colors} from 'ts/utils/colors'; import {utils} from 'ts/utils/utils'; interface BalanceBoundedInputProps { @@ -83,7 +83,7 @@ export class BalanceBoundedInput extends fullWidth={true} floatingLabelText={label} floatingLabelFixed={true} - floatingLabelStyle={{color: colors.grey500, width: 206}} + floatingLabelStyle={{color: colors.grey, width: 206}} errorText={errorText} value={this.state.amountString} hintText={<span style={{textTransform: 'capitalize'}}>amount</span>} @@ -133,7 +133,7 @@ export class BalanceBoundedInput extends const increaseBalanceText = 'Increase balance'; const linkStyle = { cursor: 'pointer', - color: colors.grey900, + color: colors.darkestGrey, textDecoration: 'underline', display: 'inline', }; diff --git a/packages/website/ts/components/inputs/eth_amount_input.tsx b/packages/website/ts/components/inputs/eth_amount_input.tsx index 5c5e23eef..3dcd2b4f3 100644 --- a/packages/website/ts/components/inputs/eth_amount_input.tsx +++ b/packages/website/ts/components/inputs/eth_amount_input.tsx @@ -22,7 +22,7 @@ interface EthAmountInputState {} export class EthAmountInput extends React.Component<EthAmountInputProps, EthAmountInputState> { public render() { const amount = this.props.amount ? - ZeroEx.toUnitAmount(this.props.amount, constants.ETH_DECIMAL_PLACES) : + ZeroEx.toUnitAmount(this.props.amount, constants.DECIMAL_PLACES_ETH) : undefined; return ( <div className="flex overflow-hidden" style={{height: 63}}> @@ -45,7 +45,7 @@ export class EthAmountInput extends React.Component<EthAmountInputProps, EthAmou private onChange(isValid: boolean, amount?: BigNumber) { const baseUnitAmountIfExists = _.isUndefined(amount) ? undefined : - ZeroEx.toBaseUnitAmount(amount, constants.ETH_DECIMAL_PLACES); + ZeroEx.toBaseUnitAmount(amount, constants.DECIMAL_PLACES_ETH); this.props.onChange(isValid, baseUnitAmountIfExists); } } diff --git a/packages/website/ts/components/inputs/token_amount_input.tsx b/packages/website/ts/components/inputs/token_amount_input.tsx index 1ae9bc85e..c9728dc5f 100644 --- a/packages/website/ts/components/inputs/token_amount_input.tsx +++ b/packages/website/ts/components/inputs/token_amount_input.tsx @@ -1,11 +1,11 @@ import {ZeroEx} from '0x.js'; import BigNumber from 'bignumber.js'; import * as _ from 'lodash'; -import {colors} from 'material-ui/styles'; import * as React from 'react'; import {Link} from 'react-router-dom'; import {BalanceBoundedInput} from 'ts/components/inputs/balance_bounded_input'; import {InputErrMsg, Token, TokenState, ValidatedBigNumberCallback, WebsitePaths} from 'ts/types'; +import {colors} from 'ts/utils/colors'; interface TokenAmountInputProps { token: Token; @@ -59,7 +59,7 @@ export class TokenAmountInput extends React.Component<TokenAmountInputProps, Tok Insufficient allowance.{' '} <Link to={`${WebsitePaths.Portal}/balances`} - style={{cursor: 'pointer', color: colors.grey900}} + style={{cursor: 'pointer', color: colors.darkestGrey}} > Set allowance </Link> diff --git a/packages/website/ts/components/inputs/token_input.tsx b/packages/website/ts/components/inputs/token_input.tsx index 67f697f05..7008da12f 100644 --- a/packages/website/ts/components/inputs/token_input.tsx +++ b/packages/website/ts/components/inputs/token_input.tsx @@ -1,6 +1,5 @@ import * as _ from 'lodash'; import Paper from 'material-ui/Paper'; -import {colors} from 'material-ui/styles'; import * as React from 'react'; import {Blockchain} from 'ts/blockchain'; import {AssetPicker} from 'ts/components/generate_order/asset_picker'; @@ -8,6 +7,7 @@ import {InputLabel} from 'ts/components/ui/input_label'; import {TokenIcon} from 'ts/components/ui/token_icon'; import {Dispatcher} from 'ts/redux/dispatcher'; import {AssetToken, BlockchainErrs, Side, Token, TokenByAddress} from 'ts/types'; +import {colors} from 'ts/utils/colors'; const TOKEN_ICON_DIMENSION = 80; @@ -62,7 +62,7 @@ export class TokenInput extends React.Component<TokenInputProps, TokenInputState > <TokenIcon token={token} diameter={TOKEN_ICON_DIMENSION} /> </div> - <div className="py1 center" style={{color: colors.grey500}}> + <div className="py1 center" style={{color: colors.grey}}> {token.name} </div> </Paper> @@ -95,7 +95,7 @@ export class TokenInput extends React.Component<TokenInputProps, TokenInputState }); } private onAssetClicked() { - if (this.props.blockchainErr !== '') { + if (this.props.blockchainErr !== BlockchainErrs.NoError) { this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); return; } diff --git a/packages/website/ts/components/order_json.tsx b/packages/website/ts/components/order_json.tsx index 83f25fd5a..340e5d91f 100644 --- a/packages/website/ts/components/order_json.tsx +++ b/packages/website/ts/components/order_json.tsx @@ -1,6 +1,6 @@ import BigNumber from 'bignumber.js'; import * as _ from 'lodash'; -import {Paper} from 'material-ui/Paper'; +import Paper from 'material-ui/Paper'; import TextField from 'material-ui/TextField'; import * as React from 'react'; import {CopyIcon} from 'ts/components/ui/copy_icon'; @@ -137,9 +137,8 @@ You can see and fill it here: ${this.state.shareLink}`); } private async generateShareLinkAsync(): Promise<string> { const longUrl = encodeURIComponent(this.getOrderUrl()); - const bitlyRequestUrl = constants.BITLY_ENDPOINT + '/v3/shorten?' + - 'access_token=' + constants.BITLY_ACCESS_TOKEN + - '&longUrl=' + longUrl; + const bitlyRequestUrl = + `${constants.URL_BITLY_API}/v3/shorten?access_token=${configs.BITLY_ACCESS_TOKEN}&longUrl=${longUrl}`; const response = await fetch(bitlyRequestUrl); const responseBody = await response.text(); const bodyObj = JSON.parse(responseBody); diff --git a/packages/website/ts/components/portal.tsx b/packages/website/ts/components/portal.tsx index 74b1bdec6..939dae6f7 100644 --- a/packages/website/ts/components/portal.tsx +++ b/packages/website/ts/components/portal.tsx @@ -1,13 +1,13 @@ import BigNumber from 'bignumber.js'; import * as _ from 'lodash'; import Paper from 'material-ui/Paper'; -import {colors} from 'material-ui/styles'; import * as React from 'react'; import * as DocumentTitle from 'react-document-title'; import {Route, Switch} from 'react-router-dom'; import {Blockchain} from 'ts/blockchain'; import {BlockchainErrDialog} from 'ts/components/dialogs/blockchain_err_dialog'; import {PortalDisclaimerDialog} from 'ts/components/dialogs/portal_disclaimer_dialog'; +import {WrappedEthSectionNoticeDialog} from 'ts/components/dialogs/wrapped_eth_section_notice_dialog'; import {EthWrappers} from 'ts/components/eth_wrappers'; import {FillOrder} from 'ts/components/fill_order'; import {Footer} from 'ts/components/footer'; @@ -32,6 +32,7 @@ import { TokenStateByAddress, WebsitePaths, } from 'ts/types'; +import {colors} from 'ts/utils/colors'; import {configs} from 'ts/utils/configs'; import {constants} from 'ts/utils/constants'; import {utils} from 'ts/utils/utils'; @@ -63,22 +64,39 @@ interface PortalAllState { prevNetworkId: number; prevNodeVersion: string; prevUserAddress: string; - hasAcceptedDisclaimer: boolean; + prevPathname: string; + isDisclaimerDialogOpen: boolean; + isWethNoticeDialogOpen: boolean; } export class Portal extends React.Component<PortalAllProps, PortalAllState> { private blockchain: Blockchain; private sharedOrderIfExists: Order; private throttledScreenWidthUpdate: () => void; + public static hasAlreadyDismissedWethNotice() { + const didDismissWethNotice = localStorage.getItemIfExists(constants.LOCAL_STORAGE_KEY_DISMISS_WETH_NOTICE); + const hasAlreadyDismissedWethNotice = !_.isUndefined(didDismissWethNotice) && + !_.isEmpty(didDismissWethNotice); + return hasAlreadyDismissedWethNotice; + } constructor(props: PortalAllProps) { super(props); this.sharedOrderIfExists = this.getSharedOrderIfExists(); this.throttledScreenWidthUpdate = _.throttle(this.updateScreenWidth.bind(this), THROTTLE_TIMEOUT); + + const isViewingBalances = _.includes(props.location.pathname, `${WebsitePaths.Portal}/balances`); + const hasAlreadyDismissedWethNotice = Portal.hasAlreadyDismissedWethNotice(); + + const didAcceptPortalDisclaimer = localStorage.getItemIfExists(constants.LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER); + const hasAcceptedDisclaimer = !_.isUndefined(didAcceptPortalDisclaimer) && + !_.isEmpty(didAcceptPortalDisclaimer); this.state = { prevNetworkId: this.props.networkId, prevNodeVersion: this.props.nodeVersion, prevUserAddress: this.props.userAddress, - hasAcceptedDisclaimer: false, + prevPathname: this.props.location.pathname, + isDisclaimerDialogOpen: !hasAcceptedDisclaimer, + isWethNoticeDialogOpen: !hasAlreadyDismissedWethNotice && isViewingBalances, }; } public componentDidMount() { @@ -87,12 +105,6 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> { } public componentWillMount() { this.blockchain = new Blockchain(this.props.dispatcher); - const didAcceptPortalDisclaimer = localStorage.getItemIfExists(constants.ACCEPT_DISCLAIMER_LOCAL_STORAGE_KEY); - const hasAcceptedDisclaimer = !_.isUndefined(didAcceptPortalDisclaimer) && - !_.isEmpty(didAcceptPortalDisclaimer); - this.setState({ - hasAcceptedDisclaimer, - }); } public componentWillUnmount() { this.blockchain.destroy(); @@ -128,6 +140,14 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> { // tslint:disable-next-line:no-floating-promises this.blockchain.nodeVersionUpdatedFireAndForgetAsync(nextProps.nodeVersion); } + if (nextProps.location.pathname !== this.state.prevPathname) { + const isViewingBalances = _.includes(nextProps.location.pathname, `${WebsitePaths.Portal}/balances`); + const hasAlreadyDismissedWethNotice = Portal.hasAlreadyDismissedWethNotice(); + this.setState({ + prevPathname: nextProps.location.pathname, + isWethNoticeDialogOpen: !hasAlreadyDismissedWethNotice && isViewingBalances, + }); + } } public render() { const updateShouldBlockchainErrDialogBeOpen = this.props.dispatcher @@ -138,6 +158,11 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> { flexDirection: 'column', justifyContent: 'space-between', }; + const portalMenuContainerStyle: React.CSSProperties = { + overflow: 'hidden', + backgroundColor: colors.darkestGrey, + color: colors.white, + }; return ( <div style={portalStyle}> <DocumentTitle title="0x Portal DApp"/> @@ -146,9 +171,9 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> { blockchainIsLoaded={this.props.blockchainIsLoaded} location={this.props.location} /> - <div id="portal" className="mx-auto max-width-4 pt4" style={{width: '100%'}}> + <div id="portal" className="mx-auto max-width-4" style={{width: '100%'}}> <Paper className="mb3 mt2"> - {!configs.isMainnetEnabled && this.props.networkId === constants.MAINNET_NETWORK_ID ? + {!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"> @@ -171,9 +196,9 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> { <div className="mx-auto flex"> <div className="col col-2 pr2 pt1 sm-hide xs-hide" - style={{overflow: 'hidden', backgroundColor: 'rgb(39, 39, 39)', color: 'white'}} + style={portalMenuContainerStyle} > - <PortalMenu menuItemStyle={{color: 'white'}} /> + <PortalMenu 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}}> @@ -215,8 +240,12 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> { toggleDialogFn={updateShouldBlockchainErrDialogBeOpen} networkId={this.props.networkId} /> + <WrappedEthSectionNoticeDialog + isOpen={this.state.isWethNoticeDialogOpen} + onToggleDialog={this.onWethNoticeAccepted.bind(this)} + /> <PortalDisclaimerDialog - isOpen={!this.state.hasAcceptedDisclaimer} + isOpen={this.state.isDisclaimerDialogOpen} onToggleDialog={this.onPortalDisclaimerAccepted.bind(this)} /> <FlashMessage @@ -224,7 +253,7 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> { flashMessage={this.props.flashMessage} /> </div> - <Footer location={this.props.location} /> + <Footer /> </div> ); } @@ -295,9 +324,15 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> { ); } private onPortalDisclaimerAccepted() { - localStorage.setItem(constants.ACCEPT_DISCLAIMER_LOCAL_STORAGE_KEY, 'set'); + localStorage.setItem(constants.LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER, 'set'); + this.setState({ + isDisclaimerDialogOpen: false, + }); + } + private onWethNoticeAccepted() { + localStorage.setItem(constants.LOCAL_STORAGE_KEY_DISMISS_WETH_NOTICE, 'set'); this.setState({ - hasAcceptedDisclaimer: true, + isWethNoticeDialogOpen: false, }); } private getSharedOrderIfExists(): Order { diff --git a/packages/website/ts/components/send_button.tsx b/packages/website/ts/components/send_button.tsx index b3fd2aeba..23e61e77e 100644 --- a/packages/website/ts/components/send_button.tsx +++ b/packages/website/ts/components/send_button.tsx @@ -70,14 +70,14 @@ export class SendButton extends React.Component<SendButtonProps, SendButtonState this.props.dispatcher.replaceTokenBalanceByAddress(token.address, balance); } catch (err) { const errMsg = `${err}`; - if (_.includes(errMsg, BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES)) { + if (_.includes(errMsg, BlockchainCallErrs.UserHasNoAssociatedAddresses)) { this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); return; } else if (!_.includes(errMsg, 'User denied transaction')) { utils.consoleLog(`Unexpected error encountered: ${err}`); utils.consoleLog(err.stack); - await errorReporter.reportAsync(err); this.props.onError(); + await errorReporter.reportAsync(err); } } this.setState({ diff --git a/packages/website/ts/components/token_balances.tsx b/packages/website/ts/components/token_balances.tsx index db4a35062..ab4b04868 100644 --- a/packages/website/ts/components/token_balances.tsx +++ b/packages/website/ts/components/token_balances.tsx @@ -7,7 +7,6 @@ import Divider from 'material-ui/Divider'; import FlatButton from 'material-ui/FlatButton'; import FloatingActionButton from 'material-ui/FloatingActionButton'; import RaisedButton from 'material-ui/RaisedButton'; -import {colors} from 'material-ui/styles'; import ContentAdd from 'material-ui/svg-icons/content/add'; import ContentRemove from 'material-ui/svg-icons/content/remove'; import { @@ -42,6 +41,7 @@ import { TokenStateByAddress, TokenVisibility, } from 'ts/types'; +import {colors} from 'ts/utils/colors'; import {configs} from 'ts/utils/configs'; import {constants} from 'ts/utils/constants'; import {errorReporter} from 'ts/utils/error_reporter'; @@ -115,7 +115,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala if (!_.isUndefined(this.state.currentZrxBalance) && !nextZrxTokenBalance.eq(this.state.currentZrxBalance)) { if (this.state.isZRXSpinnerVisible) { const receivedAmount = nextZrxTokenBalance.minus(this.state.currentZrxBalance); - const receiveAmountInUnits = ZeroEx.toUnitAmount(receivedAmount, 18); + const receiveAmountInUnits = ZeroEx.toUnitAmount(receivedAmount, constants.DECIMAL_PLACES_ZRX); this.props.dispatcher.showFlashMessage(`Received ${receiveAmountInUnits.toString(10)} Kovan ZRX`); } this.setState({ @@ -144,7 +144,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala onTouchTap={this.onDharmaDialogToggle.bind(this, false)} />, ]; - const isTestNetwork = this.props.networkId === constants.TESTNET_NETWORK_ID; + const isTestNetwork = this.props.networkId === constants.NETWORK_ID_TESTNET; const dharmaButtonColumnStyle = { paddingLeft: 3, display: isTestNetwork ? 'table-cell' : 'none', @@ -156,7 +156,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala const tokenTableHeight = allTokenRowHeight < MAX_TOKEN_TABLE_HEIGHT ? allTokenRowHeight : MAX_TOKEN_TABLE_HEIGHT; - const isSmallScreen = this.props.screenWidth === ScreenWidths.SM; + const isSmallScreen = this.props.screenWidth === ScreenWidths.Sm; const tokenColSpan = isSmallScreen ? TOKEN_COL_SPAN_SM : TOKEN_COL_SPAN_LG; const dharmaLoanExplanation = 'If you need access to larger amounts of ether,<br> \ you can request a loan from the Dharma Loan<br> \ @@ -164,7 +164,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala minutes or less.'; const allowanceExplanation = '0x smart contracts require access to your<br> \ token balances in order to execute trades.<br> \ - Toggling permissions sets an allowance for the<br> \ + Toggling sets an allowance for the<br> \ smart contract so you can start trading that token.'; return ( <div className="lg-px4 md-px4 sm-px1 pb2"> @@ -302,7 +302,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala </TableHeaderColumn> <TableHeaderColumn style={{paddingLeft: 3}}>Balance</TableHeaderColumn> <TableHeaderColumn> - <div className="inline-block">{!isSmallScreen && 'Trade '}Permissions</div> + <div className="inline-block">Allowance</div> <HelpTooltip style={{paddingLeft: 4}} explanation={allowanceExplanation} @@ -311,7 +311,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala <TableHeaderColumn> Action </TableHeaderColumn> - {this.props.screenWidth !== ScreenWidths.SM && + {this.props.screenWidth !== ScreenWidths.Sm && <TableHeaderColumn> Send </TableHeaderColumn> @@ -333,9 +333,9 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala </Dialog> <Dialog title="Request Dharma Loan" - titleStyle={{fontWeight: 100, backgroundColor: 'rgb(250, 250, 250)'}} - bodyStyle={{backgroundColor: 'rgb(37, 37, 37)'}} - actionsContainerStyle={{backgroundColor: 'rgb(250, 250, 250)'}} + titleStyle={{fontWeight: 100, backgroundColor: colors.white}} + bodyStyle={{backgroundColor: colors.dharmaDarkGrey}} + actionsContainerStyle={{backgroundColor: colors.white}} autoScrollBodyContent={true} actions={dharmaDialogActions} open={this.state.isDharmaDialogVisible} @@ -357,10 +357,10 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala ); } private renderTokenTableRows() { - if (!this.props.blockchainIsLoaded || this.props.blockchainErr !== '') { + if (!this.props.blockchainIsLoaded || this.props.blockchainErr !== BlockchainErrs.NoError) { return ''; } - const isSmallScreen = this.props.screenWidth === ScreenWidths.SM; + const isSmallScreen = this.props.screenWidth === ScreenWidths.Sm; const tokenColSpan = isSmallScreen ? TOKEN_COL_SPAN_SM : TOKEN_COL_SPAN_LG; const actionPaddingX = isSmallScreen ? 2 : 24; const allTokens = _.values(this.props.tokenByAddress); @@ -379,9 +379,9 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala private renderTokenRow(tokenColSpan: number, actionPaddingX: number, token: Token) { const tokenState = this.props.tokenStateByAddress[token.address]; const tokenLink = utils.getEtherScanLinkIfExists(token.address, this.props.networkId, - EtherscanLinkSuffixes.address); - const isMintable = _.includes(configs.symbolsOfMintableTokens, token.symbol) && - this.props.networkId !== constants.MAINNET_NETWORK_ID; + EtherscanLinkSuffixes.Address); + const isMintable = _.includes(configs.SYMBOLS_OF_MINTABLE_TOKENS, token.symbol) && + this.props.networkId !== constants.NETWORK_ID_MAINNET; return ( <TableRow key={token.address} style={{height: TOKEN_TABLE_ROW_HEIGHT}}> <TableRowColumn @@ -423,7 +423,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala onClickAsyncFn={this.onMintTestTokensAsync.bind(this, token)} /> } - {token.symbol === ZRX_TOKEN_SYMBOL && this.props.networkId === constants.TESTNET_NETWORK_ID && + {token.symbol === ZRX_TOKEN_SYMBOL && this.props.networkId === constants.NETWORK_ID_TESTNET && <LifeCycleRaisedButton labelReady="Request" labelLoading="Sending..." @@ -432,7 +432,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala /> } </TableRowColumn> - {this.props.screenWidth !== ScreenWidths.SM && + {this.props.screenWidth !== ScreenWidths.Sm && <TableRowColumn style={{paddingLeft: actionPaddingX, paddingRight: actionPaddingX}} > @@ -456,13 +456,14 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala return; } const token = this.props.tokenByAddress[tokenAddress]; - const isDefaultTrackedToken = _.includes(configs.defaultTrackedTokenSymbols, token.symbol); + const isDefaultTrackedToken = _.includes(configs.DEFAULT_TRACKED_TOKEN_SYMBOLS, token.symbol); if (!this.state.isAddingToken && !isDefaultTrackedToken) { if (token.isRegistered) { // Remove the token from tracked tokens - const newToken = _.assign({}, token, { + const newToken = { + ...token, isTracked: false, - }); + }; this.props.dispatcher.updateTokenByAddress([newToken]); } else { this.props.dispatcher.removeTokenToTokenByAddress(token); @@ -507,7 +508,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala return ( <div> Our faucet can only send test Ether to addresses on the {constants.TESTNET_NAME} - {' '}testnet (networkId {constants.TESTNET_NETWORK_ID}). Please make sure you are + {' '}testnet (networkId {constants.NETWORK_ID_TESTNET}). Please make sure you are {' '}connected to the {constants.TESTNET_NAME} testnet and try requesting ether again. </div> ); @@ -580,7 +581,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala return true; } catch (err) { const errMsg = '' + err; - if (_.includes(errMsg, BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES)) { + if (_.includes(errMsg, BlockchainCallErrs.UserHasNoAssociatedAddresses)) { this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); return false; } @@ -604,7 +605,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala // If on another network other then the testnet our faucet serves test ether // from, we must show user an error message - if (this.props.blockchain.networkId !== constants.TESTNET_NETWORK_ID) { + if (this.props.blockchain.networkId !== constants.NETWORK_ID_TESTNET) { this.setState({ errorType: BalanceErrs.incorrectNetworkForFaucet, }); @@ -614,7 +615,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala await utils.sleepAsync(ARTIFICIAL_FAUCET_REQUEST_DELAY); const segment = isEtherRequest ? 'ether' : 'zrx'; - const response = await fetch(`${constants.ETHER_FAUCET_ENDPOINT}/${segment}/${this.props.userAddress}`); + const response = await fetch(`${constants.URL_ETHER_FAUCET}/${segment}/${this.props.userAddress}`); const responseBody = await response.text(); if (response.status !== constants.SUCCESS_STATUS) { utils.consoleLog(`Unexpected status code: ${response.status} -> ${responseBody}`); diff --git a/packages/website/ts/components/top_bar.tsx b/packages/website/ts/components/top_bar.tsx index 27de49620..025ed3635 100644 --- a/packages/website/ts/components/top_bar.tsx +++ b/packages/website/ts/components/top_bar.tsx @@ -1,7 +1,6 @@ import * as _ from 'lodash'; import Drawer from 'material-ui/Drawer'; import MenuItem from 'material-ui/MenuItem'; -import {colors} from 'material-ui/styles'; import * as React from 'react'; import {Link} from 'react-router-dom'; import ReactTooltip = require('react-tooltip'); @@ -12,11 +11,9 @@ import {Identicon} from 'ts/components/ui/identicon'; import {DocsInfo} from 'ts/pages/documentation/docs_info'; import {NestedSidebarMenu} from 'ts/pages/shared/nested_sidebar_menu'; import {DocsMenu, MenuSubsectionsBySection, Styles, WebsitePaths} from 'ts/types'; +import {colors} from 'ts/utils/colors'; import {constants} from 'ts/utils/constants'; -const CUSTOM_DARK_GRAY = '#231F20'; -const SECTION_HEADER_COLOR = 'rgb(234, 234, 234)'; - interface TopBarProps { userAddress?: string; blockchainIsLoaded: boolean; @@ -44,16 +41,11 @@ const styles: Styles = { whiteSpace: 'nowrap', width: 70, }, - addressPopover: { - backgroundColor: colors.blueGrey500, - color: 'white', - padding: 3, - }, topBar: { - backgroundColor: 'white', + backgroundcolor: colors.white, height: 59, width: '100%', - position: 'fixed', + position: 'relative', top: 0, zIndex: 1100, paddingBottom: 1, @@ -63,7 +55,7 @@ const styles: Styles = { }, menuItem: { fontSize: 14, - color: CUSTOM_DARK_GRAY, + color: colors.darkestGrey, paddingTop: 6, paddingBottom: 6, marginTop: 17, @@ -114,7 +106,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { key="subMenuItem-standard-relayer-api" target="_blank" className="text-decoration-none" - href={constants.STANDARD_RELAYER_API_GITHUB} + href={constants.URL_STANDARD_RELAYER_API_GITHUB} > <MenuItem style={{fontSize: styles.menuItem.fontSize}} primaryText="Standard Relayer API" /> </a>, @@ -122,7 +114,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { key="subMenuItem-github" target="_blank" className="text-decoration-none" - href={constants.GITHUB_URL} + href={constants.URL_GITHUB_ORG} > <MenuItem style={{fontSize: styles.menuItem.fontSize}} primaryText="GitHub" /> </a>, @@ -222,7 +214,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { {this.renderPortalMenu()} {this.renderDocsMenu()} {this.renderWiki()} - <div className="pl1 py1 mt3" style={{backgroundColor: SECTION_HEADER_COLOR}}>Website</div> + <div className="pl1 py1 mt3" style={{backgroundColor: colors.lightGrey}}>Website</div> <Link to={WebsitePaths.Home} className="text-decoration-none"> <MenuItem className="py2">Home</MenuItem> </Link> @@ -262,7 +254,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { <a className="text-decoration-none" target="_blank" - href={constants.BLOG_URL} + href={constants.URL_BLOG} > <MenuItem className="py2">Blog</MenuItem> </a> @@ -286,7 +278,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { const sectionTitle = `${this.props.docsInfo.displayName} Docs`; return ( <div className="lg-hide md-hide"> - <div className="pl1 py1" style={{backgroundColor: SECTION_HEADER_COLOR}}>{sectionTitle}</div> + <div className="pl1 py1" style={{backgroundColor: colors.lightGrey}}>{sectionTitle}</div> <NestedSidebarMenu topLevelMenu={this.props.menu} menuSubsectionsBySection={this.props.menuSubsectionsBySection} @@ -306,7 +298,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { return ( <div className="lg-hide md-hide"> - <div className="pl1 py1" style={{backgroundColor: SECTION_HEADER_COLOR}}>0x Protocol Wiki</div> + <div className="pl1 py1" style={{backgroundColor: colors.lightGrey}}>0x Protocol Wiki</div> <NestedSidebarMenu topLevelMenu={this.props.menuSubsectionsBySection} menuSubsectionsBySection={this.props.menuSubsectionsBySection} @@ -323,7 +315,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { return ( <div className="lg-hide md-hide"> - <div className="pl1 py1" style={{backgroundColor: SECTION_HEADER_COLOR}}>Portal DApp</div> + <div className="pl1 py1" style={{backgroundColor: colors.lightGrey}}>Portal DApp</div> <PortalMenu menuItemStyle={{color: 'black'}} onClick={this.onMenuButtonClick.bind(this)} diff --git a/packages/website/ts/components/top_bar_menu_item.tsx b/packages/website/ts/components/top_bar_menu_item.tsx index 38dc91194..64cb48b2e 100644 --- a/packages/website/ts/components/top_bar_menu_item.tsx +++ b/packages/website/ts/components/top_bar_menu_item.tsx @@ -1,10 +1,10 @@ import * as _ from 'lodash'; import * as React from 'react'; import {Link} from 'react-router-dom'; +import {colors} from 'ts/utils/colors'; -const CUSTOM_DARK_GRAY = '#231F20'; const DEFAULT_STYLE = { - color: CUSTOM_DARK_GRAY, + color: colors.darkestGrey, }; interface TopBarMenuItemProps { @@ -28,7 +28,7 @@ export class TopBarMenuItem extends React.Component<TopBarMenuItemProps, TopBarM public render() { const primaryStyles = this.props.isPrimary ? { borderRadius: 4, - border: `1px solid ${this.props.isNightVersion ? '#979797' : 'rgb(230, 229, 229)'}`, + border: `1px solid ${this.props.isNightVersion ? colors.grey : colors.greyishPink}`, marginTop: 15, paddingLeft: 9, paddingRight: 9, @@ -36,7 +36,7 @@ export class TopBarMenuItem extends React.Component<TopBarMenuItemProps, TopBarM } : {}; const menuItemColor = this.props.isNightVersion ? 'white' : this.props.style.color; const linkColor = _.isUndefined(menuItemColor) ? - CUSTOM_DARK_GRAY : + colors.darkestGrey : menuItemColor; return ( <div diff --git a/packages/website/ts/components/track_token_confirmation.tsx b/packages/website/ts/components/track_token_confirmation.tsx index cd588f239..ff840fe8c 100644 --- a/packages/website/ts/components/track_token_confirmation.tsx +++ b/packages/website/ts/components/track_token_confirmation.tsx @@ -1,8 +1,8 @@ import * as _ from 'lodash'; -import {colors} from 'material-ui/styles'; import * as React from 'react'; import {Party} from 'ts/components/ui/party'; import {Token, TokenByAddress} from 'ts/types'; +import {colors} from 'ts/utils/colors'; import {utils} from 'ts/utils/utils'; interface TrackTokenConfirmationProps { diff --git a/packages/website/ts/components/trade_history/trade_history_item.tsx b/packages/website/ts/components/trade_history/trade_history_item.tsx index 4dcceadb7..d2a334df9 100644 --- a/packages/website/ts/components/trade_history/trade_history_item.tsx +++ b/packages/website/ts/components/trade_history/trade_history_item.tsx @@ -2,13 +2,13 @@ import {ZeroEx} from '0x.js'; import BigNumber from 'bignumber.js'; import * as _ from 'lodash'; import Paper from 'material-ui/Paper'; -import {colors} from 'material-ui/styles'; import * as moment from 'moment'; import * as React from 'react'; import * as ReactTooltip from 'react-tooltip'; import {EtherScanIcon} from 'ts/components/ui/etherscan_icon'; import {Party} from 'ts/components/ui/party'; import {EtherscanLinkSuffixes, Fill, Token, TokenByAddress} from 'ts/types'; +import {colors} from 'ts/utils/colors'; const PRECISION = 5; const IDENTICON_DIAMETER = 40; @@ -87,7 +87,7 @@ export class TradeHistoryItem extends React.Component<TradeHistoryItemProps, Tra <EtherScanIcon addressOrTxHash={fill.transactionHash} networkId={this.props.networkId} - etherscanLinkSuffixes={EtherscanLinkSuffixes.tx} + etherscanLinkSuffixes={EtherscanLinkSuffixes.Tx} /> </div> </div> diff --git a/packages/website/ts/components/ui/alert.tsx b/packages/website/ts/components/ui/alert.tsx index 71d2388f2..bc65d0f0f 100644 --- a/packages/website/ts/components/ui/alert.tsx +++ b/packages/website/ts/components/ui/alert.tsx @@ -1,8 +1,6 @@ -import {colors} from 'material-ui/styles'; import * as React from 'react'; import {AlertTypes} from 'ts/types'; - -const CUSTOM_GREEN = 'rgb(137, 199, 116)'; +import {colors} from 'ts/utils/colors'; interface AlertProps { type: AlertTypes; @@ -12,8 +10,8 @@ interface AlertProps { export function Alert(props: AlertProps) { const isAlert = props.type === AlertTypes.ERROR; const errMsgStyles = { - background: isAlert ? colors.red200 : CUSTOM_GREEN, - color: 'white', + background: isAlert ? colors.red200 : colors.lightestGreen, + color: colors.white, marginTop: 10, padding: 4, paddingLeft: 8, diff --git a/packages/website/ts/components/ui/copy_icon.tsx b/packages/website/ts/components/ui/copy_icon.tsx index 5f8e6a060..3c50430df 100644 --- a/packages/website/ts/components/ui/copy_icon.tsx +++ b/packages/website/ts/components/ui/copy_icon.tsx @@ -1,9 +1,9 @@ import * as _ from 'lodash'; -import {colors} from 'material-ui/styles'; import * as React from 'react'; import * as CopyToClipboard from 'react-copy-to-clipboard'; import * as ReactDOM from 'react-dom'; import ReactTooltip = require('react-tooltip'); +import {colors} from 'ts/utils/colors'; interface CopyIconProps { data: string; diff --git a/packages/website/ts/components/ui/drop_down_menu_item.tsx b/packages/website/ts/components/ui/drop_down_menu_item.tsx index 041688a9d..55347cb98 100644 --- a/packages/website/ts/components/ui/drop_down_menu_item.tsx +++ b/packages/website/ts/components/ui/drop_down_menu_item.tsx @@ -2,9 +2,9 @@ import * as _ from 'lodash'; import Menu from 'material-ui/Menu'; import Popover from 'material-ui/Popover'; import * as React from 'react'; +import {colors} from 'ts/utils/colors'; const CHECK_CLOSE_POPOVER_INTERVAL_MS = 300; -const CUSTOM_LIGHT_GRAY = '#848484'; const DEFAULT_STYLE = { fontSize: 14, }; @@ -72,7 +72,7 @@ export class DropDownMenuItem extends React.Component<DropDownMenuItemProps, Dro onMouseEnter={this.onHover.bind(this)} onMouseLeave={this.onHoverOff.bind(this)} > - <Menu style={{color: CUSTOM_LIGHT_GRAY}}> + <Menu style={{color: colors.grey}}> {this.props.subMenuItems} </Menu> </div> diff --git a/packages/website/ts/components/ui/ethereum_address.tsx b/packages/website/ts/components/ui/ethereum_address.tsx index b3bc0bc59..d56840689 100644 --- a/packages/website/ts/components/ui/ethereum_address.tsx +++ b/packages/website/ts/components/ui/ethereum_address.tsx @@ -26,7 +26,7 @@ export const EthereumAddress = (props: EthereumAddressProps) => { <EtherScanIcon addressOrTxHash={props.address} networkId={props.networkId} - etherscanLinkSuffixes={EtherscanLinkSuffixes.address} + etherscanLinkSuffixes={EtherscanLinkSuffixes.Address} /> </div> <ReactTooltip id={tooltipId}>{props.address}</ReactTooltip> diff --git a/packages/website/ts/components/ui/etherscan_icon.tsx b/packages/website/ts/components/ui/etherscan_icon.tsx index 9b4d172f1..111d5d478 100644 --- a/packages/website/ts/components/ui/etherscan_icon.tsx +++ b/packages/website/ts/components/ui/etherscan_icon.tsx @@ -1,8 +1,8 @@ import * as _ from 'lodash'; -import {colors} from 'material-ui/styles'; import * as React from 'react'; import ReactTooltip = require('react-tooltip'); import {EtherscanLinkSuffixes} from 'ts/types'; +import {colors} from 'ts/utils/colors'; import {utils} from 'ts/utils/utils'; interface EtherScanIconProps { @@ -13,7 +13,7 @@ interface EtherScanIconProps { export const EtherScanIcon = (props: EtherScanIconProps) => { const etherscanLinkIfExists = utils.getEtherScanLinkIfExists( - props.addressOrTxHash, props.networkId, EtherscanLinkSuffixes.address, + props.addressOrTxHash, props.networkId, EtherscanLinkSuffixes.Address, ); const transactionTooltipId = `${props.addressOrTxHash}-etherscan-icon-tooltip`; return ( diff --git a/packages/website/ts/components/ui/input_label.tsx b/packages/website/ts/components/ui/input_label.tsx index 852097519..bfa1da280 100644 --- a/packages/website/ts/components/ui/input_label.tsx +++ b/packages/website/ts/components/ui/input_label.tsx @@ -1,5 +1,5 @@ -import {colors} from 'material-ui/styles'; import * as React from 'react'; +import {colors} from 'ts/utils/colors'; export interface InputLabelProps { text: string | Element | React.ReactNode; @@ -7,7 +7,7 @@ export interface InputLabelProps { const styles = { label: { - color: colors.grey500, + color: colors.grey, fontSize: 12, pointerEvents: 'none', textAlign: 'left', diff --git a/packages/website/ts/components/ui/labeled_switcher.tsx b/packages/website/ts/components/ui/labeled_switcher.tsx deleted file mode 100644 index 80a8fbe94..000000000 --- a/packages/website/ts/components/ui/labeled_switcher.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import * as _ from 'lodash'; -import {colors} from 'material-ui/styles'; -import * as React from 'react'; - -const CUSTOM_BLUE = '#63A6F1'; - -interface LabeledSwitcherProps { - labelLeft: string; - labelRight: string; - isLeftInitiallySelected: boolean; - onLeftLabelClickAsync: () => Promise<boolean>; - onRightLabelClickAsync: () => Promise<boolean>; -} - -interface LabeledSwitcherState { - isLeftSelected: boolean; -} - -export class LabeledSwitcher extends React.Component<LabeledSwitcherProps, LabeledSwitcherState> { - constructor(props: LabeledSwitcherProps) { - super(props); - this.state = { - isLeftSelected: props.isLeftInitiallySelected, - }; - } - public render() { - const isLeft = true; - return ( - <div - className="rounded clearfix" - > - {this.renderLabel(this.props.labelLeft, isLeft, this.state.isLeftSelected)} - {this.renderLabel(this.props.labelRight, !isLeft, !this.state.isLeftSelected)} - </div> - ); - } - private renderLabel(title: string, isLeft: boolean, isSelected: boolean) { - const borderStyle = `2px solid ${isSelected ? '#4F8BCF' : '#DADADA'}`; - const style = { - cursor: 'pointer', - backgroundColor: isSelected ? CUSTOM_BLUE : colors.grey200, - color: isSelected ? 'white' : '#A5A5A5', - boxShadow: isSelected ? `inset 0px 0px 4px #4083CE` : 'inset 0px 0px 4px #F7F6F6', - borderTop: borderStyle, - borderBottom: borderStyle, - [isLeft ? 'borderLeft' : 'borderRight']: borderStyle, - paddingTop: 12, - paddingBottom: 12, - }; - return ( - <div - className={`col col-6 center p1 ${isLeft ? 'rounded-left' : 'rounded-right'}`} - style={style} - onClick={this.onLabelClickAsync.bind(this, isLeft)} - > - {title} - </div> - ); - } - private async onLabelClickAsync(isLeft: boolean): Promise<void> { - this.setState({ - isLeftSelected: isLeft, - }); - const didSucceed = isLeft ? - await this.props.onLeftLabelClickAsync() : - await this.props.onRightLabelClickAsync(); - if (!didSucceed) { - this.setState({ - isLeftSelected: !isLeft, - }); - } - } -} diff --git a/packages/website/ts/components/ui/lifecycle_raised_button.tsx b/packages/website/ts/components/ui/lifecycle_raised_button.tsx index 2d668fb82..08e8bc9ce 100644 --- a/packages/website/ts/components/ui/lifecycle_raised_button.tsx +++ b/packages/website/ts/components/ui/lifecycle_raised_button.tsx @@ -1,6 +1,7 @@ import * as _ from 'lodash'; import RaisedButton from 'material-ui/RaisedButton'; import * as React from 'react'; +import {colors} from 'ts/utils/colors'; import {utils} from 'ts/utils/utils'; const COMPLETE_STATE_SHOW_LENGTH_MS = 2000; @@ -31,8 +32,8 @@ export class LifeCycleRaisedButton extends React.Component<LifeCycleRaisedButtonProps, LifeCycleRaisedButtonState> { public static defaultProps: Partial<LifeCycleRaisedButtonProps> = { isDisabled: false, - backgroundColor: 'white', - labelColor: 'rgb(97, 97, 97)', + backgroundColor: colors.white, + labelColor: colors.darkGrey, }; private buttonTimeoutId: number; private didUnmount: boolean; diff --git a/packages/website/ts/components/ui/party.tsx b/packages/website/ts/components/ui/party.tsx index e6b6ea9e2..918d42a3b 100644 --- a/packages/website/ts/components/ui/party.tsx +++ b/packages/website/ts/components/ui/party.tsx @@ -1,15 +1,14 @@ import * as _ from 'lodash'; -import {colors} from 'material-ui/styles'; import * as React from 'react'; import ReactTooltip = require('react-tooltip'); import {EthereumAddress} from 'ts/components/ui/ethereum_address'; import {Identicon} from 'ts/components/ui/identicon'; import {EtherscanLinkSuffixes} from 'ts/types'; +import {colors} from 'ts/utils/colors'; import {utils} from 'ts/utils/utils'; const IMAGE_DIMENSION = 100; const IDENTICON_DIAMETER = 95; -const CHECK_MARK_GREEN = 'rgb(0, 195, 62)'; interface PartyProps { label: string; @@ -45,7 +44,7 @@ export class Party extends React.Component<PartyProps, PartyState> { height: IMAGE_DIMENSION, }; const etherscanLinkIfExists = utils.getEtherScanLinkIfExists( - this.props.address, this.props.networkId, EtherscanLinkSuffixes.address, + this.props.address, this.props.networkId, EtherscanLinkSuffixes.Address, ); const isRegistered = this.props.isInTokenRegistry; const registeredTooltipId = `${this.props.address}-${isRegistered}-registeredTooltip`; @@ -94,7 +93,7 @@ export class Party extends React.Component<PartyProps, PartyState> { className="mx-auto" style={{fontSize: 13, width: 127}} > - <span style={{color: isRegistered ? CHECK_MARK_GREEN : colors.red500}}> + <span style={{color: isRegistered ? colors.brightGreen : colors.red500}}> <i className={`zmdi ${isRegistered ? 'zmdi-check-circle' : 'zmdi-alert-triangle'}`} /> diff --git a/packages/website/ts/components/ui/required_label.tsx b/packages/website/ts/components/ui/required_label.tsx index db69d7278..979b06d66 100644 --- a/packages/website/ts/components/ui/required_label.tsx +++ b/packages/website/ts/components/ui/required_label.tsx @@ -1,5 +1,5 @@ -import {colors} from 'material-ui/styles'; import * as React from 'react'; +import {colors} from 'ts/utils/colors'; export interface RequiredLabelProps { label: string|React.ReactNode; diff --git a/packages/website/ts/components/ui/swap_icon.tsx b/packages/website/ts/components/ui/swap_icon.tsx index b5d4b0caa..124e7018c 100644 --- a/packages/website/ts/components/ui/swap_icon.tsx +++ b/packages/website/ts/components/ui/swap_icon.tsx @@ -1,6 +1,6 @@ import * as _ from 'lodash'; -import {colors} from 'material-ui/styles'; import * as React from 'react'; +import {colors} from 'ts/utils/colors'; interface SwapIconProps { swapTokensFn: () => void; |