Add Remove Liquidity (#98)
This commit is contained in:
parent
14b70eebeb
commit
c798045590
@ -56,6 +56,7 @@ class CurrencyInputPanel extends Component {
|
|||||||
addExchange: PropTypes.func.isRequired,
|
addExchange: PropTypes.func.isRequired,
|
||||||
filteredTokens: PropTypes.arrayOf(PropTypes.string),
|
filteredTokens: PropTypes.arrayOf(PropTypes.string),
|
||||||
disableUnlock: PropTypes.bool,
|
disableUnlock: PropTypes.bool,
|
||||||
|
renderInput: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
@ -249,16 +250,76 @@ class CurrencyInputPanel extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderInput() {
|
||||||
|
const {
|
||||||
|
errorMessage,
|
||||||
|
value,
|
||||||
|
onValueChange,
|
||||||
|
selectedTokenAddress,
|
||||||
|
disableTokenSelect,
|
||||||
|
renderInput,
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
if (typeof renderInput === 'function') {
|
||||||
|
return renderInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="currency-input-panel__input-row">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
className={classnames('currency-input-panel__input',{
|
||||||
|
'currency-input-panel__input--error': errorMessage,
|
||||||
|
})}
|
||||||
|
placeholder="0.0"
|
||||||
|
onChange={e => onValueChange(e.target.value)}
|
||||||
|
onKeyPress={e => {
|
||||||
|
const charCode = e.which ? e.which : e.keyCode;
|
||||||
|
|
||||||
|
// Prevent 'minus' character
|
||||||
|
if (charCode === 45) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
value={value}
|
||||||
|
/>
|
||||||
|
{ this.renderUnlockButton() }
|
||||||
|
<button
|
||||||
|
className={classnames("currency-input-panel__currency-select", {
|
||||||
|
'currency-input-panel__currency-select--selected': selectedTokenAddress,
|
||||||
|
'currency-input-panel__currency-select--disabled': disableTokenSelect,
|
||||||
|
})}
|
||||||
|
onClick={() => {
|
||||||
|
if (!disableTokenSelect) {
|
||||||
|
this.setState({ isShowingModal: true });
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
selectedTokenAddress
|
||||||
|
? (
|
||||||
|
<TokenLogo
|
||||||
|
className="currency-input-panel__selected-token-logo"
|
||||||
|
address={selectedTokenAddress}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
{ TOKEN_ADDRESS_TO_LABEL[selectedTokenAddress] || 'Select a token' }
|
||||||
|
<span className="currency-input-panel__dropdown-icon" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
extraText,
|
extraText,
|
||||||
errorMessage,
|
errorMessage,
|
||||||
value,
|
|
||||||
onValueChange,
|
|
||||||
selectedTokenAddress,
|
|
||||||
disableTokenSelect,
|
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -277,52 +338,7 @@ class CurrencyInputPanel extends Component {
|
|||||||
{extraText}
|
{extraText}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="currency-input-panel__input-row">
|
{this.renderInput()}
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
min="0"
|
|
||||||
className={classnames('currency-input-panel__input',{
|
|
||||||
'currency-input-panel__input--error': errorMessage,
|
|
||||||
})}
|
|
||||||
placeholder="0.0"
|
|
||||||
onChange={e => onValueChange(e.target.value)}
|
|
||||||
onKeyPress={e => {
|
|
||||||
const charCode = e.which ? e.which : e.keyCode;
|
|
||||||
|
|
||||||
// Prevent 'minus' character
|
|
||||||
if (charCode === 45) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
value={value}
|
|
||||||
/>
|
|
||||||
{ this.renderUnlockButton() }
|
|
||||||
<button
|
|
||||||
className={classnames("currency-input-panel__currency-select", {
|
|
||||||
'currency-input-panel__currency-select--selected': selectedTokenAddress,
|
|
||||||
'currency-input-panel__currency-select--disabled': disableTokenSelect,
|
|
||||||
})}
|
|
||||||
onClick={() => {
|
|
||||||
if (!disableTokenSelect) {
|
|
||||||
this.setState({ isShowingModal: true });
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{
|
|
||||||
selectedTokenAddress
|
|
||||||
? (
|
|
||||||
<TokenLogo
|
|
||||||
className="currency-input-panel__selected-token-logo"
|
|
||||||
address={selectedTokenAddress}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
{ TOKEN_ADDRESS_TO_LABEL[selectedTokenAddress] || 'Select a token' }
|
|
||||||
<span className="currency-input-panel__dropdown-icon" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{this.renderModal()}
|
{this.renderModal()}
|
||||||
</div>
|
</div>
|
||||||
|
@ -44,6 +44,7 @@ const initialState = {
|
|||||||
const TOKEN_LABEL_FALLBACK = {
|
const TOKEN_LABEL_FALLBACK = {
|
||||||
'0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359': 'DAI',
|
'0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359': 'DAI',
|
||||||
'0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2': 'MKR',
|
'0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2': 'MKR',
|
||||||
|
'0x9B913956036a3462330B0642B20D3879ce68b450': 'BAT + ETH'
|
||||||
};
|
};
|
||||||
|
|
||||||
// selectors
|
// selectors
|
||||||
@ -246,6 +247,7 @@ export const sync = () => async (dispatch, getState) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const contract = contracts[tokenAddress] || new web3.eth.Contract(ERC20_ABI, tokenAddress);
|
const contract = contracts[tokenAddress] || new web3.eth.Contract(ERC20_ABI, tokenAddress);
|
||||||
|
const contractBytes32 = contracts[tokenAddress] || new web3.eth.Contract(ERC20_WITH_BYTES_ABI, tokenAddress);
|
||||||
|
|
||||||
if (!contracts[tokenAddress]) {
|
if (!contracts[tokenAddress]) {
|
||||||
dispatch({
|
dispatch({
|
||||||
@ -262,7 +264,17 @@ export const sync = () => async (dispatch, getState) => {
|
|||||||
const tokenBalance = getBalance(address, tokenAddress);
|
const tokenBalance = getBalance(address, tokenAddress);
|
||||||
const balance = await contract.methods.balanceOf(address).call();
|
const balance = await contract.methods.balanceOf(address).call();
|
||||||
const decimals = tokenBalance.decimals || await contract.methods.decimals().call();
|
const decimals = tokenBalance.decimals || await contract.methods.decimals().call();
|
||||||
const symbol = TOKEN_LABEL_FALLBACK[tokenAddress] || tokenBalance.label || await contract.methods.symbol().call();
|
let symbol = tokenBalance.symbol;
|
||||||
|
|
||||||
|
try {
|
||||||
|
symbol = symbol || await contract.methods.symbol().call().catch();
|
||||||
|
} catch (e) {
|
||||||
|
try {
|
||||||
|
symbol = symbol || web3.utils.hexToString(await contractBytes32.methods.symbol().call().catch());
|
||||||
|
} catch (err) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (tokenBalance.value.isEqualTo(BN(balance)) && tokenBalance.label && tokenBalance.decimals) {
|
if (tokenBalance.value.isEqualTo(BN(balance)) && tokenBalance.label && tokenBalance.decimals) {
|
||||||
return;
|
return;
|
||||||
|
@ -54,6 +54,7 @@ class App extends Component {
|
|||||||
<Route exact path="/swap" component={Swap} />
|
<Route exact path="/swap" component={Swap} />
|
||||||
<Route exact path="/send" component={Send} />
|
<Route exact path="/send" component={Send} />
|
||||||
<Route exact path="/add-liquidity" component={Pool} />
|
<Route exact path="/add-liquidity" component={Pool} />
|
||||||
|
<Route exact path="/remove-liquidity" component={Pool} />
|
||||||
<Route exact path="/create-exchange" component={Pool} />
|
<Route exact path="/create-exchange" component={Pool} />
|
||||||
<Redirect exact from="/" to="/swap" />
|
<Redirect exact from="/" to="/swap" />
|
||||||
</AnimatedSwitch>
|
</AnimatedSwitch>
|
||||||
|
294
src/pages/Pool/RemoveLiquidity.js
Normal file
294
src/pages/Pool/RemoveLiquidity.js
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import classnames from "classnames";
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { BigNumber as BN } from 'bignumber.js';
|
||||||
|
import NavigationTabs from "../../components/NavigationTabs";
|
||||||
|
import ModeSelector from "./ModeSelector";
|
||||||
|
import CurrencyInputPanel from "../../components/CurrencyInputPanel";
|
||||||
|
import { selectors } from '../../ducks/web3connect';
|
||||||
|
import OversizedPanel from "../../components/OversizedPanel";
|
||||||
|
import ArrowPlus from "../../assets/images/plus-blue.svg";
|
||||||
|
import EXCHANGE_ABI from "../../abi/exchange";
|
||||||
|
import promisify from "../../helpers/web3-promisfy";
|
||||||
|
|
||||||
|
class RemoveLiquidity extends Component {
|
||||||
|
static propTypes = {
|
||||||
|
account: PropTypes.string,
|
||||||
|
balances: PropTypes.object,
|
||||||
|
web3: PropTypes.object,
|
||||||
|
exchangeAddresses: PropTypes.shape({
|
||||||
|
fromToken: PropTypes.object.isRequired,
|
||||||
|
}).isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
state = {
|
||||||
|
tokenAddress: '',
|
||||||
|
value: '',
|
||||||
|
totalSupply: BN(0),
|
||||||
|
};
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.setState({
|
||||||
|
value: '',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
validate() {
|
||||||
|
const { tokenAddress, value } = this.state;
|
||||||
|
const { account, selectors, exchangeAddresses: { fromToken }, web3 } = this.props;
|
||||||
|
const exchangeAddress = fromToken[tokenAddress];
|
||||||
|
|
||||||
|
if (!web3 || !exchangeAddress || !account || !value) {
|
||||||
|
return {
|
||||||
|
isValid: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const { getBalance } = selectors();
|
||||||
|
|
||||||
|
const { value: liquidityBalance, decimals: liquidityDecimals } = getBalance(account, exchangeAddress);
|
||||||
|
|
||||||
|
if (liquidityBalance.isLessThan(BN(value).multipliedBy(10 ** liquidityDecimals))) {
|
||||||
|
return { isValid: false, errorMessage: 'Insufficient balance' };
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
isValid: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
onTokenSelect = async tokenAddress => {
|
||||||
|
const { exchangeAddresses: { fromToken }, web3 } = this.props;
|
||||||
|
const exchangeAddress = fromToken[tokenAddress];
|
||||||
|
this.setState({ tokenAddress });
|
||||||
|
|
||||||
|
if (!web3 || !exchangeAddress) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const exchange = new web3.eth.Contract(EXCHANGE_ABI, exchangeAddress);
|
||||||
|
|
||||||
|
const totalSupply = await exchange.methods.totalSupply().call();
|
||||||
|
this.setState({
|
||||||
|
totalSupply: BN(totalSupply),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onInputChange = value => {
|
||||||
|
this.setState({ value });
|
||||||
|
};
|
||||||
|
|
||||||
|
onRemoveLiquidity = async () => {
|
||||||
|
const { tokenAddress, value: input, totalSupply } = this.state;
|
||||||
|
const {
|
||||||
|
exchangeAddresses: { fromToken },
|
||||||
|
web3,
|
||||||
|
selectors,
|
||||||
|
account,
|
||||||
|
} = this.props;
|
||||||
|
const exchangeAddress = fromToken[tokenAddress];
|
||||||
|
const { getBalance } = selectors();
|
||||||
|
if (!web3 || !exchangeAddress) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const exchange = new web3.eth.Contract(EXCHANGE_ABI, exchangeAddress);
|
||||||
|
const SLIPPAGE = .02;
|
||||||
|
const { decimals } = getBalance(account, exchangeAddress);
|
||||||
|
const { value: ethReserve } = getBalance(exchangeAddress);
|
||||||
|
const { value: tokenReserve } = getBalance(exchangeAddress, tokenAddress);
|
||||||
|
const amount = BN(input).multipliedBy(10 ** decimals);
|
||||||
|
|
||||||
|
const ownership = amount.dividedBy(totalSupply);
|
||||||
|
const ethWithdrawn = ethReserve.multipliedBy(ownership);
|
||||||
|
const tokenWithdrawn = tokenReserve.multipliedBy(ownership);
|
||||||
|
const blockNumber = await promisify(web3, 'getBlockNumber');
|
||||||
|
const block = await promisify(web3, 'getBlock', blockNumber);
|
||||||
|
const deadline = block.timestamp + 300;
|
||||||
|
|
||||||
|
exchange.methods.removeLiquidity(
|
||||||
|
amount.toFixed(0),
|
||||||
|
ethWithdrawn.multipliedBy(1 - SLIPPAGE).toFixed(0),
|
||||||
|
tokenWithdrawn.multipliedBy(1 - SLIPPAGE).toFixed(0),
|
||||||
|
deadline,
|
||||||
|
).send({ from: account }, (err, data) => {
|
||||||
|
if (data) {
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
getBalance = () => {
|
||||||
|
const {
|
||||||
|
exchangeAddresses: { fromToken },
|
||||||
|
account,
|
||||||
|
web3,
|
||||||
|
selectors,
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
const { tokenAddress } = this.state;
|
||||||
|
|
||||||
|
if (!web3) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const exchangeAddress = fromToken[tokenAddress];
|
||||||
|
if (!exchangeAddress) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
const { value, decimals } = selectors().getBalance(account, exchangeAddress);
|
||||||
|
return `Balance: ${value.dividedBy(10 ** decimals).toFixed(7)}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
renderOutput() {
|
||||||
|
const {
|
||||||
|
exchangeAddresses: { fromToken },
|
||||||
|
account,
|
||||||
|
web3,
|
||||||
|
selectors,
|
||||||
|
} = this.props;
|
||||||
|
const { getBalance } = selectors();
|
||||||
|
|
||||||
|
const { tokenAddress, totalSupply, value: input } = this.state;
|
||||||
|
|
||||||
|
|
||||||
|
const exchangeAddress = fromToken[tokenAddress];
|
||||||
|
if (!exchangeAddress || !web3 || !input) {
|
||||||
|
return [
|
||||||
|
<CurrencyInputPanel
|
||||||
|
key="remove-liquidity-input"
|
||||||
|
title="Output"
|
||||||
|
description="(estimated)"
|
||||||
|
renderInput={() => (
|
||||||
|
<div className="remove-liquidity__output"></div>
|
||||||
|
)}
|
||||||
|
disableTokenSelect
|
||||||
|
disableUnlock
|
||||||
|
/>,
|
||||||
|
<OversizedPanel key="remove-liquidity-input-under" hideBottom>
|
||||||
|
<div className="pool__summary-panel">
|
||||||
|
<div className="pool__exchange-rate-wrapper">
|
||||||
|
<span className="pool__exchange-rate">Exchange Rate</span>
|
||||||
|
<span> - </span>
|
||||||
|
</div>
|
||||||
|
<div className="pool__exchange-rate-wrapper">
|
||||||
|
<span className="swap__exchange-rate">Current Pool Size</span>
|
||||||
|
<span> - </span>
|
||||||
|
</div>
|
||||||
|
<div className="pool__exchange-rate-wrapper">
|
||||||
|
<span className="swap__exchange-rate">Your Pool Share</span>
|
||||||
|
<span> - </span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</OversizedPanel>
|
||||||
|
];
|
||||||
|
}
|
||||||
|
const { value, decimals } = getBalance(account, exchangeAddress);
|
||||||
|
const { value: ethReserve } = getBalance(exchangeAddress);
|
||||||
|
const { value: tokenReserve, label } = getBalance(exchangeAddress, tokenAddress);
|
||||||
|
|
||||||
|
const ownership = value.dividedBy(totalSupply);
|
||||||
|
const ethPer = ethReserve.dividedBy(totalSupply);
|
||||||
|
const tokenPer = tokenReserve.dividedBy(totalSupply);
|
||||||
|
|
||||||
|
return [
|
||||||
|
<CurrencyInputPanel
|
||||||
|
title="Output"
|
||||||
|
description="(estimated)"
|
||||||
|
key="remove-liquidity-input"
|
||||||
|
renderInput={() => (
|
||||||
|
<div className="remove-liquidity__output">
|
||||||
|
<div className="remove-liquidity__output-text">
|
||||||
|
{`${ethPer.multipliedBy(input).toFixed(3)} ETH`}
|
||||||
|
</div>
|
||||||
|
<div className="remove-liquidity__output-plus"> + </div>
|
||||||
|
<div className="remove-liquidity__output-text">
|
||||||
|
{`${tokenPer.multipliedBy(input).toFixed(3)} ${label}`}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
disableTokenSelect
|
||||||
|
disableUnlock
|
||||||
|
/>,
|
||||||
|
<OversizedPanel key="remove-liquidity-input-under" hideBottom>
|
||||||
|
<div className="pool__summary-panel">
|
||||||
|
<div className="pool__exchange-rate-wrapper">
|
||||||
|
<span className="pool__exchange-rate">Exchange Rate</span>
|
||||||
|
<span>{` ${ethReserve.dividedBy(10 ** 18).toFixed(2)} ETH + ${tokenReserve.dividedBy(10 ** decimals).toFixed(2)} ${label}`}</span>
|
||||||
|
</div>
|
||||||
|
<div className="pool__exchange-rate-wrapper">
|
||||||
|
<span className="swap__exchange-rate">Current Pool Size</span>
|
||||||
|
<span>{totalSupply.dividedBy(10 ** decimals).toFixed(4)}</span>
|
||||||
|
</div>
|
||||||
|
<div className="pool__exchange-rate-wrapper">
|
||||||
|
<span className="swap__exchange-rate">Your Pool Share</span>
|
||||||
|
<span>{ownership.multipliedBy(100).toFixed(2)}%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</OversizedPanel>
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { isConnected } = this.props;
|
||||||
|
const { tokenAddress, value } = this.state;
|
||||||
|
const { isValid, errorMessage } = this.validate();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key="content"
|
||||||
|
className={classnames('swap__content', {
|
||||||
|
'swap--inactive': !isConnected,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<NavigationTabs
|
||||||
|
className={classnames('header__navigation', {
|
||||||
|
'header--inactive': !isConnected,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
<ModeSelector title="Remove Liquidity" />
|
||||||
|
<CurrencyInputPanel
|
||||||
|
title="Pool Tokens"
|
||||||
|
extraText={this.getBalance(tokenAddress)}
|
||||||
|
onValueChange={this.onInputChange}
|
||||||
|
value={value}
|
||||||
|
errorMessage={errorMessage}
|
||||||
|
selectedTokenAddress={tokenAddress}
|
||||||
|
onCurrencySelected={this.onTokenSelect}
|
||||||
|
filteredTokens={['ETH']}
|
||||||
|
/>
|
||||||
|
<OversizedPanel>
|
||||||
|
<div className="swap__down-arrow-background">
|
||||||
|
<img className="swap__down-arrow" src={ArrowPlus} />
|
||||||
|
</div>
|
||||||
|
</OversizedPanel>
|
||||||
|
{ this.renderOutput() }
|
||||||
|
<div className="pool__cta-container">
|
||||||
|
<button
|
||||||
|
className={classnames('pool__cta-btn', {
|
||||||
|
'swap--inactive': !isConnected,
|
||||||
|
'pool__cta-btn--inactive': !isValid,
|
||||||
|
})}
|
||||||
|
disabled={!isValid}
|
||||||
|
onClick={this.onRemoveLiquidity}
|
||||||
|
>
|
||||||
|
Remove Liquidity
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
state => ({
|
||||||
|
isConnected: Boolean(state.web3connect.account),
|
||||||
|
web3: state.web3connect.web3,
|
||||||
|
balances: state.web3connect.balances,
|
||||||
|
account: state.web3connect.account,
|
||||||
|
exchangeAddresses: state.addresses.exchangeAddresses,
|
||||||
|
}),
|
||||||
|
dispatch => ({
|
||||||
|
selectors: () => dispatch(selectors()),
|
||||||
|
})
|
||||||
|
)(RemoveLiquidity);
|
@ -2,7 +2,8 @@ import React, { Component } from 'react';
|
|||||||
import Header from '../../components/Header';
|
import Header from '../../components/Header';
|
||||||
import AddLiquidity from './AddLiquidity';
|
import AddLiquidity from './AddLiquidity';
|
||||||
import CreateExchange from './CreateExchange';
|
import CreateExchange from './CreateExchange';
|
||||||
import { Switch, Redirect, Route } from 'react-router-dom';
|
import RemoveLiquidity from './RemoveLiquidity';
|
||||||
|
import { Switch, Route } from 'react-router-dom';
|
||||||
import "./pool.scss";
|
import "./pool.scss";
|
||||||
import MediaQuery from "react-responsive";
|
import MediaQuery from "react-responsive";
|
||||||
|
|
||||||
@ -16,7 +17,7 @@ class Pool extends Component {
|
|||||||
</MediaQuery>
|
</MediaQuery>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path="/add-liquidity" component={AddLiquidity} />
|
<Route exact path="/add-liquidity" component={AddLiquidity} />
|
||||||
{/*<Route exact path="/remove" component={Send} />*/}
|
<Route exact path="/remove-liquidity" component={RemoveLiquidity} />
|
||||||
<Route exact path="/create-exchange" component={CreateExchange} />
|
<Route exact path="/create-exchange" component={CreateExchange} />
|
||||||
</Switch>
|
</Switch>
|
||||||
</div>
|
</div>
|
||||||
|
@ -150,3 +150,22 @@
|
|||||||
color: $dove-gray;
|
color: $dove-gray;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.remove-liquidity {
|
||||||
|
&__output {
|
||||||
|
@extend %row-nowrap;
|
||||||
|
min-height: 3.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__output-text {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
line-height: 1.5rem;
|
||||||
|
padding: 1rem .75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__output-plus {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
line-height: 1.5rem;
|
||||||
|
padding: 1rem 0;
|
||||||
|
}
|
||||||
|
}
|
@ -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">
|
||||||
|
@ -450,13 +450,6 @@ class Swap extends Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(
|
|
||||||
BN(outputValue).multipliedBy(10 ** outputDecimals).toFixed(0),
|
|
||||||
BN(inputValue).multipliedBy(10 ** inputDecimals).multipliedBy(1 + TOKEN_ALLOWED_SLIPPAGE).toFixed(0),
|
|
||||||
inputAmountB.multipliedBy(1.2).toFixed(0),
|
|
||||||
deadline,
|
|
||||||
outputCurrency,
|
|
||||||
)
|
|
||||||
new web3.eth.Contract(EXCHANGE_ABI, fromToken[inputCurrency])
|
new web3.eth.Contract(EXCHANGE_ABI, fromToken[inputCurrency])
|
||||||
.methods
|
.methods
|
||||||
.tokenToTokenSwapOutput(
|
.tokenToTokenSwapOutput(
|
||||||
|
Loading…
Reference in New Issue
Block a user