diff options
-rw-r--r-- | packages/website/package.json | 2 | ||||
-rw-r--r-- | packages/website/public/images/lock_icon.svg | 3 | ||||
-rw-r--r-- | packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx | 2 | ||||
-rw-r--r-- | packages/website/ts/components/dialogs/send_dialog.tsx | 1 | ||||
-rw-r--r-- | packages/website/ts/components/inputs/balance_bounded_input.tsx | 35 | ||||
-rw-r--r-- | packages/website/ts/components/inputs/eth_amount_input.tsx | 4 | ||||
-rw-r--r-- | packages/website/ts/components/inputs/token_amount_input.tsx | 2 | ||||
-rw-r--r-- | packages/website/ts/components/top_bar/provider_display.tsx | 4 | ||||
-rw-r--r-- | packages/website/ts/components/wallet/wallet.tsx | 53 | ||||
-rw-r--r-- | packages/website/ts/components/wallet/wrap_ether_item.tsx | 5 | ||||
-rw-r--r-- | packages/website/ts/utils/constants.ts | 3 | ||||
-rw-r--r-- | packages/website/ts/utils/utils.ts | 16 | ||||
-rw-r--r-- | yarn.lock | 8 |
13 files changed, 58 insertions, 80 deletions
diff --git a/packages/website/package.json b/packages/website/package.json index c7b689356..cc7b7c05c 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -38,6 +38,7 @@ "lodash": "^4.17.4", "material-ui": "^0.17.1", "moment": "2.21.0", + "numeral": "^2.0.6", "polished": "^1.9.2", "query-string": "^6.0.0", "react": "15.6.1", @@ -71,6 +72,7 @@ "@types/lodash": "4.14.104", "@types/material-ui": "0.18.0", "@types/node": "^8.0.53", + "@types/numeral": "^0.0.22", "@types/query-string": "^5.1.0", "@types/react": "16.3.13", "@types/react-copy-to-clipboard": "^4.2.0", diff --git a/packages/website/public/images/lock_icon.svg b/packages/website/public/images/lock_icon.svg new file mode 100644 index 000000000..83e8191a1 --- /dev/null +++ b/packages/website/public/images/lock_icon.svg @@ -0,0 +1,3 @@ +<svg width="26" height="32" viewBox="0 0 26 32" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M6.47619 0C3.79509 0 1.60489 2.21216 1.60489 4.92014V6.33135C0.717479 6.33135 -3.60127e-08 7.05602 -3.60127e-08 7.95232V14.379C-3.60127e-08 15.2753 0.717479 16 1.60489 16H11.3475C12.2349 16 12.9524 15.2753 12.9524 14.379V7.95232C12.9524 7.05602 12.2349 6.33135 11.3475 6.33135V4.92014C11.3475 2.21216 9.1573 0 6.47619 0ZM9.6482 6.33135H3.30418V4.92014C3.30418 3.16567 4.72026 1.71633 6.47619 1.71633C8.23213 1.71633 9.6482 3.16567 9.6482 4.92014V6.33135Z" transform="scale(2)" fill="black"/> +</svg> 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 9ac78e80e..7b09cc92c 100644 --- a/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx +++ b/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx @@ -103,7 +103,6 @@ export class EthWethConversionDialog extends React.Component< shouldCheckAllowance={false} onChange={this._onValueChange.bind(this)} amount={this.state.value} - onVisitBalancesPageClick={this.props.onCancelled} /> ) : ( <EthAmountInput @@ -112,7 +111,6 @@ export class EthWethConversionDialog extends React.Component< onChange={this._onValueChange.bind(this)} shouldCheckBalance={true} shouldShowIncompleteErrs={this.state.shouldShowIncompleteErrs} - onVisitBalancesPageClick={this.props.onCancelled} /> )} <div className="pt1" style={{ fontSize: 12 }}> diff --git a/packages/website/ts/components/dialogs/send_dialog.tsx b/packages/website/ts/components/dialogs/send_dialog.tsx index 421f18b4f..8a98fdf69 100644 --- a/packages/website/ts/components/dialogs/send_dialog.tsx +++ b/packages/website/ts/components/dialogs/send_dialog.tsx @@ -80,7 +80,6 @@ export class SendDialog extends React.Component<SendDialogProps, SendDialogState shouldCheckAllowance={false} onChange={this._onValueChange.bind(this)} amount={this.state.value} - onVisitBalancesPageClick={this.props.onCancelled} lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} /> </div> diff --git a/packages/website/ts/components/inputs/balance_bounded_input.tsx b/packages/website/ts/components/inputs/balance_bounded_input.tsx index 968609030..f23beb436 100644 --- a/packages/website/ts/components/inputs/balance_bounded_input.tsx +++ b/packages/website/ts/components/inputs/balance_bounded_input.tsx @@ -3,9 +3,8 @@ import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; 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 { ValidatedBigNumberCallback, WebsitePaths } from 'ts/types'; +import { ValidatedBigNumberCallback } from 'ts/types'; import { utils } from 'ts/utils/utils'; interface BalanceBoundedInputProps { @@ -18,8 +17,6 @@ interface BalanceBoundedInputProps { shouldShowIncompleteErrs?: boolean; shouldCheckBalance: boolean; validate?: (amount: BigNumber) => React.ReactNode; - onVisitBalancesPageClick?: () => void; - shouldHideVisitBalancesLink?: boolean; isDisabled?: boolean; shouldShowErrs?: boolean; shouldShowUnderline?: boolean; @@ -35,7 +32,6 @@ interface BalanceBoundedInputState { export class BalanceBoundedInput extends React.Component<BalanceBoundedInputProps, BalanceBoundedInputState> { public static defaultProps: Partial<BalanceBoundedInputProps> = { shouldShowIncompleteErrs: false, - shouldHideVisitBalancesLink: false, isDisabled: false, shouldShowErrs: true, hintText: 'amount', @@ -124,38 +120,11 @@ export class BalanceBoundedInput extends React.Component<BalanceBoundedInputProp return 'Cannot be zero'; } if (this.props.shouldCheckBalance && amount.gt(balance)) { - return <span>Insufficient balance. {this._renderIncreaseBalanceLink()}</span>; + return <span>Insufficient balance.</span>; } const errMsg = _.isUndefined(this.props.validate) ? undefined : this.props.validate(amount); return errMsg; } - private _renderIncreaseBalanceLink(): React.ReactNode { - if (this.props.shouldHideVisitBalancesLink) { - return null; - } - - const increaseBalanceText = 'Increase balance'; - const linkStyle = { - cursor: 'pointer', - color: colors.darkestGrey, - textDecoration: 'underline', - display: 'inline', - }; - if (_.isUndefined(this.props.onVisitBalancesPageClick)) { - return ( - <Link to={`${WebsitePaths.Portal}/balances`} style={linkStyle}> - {increaseBalanceText} - </Link> - ); - } else { - return ( - <div onClick={this.props.onVisitBalancesPageClick} style={linkStyle}> - {increaseBalanceText} - </div> - ); - } - } - private _setAmountState(amount: string, balance: BigNumber, callback: () => void = _.noop): void { const errorMsg = this._validate(amount, balance); this.props.onErrorMsgChange(errorMsg); diff --git a/packages/website/ts/components/inputs/eth_amount_input.tsx b/packages/website/ts/components/inputs/eth_amount_input.tsx index 1f0f27410..552d4277a 100644 --- a/packages/website/ts/components/inputs/eth_amount_input.tsx +++ b/packages/website/ts/components/inputs/eth_amount_input.tsx @@ -14,9 +14,7 @@ interface EthAmountInputProps { onChange: ValidatedBigNumberCallback; onErrorMsgChange?: (errorMsg: React.ReactNode) => void; shouldShowIncompleteErrs: boolean; - onVisitBalancesPageClick?: () => void; shouldCheckBalance: boolean; - shouldHideVisitBalancesLink?: boolean; shouldShowErrs?: boolean; shouldShowUnderline?: boolean; style?: React.CSSProperties; @@ -46,8 +44,6 @@ export class EthAmountInput extends React.Component<EthAmountInputProps, EthAmou onErrorMsgChange={this.props.onErrorMsgChange} shouldCheckBalance={this.props.shouldCheckBalance} shouldShowIncompleteErrs={this.props.shouldShowIncompleteErrs} - onVisitBalancesPageClick={this.props.onVisitBalancesPageClick} - shouldHideVisitBalancesLink={this.props.shouldHideVisitBalancesLink} hintText={this.props.hintText} shouldShowErrs={this.props.shouldShowErrs} shouldShowUnderline={this.props.shouldShowUnderline} diff --git a/packages/website/ts/components/inputs/token_amount_input.tsx b/packages/website/ts/components/inputs/token_amount_input.tsx index a67120320..93ef516cf 100644 --- a/packages/website/ts/components/inputs/token_amount_input.tsx +++ b/packages/website/ts/components/inputs/token_amount_input.tsx @@ -21,7 +21,6 @@ interface TokenAmountInputProps { shouldCheckAllowance: boolean; onChange: ValidatedBigNumberCallback; onErrorMsgChange?: (errorMsg: React.ReactNode) => void; - onVisitBalancesPageClick?: () => void; lastForceTokenStateRefetch: number; shouldShowErrs?: boolean; shouldShowUnderline?: boolean; @@ -88,7 +87,6 @@ export class TokenAmountInput extends React.Component<TokenAmountInputProps, Tok validate={this._validate.bind(this)} shouldCheckBalance={this.props.shouldCheckBalance} shouldShowIncompleteErrs={this.props.shouldShowIncompleteErrs} - onVisitBalancesPageClick={this.props.onVisitBalancesPageClick} isDisabled={!this.state.isBalanceAndAllowanceLoaded} hintText={this.props.hintText} shouldShowErrs={this.props.shouldShowErrs} diff --git a/packages/website/ts/components/top_bar/provider_display.tsx b/packages/website/ts/components/top_bar/provider_display.tsx index 8743e4320..ae3be6436 100644 --- a/packages/website/ts/components/top_bar/provider_display.tsx +++ b/packages/website/ts/components/top_bar/provider_display.tsx @@ -3,7 +3,6 @@ import * as _ from 'lodash'; import CircularProgress from 'material-ui/CircularProgress'; import RaisedButton from 'material-ui/RaisedButton'; import ActionAccountBalanceWallet from 'material-ui/svg-icons/action/account-balance-wallet'; -import Lock from 'material-ui/svg-icons/action/lock'; import * as React from 'react'; import { Blockchain } from 'ts/blockchain'; @@ -12,6 +11,7 @@ import { AccountConnection } from 'ts/components/ui/account_connection'; import { Container } from 'ts/components/ui/container'; import { DropDown } from 'ts/components/ui/drop_down'; import { Identicon } from 'ts/components/ui/identicon'; +import { Image } from 'ts/components/ui/image'; import { Island } from 'ts/components/ui/island'; import { Text } from 'ts/components/ui/text'; import { Dispatcher } from 'ts/redux/dispatcher'; @@ -154,7 +154,7 @@ export class ProviderDisplay extends React.Component<ProviderDisplayProps, Provi case AccountState.Loading: return <CircularProgress size={ROOT_HEIGHT} thickness={2} />; case AccountState.Locked: - return <Lock color={colors.black} />; + return <Image src="/images/lock_icon.svg" height="20px" width="20px" />; case AccountState.Disconnected: return <ActionAccountBalanceWallet color={colors.mediumBlue} />; default: diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 1f1e3598a..6c8b398c4 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -1,6 +1,5 @@ import { constants as sharedConstants, EtherscanLinkSuffixes, utils as sharedUtils } from '@0xproject/react-shared'; import { BigNumber, errorUtils } from '@0xproject/utils'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import ActionAccountBalanceWallet from 'material-ui/svg-icons/action/account-balance-wallet'; @@ -83,7 +82,6 @@ const ICON_DIMENSION = 28; const BODY_ITEM_KEY = 'BODY'; const HEADER_ITEM_KEY = 'HEADER'; const ETHER_ITEM_KEY = 'ETHER'; -const USD_DECIMAL_PLACES = 2; const NO_ALLOWANCE_TOGGLE_SPACE_WIDTH = 56; const ACCOUNT_PATH = `${WebsitePaths.Portal}/account`; const PLACEHOLDER_COLOR = colors.grey300; @@ -320,8 +318,24 @@ export class Wallet extends React.Component<WalletProps, WalletState> { this.state.wrappedEtherDirection === accessoryItemConfig.wrappedEtherDirection && !_.isUndefined(this.props.userEtherBalanceInWei); const etherToken = this._getEthToken(); + const wrapEtherItem = shouldShowWrapEtherItem ? ( + <WrapEtherItem + userAddress={this.props.userAddress} + networkId={this.props.networkId} + blockchain={this.props.blockchain} + dispatcher={this.props.dispatcher} + userEtherBalanceInWei={this.props.userEtherBalanceInWei} + direction={accessoryItemConfig.wrappedEtherDirection} + etherToken={etherToken} + lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} + onConversionSuccessful={this._closeWrappedEtherActionRow.bind(this)} + // tslint:disable:jsx-no-lambda + refetchEthTokenStateAsync={async () => this.props.refetchTokenStateAsync(etherToken.address)} + /> + ) : null; return ( <div id={key} key={key} className={`flex flex-column ${className || ''}`}> + {this.state.wrappedEtherDirection === Side.Receive && wrapEtherItem} <StandardIconRow icon={icon} main={ @@ -331,23 +345,8 @@ export class Wallet extends React.Component<WalletProps, WalletState> { </div> } accessory={this._renderAccessoryItems(accessoryItemConfig)} - backgroundColor={shouldShowWrapEtherItem ? colors.walletFocusedItemBackground : undefined} /> - {shouldShowWrapEtherItem && ( - <WrapEtherItem - userAddress={this.props.userAddress} - networkId={this.props.networkId} - blockchain={this.props.blockchain} - dispatcher={this.props.dispatcher} - userEtherBalanceInWei={this.props.userEtherBalanceInWei} - direction={accessoryItemConfig.wrappedEtherDirection} - etherToken={etherToken} - lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} - onConversionSuccessful={this._closeWrappedEtherActionRow.bind(this)} - // tslint:disable:jsx-no-lambda - refetchEthTokenStateAsync={async () => this.props.refetchTokenStateAsync(etherToken.address)} - /> - )} + {this.state.wrappedEtherDirection === Side.Deposit && wrapEtherItem} </div> ); } @@ -411,19 +410,11 @@ export class Wallet extends React.Component<WalletProps, WalletState> { price?: BigNumber, isLoading: boolean = false, ): React.ReactNode { - let result; - if (!isLoading) { - if (_.isUndefined(price)) { - result = '--'; - } else { - const unitAmount = Web3Wrapper.toUnitAmount(amount, decimals); - const value = unitAmount.mul(price); - const formattedAmount = value.toFixed(USD_DECIMAL_PLACES); - result = `$${formattedAmount}`; - } - } else { - result = '$0.00'; - } + const result = !isLoading + ? _.isUndefined(price) + ? '--' + : utils.getUsdValueFormattedAmount(amount, decimals, price) + : '$0.00'; return ( <PlaceHolder hideChildren={isLoading} fillColor={PLACEHOLDER_COLOR}> <Text fontSize="14px" fontColor={colors.darkGrey} lineHeight="1em"> diff --git a/packages/website/ts/components/wallet/wrap_ether_item.tsx b/packages/website/ts/components/wallet/wrap_ether_item.tsx index 851b35f90..2b4cf93fe 100644 --- a/packages/website/ts/components/wallet/wrap_ether_item.tsx +++ b/packages/website/ts/components/wallet/wrap_ether_item.tsx @@ -8,6 +8,7 @@ import * as React from 'react'; import { Blockchain } from 'ts/blockchain'; import { EthAmountInput } from 'ts/components/inputs/eth_amount_input'; import { TokenAmountInput } from 'ts/components/inputs/token_amount_input'; +import { Container } from 'ts/components/ui/container'; import { Dispatcher } from 'ts/redux/dispatcher'; import { colors } from 'ts/style/colors'; import { BlockchainCallErrs, Side, Token } from 'ts/types'; @@ -94,7 +95,7 @@ export class WrapEtherItem extends React.Component<WrapEtherItemProps, WrapEther const topLabelText = isWrappingEth ? 'Convert ETH into WETH 1:1' : 'Convert WETH into ETH 1:1'; return ( - <div className="flex" style={{ backgroundColor: colors.walletFocusedItemBackground }}> + <Container className="flex" backgroundColor={colors.walletFocusedItemBackground} paddingTop="25px"> <div>{this._renderIsEthConversionHappeningSpinner()} </div> <div className="flex flex-column"> <div style={styles.topLabel}>{topLabelText}</div> @@ -142,7 +143,7 @@ export class WrapEtherItem extends React.Component<WrapEtherItemProps, WrapEther {this._renderErrorMsg()} </div> - </div> + </Container> ); } private _onValueChange(_isValid: boolean, amount?: BigNumber): void { diff --git a/packages/website/ts/utils/constants.ts b/packages/website/ts/utils/constants.ts index b0cb2fa08..0c4b88780 100644 --- a/packages/website/ts/utils/constants.ts +++ b/packages/website/ts/utils/constants.ts @@ -6,7 +6,7 @@ export const constants = { ETHER_TOKEN_SYMBOL: 'WETH', ZRX_TOKEN_SYMBOL: 'ZRX', ETHER_SYMBOL: 'ETH', - TOKEN_AMOUNT_DISPLAY_PRECISION: 5, + TOKEN_AMOUNT_DISPLAY_PRECISION: 4, GENESIS_ORDER_BLOCK_BY_NETWORK_ID: { 1: 4145578, 42: 3117574, @@ -40,6 +40,7 @@ export const constants = { UNAVAILABLE_STATUS: 503, TAKER_FEE: new BigNumber(0), TESTNET_NAME: 'Kovan', + NUMERAL_USD_FORMAT: '$0,0.00', PROJECT_URL_ETHFINEX: 'https://www.ethfinex.com/', PROJECT_URL_AMADEUS: 'http://amadeusrelay.org', PROJECT_URL_DDEX: 'https://ddex.io', diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index 0ef3d6723..fc7901463 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -8,6 +8,8 @@ import * as bowser from 'bowser'; import deepEqual = require('deep-equal'); import * as _ from 'lodash'; import * as moment from 'moment'; +import * as numeral from 'numeral'; + import { AccountState, BlockchainCallErrs, @@ -385,10 +387,20 @@ export const utils = { }, getFormattedAmount(amount: BigNumber, decimals: number, symbol: string): string { const unitAmount = Web3Wrapper.toUnitAmount(amount, decimals); - const precision = Math.min(constants.TOKEN_AMOUNT_DISPLAY_PRECISION, unitAmount.decimalPlaces()); - const formattedAmount = unitAmount.toFixed(precision); + // 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 + const precision = unitAmount.lt(1) + ? Math.min(constants.TOKEN_AMOUNT_DISPLAY_PRECISION, unitAmount.decimalPlaces()) + : 2; + const format = `0,0.${_.repeat('0', precision)}`; + const formattedAmount = numeral(unitAmount).format(format); return `${formattedAmount} ${symbol}`; }, + getUsdValueFormattedAmount(amount: BigNumber, decimals: number, price: BigNumber): string { + const unitAmount = Web3Wrapper.toUnitAmount(amount, decimals); + const value = unitAmount.mul(price); + return numeral(value).format(constants.NUMERAL_USD_FORMAT); + }, openUrl(url: string): void { window.open(url, '_blank'); }, @@ -350,6 +350,10 @@ version "8.10.8" resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.8.tgz#794cba23cc9f8d9715f6543fa8827433b5f5cd3b" +"@types/numeral@^0.0.22": + version "0.0.22" + resolved "https://registry.yarnpkg.com/@types/numeral/-/numeral-0.0.22.tgz#86bef1f0a2d743afdc2ef3168d45f2905e1a0b93" + "@types/opn@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@types/opn/-/opn-5.1.0.tgz#bff7bc371677f4bdbb37884400e03fd81f743927" @@ -8119,6 +8123,10 @@ number-to-bn@1.7.0: bn.js "4.11.6" strip-hex-prefix "1.0.0" +numeral@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/numeral/-/numeral-2.0.6.tgz#4ad080936d443c2561aed9f2197efffe25f4e506" + nyc@^11.0.1: version "11.7.1" resolved "https://registry.yarnpkg.com/nyc/-/nyc-11.7.1.tgz#7cb0a422e501b88ff2c1634341dec2560299d67b" |