diff --git a/packages/website/public/images/token_icons/ether_erc20.png b/packages/website/public/images/token_icons/ether_erc20.png index f4154db7b3..bc8beae8be 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 0000000000..397b31b1c6 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 172ba6b52c..5bc95238b9 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 0000000000..2779298706 --- /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 388c72d8e5..77a9cfddbc 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 62a5d2eacf..57e75dab34 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 d225e77849..05e797cebf 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 63fcd27b60..e84dbd38fc 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, + ], }; diff --git a/yarn.lock b/yarn.lock index 1eec4f122c..13b5b211ed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"