Commit bd28ef8d authored by Chi Kei Chan's avatar Chi Kei Chan Committed by GitHub

Add Warning Messages and various fixes (#100)

* Fix summary panel in Remove Liquidity

* Add warning message

* Add wrong network warning and env vars
parent c7980455
...@@ -34,7 +34,9 @@ ...@@ -34,7 +34,9 @@
}, },
"scripts": { "scripts": {
"start": "react-scripts start", "start": "react-scripts start",
"start:rinkeby": "REACT_APP_NETWORK_ID=4 REACT_APP_NETWORK='Rinkeby Test Network' react-scripts start",
"build": "react-scripts build && cp build/index.html build/404.html", "build": "react-scripts build && cp build/index.html build/404.html",
"build:rinkeby": "REACT_APP_NETWORK_ID=4 REACT_APP_NETWORK='Rinkeby Test Network' react-scripts build && cp build/index.html build/404.html",
"test": "react-scripts test --env=jsdom", "test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject", "eject": "react-scripts eject",
"deploy": "npm run build&&gh-pages -d build" "deploy": "npm run build&&gh-pages -d build"
......
import React from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import classnames from 'classnames'; import classnames from 'classnames';
...@@ -74,23 +74,38 @@ function isMobile() { ...@@ -74,23 +74,38 @@ function isMobile() {
return ua.getDevice().type === 'mobile'; return ua.getDevice().type === 'mobile';
} }
function Header (props) { class BlockingWarning extends Component {
return ( state = {
<div className="header"> networkId: 0,
<div };
className={classnames('header__dialog', {
'header__dialog--disconnected': !props.isConnected && props.initialized, componentWillReceiveProps(nextProps) {
})} const { web3 } = nextProps;
> const { networkId } = this.state;
<div>No Ethereum wallet found</div>
if (!networkId) {
web3.eth.net.getId((_, networkId) => this.setState({ networkId }))
}
}
render () {
const {
isConnected,
initialized,
} = this.props;
const { networkId } = this.state;
let content = [];
if (!isConnected && initialized) {
content = [
<div>No Ethereum wallet found</div>,
<div className="header__dialog__description"> <div className="header__dialog__description">
{ {
isMobile() isMobile()
? 'Please visit us from a web3-enabled mobile browser, such as Trust Wallet and Cipher Browser.' ? 'Please visit us from a web3-enabled mobile browser, such as Trust Wallet and Cipher Browser.'
: 'Please visit us after installing Metamask on Chrome or Brave.' : 'Please visit us after installing Metamask on Chrome or Brave.'
} }
</div> </div>,
<div className="header__download"> <div className="header__download">
{ {
isMobile() isMobile()
...@@ -107,8 +122,38 @@ function Header (props) { ...@@ -107,8 +122,38 @@ function Header (props) {
] ]
) )
} }
</div>,
]
}
const correctNetworkId = process.env.REACT_APP_NETWORK_ID || 1;
const correctNetwork = process.env.REACT_APP_NETWORK || 'Main Ethereum Network';
const wrongNetwork = networkId != correctNetworkId;
if (wrongNetwork) {
content = [
<div>You are on the wrong network</div>,
<div className="header__dialog__description">
{`Please switch to ${correctNetwork}`}
</div>,
];
}
return (
<div
className={classnames('header__dialog', {
'header__dialog--disconnected': (!isConnected || wrongNetwork) && initialized,
})}
>
{content}
</div> </div>
</div> );
}
}
function Header (props) {
return (
<div className="header">
<BlockingWarning {...props} />
<div <div
className={classnames('header__top', { className={classnames('header__top', {
'header--inactive': !props.isConnected, 'header--inactive': !props.isConnected,
...@@ -133,6 +178,7 @@ export default connect( ...@@ -133,6 +178,7 @@ export default connect(
state => ({ state => ({
currentAddress: state.web3connect.account, currentAddress: state.web3connect.account,
initialized: state.web3connect.initialized, initialized: state.web3connect.initialized,
isConnected: !!state.web3connect.web3 && !!state.web3connect.account, isConnected: !!state.web3connect.account && state.web3connect.networkId == process.env.REACT_APP_NETWORK_ID,
web3: state.web3connect.web3,
}), }),
)(Header); )(Header);
@import "../../variables";
.beta-message {
padding: 1rem;
margin-bottom: 1rem;
border: 1px solid rgba($salmon-red, .4);
background-color: rgba($salmon-red, .1);
border-radius: 1rem;
font-size: .75rem;
line-height: 1rem;
text-align: center;
}
...@@ -3,6 +3,8 @@ import { withRouter } from 'react-router-dom'; ...@@ -3,6 +3,8 @@ import { withRouter } from 'react-router-dom';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import {Tab, Tabs} from "../Tab"; import {Tab, Tabs} from "../Tab";
import './beta-message.scss';
class NavigationTabs extends Component { class NavigationTabs extends Component {
static propTypes = { static propTypes = {
history: PropTypes.shape({ history: PropTypes.shape({
...@@ -32,11 +34,16 @@ class NavigationTabs extends Component { ...@@ -32,11 +34,16 @@ class NavigationTabs extends Component {
render() { render() {
return ( return (
<div>
<Tabs className={this.props.className}> <Tabs className={this.props.className}>
{ this.renderTab('Swap', '/swap', /swap/) } { this.renderTab('Swap', '/swap', /swap/) }
{ this.renderTab('Send', '/send', /send/) } { this.renderTab('Send', '/send', /send/) }
{ this.renderTab('Pool', '/add-liquidity', /add-liquidity|remove-liquidity|create-exchange/) } { this.renderTab('Pool', '/add-liquidity', /add-liquidity|remove-liquidity|create-exchange/) }
</Tabs> </Tabs>
<div className="beta-message">
🦄 Uniswap is an experimental project. Use at your own risk 💀
</div>
</div>
); );
} }
} }
......
...@@ -104,6 +104,7 @@ export const setAddresses = networkId => { ...@@ -104,6 +104,7 @@ export const setAddresses = networkId => {
// Rinkeby // Rinkeby
case 4: case 4:
case '4': case '4':
default:
return { return {
type: SET_ADDRESSES, type: SET_ADDRESSES,
payload: RINKEBY, payload: RINKEBY,
......
...@@ -15,9 +15,11 @@ export const UPDATE_TOKEN_BALANCE = 'web3connect/updateTokenBalance'; ...@@ -15,9 +15,11 @@ export const UPDATE_TOKEN_BALANCE = 'web3connect/updateTokenBalance';
export const WATCH_APPROVALS = 'web3connect/watchApprovals'; export const WATCH_APPROVALS = 'web3connect/watchApprovals';
export const UPDATE_APPROVALS = 'web3connect/updateApprovals'; export const UPDATE_APPROVALS = 'web3connect/updateApprovals';
export const ADD_CONTRACT = 'web3connect/addContract'; export const ADD_CONTRACT = 'web3connect/addContract';
export const UPDATE_NETWORK_ID = 'web3connect/updateNetworkId';
const initialState = { const initialState = {
web3: null, web3: null,
networkId: 0,
initialized: false, initialized: false,
account: '', account: '',
balances: { balances: {
...@@ -212,6 +214,7 @@ export const sync = () => async (dispatch, getState) => { ...@@ -212,6 +214,7 @@ export const sync = () => async (dispatch, getState) => {
account, account,
watched, watched,
contracts, contracts,
networkId,
} = getState().web3connect; } = getState().web3connect;
// Sync Account // Sync Account
...@@ -221,6 +224,13 @@ export const sync = () => async (dispatch, getState) => { ...@@ -221,6 +224,13 @@ export const sync = () => async (dispatch, getState) => {
dispatch(watchBalance({ balanceOf: accounts[0] })); dispatch(watchBalance({ balanceOf: accounts[0] }));
} }
if (!networkId) {
dispatch({
type: UPDATE_NETWORK_ID,
payload: await web3.eth.net.getId(),
});
}
// Sync Ethereum Balances // Sync Ethereum Balances
watched.balances.ethereum.forEach(async address => { watched.balances.ethereum.forEach(async address => {
const balance = await web3.eth.getBalance(address); const balance = await web3.eth.getBalance(address);
...@@ -433,6 +443,8 @@ export default function web3connectReducer(state = initialState, { type, payload ...@@ -433,6 +443,8 @@ export default function web3connectReducer(state = initialState, { type, payload
}, },
}, },
}; };
case UPDATE_NETWORK_ID:
return { ...state, networkId: payload };
default: default:
return state; return state;
} }
......
...@@ -307,7 +307,7 @@ class AddLiquidity extends Component { ...@@ -307,7 +307,7 @@ class AddLiquidity extends Component {
</div> </div>
<div className="pool__exchange-rate-wrapper"> <div className="pool__exchange-rate-wrapper">
<span className="swap__exchange-rate">Current Pool Size</span> <span className="swap__exchange-rate">Current Pool Size</span>
<span>{` ${ethValue.dividedBy(10 ** 18).toFixed(2)} ${eth} + ${tokenValue.dividedBy(10 ** decimals).toFixed(2)} ${label}`}</span> <span>{` ${ethValue.dividedBy(10 ** 18).toFixed(2)} ${eth} / ${tokenValue.dividedBy(10 ** decimals).toFixed(2)} ${label}`}</span>
</div> </div>
</div> </div>
) )
...@@ -553,7 +553,7 @@ class AddLiquidity extends Component { ...@@ -553,7 +553,7 @@ class AddLiquidity extends Component {
export default connect( export default connect(
state => ({ state => ({
isConnected: Boolean(state.web3connect.account), isConnected: Boolean(state.web3connect.account) && state.web3connect.networkId == process.env.REACT_APP_NETWORK_ID,
account: state.web3connect.account, account: state.web3connect.account,
balances: state.web3connect.balances, balances: state.web3connect.balances,
web3: state.web3connect.web3, web3: state.web3connect.web3,
......
...@@ -207,7 +207,7 @@ class CreateExchange extends Component { ...@@ -207,7 +207,7 @@ class CreateExchange extends Component {
export default connect( export default connect(
state => ({ state => ({
isConnected: Boolean(state.web3connect.account), isConnected: Boolean(state.web3connect.account) && state.web3connect.networkId == process.env.REACT_APP_NETWORK_ID,
account: state.web3connect.account, account: state.web3connect.account,
balances: state.web3connect.balances, balances: state.web3connect.balances,
web3: state.web3connect.web3, web3: state.web3connect.web3,
......
...@@ -153,7 +153,7 @@ class RemoveLiquidity extends Component { ...@@ -153,7 +153,7 @@ class RemoveLiquidity extends Component {
const exchangeAddress = fromToken[tokenAddress]; const exchangeAddress = fromToken[tokenAddress];
if (!exchangeAddress || !web3 || !input) { if (!exchangeAddress || !web3) {
return [ return [
<CurrencyInputPanel <CurrencyInputPanel
key="remove-liquidity-input" key="remove-liquidity-input"
...@@ -183,20 +183,25 @@ class RemoveLiquidity extends Component { ...@@ -183,20 +183,25 @@ class RemoveLiquidity extends Component {
</OversizedPanel> </OversizedPanel>
]; ];
} }
const { value, decimals } = getBalance(account, exchangeAddress); const { value: liquidityBalance } = getBalance(account, exchangeAddress);
const { value: ethReserve } = getBalance(exchangeAddress); const { value: ethReserve } = getBalance(exchangeAddress);
const { value: tokenReserve, label } = getBalance(exchangeAddress, tokenAddress); const { value: tokenReserve, decimals: tokenDecimals, label } = getBalance(exchangeAddress, tokenAddress);
const ownership = value.dividedBy(totalSupply); const ownership = liquidityBalance.dividedBy(totalSupply);
const ethPer = ethReserve.dividedBy(totalSupply); const ethPer = ethReserve.dividedBy(totalSupply);
const tokenPer = tokenReserve.dividedBy(totalSupply); const tokenPer = tokenReserve.dividedBy(totalSupply);
const exchangeRate = tokenReserve.div(ethReserve);
const ownedEth = ethPer.multipliedBy(liquidityBalance).dividedBy(10 ** 18);
const ownedToken = tokenPer.multipliedBy(liquidityBalance).dividedBy(10 ** tokenDecimals);
return [ return [
<CurrencyInputPanel <CurrencyInputPanel
title="Output" title="Output"
description="(estimated)" description="(estimated)"
key="remove-liquidity-input" key="remove-liquidity-input"
renderInput={() => ( renderInput={() => input
? (
<div className="remove-liquidity__output"> <div className="remove-liquidity__output">
<div className="remove-liquidity__output-text"> <div className="remove-liquidity__output-text">
{`${ethPer.multipliedBy(input).toFixed(3)} ETH`} {`${ethPer.multipliedBy(input).toFixed(3)} ETH`}
...@@ -206,7 +211,9 @@ class RemoveLiquidity extends Component { ...@@ -206,7 +211,9 @@ class RemoveLiquidity extends Component {
{`${tokenPer.multipliedBy(input).toFixed(3)} ${label}`} {`${tokenPer.multipliedBy(input).toFixed(3)} ${label}`}
</div> </div>
</div> </div>
)} )
: <div className="remove-liquidity__output" />
}
disableTokenSelect disableTokenSelect
disableUnlock disableUnlock
/>, />,
...@@ -214,15 +221,19 @@ class RemoveLiquidity extends Component { ...@@ -214,15 +221,19 @@ class RemoveLiquidity extends Component {
<div className="pool__summary-panel"> <div className="pool__summary-panel">
<div className="pool__exchange-rate-wrapper"> <div className="pool__exchange-rate-wrapper">
<span className="pool__exchange-rate">Exchange Rate</span> <span className="pool__exchange-rate">Exchange Rate</span>
<span>{` ${ethReserve.dividedBy(10 ** 18).toFixed(2)} ETH + ${tokenReserve.dividedBy(10 ** decimals).toFixed(2)} ${label}`}</span> <span>
{`1 ETH = ${exchangeRate.toFixed(4)} ${label}`}
</span>
</div> </div>
<div className="pool__exchange-rate-wrapper"> <div className="pool__exchange-rate-wrapper">
<span className="swap__exchange-rate">Current Pool Size</span> <span className="swap__exchange-rate">Current Pool Size</span>
<span>{totalSupply.dividedBy(10 ** decimals).toFixed(4)}</span> <span>{`${ethReserve.dividedBy(10 ** 18).toFixed(2)} ETH / ${tokenReserve.dividedBy(10 ** tokenDecimals).toFixed(2)} ${label}`}</span>
</div> </div>
<div className="pool__exchange-rate-wrapper"> <div className="pool__exchange-rate-wrapper">
<span className="swap__exchange-rate">Your Pool Share</span> <span className="swap__exchange-rate">
<span>{ownership.multipliedBy(100).toFixed(2)}%</span> Your Pool Share ({ownership.multipliedBy(100).toFixed(2)}%)
</span>
<span>{`${ownedEth.toFixed(2)} ETH / ${ownedToken.toFixed(2)} ${label}`}</span>
</div> </div>
</div> </div>
</OversizedPanel> </OversizedPanel>
...@@ -282,7 +293,7 @@ class RemoveLiquidity extends Component { ...@@ -282,7 +293,7 @@ class RemoveLiquidity extends Component {
export default connect( export default connect(
state => ({ state => ({
isConnected: Boolean(state.web3connect.account), isConnected: Boolean(state.web3connect.account) && state.web3connect.networkId == process.env.REACT_APP_NETWORK_ID,
web3: state.web3connect.web3, web3: state.web3connect.web3,
balances: state.web3connect.balances, balances: state.web3connect.balances,
account: state.web3connect.account, account: state.web3connect.account,
......
...@@ -666,7 +666,7 @@ class Send extends Component { ...@@ -666,7 +666,7 @@ class Send extends Component {
</OversizedPanel> </OversizedPanel>
); );
} }
console.log(outputLabel)
return ( return (
<OversizedPanel hideBottom> <OversizedPanel hideBottom>
<div className="swap__exchange-rate-wrapper"> <div className="swap__exchange-rate-wrapper">
...@@ -776,7 +776,7 @@ class Send extends Component { ...@@ -776,7 +776,7 @@ class Send extends Component {
export default connect( export default connect(
state => ({ state => ({
balances: state.web3connect.balances, balances: state.web3connect.balances,
isConnected: !!state.web3connect.account, isConnected: !!state.web3connect.account && state.web3connect.networkId == process.env.REACT_APP_NETWORK_ID,
account: state.web3connect.account, account: state.web3connect.account,
web3: state.web3connect.web3, web3: state.web3connect.web3,
exchangeAddresses: state.addresses.exchangeAddresses, exchangeAddresses: state.addresses.exchangeAddresses,
......
...@@ -751,7 +751,7 @@ class Swap extends Component { ...@@ -751,7 +751,7 @@ class Swap extends Component {
export default connect( export default connect(
state => ({ state => ({
balances: state.web3connect.balances, balances: state.web3connect.balances,
isConnected: !!state.web3connect.account, isConnected: !!state.web3connect.account && state.web3connect.networkId == process.env.REACT_APP_NETWORK_ID,
account: state.web3connect.account, account: state.web3connect.account,
web3: state.web3connect.web3, web3: state.web3connect.web3,
exchangeAddresses: state.addresses.exchangeAddresses, exchangeAddresses: state.addresses.exchangeAddresses,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment