Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
I
interface
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
LuckySwap
interface
Commits
509ddaea
Unverified
Commit
509ddaea
authored
Oct 23, 2018
by
Chi Kei Chan
Committed by
GitHub
Oct 23, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement Add Liquidity (#77)
* CSS fixes * Add Liquidity UI and Validation * Finish Add Liquidity
parent
a4e0d11c
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
242 additions
and
54 deletions
+242
-54
currency-panel.scss
src/components/CurrencyInputPanel/currency-panel.scss
+14
-7
index.js
src/components/CurrencyInputPanel/index.js
+24
-9
tab.scss
src/components/Tab/tab.scss
+4
-5
web3connect.js
src/ducks/web3connect.js
+34
-13
index.js
src/index.js
+1
-1
AddLiquidity.js
src/pages/Pool/AddLiquidity.js
+164
-19
variables.scss
src/variables.scss
+1
-0
No files found.
src/components/CurrencyInputPanel/currency-panel.scss
View file @
509ddaea
...
@@ -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
);
position
:
relative
;
border-radius
:
1
.25rem
;
z-index
:
200
;
&
__container
{
&
__container
{
position
:
relative
;
z-index
:
200
;
border-radius
:
1
.25rem
;
border-radius
:
1
.25rem
;
bo
rder
:
0
.5px
solid
$mercury-gray
;
bo
x-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
{
bo
rder
:
0
.5px
solid
$salmon-red
;
bo
x-shadow
:
0
0
0
.5px
$salmon-red
;
}
}
&
:focus-within
{
&
:focus-within
{
bo
rder-color
:
$royal
-blue
;
bo
x-shadow
:
0
0
.5px
.5px
$malibu
-blue
;
}
}
&
--error
:focus-within
{
&
--error
:focus-within
{
bo
rder-color
:
$salmon-red
;
bo
x-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
{
...
...
src/components/CurrencyInputPanel/index.js
View file @
509ddaea
...
@@ -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,19 +67,20 @@ class CurrencyInputPanel extends Component {
...
@@ -64,19 +67,20 @@ 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
'
}
];
for
(
let
i
=
0
;
i
<
tokens
.
length
;
i
++
)
{
for
(
let
i
=
0
;
i
<
tokens
.
length
;
i
++
)
{
let
entry
=
{
value
:
''
,
label
:
''
};
let
entry
=
{
value
:
''
,
label
:
''
};
entry
.
value
=
tokens
[
i
][
0
];
entry
.
value
=
tokens
[
i
][
0
];
entry
.
label
=
tokens
[
i
][
0
];
entry
.
label
=
tokens
[
i
][
0
];
entry
.
address
=
tokens
[
i
][
1
];
entry
.
address
=
tokens
[
i
][
1
];
tokenList
.
push
(
entry
);
tokenList
.
push
(
entry
);
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
...
...
src/components/Tab/tab.scss
View file @
509ddaea
...
@@ -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
;
bo
rder
:
1px
solid
$mercury-gray
;
bo
x-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
;
bo
rder
:
1px
solid
$mercury-gray
;
bo
x-shadow
:
0
0
.5px
.5px
$mercury-gray
;
font-weight
:
500
;
font-weight
:
500
;
span
{
span
{
...
...
src/ducks/web3connect.js
View file @
509ddaea
...
@@ -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
);
};
};
...
...
src/index.js
View file @
509ddaea
...
@@ -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
:
3
000
},
polls
:
{
accounts
:
60000
,
blocks
:
60
000
},
}}
store
=
{
store
}
>
}}
store
=
{
store
}
>
<
App
/>
<
App
/>
<
/DrizzleProvider
>
<
/DrizzleProvider
>
...
...
src/pages/Pool/AddLiquidity.js
View file @
509ddaea
...
@@ -8,7 +8,9 @@ import { selectors, sync } from '../../ducks/web3connect';
...
@@ -8,7 +8,9 @@ import { selectors, sync } from '../../ducks/web3connect';
import
ArrowDown
from
'
../../assets/images/arrow-down-blue.svg
'
;
import
ArrowDown
from
'
../../assets/images/arrow-down-blue.svg
'
;
import
ModeSelector
from
'
./ModeSelector
'
;
import
ModeSelector
from
'
./ModeSelector
'
;
import
{
BigNumber
as
BN
}
from
'
bignumber.js
'
;
import
{
BigNumber
as
BN
}
from
'
bignumber.js
'
;
import
EXCHANGE_ABI
from
'
../../abi/exchange
'
;
import
"
./pool.scss
"
;
import
"
./pool.scss
"
;
import
promisify
from
"
../../helpers/web3-promisfy
"
;
const
INPUT
=
0
;
const
INPUT
=
0
;
const
OUTPUT
=
1
;
const
OUTPUT
=
1
;
...
@@ -18,6 +20,7 @@ class AddLiquidity extends Component {
...
@@ -18,6 +20,7 @@ class AddLiquidity extends Component {
isConnected
:
PropTypes
.
bool
.
isRequired
,
isConnected
:
PropTypes
.
bool
.
isRequired
,
account
:
PropTypes
.
string
.
isRequired
,
account
:
PropTypes
.
string
.
isRequired
,
selectors
:
PropTypes
.
func
.
isRequired
,
selectors
:
PropTypes
.
func
.
isRequired
,
balances
:
PropTypes
.
object
.
isRequired
,
exchangeAddresses
:
PropTypes
.
shape
({
exchangeAddresses
:
PropTypes
.
shape
({
fromToken
:
PropTypes
.
object
.
isRequired
,
fromToken
:
PropTypes
.
object
.
isRequired
,
}).
isRequired
,
}).
isRequired
,
...
@@ -26,11 +29,27 @@ class AddLiquidity extends Component {
...
@@ -26,11 +29,27 @@ class AddLiquidity extends Component {
state
=
{
state
=
{
inputValue
:
''
,
inputValue
:
''
,
outputValue
:
''
,
outputValue
:
''
,
inputCurrency
:
''
,
inputCurrency
:
'
ETH
'
,
outputCurrency
:
''
,
outputCurrency
:
''
,
lastEditedField
:
''
,
lastEditedField
:
''
,
};
};
shouldComponentUpdate
(
nextProps
,
nextState
)
{
const
{
isConnected
,
account
,
exchangeAddresses
,
balances
,
web3
}
=
this
.
props
;
const
{
inputValue
,
outputValue
,
inputCurrency
,
outputCurrency
,
lastEditedField
}
=
this
.
state
;
return
isConnected
!==
nextProps
.
isConnected
||
account
!==
nextProps
.
account
||
exchangeAddresses
!==
nextProps
.
exchangeAddresses
||
web3
!==
nextProps
.
web3
||
balances
!==
nextProps
.
balances
||
inputValue
!==
nextState
.
inputValue
||
outputValue
!==
nextState
.
outputValue
||
inputCurrency
!==
nextState
.
inputCurrency
||
outputCurrency
!==
nextState
.
outputCurrency
||
lastEditedField
!==
nextState
.
lastEditedField
;
}
getBalance
(
currency
)
{
getBalance
(
currency
)
{
const
{
selectors
,
account
}
=
this
.
props
;
const
{
selectors
,
account
}
=
this
.
props
;
...
@@ -47,6 +66,34 @@ class AddLiquidity extends Component {
...
@@ -47,6 +66,34 @@ class AddLiquidity extends Component {
return
`Balance:
${
value
.
dividedBy
(
10
**
decimals
).
toFixed
(
4
)}
`
;
return
`Balance:
${
value
.
dividedBy
(
10
**
decimals
).
toFixed
(
4
)}
`
;
}
}
onAddLiquidity
=
async
()
=>
{
const
{
account
,
web3
,
exchangeAddresses
:
{
fromToken
},
selectors
}
=
this
.
props
;
const
{
inputValue
,
outputValue
,
outputCurrency
}
=
this
.
state
;
const
exchange
=
new
web3
.
eth
.
Contract
(
EXCHANGE_ABI
,
fromToken
[
outputCurrency
]);
const
ethAmount
=
BN
(
inputValue
).
multipliedBy
(
10
**
18
);
const
{
decimals
}
=
selectors
().
getTokenBalance
(
outputCurrency
,
fromToken
[
outputCurrency
]);
const
tokenAmount
=
BN
(
outputValue
).
multipliedBy
(
10
**
decimals
);
const
{
value
:
ethReserve
}
=
selectors
().
getBalance
(
fromToken
[
outputCurrency
]);
const
totalLiquidity
=
await
exchange
.
methods
.
totalSupply
().
call
();
const
liquidityMinted
=
BN
(
totalLiquidity
).
multipliedBy
(
ethAmount
.
dividedBy
(
ethReserve
));
const
blockNumber
=
await
promisify
(
web3
,
'
getBlockNumber
'
);
const
block
=
await
promisify
(
web3
,
'
getBlock
'
,
blockNumber
);
const
deadline
=
block
.
timestamp
+
300
;
const
MAX_LIQUIDITY_SLIPPAGE
=
0.025
;
const
minLiquidity
=
liquidityMinted
.
multipliedBy
(
1
-
MAX_LIQUIDITY_SLIPPAGE
);
const
maxTokens
=
tokenAmount
.
multipliedBy
(
1
+
MAX_LIQUIDITY_SLIPPAGE
);
try
{
const
tx
=
await
exchange
.
methods
.
addLiquidity
(
minLiquidity
.
toFixed
(
0
),
maxTokens
.
toFixed
(
0
),
deadline
).
send
({
from
:
account
,
value
:
ethAmount
.
toFixed
(
0
)
});
}
catch
(
err
)
{
console
.
error
(
err
);
}
};
onInputChange
=
value
=>
{
onInputChange
=
value
=>
{
const
{
inputCurrency
,
outputCurrency
}
=
this
.
state
;
const
{
inputCurrency
,
outputCurrency
}
=
this
.
state
;
const
exchangeRate
=
this
.
getExchangeRate
();
const
exchangeRate
=
this
.
getExchangeRate
();
...
@@ -103,6 +150,39 @@ class AddLiquidity extends Component {
...
@@ -103,6 +150,39 @@ class AddLiquidity extends Component {
return
tokenValue
.
dividedBy
(
ethValue
);
return
tokenValue
.
dividedBy
(
ethValue
);
}
}
validate
()
{
const
{
selectors
,
account
}
=
this
.
props
;
const
{
inputValue
,
outputValue
,
inputCurrency
,
outputCurrency
,
}
=
this
.
state
;
let
inputError
;
let
outputError
;
let
isValid
=
true
;
if
(
!
inputValue
||
!
outputValue
||
!
inputCurrency
||
!
outputCurrency
)
{
isValid
=
false
;
}
const
{
value
:
ethValue
}
=
selectors
().
getBalance
(
account
);
const
{
value
:
tokenValue
,
decimals
}
=
selectors
().
getTokenBalance
(
outputCurrency
,
account
);
if
(
ethValue
.
isLessThan
(
BN
(
inputValue
*
10
**
18
)))
{
inputError
=
'
Insufficient Balance
'
;
}
if
(
tokenValue
.
isLessThan
(
BN
(
outputValue
*
10
**
decimals
)))
{
outputError
=
'
Insufficient Balance
'
;
}
return
{
inputError
,
outputError
,
isValid
:
isValid
&&
!
inputError
&&
!
outputError
,
};
}
renderInfo
()
{
renderInfo
()
{
const
{
selectors
,
exchangeAddresses
:
{
fromToken
}
}
=
this
.
props
;
const
{
selectors
,
exchangeAddresses
:
{
fromToken
}
}
=
this
.
props
;
const
{
inputCurrency
,
outputCurrency
}
=
this
.
state
;
const
{
inputCurrency
,
outputCurrency
}
=
this
.
state
;
...
@@ -136,11 +216,71 @@ class AddLiquidity extends Component {
...
@@ -136,11 +216,71 @@ class AddLiquidity 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
>
{
`1 ETH =
${
tokenValue
.
dividedBy
(
ethValue
).
toFixed
(
4
)}
BAT
`
}
<
/span
>
<
span
>
{
`1 ETH =
${
tokenValue
.
dividedBy
(
ethValue
).
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
>
{
`
${
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
>
)
}
renderSummary
()
{
const
{
selectors
,
exchangeAddresses
:
{
fromToken
}
}
=
this
.
props
;
const
{
inputValue
,
outputValue
,
inputCurrency
,
outputCurrency
,
}
=
this
.
state
;
if
(
!
inputCurrency
||
!
outputCurrency
)
{
return
(
<
div
className
=
"
swap__summary-wrapper
"
>
<
div
>
Select
a
token
to
continue
.
<
/div
>
<
/div
>
)
}
if
(
inputCurrency
===
outputCurrency
)
{
return
(
<
div
className
=
"
swap__summary-wrapper
"
>
<
div
>
Must
be
different
token
.
<
/div
>
<
/div
>
)
}
if
(
!
[
inputCurrency
,
outputCurrency
].
includes
(
'
ETH
'
))
{
return
(
<
div
className
=
"
swap__summary-wrapper
"
>
<
div
>
One
of
the
input
must
be
ETH
.
<
/div
>
<
/div
>
)
}
const
{
value
,
decimals
,
label
}
=
selectors
().
getTokenBalance
(
outputCurrency
,
fromToken
[
outputCurrency
]);
if
(
!
inputValue
||
!
outputValue
)
{
return
(
<
div
className
=
"
swap__summary-wrapper
"
>
<
div
>
{
`Enter a
${
inputCurrency
}
or
${
label
}
value to continue.`
}
<
/div
>
<
/div
>
)
}
const
SLIPPAGE
=
0.025
;
const
minOutput
=
BN
(
outputValue
).
multipliedBy
(
1
-
SLIPPAGE
);
const
maxOutput
=
BN
(
outputValue
).
multipliedBy
(
1
+
SLIPPAGE
);
const
tokenReserve
=
value
.
dividedBy
(
10
**
decimals
);
const
minPercentage
=
minOutput
.
dividedBy
(
minOutput
.
plus
(
tokenReserve
)).
multipliedBy
(
100
);
const
maxPercentage
=
maxOutput
.
dividedBy
(
maxOutput
.
plus
(
tokenReserve
)).
multipliedBy
(
100
);
return
(
<
div
className
=
"
swap__summary-wrapper
"
>
<
div
>
You
are
adding
between
{
b
(
`
${
minOutput
.
toFixed
(
2
)}
-
${
maxOutput
.
toFixed
(
2
)}
${
label
}
`
)}
+
{
b
(
`
${
BN
(
inputValue
).
toFixed
(
2
)}
ETH`
)}
into
the
liquidity
pool
.
<
/div
>
<
div
className
=
"
pool__last-summary-text
"
>
You
will
receive
between
{
b
(
`
${
minPercentage
.
toFixed
(
2
)}
%`
)}
and
{
b
(
`
${
maxPercentage
.
toFixed
(
2
)}
%`
)}
of
the
{
`
${
label
}
/ETH`
}
pool
tokens
.
<
/div
>
<
/div
>
<
/div
>
<
/div
>
)
)
...
@@ -159,19 +299,23 @@ class AddLiquidity extends Component {
...
@@ -159,19 +299,23 @@ class AddLiquidity extends Component {
lastEditedField
,
lastEditedField
,
}
=
this
.
state
;
}
=
this
.
state
;
const
{
inputError
,
outputError
,
isValid
}
=
this
.
validate
();
return
(
return
(
<
div
className
=
{
classnames
(
'
swap__content
'
,
{
'
swap--inactive
'
:
!
isConnected
})}
>
<
div
className
=
{
classnames
(
'
swap__content
'
,
{
'
swap--inactive
'
:
!
isConnected
,
})}
>
<
ModeSelector
/>
<
ModeSelector
/>
<
CurrencyInputPanel
<
CurrencyInputPanel
title
=
"
Deposit
"
title
=
"
Deposit
"
description
=
{
lastEditedField
===
OUTPUT
?
'
(estimated)
'
:
''
}
extraText
=
{
this
.
getBalance
(
inputCurrency
)}
extraText
=
{
this
.
getBalance
(
inputCurrency
)}
onCurrencySelected
=
{
currency
=>
{
this
.
setState
({
inputCurrency
:
currency
});
this
.
props
.
sync
();
}}
onValueChange
=
{
this
.
onInputChange
}
onValueChange
=
{
this
.
onInputChange
}
selectedTokenAddress
=
"
ETH
"
value
=
{
inputValue
}
value
=
{
inputValue
}
errorMessage
=
{
inputError
}
disableTokenSelect
/>
/>
<
OversizedPanel
>
<
OversizedPanel
>
<
div
className
=
"
swap__down-arrow-background
"
>
<
div
className
=
"
swap__down-arrow-background
"
>
...
@@ -180,32 +324,32 @@ class AddLiquidity extends Component {
...
@@ -180,32 +324,32 @@ class AddLiquidity extends Component {
<
/OversizedPanel
>
<
/OversizedPanel
>
<
CurrencyInputPanel
<
CurrencyInputPanel
title
=
"
Deposit
"
title
=
"
Deposit
"
description
=
{
lastEditedField
===
INPUT
?
'
(estimated)
'
:
''
}
description
=
"
(estimated)
"
extraText
=
{
this
.
getBalance
(
outputCurrency
)}
extraText
=
{
this
.
getBalance
(
outputCurrency
)}
selectedTokenAddress
=
{
outputCurrency
}
onCurrencySelected
=
{
currency
=>
{
onCurrencySelected
=
{
currency
=>
{
this
.
setState
({
outputCurrency
:
currency
});
this
.
setState
({
outputCurrency
:
currency
});
this
.
props
.
sync
();
this
.
props
.
sync
();
}}
}}
onValueChange
=
{
this
.
onOutputChange
}
onValueChange
=
{
this
.
onOutputChange
}
value
=
{
outputValue
}
value
=
{
outputValue
}
errorMessage
=
{
outputError
}
filteredTokens
=
{[
'
ETH
'
]}
/
>
/
>
<
OversizedPanel
hideBottom
>
<
OversizedPanel
hideBottom
>
{
this
.
renderInfo
()
}
{
this
.
renderInfo
()
}
<
/OversizedPanel
>
<
/OversizedPanel
>
<
div
className
=
"
swap__summary-wrapper
"
>
{
this
.
renderSummary
()
}
<
div
>
You
are
adding
between
{
b
`212000.00 - 216000.00 BAT`
}
+
{
b
`166.683543 ETH`
}
into
the
liquidity
pool
.
<
/div
>
<
div
className
=
"
pool__last-summary-text
"
>
You
will
receive
between
{
b
`66%`
}
and
{
b
`67%`
}
of
the
BAT
/
ETH
pool
tokens
.
<
/div
>
<
/div
>
<
div
className
=
"
pool__cta-container
"
>
<
div
className
=
"
pool__cta-container
"
>
<
button
<
button
className
=
{
classnames
(
'
pool__cta-btn
'
,
{
className
=
{
classnames
(
'
pool__cta-btn
'
,
{
'
swap--inactive
'
:
!
this
.
props
.
isConnected
,
'
swap--inactive
'
:
!
this
.
props
.
isConnected
,
'
pool__cta-btn--inactive
'
:
!
this
.
props
.
isValid
,
'
pool__cta-btn--inactive
'
:
!
isValid
,
})}
})}
disabled
=
{
!
this
.
props
.
isValid
}
disabled
=
{
!
isValid
}
onClick
=
{
this
.
on
Swap
}
onClick
=
{
this
.
on
AddLiquidity
}
>
>
Swap
Add
Liquidity
<
/button
>
<
/button
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
...
@@ -219,6 +363,7 @@ export default drizzleConnect(
...
@@ -219,6 +363,7 @@ export default drizzleConnect(
isConnected
:
Boolean
(
state
.
web3connect
.
account
),
isConnected
:
Boolean
(
state
.
web3connect
.
account
),
account
:
state
.
web3connect
.
account
,
account
:
state
.
web3connect
.
account
,
balances
:
state
.
web3connect
.
balances
,
balances
:
state
.
web3connect
.
balances
,
web3
:
state
.
web3connect
.
web3
,
exchangeAddresses
:
state
.
addresses
.
exchangeAddresses
,
exchangeAddresses
:
state
.
addresses
.
exchangeAddresses
,
}),
}),
dispatch
=>
({
dispatch
=>
({
...
...
src/variables.scss
View file @
509ddaea
...
@@ -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
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment