resolve conflicts
This commit is contained in:
commit
7a58ca810f
26650
package-lock.json
generated
Normal file
26650
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -27,7 +27,7 @@
|
||||
"noLiquidity": "No liquidity.",
|
||||
"insufficientLiquidity": "Insufficient liquidity.",
|
||||
"unlockTokenCont": "Please unlock token to continue.",
|
||||
"transactionDetails": "Transaction Details",
|
||||
"transactionDetails": "Advanced Details",
|
||||
"hideDetails": "Hide Details",
|
||||
"slippageWarning": "Slippage Warning",
|
||||
"highSlippageWarning": "High Slippage Warning",
|
||||
@ -81,5 +81,5 @@
|
||||
"decimals": "Decimals",
|
||||
"enterTokenCont": "Enter a token address to continue",
|
||||
"priceChange": "Expected price slippage",
|
||||
"forAtLeast" : "for at least "
|
||||
"forAtLeast": "for at least "
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ const ContainerRow = styled.div`
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 1.25rem;
|
||||
box-shadow: 0 0 0 0.5px ${({ error, theme }) => (error ? theme.salmonRed : theme.mercuryGray)};
|
||||
box-shadow: 0 0 0 1px ${({ error, theme }) => (error ? theme.salmonRed : theme.mercuryGray)};
|
||||
background-color: ${({ theme }) => theme.white};
|
||||
transition: box-shadow 200ms ease-in-out;
|
||||
`
|
||||
|
@ -51,8 +51,8 @@ class ContextualInfo extends Component {
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
openDetailsText: 'Transaction Details',
|
||||
closeDetailsText: 'Hide Details',
|
||||
openDetailsText: 'Advanced Details',
|
||||
closeDetailsText: 'Hide Advanced',
|
||||
renderTransactionDetails() {},
|
||||
contextualInfo: '',
|
||||
isError: false
|
||||
|
@ -32,11 +32,10 @@ const SummaryWrapperContainer = styled.div`
|
||||
|
||||
const Details = styled.div`
|
||||
background-color: ${({ theme }) => theme.concreteGray};
|
||||
padding: 1.5rem;
|
||||
padding-bottom: 1rem;
|
||||
/* padding: 1.25rem 1.25rem 1rem 1.25rem; */
|
||||
border-radius: 1rem;
|
||||
font-size: 0.75rem;
|
||||
margin-top: 1rem;
|
||||
margin: 1rem 0.5rem 0 0.5rem;
|
||||
`
|
||||
|
||||
const ErrorSpan = styled.span`
|
||||
@ -86,11 +85,10 @@ const ColoredDropdown = styled(WrappedDropdown)`
|
||||
`
|
||||
|
||||
export default function ContextualInfo({
|
||||
openDetailsText = 'Transaction Details',
|
||||
closeDetailsText = 'Hide Details',
|
||||
openDetailsText = 'Advanced Details',
|
||||
closeDetailsText = 'Hide Advanced',
|
||||
contextualInfo = '',
|
||||
allowExpand = false,
|
||||
renderTransactionDetails = () => {},
|
||||
isError = false,
|
||||
slippageWarning,
|
||||
highSlippageWarning,
|
||||
|
@ -34,6 +34,7 @@ const SubCurrencySelect = styled.button`
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
|
||||
`
|
||||
|
||||
const InputRow = styled.div`
|
||||
@ -70,7 +71,7 @@ const CurrencySelect = styled.button`
|
||||
}
|
||||
|
||||
:focus {
|
||||
box-shadow: 0 0 0.5px 0.5px ${({ theme }) => theme.malibuBlue};
|
||||
border: 1px solid ${({ theme }) => darken(0.1, theme.royalBlue)};
|
||||
}
|
||||
|
||||
:active {
|
||||
@ -104,12 +105,12 @@ const InputPanel = styled.div`
|
||||
|
||||
const Container = styled.div`
|
||||
border-radius: 1.25rem;
|
||||
box-shadow: 0 0 0 0.5px ${({ error, theme }) => (error ? theme.salmonRed : theme.mercuryGray)};
|
||||
box-shadow: 0 0 0 1px ${({ 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.5px ${({ theme }) => theme.malibuBlue};
|
||||
box-shadow: 0 0 1px 1px ${({ theme }) => theme.malibuBlue};
|
||||
}
|
||||
`
|
||||
|
||||
|
@ -5,8 +5,9 @@ import { DialogOverlay, DialogContent } from '@reach/dialog'
|
||||
import '@reach/dialog/styles.css'
|
||||
|
||||
const AnimatedDialogOverlay = animated(DialogOverlay)
|
||||
const StyledDialogOverlay = styled(AnimatedDialogOverlay).attrs({
|
||||
suppressclassnamewarning: 'true'
|
||||
const WrappedDialogOverlay = ({ suppressClassNameWarning, ...rest }) => <AnimatedDialogOverlay {...rest} />
|
||||
const StyledDialogOverlay = styled(WrappedDialogOverlay).attrs({
|
||||
suppressClassNameWarning: true
|
||||
})`
|
||||
&[data-reach-dialog-overlay] {
|
||||
z-index: 2;
|
||||
|
@ -5,7 +5,7 @@ import styled from 'styled-components'
|
||||
import { transparentize, darken } from 'polished'
|
||||
|
||||
import { useBodyKeyDown } from '../../hooks'
|
||||
import { useBetaMessageManager } from '../../contexts/Application'
|
||||
import { useBetaMessageManager } from '../../contexts/LocalStorage'
|
||||
|
||||
const tabOrder = [
|
||||
{
|
||||
@ -84,11 +84,11 @@ const StyledNavLink = styled(NavLink).attrs({
|
||||
&.${activeClassName} {
|
||||
background-color: ${({ theme }) => theme.white};
|
||||
border-radius: 3rem;
|
||||
box-shadow: 0 0 0.5px 1px ${({ theme }) => theme.mercuryGray};
|
||||
box-shadow: 0 0 1px 1px ${({ theme }) => theme.mercuryGray};
|
||||
font-weight: 500;
|
||||
color: ${({ theme }) => theme.royalBlue};
|
||||
:hover {
|
||||
box-shadow: 0 0 0.5px 1px ${({ theme }) => darken(0.1, theme.mercuryGray)};
|
||||
box-shadow: 0 0 1px 1px ${({ theme }) => darken(0.1, theme.mercuryGray)};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,38 +1,81 @@
|
||||
import React, { useState } from 'react'
|
||||
import React, { useState, useEffect, useRef } from 'react'
|
||||
import ReactGA from 'react-ga'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
import styled, { css, keyframes } from 'styled-components'
|
||||
import { darken, lighten } from 'polished'
|
||||
import { isAddress, amountFormatter } from '../../utils'
|
||||
import questionMark from '../../assets/images/question-mark.svg'
|
||||
import { useDebounce } from '../../hooks'
|
||||
|
||||
import question from '../../assets/images/question.svg'
|
||||
|
||||
import NewContextualInfo from '../../components/ContextualInfoNew'
|
||||
|
||||
const WARNING_TYPE = Object.freeze({
|
||||
none: 'none',
|
||||
emptyInput: 'emptyInput',
|
||||
invalidEntryBound: 'invalidEntryBound',
|
||||
riskyEntryHigh: 'riskyEntryHigh',
|
||||
riskyEntryLow: 'riskyEntryLow'
|
||||
})
|
||||
|
||||
const b = text => <Bold>{text}</Bold>
|
||||
|
||||
const Flex = styled.div`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
button {
|
||||
max-width: 20rem;
|
||||
}
|
||||
`
|
||||
|
||||
const SlippageRow = styled(Flex)`
|
||||
const FlexBetween = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
`
|
||||
|
||||
const WrappedSlippageRow = ({ wrap, ...rest }) => <Flex {...rest} />
|
||||
const SlippageRow = styled(WrappedSlippageRow)`
|
||||
position: relative;
|
||||
width: 100%;
|
||||
flex-wrap: ${({ wrap }) => wrap && 'wrap'};
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
font-size: 0.8rem;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
height: 24px;
|
||||
margin-bottom: 14px;
|
||||
padding-top: ${({ wrap }) => wrap && '0.25rem'};
|
||||
`
|
||||
|
||||
const QuestionWrapper = styled.div`
|
||||
const QuestionWrapper = styled.button`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-left: 0.4rem;
|
||||
margin-top: 0.2rem;
|
||||
padding: 0.2rem;
|
||||
border: none;
|
||||
background: none;
|
||||
outline: none;
|
||||
cursor: default;
|
||||
border-radius: 36px;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
:hover,
|
||||
:focus {
|
||||
opacity: 0.7;
|
||||
}
|
||||
`
|
||||
|
||||
const HelpCircleStyled = styled.img`
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
`
|
||||
|
||||
const fadeIn = keyframes`
|
||||
from {
|
||||
opacity : 0;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity : 1;
|
||||
}
|
||||
`
|
||||
|
||||
@ -41,100 +84,166 @@ const Popup = styled(Flex)`
|
||||
width: 228px;
|
||||
left: -78px;
|
||||
top: -124px;
|
||||
|
||||
flex-direction: column;
|
||||
aligm-items: center;
|
||||
|
||||
padding: 1rem;
|
||||
|
||||
line-height: 183.52%;
|
||||
background: #404040;
|
||||
align-items: center;
|
||||
padding: 0.6rem 1rem;
|
||||
line-height: 150%;
|
||||
background: ${({ theme }) => theme.charcoalBlack};
|
||||
border-radius: 8px;
|
||||
|
||||
animation: ${fadeIn} 0.15s linear;
|
||||
|
||||
color: white;
|
||||
font-style: italic;
|
||||
|
||||
${({ theme }) => theme.mediaWidth.upToSmall`
|
||||
left: -20px;
|
||||
`}
|
||||
`
|
||||
|
||||
const Option = styled(Flex)`
|
||||
const FancyButton = styled.button`
|
||||
align-items: center;
|
||||
min-width: 55px;
|
||||
height: 24px;
|
||||
margin-right: 4px;
|
||||
height: 2rem;
|
||||
border-radius: 36px;
|
||||
border: 1px solid #f2f2f2;
|
||||
font-size: 12px;
|
||||
border: 1px solid ${({ theme }) => theme.mercuryGray};
|
||||
outline: none;
|
||||
background: ${({ theme }) => theme.white};
|
||||
|
||||
${({ active }) =>
|
||||
active &&
|
||||
`
|
||||
background-color: #2f80ed;
|
||||
color: white;
|
||||
border: 1px solid #2f80ed;
|
||||
`}
|
||||
:hover {
|
||||
cursor: inherit;
|
||||
border: 1px solid ${({ theme }) => theme.chaliceGray};
|
||||
}
|
||||
:focus {
|
||||
border: 1px solid ${({ theme }) => theme.royalBlue};
|
||||
/* box-shadow: 0 0 1px 1px #5CA2FF; */
|
||||
}
|
||||
`
|
||||
|
||||
&:hover {
|
||||
const Option = styled(FancyButton)`
|
||||
margin-right: 8px;
|
||||
margin-top: 6px;
|
||||
|
||||
:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
${({ active, theme }) =>
|
||||
active &&
|
||||
css`
|
||||
background-color: ${({ theme }) => theme.royalBlue};
|
||||
color: ${({ theme }) => theme.white};
|
||||
border: none;
|
||||
|
||||
:hover {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
background-color: ${({ theme }) => darken(0.05, theme.royalBlue)};
|
||||
}
|
||||
|
||||
:focus {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
background-color: ${({ theme }) => lighten(0.05, theme.royalBlue)};
|
||||
}
|
||||
|
||||
:active {
|
||||
background-color: ${({ theme }) => darken(0.05, theme.royalBlue)};
|
||||
}
|
||||
|
||||
:hover:focus {
|
||||
background-color: ${({ theme }) => theme.royalBlue};
|
||||
}
|
||||
:hover:focus:active {
|
||||
background-color: ${({ theme }) => darken(0.05, theme.royalBlue)};
|
||||
}
|
||||
`}
|
||||
`
|
||||
|
||||
const OptionLarge = styled(Option)`
|
||||
width: 120px;
|
||||
`
|
||||
|
||||
const Input = styled.input`
|
||||
width: 123.27px;
|
||||
background: #ffffff;
|
||||
height: 2rem;
|
||||
background: ${({ theme }) => theme.white};
|
||||
flex-grow: 1;
|
||||
|
||||
outline: none;
|
||||
margin-left: 20px;
|
||||
border: 1px solid #f2f2f2;
|
||||
box-sizing: border-box;
|
||||
border-radius: 36px;
|
||||
color: #aeaeae;
|
||||
|
||||
&:focus {
|
||||
}
|
||||
|
||||
text-align: left;
|
||||
padding-left: 0.9rem;
|
||||
|
||||
&::-webkit-outer-spin-button,
|
||||
&::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
cursor: inherit;
|
||||
|
||||
color: ${({ theme }) => theme.doveGray};
|
||||
text-align: left;
|
||||
${({ active }) =>
|
||||
active &&
|
||||
`
|
||||
border: 1px solid #2f80ed;
|
||||
text-align: right;
|
||||
padding-right 1.5rem;
|
||||
padding-left 0rem;
|
||||
color : inherit;
|
||||
`}
|
||||
css`
|
||||
color: initial;
|
||||
cursor: initial;
|
||||
text-align: right;
|
||||
`}
|
||||
|
||||
${({ warning }) =>
|
||||
warning === 'red' &&
|
||||
`
|
||||
color : #FF6871;
|
||||
border: 1px solid #FF6871;
|
||||
`}
|
||||
`
|
||||
|
||||
const BottomError = styled.div`
|
||||
margin-top: 1rem;
|
||||
color: #aeaeae;
|
||||
${({ placeholder }) =>
|
||||
placeholder !== 'Custom' &&
|
||||
css`
|
||||
text-align: right;
|
||||
`}
|
||||
|
||||
${({ color }) =>
|
||||
color === 'red' &&
|
||||
`
|
||||
color : #FF6871;
|
||||
`}
|
||||
css`
|
||||
color: ${({ theme }) => theme.salmonRed};
|
||||
`}
|
||||
`
|
||||
|
||||
const Break = styled.div`
|
||||
border: 1px solid #f2f2f2;
|
||||
width: 100%;
|
||||
margin-top: 1rem;
|
||||
const BottomError = styled.div`
|
||||
${({ show }) =>
|
||||
show &&
|
||||
css`
|
||||
padding-top: 12px;
|
||||
`}
|
||||
color: ${({ theme }) => theme.doveGray};
|
||||
${({ color }) =>
|
||||
color === 'red' &&
|
||||
css`
|
||||
color: ${({ theme }) => theme.salmonRed};
|
||||
`}
|
||||
`
|
||||
|
||||
const OptionLarge = styled(Option)`
|
||||
const OptionCustom = styled(FancyButton)`
|
||||
height: 2rem;
|
||||
position: relative;
|
||||
width: 120px;
|
||||
margin-top: 6px;
|
||||
padding: 0 0.75rem;
|
||||
|
||||
${({ active }) =>
|
||||
active &&
|
||||
css`
|
||||
border: 1px solid ${({ theme }) => theme.royalBlue};
|
||||
:hover {
|
||||
border: 1px solid ${({ theme }) => darken(0.1, theme.royalBlue)};
|
||||
}
|
||||
`}
|
||||
|
||||
${({ color }) =>
|
||||
color === 'red' &&
|
||||
css`
|
||||
border: 1px solid ${({ theme }) => theme.salmonRed};
|
||||
`}
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0px;
|
||||
border-radius: 2rem;
|
||||
}
|
||||
`
|
||||
|
||||
const Bold = styled.span`
|
||||
@ -142,48 +251,67 @@ const Bold = styled.span`
|
||||
`
|
||||
|
||||
const LastSummaryText = styled.div`
|
||||
margin-top: 0.6rem;
|
||||
padding-top: 0.5rem;
|
||||
`
|
||||
|
||||
const SlippageSelector = styled.div`
|
||||
margin-top: 1rem;
|
||||
`
|
||||
|
||||
const InputGroup = styled.div`
|
||||
position: relative;
|
||||
background-color: ${({ theme }) => darken(0.04, theme.concreteGray)};
|
||||
padding: 1rem 1.25rem 1rem 1.25rem;
|
||||
border-radius: 12px;
|
||||
`
|
||||
|
||||
const Percent = styled.div`
|
||||
right: 14px;
|
||||
top: 9px;
|
||||
position: absolute;
|
||||
color: inherit;
|
||||
font-size: 0, 8rem;
|
||||
flex-grow: 0;
|
||||
|
||||
${({ color }) =>
|
||||
${({ color, theme }) =>
|
||||
(color === 'faded' &&
|
||||
`
|
||||
color : #AEAEAE
|
||||
`) ||
|
||||
css`
|
||||
color: ${theme.doveGray};
|
||||
`) ||
|
||||
(color === 'red' &&
|
||||
`
|
||||
color : #FF6871
|
||||
`)}
|
||||
css`
|
||||
color: ${theme.salmonRed};
|
||||
`)};
|
||||
`
|
||||
|
||||
const Faded = styled.span`
|
||||
opacity: 0.7;
|
||||
`
|
||||
|
||||
const ErrorEmoji = styled.span`
|
||||
left: 30px;
|
||||
top: 4px;
|
||||
position: absolute;
|
||||
const TransactionInfo = styled.div`
|
||||
padding: 1.25rem 1.25rem 1rem 1.25rem;
|
||||
`
|
||||
|
||||
const ValueWrapper = styled.span`
|
||||
padding: 0.125rem 0.3rem 0.1rem 0.3rem;
|
||||
background-color: ${({ theme }) => darken(0.04, theme.concreteGray)};
|
||||
border-radius: 12px;
|
||||
font-variant: tabular-nums;
|
||||
vertical
|
||||
`
|
||||
|
||||
export default function TransactionDetails(props) {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const [activeIndex, setActiveIndex] = useState(3)
|
||||
|
||||
const [warningType, setWarningType] = useState(WARNING_TYPE.none)
|
||||
|
||||
const inputRef = useRef()
|
||||
|
||||
const [showPopup, setPopup] = useState(false)
|
||||
|
||||
const [userInput, setUserInput] = useState('')
|
||||
const debouncedInput = useDebounce(userInput, 150)
|
||||
|
||||
useEffect(() => {
|
||||
if (activeIndex === 4) {
|
||||
checkBounds(debouncedInput)
|
||||
}
|
||||
})
|
||||
|
||||
function renderSummary() {
|
||||
let contextualInfo = ''
|
||||
let isError = false
|
||||
@ -233,23 +361,17 @@ export default function TransactionDetails(props) {
|
||||
)
|
||||
}
|
||||
|
||||
const [activeIndex, setActiveIndex] = useState(3)
|
||||
|
||||
const [placeHolder, setplaceHolder] = useState('Custom')
|
||||
|
||||
const [warningType, setWarningType] = useState('none')
|
||||
|
||||
const [showPopup, setPopup] = useState(false)
|
||||
|
||||
const dropDownContent = () => {
|
||||
return (
|
||||
<>
|
||||
{renderTransactionDetails()}
|
||||
<Break />
|
||||
<SlippageSelector>
|
||||
<SlippageRow>
|
||||
Limit addtional price slippage
|
||||
Limit additional price slippage
|
||||
<QuestionWrapper
|
||||
onClick={() => {
|
||||
setPopup(!showPopup)
|
||||
}}
|
||||
onMouseEnter={() => {
|
||||
setPopup(true)
|
||||
}}
|
||||
@ -257,105 +379,114 @@ export default function TransactionDetails(props) {
|
||||
setPopup(false)
|
||||
}}
|
||||
>
|
||||
<img src={questionMark} alt="question mark" />
|
||||
<HelpCircleStyled src={question} alt="popup" />
|
||||
</QuestionWrapper>
|
||||
{showPopup ? (
|
||||
<Popup>
|
||||
Lowering this limit decreases your risk of frontrunning. This makes it more likely that your transaction
|
||||
will fail due to normal price movements.
|
||||
Lowering this limit decreases your risk of frontrunning. However, this makes it more likely that your
|
||||
transaction will fail due to normal price movements.
|
||||
</Popup>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</SlippageRow>
|
||||
<SlippageRow>
|
||||
<SlippageRow wrap>
|
||||
<Option
|
||||
onClick={() => {
|
||||
updateSlippage(0.1)
|
||||
setWarningType('none')
|
||||
setActiveIndex(1)
|
||||
props.setcustomSlippageError('valid')
|
||||
setplaceHolder('Custom')
|
||||
setFromFixed(1, 0.1)
|
||||
}}
|
||||
active={activeIndex === 1 ? true : false}
|
||||
active={activeIndex === 1}
|
||||
>
|
||||
0.1%
|
||||
</Option>
|
||||
<Option
|
||||
onClick={() => {
|
||||
updateSlippage(1)
|
||||
setWarningType('none')
|
||||
setActiveIndex(2)
|
||||
props.setcustomSlippageError('valid')
|
||||
setplaceHolder('Custom')
|
||||
setFromFixed(2, 0.5)
|
||||
}}
|
||||
active={activeIndex === 2 ? true : false}
|
||||
active={activeIndex === 2}
|
||||
>
|
||||
1%
|
||||
0.5%
|
||||
</Option>
|
||||
<OptionLarge
|
||||
onClick={() => {
|
||||
updateSlippage(2)
|
||||
setWarningType('none')
|
||||
setActiveIndex(3)
|
||||
props.setcustomSlippageError('valid')
|
||||
setplaceHolder('Custom')
|
||||
setFromFixed(3, 1)
|
||||
}}
|
||||
active={activeIndex === 3 ? true : false}
|
||||
active={activeIndex === 3}
|
||||
>
|
||||
2%
|
||||
<Faded>(suggested)</Faded>
|
||||
1% <Faded>(suggested)</Faded>
|
||||
</OptionLarge>
|
||||
<InputGroup>
|
||||
{warningType !== 'none' ? <ErrorEmoji>⚠️</ErrorEmoji> : ''}
|
||||
<Input
|
||||
placeholder={placeHolder}
|
||||
value={userInput || ''}
|
||||
onChange={parseInput}
|
||||
onClick={e => {
|
||||
setActiveIndex(4)
|
||||
setplaceHolder('')
|
||||
parseInput(e)
|
||||
}}
|
||||
active={activeIndex === 4 ? true : false}
|
||||
warning={
|
||||
warningType === 'emptyInput'
|
||||
? ''
|
||||
: warningType !== 'none' && warningType !== 'riskyEntryLow'
|
||||
? 'red'
|
||||
: ''
|
||||
}
|
||||
/>
|
||||
<Percent
|
||||
color={
|
||||
warningType === 'emptyInput'
|
||||
? 'faded'
|
||||
: warningType !== 'none' && warningType !== 'riskyEntryLow'
|
||||
? 'red'
|
||||
: activeIndex !== 4
|
||||
? 'faded'
|
||||
: ''
|
||||
}
|
||||
>
|
||||
%
|
||||
</Percent>
|
||||
</InputGroup>
|
||||
<OptionCustom
|
||||
active={activeIndex === 4}
|
||||
color={
|
||||
warningType === WARNING_TYPE.emptyInput
|
||||
? ''
|
||||
: warningType !== WARNING_TYPE.none && warningType !== WARNING_TYPE.riskyEntryLow
|
||||
? 'red'
|
||||
: ''
|
||||
}
|
||||
onClick={() => {
|
||||
setFromCustom()
|
||||
}}
|
||||
>
|
||||
<FlexBetween>
|
||||
{!(warningType === WARNING_TYPE.none || warningType === WARNING_TYPE.emptyInput) && (
|
||||
<span role="img" aria-label="warning">
|
||||
⚠️
|
||||
</span>
|
||||
)}
|
||||
<Input
|
||||
tabIndex={-1}
|
||||
ref={inputRef}
|
||||
active={activeIndex === 4}
|
||||
placeholder={
|
||||
activeIndex === 4
|
||||
? !!userInput
|
||||
? ''
|
||||
: '0'
|
||||
: activeIndex !== 4 && userInput !== ''
|
||||
? userInput
|
||||
: 'Custom'
|
||||
}
|
||||
value={activeIndex === 4 ? userInput : ''}
|
||||
onChange={parseInput}
|
||||
color={
|
||||
warningType === WARNING_TYPE.emptyInput
|
||||
? ''
|
||||
: warningType !== WARNING_TYPE.none && warningType !== WARNING_TYPE.riskyEntryLow
|
||||
? 'red'
|
||||
: ''
|
||||
}
|
||||
/>
|
||||
<Percent
|
||||
color={
|
||||
activeIndex !== 4
|
||||
? 'faded'
|
||||
: warningType === WARNING_TYPE.riskyEntryHigh || warningType === WARNING_TYPE.invalidEntryBound
|
||||
? 'red'
|
||||
: ''
|
||||
}
|
||||
>
|
||||
%
|
||||
</Percent>
|
||||
</FlexBetween>
|
||||
</OptionCustom>
|
||||
</SlippageRow>
|
||||
<SlippageRow>
|
||||
<BottomError
|
||||
show={activeIndex === 4}
|
||||
color={
|
||||
warningType === 'emptyInput'
|
||||
warningType === WARNING_TYPE.emptyInput
|
||||
? ''
|
||||
: warningType !== 'none' && warningType !== 'riskyEntryLow'
|
||||
: warningType !== WARNING_TYPE.none && warningType !== WARNING_TYPE.riskyEntryLow
|
||||
? 'red'
|
||||
: ''
|
||||
}
|
||||
>
|
||||
{warningType === 'emptyInput' ? 'Enter a slippage percentage.' : ''}
|
||||
{warningType === 'invalidEntry' ? 'Please input a valid percentage.' : ''}
|
||||
{warningType === 'invalidEntryBound' ? 'Pleae select value less than 50%' : ''}
|
||||
{warningType === 'riskyEntryHigh' ? 'Your transaction may be frontrun.' : ''}
|
||||
{warningType === 'riskyEntryLow' ? 'Your transaction may fail.' : ''}
|
||||
{activeIndex === 4 && warningType.toString() === 'none' && 'Custom slippage value entered'}
|
||||
{warningType === WARNING_TYPE.emptyInput && 'Enter a slippage percentage.'}
|
||||
{warningType === WARNING_TYPE.invalidEntryBound && 'Please select value less than 50%'}
|
||||
{warningType === WARNING_TYPE.riskyEntryHigh && 'Your transaction may be frontrun.'}
|
||||
{warningType === WARNING_TYPE.riskyEntryLow && 'Your transaction may fail.'}
|
||||
</BottomError>
|
||||
</SlippageRow>
|
||||
</SlippageSelector>
|
||||
@ -363,52 +494,65 @@ export default function TransactionDetails(props) {
|
||||
)
|
||||
}
|
||||
|
||||
const [userInput, setUserInput] = useState()
|
||||
|
||||
const parseInput = e => {
|
||||
let input = e.target.value
|
||||
if (input === '') {
|
||||
setUserInput(input)
|
||||
props.setcustomSlippageError('invalid')
|
||||
return setWarningType('emptyInput')
|
||||
}
|
||||
//check for decimal
|
||||
let isValid = /^[+]?\d*\.?\d{1,2}$/.test(input) || /^[+]?\d*\.$/.test(input)
|
||||
let decimalLimit = /^\d+\.?\d{0,2}$/.test(input) || input === ''
|
||||
if (decimalLimit) {
|
||||
setUserInput(input)
|
||||
} else {
|
||||
return
|
||||
}
|
||||
if (isValid) {
|
||||
checkAcceptablePercentValue(input)
|
||||
} else {
|
||||
setWarningType('invalidEntry')
|
||||
}
|
||||
const setFromCustom = () => {
|
||||
setActiveIndex(4)
|
||||
inputRef.current.focus()
|
||||
// if there's a value, evaluate the bounds
|
||||
checkBounds(userInput)
|
||||
}
|
||||
|
||||
const checkAcceptablePercentValue = input => {
|
||||
setTimeout(function() {
|
||||
setWarningType('none')
|
||||
// used for slippage presets
|
||||
const setFromFixed = (index, slippage) => {
|
||||
// update slippage in parent, reset errors and input state
|
||||
updateSlippage(slippage)
|
||||
setWarningType(WARNING_TYPE.none)
|
||||
setActiveIndex(index)
|
||||
props.setcustomSlippageError('valid`')
|
||||
}
|
||||
|
||||
const checkBounds = slippageValue => {
|
||||
setWarningType(WARNING_TYPE.none)
|
||||
props.setcustomSlippageError('valid')
|
||||
|
||||
if (slippageValue === '') {
|
||||
props.setcustomSlippageError('invalid')
|
||||
return setWarningType(WARNING_TYPE.emptyInput)
|
||||
}
|
||||
|
||||
// check bounds and set errors
|
||||
if (slippageValue < 0 || slippageValue > 50) {
|
||||
props.setcustomSlippageError('invalid')
|
||||
return setWarningType(WARNING_TYPE.invalidEntryBound)
|
||||
}
|
||||
if (slippageValue >= 0 && slippageValue < 0.1) {
|
||||
props.setcustomSlippageError('valid')
|
||||
if (input < 0 || input > 50) {
|
||||
props.setcustomSlippageError('invalid')
|
||||
return setWarningType('invalidEntryBound')
|
||||
}
|
||||
if (input >= 0 && input < 0.1) {
|
||||
props.setcustomSlippageError('valid')
|
||||
setWarningType('riskyEntryLow')
|
||||
}
|
||||
if (input >= 5) {
|
||||
props.setcustomSlippageError('warning')
|
||||
setWarningType('riskyEntryHigh')
|
||||
}
|
||||
updateSlippage(input)
|
||||
}, 300)
|
||||
setWarningType(WARNING_TYPE.riskyEntryLow)
|
||||
}
|
||||
if (slippageValue > 5) {
|
||||
props.setcustomSlippageError('warning')
|
||||
setWarningType(WARNING_TYPE.riskyEntryHigh)
|
||||
}
|
||||
//update the actual slippage value in parent
|
||||
updateSlippage(slippageValue)
|
||||
}
|
||||
|
||||
// check that the theyve entered number and correct decimal
|
||||
const parseInput = e => {
|
||||
let input = e.target.value
|
||||
|
||||
// restrict to 2 decimal places
|
||||
let acceptableValues = [/^$/, /^\d{1,2}$/, /^\d{0,2}\.\d{0,2}$/]
|
||||
// if its within accepted decimal limit, update the input state
|
||||
if (acceptableValues.some(a => a.test(input))) {
|
||||
setUserInput(input)
|
||||
}
|
||||
}
|
||||
|
||||
const updateSlippage = newSlippage => {
|
||||
// round to 2 decimals to prevent ethers error
|
||||
let numParsed = parseFloat((newSlippage * 100).toFixed(2))
|
||||
|
||||
// set both slippage values in parents
|
||||
props.setRawSlippage(numParsed)
|
||||
props.setRawTokenSlippage(numParsed)
|
||||
}
|
||||
@ -423,113 +567,129 @@ export default function TransactionDetails(props) {
|
||||
|
||||
if (props.independentField === props.INPUT) {
|
||||
return props.sending ? (
|
||||
<div>
|
||||
<TransactionInfo>
|
||||
<div>
|
||||
{t('youAreSelling')}{' '}
|
||||
{b(
|
||||
`${amountFormatter(
|
||||
props.independentValueParsed,
|
||||
props.independentDecimals,
|
||||
Math.min(4, props.independentDecimals)
|
||||
)} ${props.inputSymbol}`
|
||||
)}
|
||||
<ValueWrapper>
|
||||
{b(
|
||||
`${amountFormatter(
|
||||
props.independentValueParsed,
|
||||
props.independentDecimals,
|
||||
Math.min(4, props.independentDecimals)
|
||||
)} ${props.inputSymbol}`
|
||||
)}
|
||||
</ValueWrapper>
|
||||
.
|
||||
</div>
|
||||
<LastSummaryText>
|
||||
{b(props.recipientAddress)} {t('willReceive')}{' '}
|
||||
{b(
|
||||
`${amountFormatter(
|
||||
props.dependentValueMinumum,
|
||||
props.dependentDecimals,
|
||||
Math.min(4, props.dependentDecimals)
|
||||
)} ${props.outputSymbol}`
|
||||
)}{' '}
|
||||
<ValueWrapper>
|
||||
{b(
|
||||
`${amountFormatter(
|
||||
props.dependentValueMinumum,
|
||||
props.dependentDecimals,
|
||||
Math.min(4, props.dependentDecimals)
|
||||
)} ${props.outputSymbol}`
|
||||
)}
|
||||
</ValueWrapper>{' '}
|
||||
</LastSummaryText>
|
||||
<LastSummaryText>
|
||||
{t('priceChange')} {b(`${props.percentSlippageFormatted}%`)}.
|
||||
{t('priceChange')} <ValueWrapper>{b(`${props.percentSlippageFormatted}%`)}</ValueWrapper>.
|
||||
</LastSummaryText>
|
||||
</div>
|
||||
</TransactionInfo>
|
||||
) : (
|
||||
<div>
|
||||
<TransactionInfo>
|
||||
<div>
|
||||
{t('youAreSelling')}{' '}
|
||||
{b(
|
||||
`${amountFormatter(
|
||||
props.independentValueParsed,
|
||||
props.independentDecimals,
|
||||
Math.min(4, props.independentDecimals)
|
||||
)} ${props.inputSymbol}`
|
||||
)}{' '}
|
||||
<ValueWrapper>
|
||||
{b(
|
||||
`${amountFormatter(
|
||||
props.independentValueParsed,
|
||||
props.independentDecimals,
|
||||
Math.min(4, props.independentDecimals)
|
||||
)} ${props.inputSymbol}`
|
||||
)}
|
||||
</ValueWrapper>{' '}
|
||||
{t('forAtLeast')}
|
||||
{b(
|
||||
`${amountFormatter(
|
||||
props.dependentValueMinumum,
|
||||
props.dependentDecimals,
|
||||
Math.min(4, props.dependentDecimals)
|
||||
)} ${props.outputSymbol}`
|
||||
)}
|
||||
<ValueWrapper>
|
||||
{b(
|
||||
`${amountFormatter(
|
||||
props.dependentValueMinumum,
|
||||
props.dependentDecimals,
|
||||
Math.min(4, props.dependentDecimals)
|
||||
)} ${props.outputSymbol}`
|
||||
)}
|
||||
</ValueWrapper>
|
||||
.
|
||||
</div>
|
||||
<LastSummaryText>
|
||||
{t('priceChange')} {b(`${props.percentSlippageFormatted}%`)}.
|
||||
{t('priceChange')} <ValueWrapper>{b(`${props.percentSlippageFormatted}%`)}</ValueWrapper>.
|
||||
</LastSummaryText>
|
||||
</div>
|
||||
</TransactionInfo>
|
||||
)
|
||||
} else {
|
||||
return props.sending ? (
|
||||
<div>
|
||||
<TransactionInfo>
|
||||
<div>
|
||||
{t('youAreSending')}{' '}
|
||||
{b(
|
||||
`${amountFormatter(
|
||||
props.independentValueParsed,
|
||||
props.independentDecimals,
|
||||
Math.min(4, props.independentDecimals)
|
||||
)} ${props.outputSymbol}`
|
||||
)}{' '}
|
||||
<ValueWrapper>
|
||||
{b(
|
||||
`${amountFormatter(
|
||||
props.independentValueParsed,
|
||||
props.independentDecimals,
|
||||
Math.min(4, props.independentDecimals)
|
||||
)} ${props.outputSymbol}`
|
||||
)}
|
||||
</ValueWrapper>{' '}
|
||||
{t('to')} {b(props.recipientAddress)}.
|
||||
</div>
|
||||
<LastSummaryText>
|
||||
{t('itWillCost')}{' '}
|
||||
{b(
|
||||
`${amountFormatter(
|
||||
props.dependentValueMaximum,
|
||||
props.dependentDecimals,
|
||||
Math.min(4, props.dependentDecimals)
|
||||
)} ${props.inputSymbol}`
|
||||
)}{' '}
|
||||
<ValueWrapper>
|
||||
{b(
|
||||
`${amountFormatter(
|
||||
props.dependentValueMaximum,
|
||||
props.dependentDecimals,
|
||||
Math.min(4, props.dependentDecimals)
|
||||
)} ${props.inputSymbol}`
|
||||
)}
|
||||
</ValueWrapper>{' '}
|
||||
</LastSummaryText>
|
||||
<LastSummaryText>
|
||||
{t('priceChange')} {b(`${props.percentSlippageFormatted}%`)}.
|
||||
{t('priceChange')} <ValueWrapper>{b(`${props.percentSlippageFormatted}%`)}</ValueWrapper>.
|
||||
</LastSummaryText>
|
||||
</div>
|
||||
</TransactionInfo>
|
||||
) : (
|
||||
<div>
|
||||
<TransactionInfo>
|
||||
<div>
|
||||
{t('youAreBuying')}{' '}
|
||||
{b(
|
||||
`${amountFormatter(
|
||||
props.independentValueParsed,
|
||||
props.independentDecimals,
|
||||
Math.min(4, props.independentDecimals)
|
||||
)} ${props.outputSymbol}`
|
||||
)}
|
||||
<ValueWrapper>
|
||||
{b(
|
||||
`${amountFormatter(
|
||||
props.independentValueParsed,
|
||||
props.independentDecimals,
|
||||
Math.min(4, props.independentDecimals)
|
||||
)} ${props.outputSymbol}`
|
||||
)}
|
||||
</ValueWrapper>
|
||||
.
|
||||
</div>
|
||||
<LastSummaryText>
|
||||
{t('itWillCost')}{' '}
|
||||
{b(
|
||||
`${amountFormatter(
|
||||
props.dependentValueMaximum,
|
||||
props.dependentDecimals,
|
||||
Math.min(4, props.dependentDecimals)
|
||||
)} ${props.inputSymbol}`
|
||||
)}{' '}
|
||||
<ValueWrapper>
|
||||
{b(
|
||||
`${amountFormatter(
|
||||
props.dependentValueMaximum,
|
||||
props.dependentDecimals,
|
||||
Math.min(4, props.dependentDecimals)
|
||||
)} ${props.inputSymbol}`
|
||||
)}
|
||||
</ValueWrapper>{' '}
|
||||
</LastSummaryText>
|
||||
<LastSummaryText>
|
||||
{t('priceChange')} {b(`${props.percentSlippageFormatted}%`)}.
|
||||
{t('priceChange')} <ValueWrapper>{b(`${props.percentSlippageFormatted}%`)}</ValueWrapper>.
|
||||
</LastSummaryText>
|
||||
</div>
|
||||
</TransactionInfo>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import { useWeb3Context, Connectors } from 'web3-react'
|
||||
import { darken, transparentize } from 'polished'
|
||||
import Jazzicon from 'jazzicon'
|
||||
import { ethers } from 'ethers'
|
||||
import { Activity, ArrowRight } from 'react-feather'
|
||||
import { Activity } from 'react-feather'
|
||||
|
||||
import { shortenAddress } from '../../utils'
|
||||
import { useENSName } from '../../hooks'
|
||||
@ -91,13 +91,6 @@ const NetworkIcon = styled(Activity)`
|
||||
height: 16px;
|
||||
`
|
||||
|
||||
const ArrowIcon = styled(ArrowRight)`
|
||||
margin-left: 0.25rem;
|
||||
margin-right: 0.5rem;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
`
|
||||
|
||||
const SpinnerWrapper = styled(Spinner)`
|
||||
margin: 0 0.25rem 0 0.25rem;
|
||||
`
|
||||
@ -251,7 +244,6 @@ export default function Web3Status() {
|
||||
return (
|
||||
<Web3StatusConnect onClick={onClick}>
|
||||
<Text>{t('Connect')}</Text>
|
||||
<ArrowIcon />
|
||||
</Web3StatusConnect>
|
||||
)
|
||||
} else {
|
||||
|
@ -2,10 +2,8 @@ import React, { createContext, useContext, useReducer, useMemo, useCallback, use
|
||||
import { useWeb3Context } from 'web3-react'
|
||||
import { safeAccess } from '../utils'
|
||||
|
||||
const SHOW_BETA_MESSAGE = 'SHOW_BETA_MESSAGE'
|
||||
const BLOCK_NUMBERS = 'BLOCK_NUMBERS'
|
||||
|
||||
const DISMISS_BETA_MESSAGE = 'DISMISS_BETA_MESSAGE'
|
||||
const UPDATE_BLOCK_NUMBER = 'UPDATE_BLOCK_NUMBER'
|
||||
|
||||
const ApplicationContext = createContext()
|
||||
@ -16,12 +14,6 @@ function useApplicationContext() {
|
||||
|
||||
function reducer(state, { type, payload }) {
|
||||
switch (type) {
|
||||
case DISMISS_BETA_MESSAGE: {
|
||||
return {
|
||||
...state,
|
||||
[SHOW_BETA_MESSAGE]: false
|
||||
}
|
||||
}
|
||||
case UPDATE_BLOCK_NUMBER: {
|
||||
const { networkId, blockNumber } = payload
|
||||
return {
|
||||
@ -40,25 +32,15 @@ function reducer(state, { type, payload }) {
|
||||
|
||||
export default function Provider({ children }) {
|
||||
const [state, dispatch] = useReducer(reducer, {
|
||||
[SHOW_BETA_MESSAGE]: true,
|
||||
[BLOCK_NUMBERS]: {}
|
||||
})
|
||||
|
||||
const dismissBetaMessage = useCallback(() => {
|
||||
dispatch({ type: DISMISS_BETA_MESSAGE })
|
||||
}, [])
|
||||
const updateBlockNumber = useCallback((networkId, blockNumber) => {
|
||||
dispatch({ type: UPDATE_BLOCK_NUMBER, payload: { networkId, blockNumber } })
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<ApplicationContext.Provider
|
||||
value={useMemo(() => [state, { dismissBetaMessage, updateBlockNumber }], [
|
||||
state,
|
||||
dismissBetaMessage,
|
||||
updateBlockNumber
|
||||
])}
|
||||
>
|
||||
<ApplicationContext.Provider value={useMemo(() => [state, { updateBlockNumber }], [state, updateBlockNumber])}>
|
||||
{children}
|
||||
</ApplicationContext.Provider>
|
||||
)
|
||||
@ -101,12 +83,6 @@ export function Updater() {
|
||||
return null
|
||||
}
|
||||
|
||||
export function useBetaMessageManager() {
|
||||
const [state, { dismissBetaMessage }] = useApplicationContext()
|
||||
|
||||
return [safeAccess(state, [SHOW_BETA_MESSAGE]), dismissBetaMessage]
|
||||
}
|
||||
|
||||
export function useBlockNumber() {
|
||||
const { networkId } = useWeb3Context()
|
||||
|
||||
|
90
src/contexts/LocalStorage.js
Normal file
90
src/contexts/LocalStorage.js
Normal file
@ -0,0 +1,90 @@
|
||||
import React, { createContext, useContext, useReducer, useMemo, useCallback, useEffect } from 'react'
|
||||
|
||||
const UNISWAP = 'UNISWAP'
|
||||
|
||||
const VERSION = 'VERSION'
|
||||
const CURRENT_VERSION = 0
|
||||
const LAST_SAVED = 'LAST_SAVED'
|
||||
|
||||
const BETA_MESSAGE_DISMISSED = 'BETA_MESSAGE_DISMISSED'
|
||||
const UPDATABLE_KEYS = [BETA_MESSAGE_DISMISSED]
|
||||
|
||||
const UPDATE_KEY = 'UPDATE_KEY'
|
||||
|
||||
const LocalStorageContext = createContext()
|
||||
|
||||
function useLocalStorageContext() {
|
||||
return useContext(LocalStorageContext)
|
||||
}
|
||||
|
||||
function reducer(state, { type, payload }) {
|
||||
switch (type) {
|
||||
case UPDATE_KEY: {
|
||||
const { key, value } = payload
|
||||
if (!UPDATABLE_KEYS.some(k => k === key)) {
|
||||
throw Error(`Unexpected key in LocalStorageContext reducer: '${key}'.`)
|
||||
} else {
|
||||
return {
|
||||
...state,
|
||||
[key]: value
|
||||
}
|
||||
}
|
||||
}
|
||||
default: {
|
||||
throw Error(`Unexpected action type in LocalStorageContext reducer: '${type}'.`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
const defaultLocalStorage = {
|
||||
[VERSION]: CURRENT_VERSION,
|
||||
[BETA_MESSAGE_DISMISSED]: false
|
||||
}
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(window.localStorage.getItem(UNISWAP))
|
||||
if (parsed[VERSION] !== CURRENT_VERSION) {
|
||||
// this is where we could run migration logic
|
||||
return defaultLocalStorage
|
||||
} else {
|
||||
return parsed
|
||||
}
|
||||
} catch {
|
||||
return defaultLocalStorage
|
||||
}
|
||||
}
|
||||
|
||||
export default function Provider({ children }) {
|
||||
const [state, dispatch] = useReducer(reducer, undefined, init)
|
||||
|
||||
const updateKey = useCallback((key, value) => {
|
||||
dispatch({ type: UPDATE_KEY, payload: { key, value } })
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<LocalStorageContext.Provider value={useMemo(() => [state, { updateKey }], [state, updateKey])}>
|
||||
{children}
|
||||
</LocalStorageContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export function Updater() {
|
||||
const [state] = useLocalStorageContext()
|
||||
|
||||
useEffect(() => {
|
||||
window.localStorage.setItem(UNISWAP, JSON.stringify({ ...state, [LAST_SAVED]: Math.floor(Date.now() / 1000) }))
|
||||
})
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export function useBetaMessageManager() {
|
||||
const [state, { updateKey }] = useLocalStorageContext()
|
||||
|
||||
const dismissBetaMessage = useCallback(() => {
|
||||
updateKey(BETA_MESSAGE_DISMISSED, true)
|
||||
}, [updateKey])
|
||||
|
||||
return [!state[BETA_MESSAGE_DISMISSED], dismissBetaMessage]
|
||||
}
|
@ -89,6 +89,14 @@ const INITIAL_TOKENS_CONTEXT = {
|
||||
[DECIMALS]: 9,
|
||||
[EXCHANGE_ADDRESS]: '0xb92dE8B30584392Af27726D5ce04Ef3c4e5c9924'
|
||||
},
|
||||
|
||||
'0xc719d010B63E5bbF2C0551872CD5316ED26AcD83': {
|
||||
[NAME]: 'Decentralized Insurance Protocol',
|
||||
[SYMBOL]: 'DIP',
|
||||
[DECIMALS]: 18,
|
||||
[EXCHANGE_ADDRESS]: '0x61792F290e5100FBBcBb2309F03A1Bab869fb850'
|
||||
},
|
||||
|
||||
'0x4946Fcea7C692606e8908002e55A582af44AC121': {
|
||||
[NAME]: 'FOAM Token',
|
||||
[SYMBOL]: 'FOAM',
|
||||
@ -191,6 +199,12 @@ const INITIAL_TOKENS_CONTEXT = {
|
||||
[DECIMALS]: 18,
|
||||
[EXCHANGE_ADDRESS]: '0x2C4Bd064b998838076fa341A83d007FC2FA50957'
|
||||
},
|
||||
'0xec67005c4E498Ec7f55E092bd1d35cbC47C91892': {
|
||||
[NAME]: 'Melon Token',
|
||||
[SYMBOL]: 'MLN',
|
||||
[DECIMALS]: 18,
|
||||
[EXCHANGE_ADDRESS]: '0xA931F4eB165AC307fD7431b5EC6eADde53E14b0C'
|
||||
},
|
||||
'0x957c30aB0426e0C93CD8241E2c60392d08c6aC8e': {
|
||||
[NAME]: 'Modum Token',
|
||||
[SYMBOL]: 'MOD',
|
||||
|
22
src/index.js
22
src/index.js
@ -4,6 +4,7 @@ import ReactGA from 'react-ga'
|
||||
import Web3Provider, { Connectors } from 'web3-react'
|
||||
|
||||
import ThemeProvider, { GlobalStyle } from './theme'
|
||||
import LocalStorageContextProvider, { Updater as LocalStorageContextUpdater } from './contexts/LocalStorage'
|
||||
import ApplicationContextProvider, { Updater as ApplicationContextUpdater } from './contexts/Application'
|
||||
import TransactionContextProvider, { Updater as TransactionContextUpdater } from './contexts/Transactions'
|
||||
import TokensContextProvider from './contexts/Tokens'
|
||||
@ -29,21 +30,24 @@ const connectors = { Injected, Network }
|
||||
|
||||
function ContextProviders({ children }) {
|
||||
return (
|
||||
<ApplicationContextProvider>
|
||||
<TransactionContextProvider>
|
||||
<TokensContextProvider>
|
||||
<BalancesContextProvider>
|
||||
<AllowancesContextProvider>{children}</AllowancesContextProvider>
|
||||
</BalancesContextProvider>
|
||||
</TokensContextProvider>
|
||||
</TransactionContextProvider>
|
||||
</ApplicationContextProvider>
|
||||
<LocalStorageContextProvider>
|
||||
<ApplicationContextProvider>
|
||||
<TransactionContextProvider>
|
||||
<TokensContextProvider>
|
||||
<BalancesContextProvider>
|
||||
<AllowancesContextProvider>{children}</AllowancesContextProvider>
|
||||
</BalancesContextProvider>
|
||||
</TokensContextProvider>
|
||||
</TransactionContextProvider>
|
||||
</ApplicationContextProvider>
|
||||
</LocalStorageContextProvider>
|
||||
)
|
||||
}
|
||||
|
||||
function Updaters() {
|
||||
return (
|
||||
<>
|
||||
<LocalStorageContextUpdater />
|
||||
<ApplicationContextUpdater />
|
||||
<TransactionContextUpdater />
|
||||
</>
|
||||
|
@ -362,6 +362,7 @@ export default function AddLiquidity() {
|
||||
})
|
||||
|
||||
const deadline = Math.ceil(Date.now() / 1000) + DEADLINE_FROM_NOW
|
||||
|
||||
const estimatedGasLimit = await exchangeContract.estimate.addLiquidity(
|
||||
isNewExchange ? ethers.constants.Zero : liquidityTokensMin,
|
||||
isNewExchange ? outputValueParsed : outputValueMax,
|
||||
@ -371,6 +372,8 @@ export default function AddLiquidity() {
|
||||
}
|
||||
)
|
||||
|
||||
const gasLimit = calculateGasMargin(estimatedGasLimit, GAS_MARGIN)
|
||||
|
||||
exchangeContract
|
||||
.addLiquidity(
|
||||
isNewExchange ? ethers.constants.Zero : liquidityTokensMin,
|
||||
@ -378,7 +381,7 @@ export default function AddLiquidity() {
|
||||
deadline,
|
||||
{
|
||||
value: inputValueParsed,
|
||||
gasLimit: calculateGasMargin(estimatedGasLimit, GAS_MARGIN)
|
||||
gasLimit
|
||||
}
|
||||
)
|
||||
.then(response => {
|
||||
|
@ -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.5px ${({ theme }) => theme.mercuryGray};
|
||||
box-shadow: 0 0 1px 1px ${({ theme }) => theme.mercuryGray};
|
||||
font-weight: 500;
|
||||
color: ${({ theme }) => theme.royalBlue};
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import styled, { keyframes } from 'styled-components'
|
||||
import { lighten, darken } from 'polished'
|
||||
import { darken } from 'polished'
|
||||
|
||||
export const Button = styled.button.attrs(({ warning, theme }) => ({
|
||||
backgroundColor: warning ? theme.salmonRed : theme.royalBlue
|
||||
@ -18,11 +18,11 @@ export const Button = styled.button.attrs(({ warning, theme }) => ({
|
||||
|
||||
:hover,
|
||||
:focus {
|
||||
background-color: ${({ backgroundColor }) => lighten(0.05, backgroundColor)};
|
||||
background-color: ${({ backgroundColor }) => darken(0.05, backgroundColor)};
|
||||
}
|
||||
|
||||
:active {
|
||||
background-color: ${({ backgroundColor }) => darken(0.05, backgroundColor)};
|
||||
background-color: ${({ backgroundColor }) => darken(0.1, backgroundColor)};
|
||||
}
|
||||
|
||||
:disabled {
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user