diff options
-rw-r--r-- | packages/website/ts/components/eth_wrappers.tsx | 249 | ||||
-rw-r--r-- | packages/website/ts/types.ts | 8 | ||||
-rw-r--r-- | packages/website/ts/utils/configs.ts | 23 |
3 files changed, 208 insertions, 72 deletions
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<EthWrappersProps, EthWrappersState> { 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 ( <div className="clearfix lg-px4 md-px4 sm-px2" style={{minHeight: 600}}> - <h3>ETH Wrapper</h3> + <div className="relative"> + <h3>ETH Wrapper</h3> + <div className="absolute" style={{top: 0, right: 0}}> + <a + target="_blank" + href="https://weth.io/" + style={{color: LIGHT_GRAY}} + > + <div className="flex"> + <div>About Wrapped ETH</div> + <div className="pl1"> + <i className="zmdi zmdi-open-in-new" /> + </div> + </div> + </a> + </div> + </div> <Divider /> <div> <div className="py2"> @@ -100,11 +146,14 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt {this.props.userEtherBalance.toFixed(PRECISION)} ETH </TableRowColumn> <TableRowColumn style={{paddingLeft: 3}}> - <LifeCycleRaisedButton - labelReady="Wrap" - labelLoading="Wrapping..." - labelComplete="Wrapped!" - onClickAsyncFn={this.wrapEthAsync.bind(this, true)} + <EthWethConversionButton + isOutdatedWrappedEther={false} + direction={Side.deposit} + ethToken={etherToken} + ethTokenState={etherTokenState} + dispatcher={this.props.dispatcher} + blockchain={this.props.blockchain} + userEtherBalance={this.props.userEtherBalance} /> </TableRowColumn> </TableRow> @@ -124,11 +173,14 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt {wethBalance.toFixed(PRECISION)} WETH </TableRowColumn> <TableRowColumn style={{paddingLeft: 3}}> - <LifeCycleRaisedButton - labelReady="Unwrap" - labelLoading="Unwrapping..." - labelComplete="Unwrapped!" - onClickAsyncFn={this.unwrapEthAsync.bind(this, true)} + <EthWethConversionButton + isOutdatedWrappedEther={false} + direction={Side.receive} + ethToken={etherToken} + ethTokenState={etherTokenState} + dispatcher={this.props.dispatcher} + blockchain={this.props.blockchain} + userEtherBalance={this.props.userEtherBalance} /> </TableRowColumn> </TableRow> @@ -136,46 +188,66 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt </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> + <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(etherToken, etherTokenState)} + </TableBody> + </Table> + </div> </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); + 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 ( <TableRow key={`weth-${outdatedWETH.address}`}> <TableRowColumn className="py1"> @@ -185,19 +257,27 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt src={OUTDATED_WETH_ICON_PATH} /> <div className="mt2 ml2 sm-hide xs-hide"> - {startMoment.format(DATE_FORMAT)}-{endMoment.format(DATE_FORMAT)} + {dateRange} </div> </div> </TableRowColumn> <TableRowColumn> - 0 WETH + {isStateLoaded ? + `${balanceInEthIfExists} WETH` : + <i className="zmdi zmdi-spinner zmdi-hc-spin" /> + } </TableRowColumn> <TableRowColumn style={{paddingLeft: 3}}> - <LifeCycleRaisedButton - labelReady="Unwrap" - labelLoading="Unwrapping..." - labelComplete="Unwrapped!" - onClickAsyncFn={this.unwrapEthAsync.bind(this, true)} + <EthWethConversionButton + isDisabled={!isStateLoaded} + isOutdatedWrappedEther={true} + direction={Side.receive} + ethToken={outdatedEtherToken} + ethTokenState={outdatedEtherTokenState} + dispatcher={this.props.dispatcher} + blockchain={this.props.blockchain} + userEtherBalance={this.props.userEtherBalance} + onConversionSuccessful={onConversionSuccessful} /> </TableRowColumn> </TableRow> @@ -205,10 +285,53 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt }); return rows; } - private async wrapEthAsync() { - // TODO + private async onOutdatedConversionSuccessfulAsync(outdatedWETHAddress: string) { + this.setState({ + outdatedWETHAddressToIsStateLoaded: { + ...this.state.outdatedWETHAddressToIsStateLoaded, + [outdatedWETHAddress]: false, + }, + }); + const [balance, allowance] = await this.props.blockchain.getTokenBalanceAndAllowanceAsync( + this.props.userAddress, outdatedWETHAddress, + ); + this.setState({ + outdatedWETHAddressToIsStateLoaded: { + ...this.state.outdatedWETHAddressToIsStateLoaded, + [outdatedWETHAddress]: true, + }, + outdatedWETHStateByAddress: { + ...this.state.outdatedWETHStateByAddress, + [outdatedWETHAddress]: { + balance, + allowance, + }, + }, + }); } - private async unwrapEthAsync() { - // TODO + private async fetchOutdatedWETHStateAsync() { + const outdatedWETHAddresses = this.getOutdatedWETHAddresses(); + const outdatedWETHAddressToIsStateLoaded: OutdatedWETHAddressToIsStateLoaded = {}; + const outdatedWETHStateByAddress: OutdatedWETHStateByAddress = {}; + for (const address of outdatedWETHAddresses) { + const [balance, allowance] = await this.props.blockchain.getTokenBalanceAndAllowanceAsync( + this.props.userAddress, address, + ); + outdatedWETHStateByAddress[address] = { + balance, + allowance, + }; + outdatedWETHAddressToIsStateLoaded[address] = true; + } + this.setState({ + outdatedWETHStateByAddress, + outdatedWETHAddressToIsStateLoaded, + }); + } + private getOutdatedWETHAddresses(): string[] { + const outdatedWETHAddresses = _.map(configs.outdatedWrappedEthers, outdatedWrappedEther => { + 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[], }; |