Commit 509ddaea authored by Chi Kei Chan's avatar Chi Kei Chan Committed by GitHub

Implement Add Liquidity (#77)

* CSS fixes

* Add Liquidity UI and Validation

* Finish Add Liquidity
parent a4e0d11c
...@@ -2,25 +2,26 @@ ...@@ -2,25 +2,26 @@
.currency-input-panel { .currency-input-panel {
@extend %col-nowrap; @extend %col-nowrap;
box-shadow: 0 4px 8px 0 rgba($royal-blue, 0.1);
&__container {
position: relative; position: relative;
border-radius: 1.25rem;
z-index: 200; z-index: 200;
&__container {
border-radius: 1.25rem; border-radius: 1.25rem;
border: 0.5px solid $mercury-gray; box-shadow: 0 0 0 .5px $mercury-gray;
background-color: $white; background-color: $white;
box-shadow: 0px 4px 4px 2px rgba($royal-blue, 0.05);
&--error { &--error {
border: 0.5px solid $salmon-red; box-shadow: 0 0 0 .5px $salmon-red;
} }
&:focus-within { &:focus-within {
border-color: $royal-blue; box-shadow: 0 0 .5px .5px $malibu-blue;
} }
&--error:focus-within { &--error:focus-within {
border-color: $salmon-red; box-shadow: 0 0 .5px .5px $salmon-red;
} }
} }
...@@ -93,6 +94,12 @@ ...@@ -93,6 +94,12 @@
background-image: url(../../assets/images/dropdown.svg); background-image: url(../../assets/images/dropdown.svg);
} }
} }
&--disabled {
.currency-input-panel__dropdown-icon {
opacity: 0;
}
}
} }
&__sub-currency-select { &__sub-currency-select {
......
...@@ -45,10 +45,13 @@ class CurrencyInputPanel extends Component { ...@@ -45,10 +45,13 @@ class CurrencyInputPanel extends Component {
selectedTokens: PropTypes.array.isRequired, selectedTokens: PropTypes.array.isRequired,
errorMessage: PropTypes.string, errorMessage: PropTypes.string,
selectedTokenAddress: PropTypes.string, selectedTokenAddress: PropTypes.string,
disableTokenSelect: PropTypes.bool,
filteredTokens: PropTypes.arrayOf(PropTypes.string),
}; };
static defaultProps = { static defaultProps = {
selectedTokens: [], selectedTokens: [],
filteredTokens: [],
onCurrencySelected() {}, onCurrencySelected() {},
onValueChange() {}, onValueChange() {},
selectedTokenAddress: '', selectedTokenAddress: '',
...@@ -64,6 +67,7 @@ class CurrencyInputPanel extends Component { ...@@ -64,6 +67,7 @@ class CurrencyInputPanel extends Component {
}; };
createTokenList = () => { createTokenList = () => {
const { filteredTokens } = this.props;
let tokens = this.props.tokenAddresses.addresses; let tokens = this.props.tokenAddresses.addresses;
let tokenList = [ { value: 'ETH', label: 'ETH', address: 'ETH' } ]; let tokenList = [ { value: 'ETH', label: 'ETH', address: 'ETH' } ];
...@@ -76,7 +80,7 @@ class CurrencyInputPanel extends Component { ...@@ -76,7 +80,7 @@ class CurrencyInputPanel extends Component {
TOKEN_ADDRESS_TO_LABEL[tokens[i][1]] = tokens[i][0]; TOKEN_ADDRESS_TO_LABEL[tokens[i][1]] = tokens[i][0];
} }
return tokenList; return tokenList.filter(({ address }) => !filteredTokens.includes(address));
}; };
onTokenSelect = (address) => { onTokenSelect = (address) => {
...@@ -122,7 +126,12 @@ class CurrencyInputPanel extends Component { ...@@ -122,7 +126,12 @@ class CurrencyInputPanel extends Component {
renderTokenList() { renderTokenList() {
const tokens = this.createTokenList(); const tokens = this.createTokenList();
const { searchQuery } = this.state; const { searchQuery } = this.state;
const { selectedTokens } = this.props; const { selectedTokens, disableTokenSelect } = this.props;
if (disableTokenSelect) {
return;
}
let results; let results;
if (!searchQuery) { if (!searchQuery) {
...@@ -196,6 +205,7 @@ class CurrencyInputPanel extends Component { ...@@ -196,6 +205,7 @@ class CurrencyInputPanel extends Component {
value, value,
onValueChange, onValueChange,
selectedTokenAddress, selectedTokenAddress,
disableTokenSelect,
} = this.props; } = this.props;
return ( return (
...@@ -232,8 +242,13 @@ class CurrencyInputPanel extends Component { ...@@ -232,8 +242,13 @@ class CurrencyInputPanel extends Component {
<button <button
className={classnames("currency-input-panel__currency-select", { className={classnames("currency-input-panel__currency-select", {
'currency-input-panel__currency-select--selected': selectedTokenAddress, 'currency-input-panel__currency-select--selected': selectedTokenAddress,
'currency-input-panel__currency-select--disabled': disableTokenSelect,
})} })}
onClick={() => this.setState({ isShowingModal: true })} onClick={() => {
if (!disableTokenSelect) {
this.setState({ isShowingModal: true });
}
}}
> >
{ {
selectedTokenAddress selectedTokenAddress
......
...@@ -6,14 +6,14 @@ ...@@ -6,14 +6,14 @@
height: 3rem; height: 3rem;
background-color: $concrete-gray; background-color: $concrete-gray;
border-radius: 3rem; border-radius: 3rem;
border: 1px solid $mercury-gray; box-shadow: 0 0 0 .5px darken($concrete-gray, 5);
.tab:first-child { .tab:first-child {
margin-left: -1px; //margin-left: -1px;
} }
.tab:last-child { .tab:last-child {
margin-right: -1px; //margin-right: -1px;
} }
} }
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
height: 3rem; height: 3rem;
flex: 1 0 auto; flex: 1 0 auto;
border-radius: 3rem; border-radius: 3rem;
border: 1px solid transparent;
transition: 300ms ease-in-out; transition: 300ms ease-in-out;
cursor: pointer; cursor: pointer;
...@@ -36,7 +35,7 @@ ...@@ -36,7 +35,7 @@
&--selected { &--selected {
background-color: $white; background-color: $white;
border-radius: 3rem; border-radius: 3rem;
border: 1px solid $mercury-gray; box-shadow: 0 0 .5px .5px $mercury-gray;
font-weight: 500; font-weight: 500;
span { span {
......
...@@ -17,6 +17,7 @@ export const ADD_CONTRACT = 'web3connect/addContract'; ...@@ -17,6 +17,7 @@ export const ADD_CONTRACT = 'web3connect/addContract';
const initialState = { const initialState = {
web3: null, web3: null,
initialized: false,
account: '', account: '',
balances: { balances: {
ethereum: {}, ethereum: {},
...@@ -39,7 +40,7 @@ export const selectors = () => (dispatch, getState) => { ...@@ -39,7 +40,7 @@ export const selectors = () => (dispatch, getState) => {
return { return {
getBalance: address => { getBalance: address => {
const balance = state.balances.ethereum[address]; const balance = state.balances.ethereum[address];
console.log({balance})
if (!balance) { if (!balance) {
dispatch(watchBalance({ balanceOf: address })); dispatch(watchBalance({ balanceOf: address }));
return Balance(0, 'ETH'); return Balance(0, 'ETH');
...@@ -98,7 +99,6 @@ export const initialize = () => (dispatch, getState) => { ...@@ -98,7 +99,6 @@ export const initialize = () => (dispatch, getState) => {
if (typeof window.web3 !== 'undefined') { if (typeof window.web3 !== 'undefined') {
const web3 = new Web3(window.web3.currentProvider); const web3 = new Web3(window.web3.currentProvider);
await window.ethereum.enable();
dispatch({ dispatch({
type: INITIALIZE, type: INITIALIZE,
payload: web3, payload: web3,
...@@ -108,28 +108,38 @@ export const initialize = () => (dispatch, getState) => { ...@@ -108,28 +108,38 @@ export const initialize = () => (dispatch, getState) => {
}) })
}; };
export const watchBalance = ({ balanceOf, tokenAddress }) => { export const watchBalance = ({ balanceOf, tokenAddress }) => (dispatch, getState) => {
if (!balanceOf) { if (!balanceOf) {
return { type: '' }; return;
} }
const { web3connect } = getState();
const { watched } = web3connect;
if (!tokenAddress) { if (!tokenAddress) {
return { if (watched.balances.ethereum.includes(balanceOf)) {
return;
}
dispatch({
type: WATCH_ETH_BALANCE, type: WATCH_ETH_BALANCE,
payload: balanceOf, payload: balanceOf,
}; });
} else if (tokenAddress) { } else if (tokenAddress) {
return { if (watched.balances[tokenAddress] && watched.balances[tokenAddress].includes(balanceOf)) {
return;
}
dispatch({
type: WATCH_TOKEN_BALANCE, type: WATCH_TOKEN_BALANCE,
payload: { payload: {
tokenAddress, tokenAddress,
balanceOf, balanceOf,
}, },
}; });
} }
} };
export const sync = () => async (dispatch, getState) => { export const sync = () => async (dispatch, getState) => {
const { getBalance, getTokenBalance } = dispatch(selectors());
const web3 = await dispatch(initialize()); const web3 = await dispatch(initialize());
const { const {
account, account,
...@@ -142,12 +152,17 @@ export const sync = () => async (dispatch, getState) => { ...@@ -142,12 +152,17 @@ export const sync = () => async (dispatch, getState) => {
if (account !== accounts[0]) { if (account !== accounts[0]) {
dispatch({ type: UPDATE_ACCOUNT, payload: accounts[0] }); dispatch({ type: UPDATE_ACCOUNT, payload: accounts[0] });
dispatch(watchBalance({ balanceOf: accounts[0] })); dispatch(watchBalance({ balanceOf: accounts[0] }));
// dispatch(watchBalance({ balanceOf: accounts[0], tokenAddress: '0xDA5B056Cfb861282B4b59d29c9B395bcC238D29B' }));
} }
// 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);
const { value } = getBalance(address);
if (value.isEqualTo(BN(balance))) {
return;
}
dispatch({ dispatch({
type: UPDATE_ETH_BALANCE, type: UPDATE_ETH_BALANCE,
payload: { payload: {
...@@ -178,9 +193,16 @@ export const sync = () => async (dispatch, getState) => { ...@@ -178,9 +193,16 @@ export const sync = () => async (dispatch, getState) => {
const watchlist = watched.balances[tokenAddress] || []; const watchlist = watched.balances[tokenAddress] || [];
watchlist.forEach(async address => { watchlist.forEach(async address => {
const tokenBalance = getTokenBalance(tokenAddress, address);
const balance = await contract.methods.balanceOf(address).call(); const balance = await contract.methods.balanceOf(address).call();
const decimals = await contract.methods.decimals().call(); const decimals = tokenBalance.decimals || await contract.methods.decimals().call();
const symbol = await contract.methods.symbol().call(); const symbol = tokenBalance.label || await contract.methods.symbol().call();
if (tokenBalance.value.isEqualTo(BN(balance))) {
console.log('block');
return;
}
dispatch({ dispatch({
type: UPDATE_TOKEN_BALANCE, type: UPDATE_TOKEN_BALANCE,
payload: { payload: {
...@@ -200,7 +222,6 @@ export const startWatching = () => async (dispatch, getState) => { ...@@ -200,7 +222,6 @@ export const startWatching = () => async (dispatch, getState) => {
: 5000; : 5000;
dispatch(sync()); dispatch(sync());
setTimeout(() => dispatch(startWatching()), timeout); setTimeout(() => dispatch(startWatching()), timeout);
}; };
......
...@@ -11,7 +11,7 @@ window.addEventListener('load', function() { ...@@ -11,7 +11,7 @@ window.addEventListener('load', function() {
<DrizzleProvider options={{ <DrizzleProvider options={{
contracts: [], contracts: [],
events: [], events: [],
polls: { accounts: 3000, blocks: 3000 }, polls: { accounts: 60000, blocks: 60000 },
}} store={store}> }} store={store}>
<App /> <App />
</DrizzleProvider> </DrizzleProvider>
......
This diff is collapsed.
...@@ -11,6 +11,7 @@ $mine-shaft-gray: #2B2B2B; ...@@ -11,6 +11,7 @@ $mine-shaft-gray: #2B2B2B;
// Blue // Blue
$zumthor-blue: #EBF4FF; $zumthor-blue: #EBF4FF;
$malibu-blue: #5CA2FF;
$royal-blue: #2F80ED; $royal-blue: #2F80ED;
// Purple // Purple
......
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