import {ZeroEx} from '0x.js'; import BigNumber from 'bignumber.js'; import * as _ from 'lodash'; import Divider from 'material-ui/Divider'; 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 {EthWethConversionButton} from 'ts/components/eth_weth_conversion_button'; import {Dispatcher} from 'ts/redux/dispatcher'; import { OutdatedWrappedEtherByNetworkId, Side, Token, TokenByAddress, TokenState, TokenStateByAddress, } from 'ts/types'; import {colors} from 'ts/utils/colors'; import {configs} from 'ts/utils/configs'; import {constants} from 'ts/utils/constants'; 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'; interface OutdatedWETHAddressToIsStateLoaded { [address: string]: boolean; } interface OutdatedWETHStateByAddress { [address: string]: TokenState; } interface EthWrappersProps { networkId: number; blockchain: Blockchain; dispatcher: Dispatcher; tokenByAddress: TokenByAddress; tokenStateByAddress: TokenStateByAddress; userAddress: string; userEtherBalance: BigNumber; } interface EthWrappersState { outdatedWETHAddressToIsStateLoaded: OutdatedWETHAddressToIsStateLoaded; outdatedWETHStateByAddress: OutdatedWETHStateByAddress; } export class EthWrappers extends React.Component { constructor(props: EthWrappersProps) { super(props); 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 etherToken = _.find(tokens, {symbol: 'WETH'}); const etherTokenState = this.props.tokenStateByAddress[etherToken.address]; const wethBalance = ZeroEx.toUnitAmount(etherTokenState.balance, constants.DECIMAL_PLACES_ETH); const isBidirectional = true; return (

ETH Wrapper

About Wrapped ETH
Wrap ETH into an ERC20-compliant Ether token. 1 ETH = 1 WETH.
ETH Token Balance {this.renderActionColumnTitle(isBidirectional)}
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 {this.renderActionColumnTitle(!isBidirectional)} {this.renderOutdatedWeths(etherToken, etherTokenState)}
); } 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.OUTDATED_WRAPPED_ETHERS, (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, constants.DECIMAL_PLACES_ETH, ).toFixed(PRECISION) : undefined; const onConversionSuccessful = this.onOutdatedConversionSuccessfulAsync.bind(this, outdatedWETH.address); return (
{dateRange}
{isStateLoaded ? `${balanceInEthIfExists} WETH` : }
); }); return rows; } 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 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.OUTDATED_WRAPPED_ETHERS, outdatedWrappedEther => { return outdatedWrappedEther[this.props.networkId].address; }); return outdatedWETHAddresses; } } // tslint:disable:max-file-line-count