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
30887ef1
Commit
30887ef1
authored
Jul 26, 2019
by
Ian Lapham
Committed by
Noah Zinsmeister
Jul 26, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add slippage option (#369)
* add custom slippage to /swap
parent
12344f74
Changes
12
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
647 additions
and
145 deletions
+647
-145
en.json
public/locales/en.json
+2
-1
question-mark.svg
src/assets/images/question-mark.svg
+4
-0
question.svg
src/assets/images/question.svg
+4
-0
index.js
src/components/AddressInputPanel/index.js
+1
-1
index.js
src/components/ContextualInfoNew/index.js
+5
-6
index.js
src/components/CurrencyInputPanel/index.js
+3
-3
index.js
src/components/NavigationTabs/index.js
+2
-2
index.js
src/components/TransactionDetails/index.js
+571
-0
ModeSelector.js
src/pages/Pool/ModeSelector.js
+1
-1
index.js
src/pages/Send/index.js
+1
-1
index.js
src/pages/Swap/index.js
+49
-130
index.js
src/theme/index.js
+4
-0
No files found.
public/locales/en.json
View file @
30887ef1
...
...
@@ -80,5 +80,6 @@
"symbol"
:
"Symbol"
,
"decimals"
:
"Decimals"
,
"enterTokenCont"
:
"Enter a token address to continue"
,
"priceChange"
:
"This trade will cause the price to change by"
"priceChange"
:
"Expected price slippage"
,
"forAtLeast"
:
"for at least "
}
src/assets/images/question-mark.svg
0 → 100644
View file @
30887ef1
<svg
width=
"18"
height=
"18"
viewBox=
"0 0 18 18"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<circle
cx=
"9"
cy=
"9"
r=
"9"
fill=
"#E1E1E1"
/>
<path
d=
"M8.06493 10.8317H9.15706V10.7592C9.17233 9.88089 9.42436 9.48757 10.0735 9.08662C10.7571 8.67421 11.1771 8.09378 11.1771 7.23459C11.1771 5.99354 10.2377 5.15344 8.83629 5.15344C7.54942 5.15344 6.51839 5.90571 6.46875 7.28041H7.62961C7.67543 6.47086 8.25204 6.11573 8.83629 6.11573C9.48546 6.11573 10.0124 6.54724 10.0124 7.22313C10.0124 7.79211 9.65729 8.19306 9.20288 8.47564C8.49262 8.91096 8.07257 9.34246 8.06493 10.7592V10.8317ZM8.64154 13.1534C9.05777 13.1534 9.40527 12.8136 9.40527 12.3897C9.40527 11.9735 9.05777 11.6298 8.64154 11.6298C8.22149 11.6298 7.87782 11.9735 7.87782 12.3897C7.87782 12.8136 8.22149 13.1534 8.64154 13.1534Z"
fill=
"#737373"
/>
</svg>
src/assets/images/question.svg
0 → 100644
View file @
30887ef1
<svg
width=
"16"
height=
"16"
viewBox=
"0 0 16 16"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<circle
cx=
"8"
cy=
"8"
r=
"8"
fill=
"#E1E1E1"
/>
<path
d=
"M7.09618 9.67828H8.18831V9.60573C8.20358 8.72745 8.45561 8.33413 9.10477 7.93317C9.78831 7.52076 10.2084 6.94033 10.2084 6.08115C10.2084 4.8401 9.26897 4 7.86754 4C6.58067 4 5.54964 4.75227 5.5 6.12697H6.66086C6.70668 5.31742 7.28329 4.96229 7.86754 4.96229C8.51671 4.96229 9.04368 5.39379 9.04368 6.06969C9.04368 6.63866 8.68854 7.03962 8.23413 7.3222C7.52387 7.75752 7.10382 8.18902 7.09618 9.60573V9.67828ZM7.67279 12C8.08902 12 8.43652 11.6601 8.43652 11.2363C8.43652 10.82 8.08902 10.4764 7.67279 10.4764C7.25274 10.4764 6.90907 10.82 6.90907 11.2363C6.90907 11.6601 7.25274 12 7.67279 12Z"
fill=
"#737373"
/>
</svg>
src/components/AddressInputPanel/index.js
View file @
30887ef1
...
...
@@ -21,7 +21,7 @@ const ContainerRow = styled.div`
justify-content: center;
align-items: center;
border-radius: 1.25rem;
box-shadow: 0 0 0
0.5
px
${({
error
,
theme
})
=>
(
error
?
theme
.
salmonRed
:
theme
.
mercuryGray
)}
;
box-shadow: 0 0 0
1
px
${({
error
,
theme
})
=>
(
error
?
theme
.
salmonRed
:
theme
.
mercuryGray
)}
;
background-color:
${({
theme
})
=>
theme
.
white
}
;
transition: box-shadow 200ms ease-in-out;
`
...
...
src/components/ContextualInfoNew/index.js
View file @
30887ef1
...
...
@@ -32,10 +32,10 @@ const SummaryWrapperContainer = styled.div`
const
Details
=
styled
.
div
`
background-color:
${({
theme
})
=>
theme
.
concreteGray
}
;
padding: 1.5rem;
/* padding: 1.25rem 1.25rem 1rem 1.25rem; */
border-radius: 1rem;
font-size: 0.75rem;
margin
-top: 1
rem;
margin
: 1rem 0.5rem 0 0.5
rem;
`
const
ErrorSpan
=
styled
.
span
`
...
...
@@ -89,13 +89,12 @@ export default function ContextualInfo({
closeDetailsText
=
'
Hide Details
'
,
contextualInfo
=
''
,
allowExpand
=
false
,
renderTransactionDetails
=
()
=>
{},
isError
=
false
,
slippageWarning
,
highSlippageWarning
highSlippageWarning
,
dropDownContent
})
{
const
[
showDetails
,
setShowDetails
]
=
useState
(
false
)
return
!
allowExpand
?
(
<
SummaryWrapper
>
{
contextualInfo
}
<
/SummaryWrapper
>
)
:
(
...
...
@@ -117,7 +116,7 @@ export default function ContextualInfo({
)}
<
/
>
<
/SummaryWrapperContainer
>
{
showDetails
&&
<
Details
>
{
renderTransactionDetails
()}
<
/Details>
}
{
showDetails
&&
<
Details
>
{
dropDownContent
()}
<
/Details>
}
<
/
>
)
}
src/components/CurrencyInputPanel/index.js
View file @
30887ef1
...
...
@@ -70,7 +70,7 @@ const CurrencySelect = styled.button`
}
:focus {
box-shadow: 0 0
0.5px 0.5
px
${({
theme
})
=>
theme
.
malibuBlue
}
;
box-shadow: 0 0
1px 1
px
${({
theme
})
=>
theme
.
malibuBlue
}
;
}
:active {
...
...
@@ -104,12 +104,12 @@ const InputPanel = styled.div`
const
Container
=
styled
.
div
`
border-radius: 1.25rem;
box-shadow: 0 0 0
0.5
px
${({
error
,
theme
})
=>
(
error
?
theme
.
salmonRed
:
theme
.
mercuryGray
)}
;
box-shadow: 0 0 0
1
px
${({
error
,
theme
})
=>
(
error
?
theme
.
salmonRed
:
theme
.
mercuryGray
)}
;
background-color:
${({
theme
})
=>
theme
.
white
}
;
transition: box-shadow 200ms ease-in-out;
:focus-within {
box-shadow: 0 0
0.5px 0.5
px
${({
theme
})
=>
theme
.
malibuBlue
}
;
box-shadow: 0 0
1px 1
px
${({
theme
})
=>
theme
.
malibuBlue
}
;
}
`
...
...
src/components/NavigationTabs/index.js
View file @
30887ef1
...
...
@@ -84,11 +84,11 @@ const StyledNavLink = styled(NavLink).attrs({
&.
${
activeClassName
}
{
background-color:
${({
theme
})
=>
theme
.
white
}
;
border-radius: 3rem;
box-shadow: 0 0
0.5
px 1px
${({
theme
})
=>
theme
.
mercuryGray
}
;
box-shadow: 0 0
1
px 1px
${({
theme
})
=>
theme
.
mercuryGray
}
;
font-weight: 500;
color:
${({
theme
})
=>
theme
.
royalBlue
}
;
:hover {
box-shadow: 0 0
0.5
px 1px
${({
theme
})
=>
darken
(
0.1
,
theme
.
mercuryGray
)}
;
box-shadow: 0 0
1
px 1px
${({
theme
})
=>
darken
(
0.1
,
theme
.
mercuryGray
)}
;
}
}
...
...
src/components/TransactionDetails/index.js
0 → 100644
View file @
30887ef1
This diff is collapsed.
Click to expand it.
src/pages/Pool/ModeSelector.js
View file @
30887ef1
...
...
@@ -64,7 +64,7 @@ const StyledNavLink = styled(NavLink).attrs({
&.
${
activeClassName
}
{
background-color:
${({
theme
})
=>
theme
.
white
}
;
border-radius: 3rem;
box-shadow: 0 0
0.5px 0.5
px
${({
theme
})
=>
theme
.
mercuryGray
}
;
box-shadow: 0 0
1px 1
px
${({
theme
})
=>
theme
.
mercuryGray
}
;
font-weight: 500;
color:
${({
theme
})
=>
theme
.
royalBlue
}
;
}
...
...
src/pages/Send/index.js
View file @
30887ef1
...
...
@@ -612,7 +612,7 @@ export default function Swap({ initialCurrency }) {
isError
=
{
isError
}
slippageWarning
=
{
slippageWarning
&&
slippageWarningText
}
highSlippageWarning
=
{
highSlippageWarning
&&
slippageWarningText
}
renderTransactionDetails
=
{
renderTransactionDetails
}
dropDownContent
=
{
renderTransactionDetails
}
/
>
)
}
...
...
src/pages/Swap/index.js
View file @
30887ef1
...
...
@@ -7,8 +7,8 @@ import styled from 'styled-components'
import
{
Button
}
from
'
../../theme
'
import
CurrencyInputPanel
from
'
../../components/CurrencyInputPanel
'
import
NewContextualInfo
from
'
../../components/ContextualInfoNew
'
import
OversizedPanel
from
'
../../components/OversizedPanel
'
import
TransactionDetails
from
'
../../components/TransactionDetails
'
import
ArrowDownBlue
from
'
../../assets/images/arrow-down-blue.svg
'
import
ArrowDownGrey
from
'
../../assets/images/arrow-down-grey.svg
'
import
{
amountFormatter
,
calculateGasMargin
}
from
'
../../utils
'
...
...
@@ -26,8 +26,8 @@ const TOKEN_TO_ETH = 1
const
TOKEN_TO_TOKEN
=
2
// denominated in bips
const
ALLOWED_SLIPPAGE
=
ethers
.
utils
.
bigNumberify
(
200
)
const
TOKEN_ALLOWED_SLIPPAGE
=
ethers
.
utils
.
bigNumberify
(
400
)
const
ALLOWED_SLIPPAGE
_DEFAULT
=
100
const
TOKEN_ALLOWED_SLIPPAGE
_DEFAULT
=
100
// denominated in seconds
const
DEADLINE_FROM_NOW
=
60
*
15
...
...
@@ -35,14 +35,6 @@ const DEADLINE_FROM_NOW = 60 * 15
// denominated in bips
const
GAS_MARGIN
=
ethers
.
utils
.
bigNumberify
(
1000
)
const
BlueSpan
=
styled
.
span
`
color:
${({
theme
})
=>
theme
.
royalBlue
}
;
`
const
LastSummaryText
=
styled
.
div
`
margin-top: 1rem;
`
const
DownArrowBackground
=
styled
.
div
`
${({
theme
})
=>
theme
.
flexRowNoWrap
}
justify-content: center;
...
...
@@ -81,9 +73,9 @@ const Flex = styled.div`
}
`
function
calculateSlippageBounds
(
value
,
token
=
false
)
{
function
calculateSlippageBounds
(
value
,
token
=
false
,
tokenAllowedSlippage
,
allowedSlippage
)
{
if
(
value
)
{
const
offset
=
value
.
mul
(
token
?
TOKEN_ALLOWED_SLIPPAGE
:
ALLOWED_SLIPPAGE
).
div
(
ethers
.
utils
.
bigNumberify
(
10000
))
const
offset
=
value
.
mul
(
token
?
tokenAllowedSlippage
:
allowedSlippage
).
div
(
ethers
.
utils
.
bigNumberify
(
10000
))
const
minimum
=
value
.
sub
(
offset
)
const
maximum
=
value
.
add
(
offset
)
return
{
...
...
@@ -244,12 +236,18 @@ export default function Swap({ initialCurrency }) {
const
addTransaction
=
useTransactionAdder
()
const
[
rawSlippage
,
setRawSlippage
]
=
useState
(
ALLOWED_SLIPPAGE_DEFAULT
)
const
[
rawTokenSlippage
,
setRawTokenSlippage
]
=
useState
(
TOKEN_ALLOWED_SLIPPAGE_DEFAULT
)
let
allowedSlippageBig
=
ethers
.
utils
.
bigNumberify
(
rawSlippage
)
let
tokenAllowedSlippageBig
=
ethers
.
utils
.
bigNumberify
(
rawTokenSlippage
)
// analytics
useEffect
(()
=>
{
ReactGA
.
pageview
(
window
.
location
.
pathname
+
window
.
location
.
search
)
},
[])
// core swap state
// core swap state
-
const
[
swapState
,
dispatchSwapState
]
=
useReducer
(
swapStateReducer
,
initialCurrency
,
getInitialSwapState
)
const
{
independentValue
,
dependentValue
,
independentField
,
inputCurrency
,
outputCurrency
}
=
swapState
...
...
@@ -326,7 +324,9 @@ export default function Swap({ initialCurrency }) {
// calculate slippage from target rate
const
{
minimum
:
dependentValueMinumum
,
maximum
:
dependentValueMaximum
}
=
calculateSlippageBounds
(
dependentValue
,
swapType
===
TOKEN_TO_TOKEN
swapType
===
TOKEN_TO_TOKEN
,
tokenAllowedSlippageBig
,
allowedSlippageBig
)
// validate input allowance + balance
...
...
@@ -496,118 +496,6 @@ export default function Swap({ initialCurrency }) {
return
`Balance:
${
value
}
`
}
function
renderTransactionDetails
()
{
ReactGA
.
event
({
category
:
'
TransactionDetail
'
,
action
:
'
Open
'
})
const
b
=
text
=>
<
BlueSpan
>
{
text
}
<
/BlueSpan
>
if
(
independentField
===
INPUT
)
{
return
(
<
div
>
<
div
>
{
t
(
'
youAreSelling
'
)}{
'
'
}
{
b
(
`
${
amountFormatter
(
independentValueParsed
,
independentDecimals
,
Math
.
min
(
4
,
independentDecimals
)
)}
${
inputSymbol
}
`
)}
.
<
/div
>
<
LastSummaryText
>
{
t
(
'
youWillReceive
'
)}{
'
'
}
{
b
(
`
${
amountFormatter
(
dependentValueMinumum
,
dependentDecimals
,
Math
.
min
(
4
,
dependentDecimals
)
)}
${
outputSymbol
}
`
)}{
'
'
}
{
t
(
'
orTransFail
'
)}
<
/LastSummaryText
>
<
LastSummaryText
>
{(
slippageWarning
||
highSlippageWarning
)
&&
(
<
span
role
=
"
img
"
aria
-
label
=
"
warning
"
>
⚠️
<
/span
>
)}
{
t
(
'
priceChange
'
)}
{
b
(
`
${
percentSlippageFormatted
}
%`
)}.
<
/LastSummaryText
>
<
/div
>
)
}
else
{
return
(
<
div
>
<
div
>
{
t
(
'
youAreBuying
'
)}{
'
'
}
{
b
(
`
${
amountFormatter
(
independentValueParsed
,
independentDecimals
,
Math
.
min
(
4
,
independentDecimals
)
)}
${
outputSymbol
}
`
)}
.
<
/div
>
<
LastSummaryText
>
{
t
(
'
itWillCost
'
)}{
'
'
}
{
b
(
`
${
amountFormatter
(
dependentValueMaximum
,
dependentDecimals
,
Math
.
min
(
4
,
dependentDecimals
)
)}
${
inputSymbol
}
`
)}{
'
'
}
{
t
(
'
orTransFail
'
)}
<
/LastSummaryText
>
<
LastSummaryText
>
{
t
(
'
priceChange
'
)}
{
b
(
`
${
percentSlippageFormatted
}
%`
)}.
<
/LastSummaryText
>
<
/div
>
)
}
}
function
renderSummary
()
{
let
contextualInfo
=
''
let
isError
=
false
if
(
inputError
||
independentError
)
{
contextualInfo
=
inputError
||
independentError
isError
=
true
}
else
if
(
!
inputCurrency
||
!
outputCurrency
)
{
contextualInfo
=
t
(
'
selectTokenCont
'
)
}
else
if
(
!
independentValue
)
{
contextualInfo
=
t
(
'
enterValueCont
'
)
}
else
if
(
!
account
)
{
contextualInfo
=
t
(
'
noWallet
'
)
isError
=
true
}
const
slippageWarningText
=
highSlippageWarning
?
t
(
'
highSlippageWarning
'
)
:
slippageWarning
?
t
(
'
slippageWarning
'
)
:
''
return
(
<
NewContextualInfo
openDetailsText
=
{
t
(
'
transactionDetails
'
)}
closeDetailsText
=
{
t
(
'
hideDetails
'
)}
contextualInfo
=
{
contextualInfo
?
contextualInfo
:
slippageWarningText
}
allowExpand
=
{
!!
(
inputCurrency
&&
outputCurrency
&&
inputValueParsed
&&
outputValueParsed
)}
isError
=
{
isError
}
slippageWarning
=
{
slippageWarning
&&
!
contextualInfo
}
highSlippageWarning
=
{
highSlippageWarning
&&
!
contextualInfo
}
renderTransactionDetails
=
{
renderTransactionDetails
}
/
>
)
}
async
function
onSwap
()
{
const
deadline
=
Math
.
ceil
(
Date
.
now
()
/
1000
)
+
DEADLINE_FROM_NOW
...
...
@@ -664,6 +552,8 @@ export default function Swap({ initialCurrency }) {
})
}
const
[
customSlippageError
,
setcustomSlippageError
]
=
useState
(
''
)
return
(
<>
<
CurrencyInputPanel
...
...
@@ -743,10 +633,39 @@ export default function Swap({ initialCurrency }) {
)}
<
/ExchangeRateWrapper
>
<
/OversizedPanel
>
{
renderSummary
()}
<
TransactionDetails
account
=
{
account
}
setRawSlippage
=
{
setRawSlippage
}
setRawTokenSlippage
=
{
setRawTokenSlippage
}
rawSlippage
=
{
rawSlippage
}
slippageWarning
=
{
slippageWarning
}
highSlippageWarning
=
{
highSlippageWarning
}
inputError
=
{
inputError
}
independentError
=
{
independentError
}
inputCurrency
=
{
inputCurrency
}
outputCurrency
=
{
outputCurrency
}
independentValue
=
{
independentValue
}
independentValueParsed
=
{
independentValueParsed
}
independentField
=
{
independentField
}
INPUT
=
{
INPUT
}
inputValueParsed
=
{
inputValueParsed
}
outputValueParsed
=
{
outputValueParsed
}
inputSymbol
=
{
inputSymbol
}
outputSymbol
=
{
outputSymbol
}
dependentValueMinumum
=
{
dependentValueMinumum
}
dependentValueMaximum
=
{
dependentValueMaximum
}
dependentDecimals
=
{
dependentDecimals
}
independentDecimals
=
{
independentDecimals
}
percentSlippageFormatted
=
{
percentSlippageFormatted
}
setcustomSlippageError
=
{
setcustomSlippageError
}
/
>
<
Flex
>
<
Button
disabled
=
{
!
isValid
}
onClick
=
{
onSwap
}
warning
=
{
highSlippageWarning
}
>
{
highSlippageWarning
?
t
(
'
swapAnyway
'
)
:
t
(
'
swap
'
)}
<
Button
disabled
=
{
!
isValid
||
customSlippageError
===
'
invalid
'
}
onClick
=
{
onSwap
}
warning
=
{
highSlippageWarning
||
customSlippageError
===
'
warning
'
}
>
{
highSlippageWarning
||
customSlippageError
===
'
warning
'
?
t
(
'
swapAnyway
'
)
:
t
(
'
swap
'
)}
<
/Button
>
<
/Flex
>
<
/
>
...
...
src/theme/index.js
View file @
30887ef1
...
...
@@ -38,6 +38,9 @@ const theme = {
chaliceGray
:
'
#AEAEAE
'
,
doveGray
:
'
#737373
'
,
mineshaftGray
:
'
#2B2B2B
'
,
buttonOutlineGrey
:
'
#f2f2f2
'
,
//blacks
charcoalBlack
:
'
#404040
'
,
// blues
zumthorBlue
:
'
#EBF4FF
'
,
malibuBlue
:
'
#5CA2FF
'
,
...
...
@@ -53,6 +56,7 @@ const theme = {
// pink
uniswapPink
:
'
#DC6BE5
'
,
connectedGreen
:
'
#27AE60
'
,
// media queries
mediaWidth
:
mediaWidthTemplates
,
// css snippets
...
...
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