diff options
-rw-r--r-- | packages/website/public/images/token_icons/ether_erc20.png | bin | 69772 -> 7584 bytes | |||
-rw-r--r-- | packages/website/public/images/wrapped_eth_gray.png | bin | 0 -> 7649 bytes | |||
-rw-r--r-- | packages/website/ts/blockchain.ts | 2 | ||||
-rw-r--r-- | packages/website/ts/components/eth_wrappers.tsx | 214 | ||||
-rw-r--r-- | packages/website/ts/components/fill_order.tsx | 1 | ||||
-rw-r--r-- | packages/website/ts/components/portal.tsx | 18 | ||||
-rw-r--r-- | packages/website/ts/components/portal_menu.tsx | 8 | ||||
-rw-r--r-- | packages/website/ts/types.ts | 10 | ||||
-rw-r--r-- | packages/website/ts/utils/configs.ts | 13 | ||||
-rw-r--r-- | yarn.lock | 22 |
10 files changed, 285 insertions, 3 deletions
diff --git a/packages/website/public/images/token_icons/ether_erc20.png b/packages/website/public/images/token_icons/ether_erc20.png Binary files differindex f4154db7b..bc8beae8b 100644 --- a/packages/website/public/images/token_icons/ether_erc20.png +++ b/packages/website/public/images/token_icons/ether_erc20.png diff --git a/packages/website/public/images/wrapped_eth_gray.png b/packages/website/public/images/wrapped_eth_gray.png Binary files differnew file mode 100644 index 000000000..397b31b1c --- /dev/null +++ b/packages/website/public/images/wrapped_eth_gray.png 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<EthWrappersProps, EthWrappersState> { + 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 ( + <div className="clearfix lg-px4 md-px4 sm-px2" style={{minHeight: 600}}> + <h3>ETH Wrapper</h3> + <Divider /> + <div> + <div className="py2"> + Wrap ETH into an ERC20-compliant Ether token + </div> + <div> + <Table + selectable={false} + style={{backgroundColor: colors.grey50}} + > + <TableHeader displaySelectAll={false} adjustForCheckbox={false}> + <TableRow> + <TableHeaderColumn>ETH Token</TableHeaderColumn> + <TableHeaderColumn>Balance</TableHeaderColumn> + <TableHeaderColumn> + {'ETH <-> WETH'} + </TableHeaderColumn> + </TableRow> + </TableHeader> + <TableBody displayRowCheckbox={false}> + <TableRow key="ETH"> + <TableRowColumn className="py1"> + <div className="flex"> + <img + style={{width: ICON_DIMENSION, height: ICON_DIMENSION}} + src={ETHER_ICON_PATH} + /> + <div className="mt2 ml2 sm-hide xs-hide"> + Ether + </div> + </div> + </TableRowColumn> + <TableRowColumn> + {this.props.userEtherBalance.toFixed(PRECISION)} ETH + </TableRowColumn> + <TableRowColumn style={{paddingLeft: 3}}> + <LifeCycleRaisedButton + labelReady="Wrap" + labelLoading="Wrapping..." + labelComplete="Wrapped!" + onClickAsyncFn={this.wrapEthAsync.bind(this, true)} + /> + </TableRowColumn> + </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> + </TableRowColumn> + <TableRowColumn> + {wethBalance.toFixed(PRECISION)} WETH + </TableRowColumn> + <TableRowColumn style={{paddingLeft: 3}}> + <LifeCycleRaisedButton + labelReady="Unwrap" + labelLoading="Unwrapping..." + labelComplete="Unwrapped!" + onClickAsyncFn={this.unwrapEthAsync.bind(this, true)} + /> + </TableRowColumn> + </TableRow> + </TableBody> + </Table> + </div> + </div> + <h4>Outdated WETH</h4> + <Divider /> + <div className="pt2" style={{lineHeight: 1.5}}> + The{' '} + <a + href="https://blog.0xproject.com/canonical-weth-a9aa7d0279dd" + target="_blank" + > + canonical WETH + </a> contract is updated when necessary. + Unwrap outdated WETH in order to
retrieve your ETH and move it + to the updated WETH token. + </div> + <div> + <Table + selectable={false} + style={{backgroundColor: colors.grey50}} + > + <TableHeader displaySelectAll={false} adjustForCheckbox={false}> + <TableRow> + <TableHeaderColumn>WETH Version</TableHeaderColumn> + <TableHeaderColumn>Balance</TableHeaderColumn> + <TableHeaderColumn> + {'WETH -> ETH'} + </TableHeaderColumn> + </TableRow> + </TableHeader> + <TableBody displayRowCheckbox={false}> + {this.renderOutdatedWeths()} + </TableBody> + </Table> + </div> + </div> + ); + } + 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 ( + <TableRow key={`weth-${outdatedWETH.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"> + {startMoment.format(DATE_FORMAT)}-{endMoment.format(DATE_FORMAT)} + </div> + </div> + </TableRowColumn> + <TableRowColumn> + 0 WETH + </TableRowColumn> + <TableRowColumn style={{paddingLeft: 3}}> + <LifeCycleRaisedButton + labelReady="Unwrap" + labelLoading="Unwrapping..." + labelComplete="Unwrapped!" + onClickAsyncFn={this.unwrapEthAsync.bind(this, true)} + /> + </TableRowColumn> + </TableRow> + ); + }); + 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'; @@ -206,6 +207,10 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> { {this.props.blockchainIsLoaded ? <Switch> <Route + path={`${WebsitePaths.Portal}/weth`} + render={this.renderEthWrapper.bind(this)} + /> + <Route path={`${WebsitePaths.Portal}/fill`} render={this.renderFillOrder.bind(this)} /> @@ -250,6 +255,19 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> { </div> ); } + private renderEthWrapper() { + return ( + <EthWrappers + networkId={this.props.networkId} + blockchain={this.blockchain} + dispatcher={this.props.dispatcher} + tokenByAddress={this.props.tokenByAddress} + tokenStateByAddress={this.props.tokenStateByAddress} + userAddress={this.props.userAddress} + userEtherBalance={this.props.userEtherBalance} + /> + ); + } private renderTradeHistory() { return ( <TradeHistory diff --git a/packages/website/ts/components/portal_menu.tsx b/packages/website/ts/components/portal_menu.tsx index 869df3e71..e00fbd40c 100644 --- a/packages/website/ts/components/portal_menu.tsx +++ b/packages/website/ts/components/portal_menu.tsx @@ -50,6 +50,14 @@ export class PortalMenu extends React.Component<PortalMenuProps, PortalMenuState > {this.renderMenuItemWithIcon('Trade history', 'zmdi-format-list-bulleted')} </MenuItem> + <MenuItem + style={this.props.menuItemStyle} + className="py2" + to={`${WebsitePaths.Portal}/weth`} + onClick={this.props.onClick.bind(this)} + > + {this.renderMenuItemWithIcon('ETH wrapper', 'zmdi-circle-o')} + </MenuItem> </div> ); } 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, + ], }; @@ -9,6 +9,26 @@ jsonschema "^1.2.0" lodash.values "^4.3.0" +"0x.js@0.27.1": + version "0.27.1" + resolved "https://registry.yarnpkg.com/0x.js/-/0x.js-0.27.1.tgz#e0dff70e257efbb7f54dddb55dddf2dce0b971ab" + dependencies: + "@0xproject/assert" "^0.0.6" + "@0xproject/json-schemas" "^0.6.9" + bignumber.js "~4.1.0" + bintrees "^1.0.2" + bn.js "4.11.8" + compare-versions "^3.0.1" + es6-promisify "^5.0.0" + ethereumjs-abi "^0.6.4" + ethereumjs-blockstream "^2.0.6" + ethereumjs-util "^5.1.1" + find-versions "^2.0.0" + js-sha3 "^0.6.1" + lodash "^4.17.4" + uuid "^3.1.0" + web3 "^0.20.0" + "0x.js@^0.22.6": version "0.22.6" resolved "https://registry.yarnpkg.com/0x.js/-/0x.js-0.22.6.tgz#bc3ff79b6d71f8cf7fae3c78b2c776cfa79c193a" @@ -1345,7 +1365,7 @@ bn.js@4.11.7: version "4.11.7" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.7.tgz#ddb048e50d9482790094c13eb3fcfc833ce7ab46" -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.10.0, bn.js@^4.11.3, bn.js@^4.11.6, bn.js@^4.11.7, bn.js@^4.11.8, bn.js@^4.4.0, bn.js@^4.8.0: +bn.js@4.11.8, bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.10.0, bn.js@^4.11.3, bn.js@^4.11.6, bn.js@^4.11.7, bn.js@^4.11.8, bn.js@^4.4.0, bn.js@^4.8.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" |