From d0916e196c5872ee9ac82941f4a9f323f5179e74 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Tue, 12 Dec 2017 14:53:39 -0600 Subject: progress weth page --- .../public/images/token_icons/ether_erc20.png | Bin 69772 -> 7584 bytes .../website/public/images/wrapped_eth_gray.png | Bin 0 -> 7649 bytes packages/website/ts/blockchain.ts | 2 + packages/website/ts/components/eth_wrappers.tsx | 214 +++++++++++++++++++++ packages/website/ts/components/fill_order.tsx | 1 - packages/website/ts/components/portal.tsx | 18 ++ packages/website/ts/components/portal_menu.tsx | 8 + packages/website/ts/types.ts | 10 + packages/website/ts/utils/configs.ts | 13 +- 9 files changed, 264 insertions(+), 2 deletions(-) create mode 100644 packages/website/public/images/wrapped_eth_gray.png create mode 100644 packages/website/ts/components/eth_wrappers.tsx (limited to 'packages') diff --git a/packages/website/public/images/token_icons/ether_erc20.png b/packages/website/public/images/token_icons/ether_erc20.png index f4154db7b..bc8beae8b 100644 Binary files a/packages/website/public/images/token_icons/ether_erc20.png and b/packages/website/public/images/token_icons/ether_erc20.png differ diff --git a/packages/website/public/images/wrapped_eth_gray.png b/packages/website/public/images/wrapped_eth_gray.png new file mode 100644 index 000000000..397b31b1c Binary files /dev/null and b/packages/website/public/images/wrapped_eth_gray.png differ diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 172ba6b52..5bc95238b 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -602,6 +602,8 @@ export class Blockchain { // HACK: For now we have a hard-coded list of iconUrls for the dummyTokens // TODO: Refactor this out and pull the iconUrl directly from the TokenRegistry const iconUrl = constants.iconUrlBySymbol[t.symbol]; + // TEMPORARY HACK: Swap out for new WETH address + const address = t.symbol === 'WETH' ? '0x739E78d6bEbbDF24105a5145fA04436589d1CBd9' : t.address; const token: Token = { iconUrl, address: t.address, diff --git a/packages/website/ts/components/eth_wrappers.tsx b/packages/website/ts/components/eth_wrappers.tsx new file mode 100644 index 000000000..277929870 --- /dev/null +++ b/packages/website/ts/components/eth_wrappers.tsx @@ -0,0 +1,214 @@ +import {ZeroEx} from '0x.js'; +import BigNumber from 'bignumber.js'; +import * as _ from 'lodash'; +import Divider from 'material-ui/Divider'; +import Paper from 'material-ui/Paper'; +import RaisedButton from 'material-ui/RaisedButton'; +import {colors} from 'material-ui/styles'; +import { + Table, + TableBody, + TableHeader, + TableHeaderColumn, + TableRow, + TableRowColumn, +} from 'material-ui/Table'; +import * as moment from 'moment'; +import * as React from 'react'; +import {Blockchain} from 'ts/blockchain'; +import {LifeCycleRaisedButton} from 'ts/components/ui/lifecycle_raised_button'; +import {trackedTokenStorage} from 'ts/local_storage/tracked_token_storage'; +import {Dispatcher} from 'ts/redux/dispatcher'; +import { + OutdatedWrappedEther, + TokenByAddress, + TokenStateByAddress, +} from 'ts/types'; +import {configs} from 'ts/utils/configs'; +import {constants} from 'ts/utils/constants'; +import {errorReporter} from 'ts/utils/error_reporter'; +import {utils} from 'ts/utils/utils'; + +const PRECISION = 5; +const DATE_FORMAT = 'D/M/YY'; +const ICON_DIMENSION = 40; +const ETHER_ICON_PATH = '/images/ether.png'; +const OUTDATED_WETH_ICON_PATH = '/images/wrapped_eth_gray.png'; +const ETHER_TOKEN_SYMBOL = 'WETH'; + +interface EthWrappersProps { + networkId: number; + blockchain: Blockchain; + dispatcher: Dispatcher; + tokenByAddress: TokenByAddress; + tokenStateByAddress: TokenStateByAddress; + userAddress: string; + userEtherBalance: BigNumber; +} + +interface EthWrappersState {} + +export class EthWrappers extends React.Component { + constructor(props: EthWrappersProps) { + super(props); + this.state = {}; + } + public componentDidMount() { + window.scrollTo(0, 0); + } + public render() { + const tokens = _.values(this.props.tokenByAddress); + const wethToken = _.find(tokens, {symbol: 'WETH'}); + const wethState = this.props.tokenStateByAddress[wethToken.address]; + const wethBalance = ZeroEx.toUnitAmount(wethState.balance, 18); + return ( +
+

ETH Wrapper

+ +
+
+ Wrap ETH into an ERC20-compliant Ether token +
+
+ + + + ETH Token + Balance + + {'ETH <-> WETH'} + + + + + + +
+ +
+ Ether +
+
+
+ + {this.props.userEtherBalance.toFixed(PRECISION)} ETH + + + + +
+ + +
+ +
+ Wrapped Ether +
+
+
+ + {wethBalance.toFixed(PRECISION)} WETH + + + + +
+
+
+
+
+

Outdated WETH

+ +
+ The{' '} + + canonical WETH + contract is updated when necessary. + Unwrap outdated WETH in order to
 retrieve your ETH and move it + to the updated WETH token. +
+
+ + + + WETH Version + Balance + + {'WETH -> ETH'} + + + + + {this.renderOutdatedWeths()} + +
+
+
+ ); + } + private renderOutdatedWeths() { + const rows = _.map(configs.outdatedWrappedEthers, (outdatedWETH: OutdatedWrappedEther) => { + const timestampMsRange = outdatedWETH.timestampMsRangeByNetworkId[this.props.networkId]; + const startMoment = moment(timestampMsRange.startTimestampMs); + const endMoment = moment(timestampMsRange.endTimestampMs); + return ( + + +
+ +
+ {startMoment.format(DATE_FORMAT)}-{endMoment.format(DATE_FORMAT)} +
+
+
+ + 0 WETH + + + + +
+ ); + }); + return rows; + } + private async wrapEthAsync() { + // TODO + } + private async unwrapEthAsync() { + // TODO + } +} // 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 388c72d8e..77a9cfddb 100644 --- a/packages/website/ts/components/fill_order.tsx +++ b/packages/website/ts/components/fill_order.tsx @@ -4,7 +4,6 @@ import BigNumber from 'bignumber.js'; import * as _ from 'lodash'; import {Card, CardHeader, CardText} from 'material-ui/Card'; import Divider from 'material-ui/Divider'; -import Paper from 'material-ui/Paper'; import RaisedButton from 'material-ui/RaisedButton'; import TextField from 'material-ui/TextField'; import * as moment from 'moment'; diff --git a/packages/website/ts/components/portal.tsx b/packages/website/ts/components/portal.tsx index 62a5d2eac..57e75dab3 100644 --- a/packages/website/ts/components/portal.tsx +++ b/packages/website/ts/components/portal.tsx @@ -9,6 +9,7 @@ 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 {EthWrappers} from 'ts/components/eth_wrappers'; import {FillOrder} from 'ts/components/fill_order'; import {Footer} from 'ts/components/footer'; import {PortalMenu} from 'ts/components/portal_menu'; @@ -205,6 +206,10 @@ export class Portal extends React.Component {
{this.props.blockchainIsLoaded ? + {
); } + private renderEthWrapper() { + return ( + + ); + } private renderTradeHistory() { return ( {this.renderMenuItemWithIcon('Trade history', 'zmdi-format-list-bulleted')} + + {this.renderMenuItemWithIcon('ETH wrapper', 'zmdi-circle-o')} + ); } diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts index d225e7784..05e797ceb 100644 --- a/packages/website/ts/types.ts +++ b/packages/website/ts/types.ts @@ -683,4 +683,14 @@ export interface DocsInfoConfig { menuSubsectionToVersionWhenIntroduced?: {[sectionName: string]: string}; } +export interface TimestampMsRange { + startTimestampMs: number; + endTimestampMs: number; +} + +export interface OutdatedWrappedEther { + address: string; + timestampMsRangeByNetworkId: {[networkId: number]: TimestampMsRange}; +} + // tslint:disable:max-file-line-count diff --git a/packages/website/ts/utils/configs.ts b/packages/website/ts/utils/configs.ts index 63fcd27b6..e84dbd38f 100644 --- a/packages/website/ts/utils/configs.ts +++ b/packages/website/ts/utils/configs.ts @@ -1,5 +1,5 @@ import * as _ from 'lodash'; -import {Environments} from 'ts/types'; +import {Environments, OutdatedWrappedEther} from 'ts/types'; const BASE_URL = window.location.origin; const isDevelopment = _.includes(BASE_URL, 'https://0xproject.dev:3572') || @@ -15,4 +15,15 @@ export const configs = { defaultTrackedTokenSymbols: ['WETH', 'ZRX'], lastLocalStorageFillClearanceDate: '2017-11-22', isMainnetEnabled: true, + outdatedWrappedEthers: [ + { + address: '0x05d090b51c40b020eab3bfcb6a2dff130df22e9c', + timestampMsRangeByNetworkId: { + 42: { + startTimestampMs: 1501614680000, + endTimestampMs: 1513106129000, + }, + }, + } as OutdatedWrappedEther, + ], }; -- cgit v1.2.3 From 5619780cc18a5bdc6d1ff638c413870f56cf07e0 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Wed, 13 Dec 2017 19:43:43 -0600 Subject: Use boxed ETH --- packages/website/public/images/ether.png | Bin 2312 -> 4235 bytes 1 file changed, 0 insertions(+), 0 deletions(-) (limited to 'packages') diff --git a/packages/website/public/images/ether.png b/packages/website/public/images/ether.png index 6a40a976d..c92f45681 100644 Binary files a/packages/website/public/images/ether.png and b/packages/website/public/images/ether.png differ -- cgit v1.2.3 From 565010408e9dc2dd43a00dfdaefd51035008dd6f Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Wed, 13 Dec 2017 19:44:27 -0600 Subject: Remove temporary hack --- packages/website/ts/blockchain.ts | 2 -- 1 file changed, 2 deletions(-) (limited to 'packages') diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts index 5bc95238b..172ba6b52 100644 --- a/packages/website/ts/blockchain.ts +++ b/packages/website/ts/blockchain.ts @@ -602,8 +602,6 @@ export class Blockchain { // HACK: For now we have a hard-coded list of iconUrls for the dummyTokens // TODO: Refactor this out and pull the iconUrl directly from the TokenRegistry const iconUrl = constants.iconUrlBySymbol[t.symbol]; - // TEMPORARY HACK: Swap out for new WETH address - const address = t.symbol === 'WETH' ? '0x739E78d6bEbbDF24105a5145fA04436589d1CBd9' : t.address; const token: Token = { iconUrl, address: t.address, -- cgit v1.2.3 From b054080fa1da88460f52021278fb33b8d88371a3 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Wed, 13 Dec 2017 19:45:44 -0600 Subject: Remove ETH-WETH convert button from balances page --- packages/website/ts/components/token_balances.tsx | 24 ----------------------- packages/website/ts/types.ts | 1 - 2 files changed, 25 deletions(-) (limited to 'packages') diff --git a/packages/website/ts/components/token_balances.tsx b/packages/website/ts/components/token_balances.tsx index ae5ef9222..799fecc69 100644 --- a/packages/website/ts/components/token_balances.tsx +++ b/packages/website/ts/components/token_balances.tsx @@ -23,7 +23,6 @@ import * as React from 'react'; import ReactTooltip = require('react-tooltip'); import firstBy = require('thenby'); import {Blockchain} from 'ts/blockchain'; -import {EthWethConversionButton} from 'ts/components/eth_weth_conversion_button'; import {AssetPicker} from 'ts/components/generate_order/asset_picker'; import {AllowanceToggle} from 'ts/components/inputs/allowance_toggle'; import {SendButton} from 'ts/components/send_button'; @@ -425,16 +424,6 @@ export class TokenBalances extends React.Component } - {token.symbol === ETHER_TOKEN_SYMBOL && - - } {token.symbol === ZRX_TOKEN_SYMBOL && this.props.networkId === constants.TESTNET_NETWORK_ID && ); - case BalanceErrs.wethConversionFailed: - return ( -
- Converting between Ether and Ether Tokens failed unexpectedly. - Please refresh the page and try again. -
- ); - case BalanceErrs.allowanceSettingFailed: return (
diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts index 05e797ceb..4caa09025 100644 --- a/packages/website/ts/types.ts +++ b/packages/website/ts/types.ts @@ -135,7 +135,6 @@ export enum BalanceErrs { faucetRequestFailed, faucetQueueIsFull, mintingFailed, - wethConversionFailed, sendFailed, allowanceSettingFailed, } -- cgit v1.2.3 From ceae51fe322ebf444d0c8b61fdb7a86ab11c8071 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Wed, 13 Dec 2017 19:46:48 -0600 Subject: Make label optional and make sure the input field still renders properly without it --- packages/website/ts/components/inputs/token_amount_input.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'packages') diff --git a/packages/website/ts/components/inputs/token_amount_input.tsx b/packages/website/ts/components/inputs/token_amount_input.tsx index f39341a4f..1ae9bc85e 100644 --- a/packages/website/ts/components/inputs/token_amount_input.tsx +++ b/packages/website/ts/components/inputs/token_amount_input.tsx @@ -8,9 +8,9 @@ import {BalanceBoundedInput} from 'ts/components/inputs/balance_bounded_input'; import {InputErrMsg, Token, TokenState, ValidatedBigNumberCallback, WebsitePaths} from 'ts/types'; interface TokenAmountInputProps { - label: string; token: Token; tokenState: TokenState; + label?: string; amount?: BigNumber; shouldShowIncompleteErrs: boolean; shouldCheckBalance: boolean; @@ -26,8 +26,9 @@ export class TokenAmountInput extends React.Component +
-
+
{this.props.token.symbol}
-- cgit v1.2.3 From 105bcc6664f0d4ab642486977f1edaf8d84b020e Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Wed, 13 Dec 2017 19:58:33 -0600 Subject: Clear trackedTokens so that a user starts tracking the new WETH and no longer the old one --- packages/website/ts/index.tsx | 2 ++ packages/website/ts/local_storage/tracked_token_storage.ts | 11 +++++++++++ packages/website/ts/utils/configs.ts | 1 + 3 files changed, 14 insertions(+) (limited to 'packages') diff --git a/packages/website/ts/index.tsx b/packages/website/ts/index.tsx index 922102d96..61cd6c2f5 100644 --- a/packages/website/ts/index.tsx +++ b/packages/website/ts/index.tsx @@ -10,6 +10,7 @@ import {BrowserRouter as Router, Link, Redirect, Route, Switch} from 'react-rout import * as injectTapEventPlugin from 'react-tap-event-plugin'; import {createStore, Store as ReduxStore} from 'redux'; import {createLazyComponent} from 'ts/lazy_component'; +import {trackedTokenStorage} from 'ts/local_storage/tracked_token_storage'; import {tradeHistoryStorage} from 'ts/local_storage/trade_history_storage'; import {About} from 'ts/pages/about/about'; import {FAQ} from 'ts/pages/faq/faq'; @@ -29,6 +30,7 @@ BigNumber.config({ // Check if we've introduced an update that requires us to clear the tradeHistory local storage entries tradeHistoryStorage.clearIfRequired(); +trackedTokenStorage.clearIfRequired(); const CUSTOM_GREY = 'rgb(39, 39, 39)'; const CUSTOM_GREEN = 'rgb(102, 222, 117)'; diff --git a/packages/website/ts/local_storage/tracked_token_storage.ts b/packages/website/ts/local_storage/tracked_token_storage.ts index 051a78ae1..086b06af5 100644 --- a/packages/website/ts/local_storage/tracked_token_storage.ts +++ b/packages/website/ts/local_storage/tracked_token_storage.ts @@ -1,10 +1,21 @@ import * as _ from 'lodash'; import {localStorage} from 'ts/local_storage/local_storage'; import {Token, TrackedTokensByNetworkId} from 'ts/types'; +import {configs} from 'ts/utils/configs'; const TRACKED_TOKENS_KEY = 'trackedTokens'; +const TRACKED_TOKENS_CLEAR_KEY = 'lastClearTrackedTokensDate'; export const trackedTokenStorage = { + // Clear trackedTokens localStorage if we've updated the config variable in an update + // that introduced a backward incompatible change requiring the tracked tokens to be re-set + clearIfRequired() { + const lastClearFillDate = localStorage.getItemIfExists(TRACKED_TOKENS_CLEAR_KEY); + if (lastClearFillDate !== configs.lastLocalStorageTrackedTokenClearanceDate) { + localStorage.removeItem(TRACKED_TOKENS_KEY); + } + localStorage.setItem(TRACKED_TOKENS_CLEAR_KEY, configs.lastLocalStorageTrackedTokenClearanceDate); + }, addTrackedTokenToUser(userAddress: string, networkId: number, token: Token) { const trackedTokensByUserAddress = this.getTrackedTokensByUserAddress(); let trackedTokensByNetworkId = trackedTokensByUserAddress[userAddress]; diff --git a/packages/website/ts/utils/configs.ts b/packages/website/ts/utils/configs.ts index e84dbd38f..c887d176f 100644 --- a/packages/website/ts/utils/configs.ts +++ b/packages/website/ts/utils/configs.ts @@ -14,6 +14,7 @@ export const configs = { // WARNING: ZRX & WETH MUST always be default trackedTokens defaultTrackedTokenSymbols: ['WETH', 'ZRX'], lastLocalStorageFillClearanceDate: '2017-11-22', + lastLocalStorageTrackedTokenClearanceDate: '2017-12-13', isMainnetEnabled: true, outdatedWrappedEthers: [ { -- cgit v1.2.3 From 7ce1021798ac2d459f80d1827a3259e781b4b201 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 14 Dec 2017 10:41:33 -0600 Subject: Refactor the WETH conversion dialog/button to be either wrap or unwrap specific and not both --- .../dialogs/eth_weth_conversion_dialog.tsx | 130 ++++++++++++--------- .../ts/components/eth_weth_conversion_button.tsx | 38 ++++-- 2 files changed, 109 insertions(+), 59 deletions(-) (limited to 'packages') 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 aba5b9faf..4904ee9e2 100644 --- a/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx +++ b/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx @@ -1,14 +1,15 @@ import BigNumber from 'bignumber.js'; import Dialog from 'material-ui/Dialog'; import FlatButton from 'material-ui/FlatButton'; -import RadioButton from 'material-ui/RadioButton'; -import RadioButtonGroup from 'material-ui/RadioButton/RadioButtonGroup'; 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'; + interface EthWethConversionDialogProps { + direction: Side; onComplete: (direction: Side, value: BigNumber) => void; onCancelled: () => void; isOpen: boolean; @@ -19,7 +20,6 @@ interface EthWethConversionDialogProps { interface EthWethConversionDialogState { value?: BigNumber; - direction: Side; shouldShowIncompleteErrs: boolean; hasErrors: boolean; } @@ -29,7 +29,6 @@ export class EthWethConversionDialog extends constructor() { super(); this.state = { - direction: Side.deposit, shouldShowIncompleteErrs: false, hasErrors: true, }; @@ -48,11 +47,13 @@ export class EthWethConversionDialog extends onTouchTap={this.onConvertClick.bind(this)} />, ]; + const title = this.props.direction === Side.deposit ? 'Wrap ETH' : 'Unwrap WETH'; return ( {this.renderConversionDialogBody()} @@ -60,56 +61,81 @@ export class EthWethConversionDialog extends ); } private renderConversionDialogBody() { + 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; return ( -
- - - - - {this.state.direction === Side.receive ? - : - - } +
+
+ {explanation} +
+
+
+ {this.renderCurrency(isWrappedVersion)} +
+ +
+ {this.renderCurrency(!isWrappedVersion)} +
+
+ {this.props.direction === Side.receive ? + : + + } +
+ 1 ETH = 1 WETH +
+
+
); } - private onConversionDirectionChange(e: any, direction: Side) { - this.setState({ - value: undefined, - shouldShowIncompleteErrs: false, - direction, - hasErrors: true, - }); + private renderCurrency(isWrappedVersion: boolean) { + const name = isWrappedVersion ? 'Wrapped Ether' : 'Ether'; + const iconUrl = isWrappedVersion ? '/images/token_icons/ether_erc20.png' : '/images/ether.png'; + const symbol = isWrappedVersion ? 'WETH' : 'ETH'; + return ( +
+
+ {name} +
+
+ +
+
+ ({symbol}) +
+
+ ); } private onValueChange(isValid: boolean, amount?: BigNumber) { this.setState({ @@ -127,7 +153,7 @@ export class EthWethConversionDialog extends this.setState({ value: undefined, }); - this.props.onComplete(this.state.direction, value); + this.props.onComplete(this.props.direction, value); } } private onCancel() { diff --git a/packages/website/ts/components/eth_weth_conversion_button.tsx b/packages/website/ts/components/eth_weth_conversion_button.tsx index a83b1543f..bf686d44b 100644 --- a/packages/website/ts/components/eth_weth_conversion_button.tsx +++ b/packages/website/ts/components/eth_weth_conversion_button.tsx @@ -12,12 +12,15 @@ import {errorReporter} from 'ts/utils/error_reporter'; import {utils} from 'ts/utils/utils'; interface EthWethConversionButtonProps { + direction: Side; ethToken: Token; ethTokenState: TokenState; dispatcher: Dispatcher; blockchain: Blockchain; userEtherBalance: BigNumber; - onError: () => void; + isOutdatedWrappedEther: boolean; + onConversionSuccessful?: () => void; + isDisabled?: boolean; } interface EthWethConversionButtonState { @@ -27,6 +30,9 @@ interface EthWethConversionButtonState { export class EthWethConversionButton extends React.Component { + public static defaultProps: Partial = { + isDisabled: false, + }; public constructor(props: EthWethConversionButtonProps) { super(props); this.state = { @@ -36,16 +42,26 @@ export class EthWethConversionButton extends } public render() { const labelStyle = this.state.isEthConversionHappening ? {fontSize: 10} : {}; + let callToActionLabel; + let inProgressLabel; + if (this.props.direction === Side.deposit) { + callToActionLabel = 'Wrap'; + inProgressLabel = 'Wrapping...'; + } else { + callToActionLabel = 'Unwrap'; + inProgressLabel = 'Unwrapping...'; + } return (
Date: Thu, 14 Dec 2017 10:43:20 -0600 Subject: Use new wrap/unwrap buttons, fetch outdated WETH balances and re-fetch after a successful unwrap. --- packages/website/ts/components/eth_wrappers.tsx | 249 ++++++++++++++++++------ packages/website/ts/types.ts | 8 +- packages/website/ts/utils/configs.ts | 23 ++- 3 files changed, 208 insertions(+), 72 deletions(-) (limited to 'packages') diff --git a/packages/website/ts/components/eth_wrappers.tsx b/packages/website/ts/components/eth_wrappers.tsx index 277929870..c2f9b7b45 100644 --- a/packages/website/ts/components/eth_wrappers.tsx +++ b/packages/website/ts/components/eth_wrappers.tsx @@ -16,12 +16,16 @@ import { import * as moment from 'moment'; import * as React from 'react'; import {Blockchain} from 'ts/blockchain'; +import {EthWethConversionButton} from 'ts/components/eth_weth_conversion_button'; import {LifeCycleRaisedButton} from 'ts/components/ui/lifecycle_raised_button'; import {trackedTokenStorage} from 'ts/local_storage/tracked_token_storage'; import {Dispatcher} from 'ts/redux/dispatcher'; import { - OutdatedWrappedEther, + OutdatedWrappedEtherByNetworkId, + Side, + Token, TokenByAddress, + TokenState, TokenStateByAddress, } from 'ts/types'; import {configs} from 'ts/utils/configs'; @@ -31,11 +35,19 @@ 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'; const ETHER_TOKEN_SYMBOL = 'WETH'; +interface OutdatedWETHAddressToIsStateLoaded { + [address: string]: boolean; +} +interface OutdatedWETHStateByAddress { + [address: string]: TokenState; +} + interface EthWrappersProps { networkId: number; blockchain: Blockchain; @@ -46,24 +58,58 @@ interface EthWrappersProps { userEtherBalance: BigNumber; } -interface EthWrappersState {} +interface EthWrappersState { + outdatedWETHAddressToIsStateLoaded: OutdatedWETHAddressToIsStateLoaded; + outdatedWETHStateByAddress: OutdatedWETHStateByAddress; +} export class EthWrappers extends React.Component { constructor(props: EthWrappersProps) { super(props); - this.state = {}; + const outdatedWETHAddresses = this.getOutdatedWETHAddresses(); + const outdatedWETHAddressToIsStateLoaded: OutdatedWETHAddressToIsStateLoaded = {}; + const outdatedWETHStateByAddress: OutdatedWETHStateByAddress = {}; + _.each(outdatedWETHAddresses, outdatedWETHAddress => { + outdatedWETHAddressToIsStateLoaded[outdatedWETHAddress] = false; + outdatedWETHStateByAddress[outdatedWETHAddress] = { + balance: new BigNumber(0), + allowance: new BigNumber(0), + }; + }); + this.state = { + outdatedWETHAddressToIsStateLoaded, + outdatedWETHStateByAddress, + }; } public componentDidMount() { window.scrollTo(0, 0); + // tslint:disable-next-line:no-floating-promises + this.fetchOutdatedWETHStateAsync(); } public render() { const tokens = _.values(this.props.tokenByAddress); - const wethToken = _.find(tokens, {symbol: 'WETH'}); - const wethState = this.props.tokenStateByAddress[wethToken.address]; - const wethBalance = ZeroEx.toUnitAmount(wethState.balance, 18); + const etherToken = _.find(tokens, {symbol: 'WETH'}); + const etherTokenState = this.props.tokenStateByAddress[etherToken.address]; + const wethBalance = ZeroEx.toUnitAmount(etherTokenState.balance, 18); return (
-

ETH Wrapper

+
+

ETH Wrapper

+ +
@@ -100,11 +146,14 @@ export class EthWrappers extends React.Component - @@ -124,11 +173,14 @@ export class EthWrappers extends React.Component - @@ -136,46 +188,66 @@ export class EthWrappers extends React.Component
-

Outdated WETH

- -
- The{' '} - - canonical WETH - contract is updated when necessary. - Unwrap outdated WETH in order to
 retrieve your ETH and move it - to the updated WETH token. -
- - - - WETH Version - Balance - - {'WETH -> ETH'} - - - - - {this.renderOutdatedWeths()} - -
+

Outdated WETH

+ +
+ The{' '} + + canonical WETH + contract is updated when necessary. + Unwrap outdated WETH in order to
 retrieve your ETH and move it + to the updated WETH token. +
+
+ + + + WETH Version + Balance + + {'WETH -> ETH'} + + + + + {this.renderOutdatedWeths(etherToken, etherTokenState)} + +
+
); } - private renderOutdatedWeths() { - const rows = _.map(configs.outdatedWrappedEthers, (outdatedWETH: OutdatedWrappedEther) => { - const timestampMsRange = outdatedWETH.timestampMsRangeByNetworkId[this.props.networkId]; - const startMoment = moment(timestampMsRange.startTimestampMs); - const endMoment = moment(timestampMsRange.endTimestampMs); + private renderOutdatedWeths(etherToken: Token, etherTokenState: TokenState) { + const rows = _.map(configs.outdatedWrappedEthers, + (outdatedWETHByNetworkId: OutdatedWrappedEtherByNetworkId) => { + const outdatedWETH = outdatedWETHByNetworkId[this.props.networkId]; + const timestampMsRange = outdatedWETH.timestampMsRange; + let dateRange: string; + if (!_.isUndefined(timestampMsRange)) { + const startMoment = moment(timestampMsRange.startTimestampMs); + const endMoment = moment(timestampMsRange.endTimestampMs); + dateRange = `${startMoment.format(DATE_FORMAT)}-${endMoment.format(DATE_FORMAT)}`; + } else { + dateRange = '-'; + } + const outdatedEtherToken = { + ...etherToken, + address: outdatedWETH.address, + }; + const isStateLoaded = this.state.outdatedWETHAddressToIsStateLoaded[outdatedWETH.address]; + const outdatedEtherTokenState = this.state.outdatedWETHStateByAddress[outdatedWETH.address]; + const balanceInEthIfExists = isStateLoaded ? + ZeroEx.toUnitAmount(outdatedEtherTokenState.balance, 18).toFixed(PRECISION) : + undefined; + const onConversionSuccessful = this.onOutdatedConversionSuccessfulAsync.bind(this, outdatedWETH.address); return ( @@ -185,19 +257,27 @@ export class EthWrappers extends React.Component
- {startMoment.format(DATE_FORMAT)}-{endMoment.format(DATE_FORMAT)} + {dateRange}
- 0 WETH + {isStateLoaded ? + `${balanceInEthIfExists} WETH` : + + } - @@ -205,10 +285,53 @@ export class EthWrappers extends React.Component { + return outdatedWrappedEther[this.props.networkId].address; + }); + return outdatedWETHAddresses; } } // tslint:disable:max-file-line-count diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts index 4caa09025..2005cf265 100644 --- a/packages/website/ts/types.ts +++ b/packages/website/ts/types.ts @@ -687,9 +687,11 @@ export interface TimestampMsRange { endTimestampMs: number; } -export interface OutdatedWrappedEther { - address: string; - timestampMsRangeByNetworkId: {[networkId: number]: TimestampMsRange}; +export interface OutdatedWrappedEtherByNetworkId { + [networkId: number]: { + address: string; + timestampMsRange: TimestampMsRange; + }; } // tslint:disable:max-file-line-count diff --git a/packages/website/ts/utils/configs.ts b/packages/website/ts/utils/configs.ts index c887d176f..adc51374f 100644 --- a/packages/website/ts/utils/configs.ts +++ b/packages/website/ts/utils/configs.ts @@ -1,5 +1,9 @@ import * as _ from 'lodash'; -import {Environments, OutdatedWrappedEther} from 'ts/types'; +import { + Environments, + OutdatedWrappedEtherByNetworkId, + TimestampMsRange, +} from 'ts/types'; const BASE_URL = window.location.origin; const isDevelopment = _.includes(BASE_URL, 'https://0xproject.dev:3572') || @@ -18,13 +22,20 @@ export const configs = { isMainnetEnabled: true, outdatedWrappedEthers: [ { - address: '0x05d090b51c40b020eab3bfcb6a2dff130df22e9c', - timestampMsRangeByNetworkId: { - 42: { + 42: { + address: '0x05d090b51c40b020eab3bfcb6a2dff130df22e9c', + timestampMsRange: { startTimestampMs: 1501614680000, endTimestampMs: 1513106129000, }, }, - } as OutdatedWrappedEther, - ], + 1: { + address: '0x2956356cd2a2bf3202f771f50d3d14a367b48070', + timestampMsRange: { + startTimestampMs: 1513123415000, + endTimestampMs: 1513106129000, + }, + }, + }, + ] as OutdatedWrappedEtherByNetworkId[], }; -- cgit v1.2.3 From ac1fbeb9623682ce678990d1815fcff63a6c40ae Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 14 Dec 2017 19:28:49 -0600 Subject: Improve WETH page styling --- .../dialogs/eth_weth_conversion_dialog.tsx | 8 ++--- packages/website/ts/components/eth_wrappers.tsx | 39 +++++++++++++++++----- 2 files changed, 35 insertions(+), 12 deletions(-) (limited to 'packages') 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 4904ee9e2..c8bdced9b 100644 --- a/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx +++ b/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx @@ -53,7 +53,7 @@ export class EthWethConversionDialog extends title={title} titleStyle={{fontWeight: 100}} actions={convertDialogActions} - contentStyle={{width: 600}} + contentStyle={{width: 448}} open={this.props.isOpen} > {this.renderConversionDialogBody()} @@ -70,7 +70,7 @@ export class EthWethConversionDialog extends
{explanation}
-
+
{this.renderCurrency(isWrappedVersion)}
@@ -83,7 +83,7 @@ export class EthWethConversionDialog extends
{this.props.direction === Side.receive ?
-
+
({symbol})
diff --git a/packages/website/ts/components/eth_wrappers.tsx b/packages/website/ts/components/eth_wrappers.tsx index c2f9b7b45..ccbed4188 100644 --- a/packages/website/ts/components/eth_wrappers.tsx +++ b/packages/website/ts/components/eth_wrappers.tsx @@ -91,6 +91,7 @@ export class EthWrappers extends React.Component
@@ -113,7 +114,7 @@ export class EthWrappers extends React.Component
- Wrap ETH into an ERC20-compliant Ether token + Wrap ETH into an ERC20-compliant Ether token. 1 ETH = 1 WETH.
ETH TokenBalance - - {'ETH <-> WETH'} + + {this.renderActionColumnTitle(isBidirectional)} @@ -145,7 +146,7 @@ export class EthWrappers extends React.Component {this.props.userEtherBalance.toFixed(PRECISION)} ETH - + {wethBalance.toFixed(PRECISION)} WETH - + WETH Version Balance - - {'WETH -> ETH'} + + {this.renderActionColumnTitle(!isBidirectional)} @@ -225,6 +226,28 @@ export class EthWrappers extends React.Component ); } + private renderActionColumnTitle(isBidirectional: boolean) { + let iconClass = 'zmdi-long-arrow-right'; + let leftSymbol = 'WETH'; + let rightSymbol = 'ETH'; + if (isBidirectional) { + iconClass = 'zmdi-swap'; + leftSymbol = 'ETH'; + rightSymbol = 'WETH'; + } + return ( +
+
{leftSymbol}
+
+ +
+
{rightSymbol}
+
+ ); + } private renderOutdatedWeths(etherToken: Token, etherTokenState: TokenState) { const rows = _.map(configs.outdatedWrappedEthers, (outdatedWETHByNetworkId: OutdatedWrappedEtherByNetworkId) => { @@ -267,7 +290,7 @@ export class EthWrappers extends React.Component }
- + Date: Fri, 15 Dec 2017 11:05:53 -0600 Subject: Add default value for onConversionSuccessful --- packages/website/ts/components/eth_weth_conversion_button.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'packages') diff --git a/packages/website/ts/components/eth_weth_conversion_button.tsx b/packages/website/ts/components/eth_weth_conversion_button.tsx index bf686d44b..b017de27b 100644 --- a/packages/website/ts/components/eth_weth_conversion_button.tsx +++ b/packages/website/ts/components/eth_weth_conversion_button.tsx @@ -32,6 +32,7 @@ export class EthWethConversionButton extends React.Component { public static defaultProps: Partial = { isDisabled: false, + onConversionSuccessful: _.noop, }; public constructor(props: EthWethConversionButtonProps) { super(props); @@ -100,9 +101,7 @@ export class EthWethConversionButton extends if (!this.props.isOutdatedWrappedEther) { this.props.dispatcher.replaceTokenBalanceByAddress(token.address, balance); } - if (!_.isUndefined(this.props.onConversionSuccessful)) { - this.props.onConversionSuccessful(); - } + this.props.onConversionSuccessful(); } catch (err) { const errMsg = '' + err; if (_.includes(errMsg, BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES)) { -- cgit v1.2.3 From 484dd4c33aa5786def1f0b159f5b51f99a585aa8 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 15 Dec 2017 11:06:18 -0600 Subject: Update name to be a call to action --- packages/website/ts/components/portal_menu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages') diff --git a/packages/website/ts/components/portal_menu.tsx b/packages/website/ts/components/portal_menu.tsx index e00fbd40c..db8e3a9f1 100644 --- a/packages/website/ts/components/portal_menu.tsx +++ b/packages/website/ts/components/portal_menu.tsx @@ -56,7 +56,7 @@ export class PortalMenu extends React.Component - {this.renderMenuItemWithIcon('ETH wrapper', 'zmdi-circle-o')} + {this.renderMenuItemWithIcon('Wrap ETH', 'zmdi-circle-o')} ); -- cgit v1.2.3 From 13279f1f20cb0eeb95c09781bba4280b31ffd210 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Fri, 15 Dec 2017 12:47:16 -0600 Subject: Fix linter errors --- packages/website/ts/components/eth_wrappers.tsx | 7 ------- packages/website/ts/components/token_balances.tsx | 5 ----- packages/website/ts/utils/configs.ts | 1 - 3 files changed, 13 deletions(-) (limited to 'packages') diff --git a/packages/website/ts/components/eth_wrappers.tsx b/packages/website/ts/components/eth_wrappers.tsx index ccbed4188..58b73b11c 100644 --- a/packages/website/ts/components/eth_wrappers.tsx +++ b/packages/website/ts/components/eth_wrappers.tsx @@ -2,8 +2,6 @@ import {ZeroEx} from '0x.js'; import BigNumber from 'bignumber.js'; import * as _ from 'lodash'; import Divider from 'material-ui/Divider'; -import Paper from 'material-ui/Paper'; -import RaisedButton from 'material-ui/RaisedButton'; import {colors} from 'material-ui/styles'; import { Table, @@ -17,8 +15,6 @@ import * as moment from 'moment'; import * as React from 'react'; import {Blockchain} from 'ts/blockchain'; import {EthWethConversionButton} from 'ts/components/eth_weth_conversion_button'; -import {LifeCycleRaisedButton} from 'ts/components/ui/lifecycle_raised_button'; -import {trackedTokenStorage} from 'ts/local_storage/tracked_token_storage'; import {Dispatcher} from 'ts/redux/dispatcher'; import { OutdatedWrappedEtherByNetworkId, @@ -30,8 +26,6 @@ import { } from 'ts/types'; import {configs} from 'ts/utils/configs'; import {constants} from 'ts/utils/constants'; -import {errorReporter} from 'ts/utils/error_reporter'; -import {utils} from 'ts/utils/utils'; const PRECISION = 5; const DATE_FORMAT = 'D/M/YY'; @@ -39,7 +33,6 @@ 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'; -const ETHER_TOKEN_SYMBOL = 'WETH'; interface OutdatedWETHAddressToIsStateLoaded { [address: string]: boolean; diff --git a/packages/website/ts/components/token_balances.tsx b/packages/website/ts/components/token_balances.tsx index ab232326a..db4a35062 100644 --- a/packages/website/ts/components/token_balances.tsx +++ b/packages/website/ts/components/token_balances.tsx @@ -655,11 +655,6 @@ export class TokenBalances extends React.Component