Commit 006fe9b3 authored by Ian Lapham's avatar Ian Lapham Committed by GitHub

Updated context keys, remove logs (#680)

* updated keys in pair context

* fix bug on imported liquidity

* Add price bar and spacing tweaks

* Header tweaks

* Base for token import, query params, styling updates

* remove unused imports

* query params, create flow

* set ETH as default for create

* Style tweaks and price bar location

* add mobile popups, mobile styling on header

* updated mobile styles

* style updates mobile, fix build
Co-authored-by: default avatarCallil Capuozzo <callil.capuozzo@gmail.com>
parent 50c9d997
......@@ -44,7 +44,8 @@
"react-use-gesture": "^6.0.14",
"rebass": "^4.0.7",
"styled-components": "^4.2.0",
"typescript": "^3.7.5"
"typescript": "^3.7.5",
"use-media": "^1.4.0"
},
"scripts": {
"start": "react-scripts start",
......
<svg viewBox="0 0 24 24" focusable="false" role="presentation" aria-hidden="true" class="css-yyruks"><g fill="none" stroke="currentColor" stroke-linecap="full" stroke-width="2"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><path d="M15 3h6v6"></path><path d="M10 14L21 3"></path></g></svg>
\ No newline at end of file
This diff is collapsed.
<svg width="78" height="12" viewBox="0 0 78 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M36.3965 1.03412C34.6091 1.48449 33.7713 2.88605 34.2793 4.5758C34.4969 5.29984 35.1665 6.03027 36.1133 6.57652C37.8197 7.56094 38.3221 7.95961 38.6139 8.56025C38.8574 9.06134 38.8785 9.22884 38.7557 9.68301C38.4676 10.7492 37.7153 11.3372 36.6391 11.3372C35.5405 11.3372 34.7691 10.721 34.597 9.70595C34.5278 9.29775 34.4426 9.1674 34.2454 9.1674C34.0098 9.1674 33.9852 9.27538 33.9852 10.3093V11.451L34.6997 11.6937C35.8154 12.0726 37.4024 12.0273 38.3494 11.5896C40.1941 10.7367 40.9011 9.04384 40.0731 7.46204C39.7635 6.87036 38.9864 6.20995 37.655 5.40685C36.2557 4.56266 35.6321 3.9486 35.5406 3.32451C35.4002 2.36545 36.2628 1.5717 37.4417 1.57509C38.3652 1.57767 38.7615 1.79628 39.0888 2.48357C39.2937 2.91387 39.4404 3.05611 39.6831 3.0599C39.9515 3.06397 39.9915 3.01394 39.923 2.75966C39.878 2.59191 39.8401 2.17125 39.8392 1.82489C39.8378 1.38509 39.7743 1.17109 39.6282 1.11535C39.2306 0.963192 36.9092 0.904878 36.3965 1.03412ZM0.505859 1.43744C0.505859 1.63258 0.596635 1.70866 0.829493 1.70866C1.48656 1.70866 1.52181 1.89826 1.59462 5.83132C1.65818 9.26736 1.68172 9.54172 1.95636 10.0489C2.34981 10.7754 2.88344 11.2588 3.70409 11.6324C4.2663 11.8883 4.62123 11.9426 5.74551 11.9449C6.96519 11.9472 7.18744 11.9079 7.88629 11.5659C8.31512 11.3561 8.84929 10.9628 9.07331 10.692C9.85 9.7531 9.9322 9.29938 10.0203 5.4668C10.105 1.77622 10.1166 1.71625 10.747 1.71069C10.8937 1.70947 10.9852 1.60451 10.9852 1.43744C10.9852 1.18126 10.8944 1.16621 9.35203 1.16621C7.82749 1.16621 7.71889 1.1837 7.71889 1.42889C7.71889 1.62553 7.82913 1.70215 8.15807 1.73402C8.88087 1.80386 8.93952 2.08162 8.9417 5.44728C8.94402 8.85945 8.82752 9.51593 8.09683 10.2069C7.41744 10.8496 6.87673 11.066 5.95102 11.066C4.62137 11.066 3.67905 10.4471 3.37011 9.37084C3.26614 9.00888 3.22789 7.67782 3.25511 5.37022L3.2958 1.91208L3.77214 1.75898C4.03412 1.67476 4.2682 1.507 4.29243 1.38603C4.33135 1.1917 4.11455 1.16621 2.42112 1.16621C0.596634 1.16621 0.505859 1.17909 0.505859 1.43744ZM13.1627 1.43744C13.1627 1.64737 13.2535 1.70866 13.5646 1.70866C14.2576 1.70866 14.6479 1.97502 14.8045 2.55477C14.8937 2.88444 14.9321 4.4589 14.9059 6.70913C14.8592 10.727 14.8041 10.9898 13.9731 11.1554C13.6992 11.21 13.571 11.3166 13.571 11.4898C13.571 11.7263 13.7041 11.744 15.4763 11.744C17.2174 11.744 17.3816 11.7232 17.3816 11.5009C17.3816 11.3279 17.2073 11.2114 16.7763 11.0965C16.241 10.9538 16.1545 10.876 16.0284 10.4243C15.8669 9.84451 15.8286 3.73664 15.9867 3.75427C16.0427 3.76051 16.5706 4.32504 17.1598 5.00867C17.7488 5.6923 19.3604 7.4874 20.7411 8.99787C22.9022 11.3619 23.3064 11.744 23.6459 11.744H24.0403L24.0794 6.93644C24.107 3.52292 24.1641 2.08337 24.2758 1.97203C24.3625 1.88578 24.6381 1.77349 24.8882 1.7225C25.1537 1.66839 25.3432 1.54728 25.3432 1.43188C25.3432 1.26995 25.0039 1.22723 23.4719 1.19631C21.6701 1.15997 21.6006 1.16878 21.6006 1.43363C21.6006 1.63488 21.6897 1.70866 21.9332 1.70866C22.1162 1.70866 22.4377 1.85581 22.6477 2.03577L23.0296 2.36287L23.0724 5.62951C23.0968 7.47386 23.0628 8.8962 22.9946 8.8962C22.9282 8.8962 22.5127 8.4843 22.0712 7.98077C21.6298 7.47724 20.3729 6.08898 19.278 4.89558C18.1831 3.70218 16.9869 2.37981 16.62 1.9571L15.9526 1.18845L14.5577 1.17733C13.2496 1.16689 13.1627 1.18316 13.1627 1.43744ZM27.4526 1.43744C27.4526 1.64425 27.5434 1.70866 27.8349 1.70866C28.0452 1.70866 28.336 1.79518 28.4814 1.90096C28.7307 2.08254 28.748 2.31663 28.7882 6.07109C28.8384 10.7592 28.7971 11.022 27.9919 11.1503C27.5863 11.215 27.4526 11.2992 27.4526 11.4902C27.4526 11.727 27.5898 11.744 29.4941 11.744C31.4447 11.744 31.5355 11.732 31.5355 11.4728C31.5355 11.2799 31.4447 11.2016 31.2213 11.2016C31.0484 11.2016 30.7882 11.1151 30.6429 11.0093C30.3926 10.8271 30.3766 10.5926 30.3392 6.5395C30.3008 2.38756 30.3078 2.25398 30.5774 1.98533C30.7301 1.83317 31.0081 1.70866 31.1953 1.70866C31.4447 1.70866 31.5355 1.63638 31.5355 1.43744C31.5355 1.17828 31.4447 1.16621 29.4941 1.16621C27.5434 1.16621 27.4526 1.17828 27.4526 1.43744ZM41.7031 1.43744C41.7472 1.60546 41.8888 1.70866 42.075 1.70866C42.2403 1.70866 42.5095 1.85065 42.6732 2.02437C42.8395 2.20067 43.77 4.43002 44.7817 7.07597L46.5928 11.8119L47.0676 11.8524L47.5424 11.893L48.8147 8.5299C49.5145 6.68027 50.1604 5.02047 50.2502 4.84146C50.4041 4.53498 50.4384 4.58165 50.8474 5.65517C51.0859 6.2817 51.7212 7.93848 52.2589 9.33693L53.2365 11.8797H53.6672C53.9043 11.8797 54.1293 11.7986 54.1675 11.6995C54.2056 11.6005 54.831 9.99843 55.5571 8.13958C56.2833 6.28086 57.0876 4.22158 57.3445 3.56358C57.9297 2.06519 58.0469 1.88021 58.5135 1.71815C58.7209 1.64614 58.8906 1.49251 58.8906 1.37669C58.8906 1.19822 58.6427 1.16621 57.2574 1.16621C55.7151 1.16621 55.6243 1.18126 55.6243 1.43744C55.6243 1.63394 55.7151 1.70866 55.9534 1.70866C56.4824 1.70866 56.7131 1.85187 56.7131 2.18046C56.7131 2.45467 54.1209 9.49028 53.9611 9.64935C53.863 9.74713 51.5223 3.21154 51.4376 2.60345C51.3554 2.01272 51.6077 1.70866 52.1799 1.70866C52.4033 1.70866 52.4941 1.63041 52.4941 1.43744C52.4941 1.17787 52.4033 1.16621 50.3846 1.16621C48.3659 1.16621 48.2752 1.17787 48.2752 1.43744C48.2752 1.59204 48.3659 1.70866 48.4861 1.70866C48.911 1.70866 49.4742 2.11767 49.619 2.53156C49.8268 3.12541 49.6678 3.72752 48.4442 6.9836L47.4047 9.74974L47.1808 9.22122C47.0577 8.9306 46.4168 7.21564 45.7569 5.41036C44.4602 1.86379 44.441 1.70866 45.2977 1.70866C45.5986 1.70866 45.6894 1.64587 45.6894 1.43744C45.6894 1.17828 45.5986 1.16621 43.6607 1.16621C41.6991 1.16621 41.6344 1.17516 41.7031 1.43744ZM69.2643 1.53106C69.2643 1.53106 69.2642 1.7162 69.287 1.76771C69.3098 1.81923 69.4562 1.83858 69.4562 1.83858C69.547 1.86294 69.6333 1.88433 69.7149 1.90453L69.715 1.90457C70.1264 2.00642 70.4153 2.07797 70.5307 2.348C70.6087 2.53041 70.6136 3.16468 70.6145 6.56497C70.6155 10.1505 70.6149 10.5898 70.519 10.8267C70.3999 11.1206 70.1722 11.2766 69.6469 11.4241C69.6469 11.4241 69.4145 11.4888 69.3519 11.5466C69.2893 11.6044 69.2775 11.7335 69.2775 11.7335C69.2775 11.7335 69.2726 11.8534 69.3262 11.911C69.3797 11.9685 69.5227 11.9411 69.5227 11.9411L70.8847 11.9447L73.1436 11.963C73.1436 11.963 73.2359 11.9752 73.2837 11.9141C73.3316 11.853 73.3194 11.7332 73.3194 11.7332C73.3194 11.7332 73.3194 11.6052 73.2599 11.5475C73.2004 11.4898 72.9696 11.4357 72.9696 11.4357C72.4595 11.3101 72.1977 11.1465 72.0819 10.8809C71.9959 10.6834 71.9867 10.1504 71.9738 9.04021V7.41256C72.0308 7.44472 72.0829 7.48119 72.138 7.51971C72.3983 7.70191 72.7244 7.93005 73.9424 7.9653C75.418 8.00801 76.3057 7.35142 76.8336 6.58882C77.3615 5.82621 77.5663 4.62811 77.179 3.3518C76.7917 2.07549 75.6552 1.30313 74.0574 1.22328C73.2246 1.18167 72.0128 1.22276 71.3357 1.25349L71.146 1.262C70.5307 1.28884 69.7934 1.34767 69.426 1.38261L69.425 1.38271C69.325 1.39222 69.3151 1.39316 69.2871 1.42867C69.2591 1.46429 69.2643 1.53106 69.2643 1.53106ZM75.2609 6.53069C75.8545 5.9727 75.8643 5.09985 75.8643 4.54224C75.806 3.66792 75.4537 1.98647 73.4581 1.98647C72.9915 1.9625 72.0369 2.04301 72.0106 2.69023C71.9816 2.80455 71.9687 3.60431 71.9761 4.8317L71.9879 6.79067L72.191 6.89765L72.202 6.90344C72.3122 6.96163 72.4552 7.03716 72.7052 7.08612C73.4986 7.24148 74.6673 7.08869 75.2609 6.53069ZM62.7751 1.33727C62.9229 1.28126 63.0203 1.24385 63.0203 1.24385C63.0203 1.24385 63.2412 1.15306 63.3126 1.24385C63.3345 1.27181 63.4146 1.47841 63.613 1.99046C63.652 2.0911 63.6956 2.20354 63.7442 2.32873C64.04 3.09094 64.4651 4.18501 64.6887 4.76001L65.6718 7.28853C65.9888 8.10422 66.3957 9.15065 66.5761 9.6139C66.7564 10.0772 66.9868 10.5589 67.0513 10.6468C67.0829 10.6899 67.1153 10.7435 67.1508 10.8023C67.29 11.033 67.4768 11.3427 67.852 11.4032C67.852 11.4032 68.1457 11.4518 68.1892 11.4978C68.2327 11.5439 68.2426 11.6275 68.2426 11.6275V11.7847C68.2426 11.7847 68.2376 11.8249 68.2134 11.859C68.1893 11.8931 68.1004 11.8837 68.1004 11.8837L65.8356 11.8838L64.2243 11.8954C64.2243 11.8954 64.1681 11.9023 64.1349 11.8748C64.1016 11.8474 64.0844 11.778 64.0844 11.778V11.6596C64.0844 11.6596 64.0705 11.5706 64.1349 11.4932C64.1992 11.4158 64.458 11.4068 64.458 11.4068C64.9457 11.3645 65.1394 10.949 65.239 10.735C65.2465 10.7191 65.2534 10.7042 65.2599 10.6907C65.3661 10.4696 65.3277 10.3256 64.8478 9.14352C64.5312 8.36338 64.4233 8.14427 64.3462 8.12482C64.2923 8.11116 63.4493 8.10611 62.473 8.11359L60.6981 8.12711L60.5919 8.41886C60.285 9.26276 60.0124 10.1011 59.9713 10.3278C59.8876 10.7889 60.0043 11.3019 60.6825 11.391C60.6825 11.391 60.934 11.4256 61.001 11.4763C61.0681 11.5269 61.0917 11.6566 61.0917 11.6566V11.7761C61.0917 11.7761 61.0789 11.833 61.0327 11.8712C60.9865 11.9095 60.8667 11.8956 60.8667 11.8956H59.1726L57.5336 11.9142C57.5336 11.9142 57.4636 11.9126 57.4119 11.8852C57.3602 11.8578 57.3519 11.8027 57.3519 11.8027V11.6892C57.3519 11.6892 57.3431 11.6154 57.4343 11.5253C57.5256 11.4351 57.772 11.411 57.772 11.411C58.22 11.3388 58.4738 10.862 58.6198 10.5875C58.6306 10.5673 58.6408 10.5481 58.6504 10.5303C58.7083 10.4234 58.9693 9.79988 59.2305 9.14464C59.4918 8.48942 59.7849 7.75638 59.882 7.51568C60.2121 6.69727 60.5258 5.91318 61.0007 4.71971C61.2615 4.06448 61.6475 3.09731 61.8585 2.57046L62.2422 1.6125L62.7751 1.33727ZM62.6353 3.6658C62.7175 3.873 62.8434 4.18479 62.9149 4.35862C62.9865 4.53246 63.1868 5.02479 63.3599 5.4527C63.5331 5.8806 63.7459 6.40133 63.8328 6.60989C63.9198 6.81849 63.9909 6.99899 63.9909 7.01105C63.9909 7.02316 63.3386 7.03303 62.5413 7.03303C61.626 7.03303 61.0917 7.01547 61.0917 6.98537C61.0917 6.95916 61.1223 6.85526 61.1598 6.75441C61.2194 6.59404 61.5169 5.74275 62.1738 3.85224C62.2752 3.56034 62.3693 3.30286 62.3828 3.28011C62.429 3.20226 62.4859 3.289 62.6353 3.6658Z" fill="black"/>
</svg>
......@@ -47,7 +47,6 @@ const HeaderRow = styled.div`
const UpperSection = styled.div`
position: relative;
background-color: ${({ theme }) => theme.bg1};
h5 {
margin: 0;
......@@ -134,6 +133,9 @@ const LowerSection = styled.div`
padding: 2rem;
flex-grow: 1;
overflow: auto;
background-color: ${({ theme }) => theme.bg2};
border-bottom-left-radius: 25px;
border-bottom-right-radius: 20px;
h5 {
margin: 0;
......
import React, { useState, useEffect } from 'react'
import styled from 'styled-components'
import { transparentize } from 'polished'
// import QR from '../../assets/svg/QR.svg'
import { isAddress } from '../../utils'
......@@ -8,14 +7,12 @@ import { useWeb3React, useDebounce } from '../../hooks'
const InputPanel = styled.div`
${({ theme }) => theme.flexColumnNoWrap}
box-shadow: 0 4px 8px 0 ${({ theme }) => transparentize(0.95, theme.shadow1)};
position: relative;
border-radius: 1.25rem;
background-color: ${({ theme }) => theme.bg1};
z-index: 1;
width: 100%;
height: 60px;
`
const ContainerRow = styled.div`
......
......@@ -77,7 +77,7 @@ export default function AdvancedSettings({ setIsOpen, setDeadline, allowedSlippa
}, [allowedSlippage, parseCustomInput])
return (
<AutoColumn gap="20px">
<AutoColumn gap="lg">
<Link
onClick={() => {
setIsOpen(false)
......
......@@ -199,7 +199,7 @@ export function ButtonError({ children, error, ...rest }) {
export function ButtonDropwdown({ disabled = false, children, ...rest }) {
return (
<ButtonPrimary {...rest}>
<ButtonPrimary {...rest} disabled={disabled}>
<RowBetween>
<div style={{ display: 'flex', alignItems: 'center' }}>{children}</div>
<ChevronDown size={24} />
......@@ -210,7 +210,7 @@ export function ButtonDropwdown({ disabled = false, children, ...rest }) {
export function ButtonDropwdownLight({ disabled = false, children, ...rest }) {
return (
<ButtonEmpty {...rest}>
<ButtonEmpty {...rest} disabled={disabled}>
<RowBetween>
<div style={{ display: 'flex', alignItems: 'center' }}>{children}</div>
<ChevronDown size={24} />
......
......@@ -5,8 +5,8 @@ import { Box } from 'rebass/styled-components'
const Card = styled(Box)`
width: 100%;
border-radius: 8px;
padding: 1rem;
border-radius: 16px;
padding: 1.25rem;
padding: ${({ padding }) => padding};
border: ${({ border }) => border};
border-radius: ${({ borderRadius }) => borderRadius};
......@@ -14,7 +14,7 @@ const Card = styled(Box)`
export default Card
export const LightCard = styled(Card)`
border: 1px solid ${({ theme }) => theme.bg3};
border: 1px solid ${({ theme }) => theme.bg2};
`
export const GreyCard = styled(Card)`
......@@ -24,27 +24,26 @@ export const GreyCard = styled(Card)`
export const YellowCard = styled(Card)`
background-color: rgba(243, 190, 30, 0.3);
color: ${({ theme }) => theme.yellow2};
fontweight: 500;
font-weight: 500;
`
export const PinkCard = styled(Card)`
background-color: rgba(255, 0, 122, 0.03);
color: ${({ theme }) => theme.pink2};
fontweight: 500;
font-weight: 500;
`
const BlueCardStyled = styled(Card)`
background-color: ${({ theme }) => theme.blue5};
color: ${({ theme }) => theme.blue1};
border-radius: 12px;
padding: 8px;
width: fit-content;
`
export const BlueCard = ({ children }) => {
return (
<BlueCardStyled>
<Text textAlign="center" fontWeight={500} color="#2172E5">
<Text fontWeight={500} color="#2172E5">
{children}
</Text>
</BlueCardStyled>
......
......@@ -13,7 +13,7 @@ export const ColumnCenter = styled(Column)`
export const AutoColumn = styled.div`
display: grid;
grid-auto-rows: auto;
grid-row-gap: ${({ gap }) => gap};
grid-row-gap: ${({ gap }) => (gap === 'sm' && '8px') || (gap === 'md' && '12px') || (gap === 'lg' && '24px') || gap};
justify-items: ${({ justify }) => justify && justify};
`
......
import React from 'react'
import styled from 'styled-components'
import { withRouter } from 'react-router-dom'
import Modal from '../Modal'
import Loader from '../Loader'
......@@ -31,7 +32,8 @@ const ConfirmedIcon = styled(ColumnCenter)`
padding: 60px 0;
`
export default function ConfirmationModal({
function ConfirmationModal({
history,
isOpen,
onDismiss,
hash,
......@@ -44,7 +46,10 @@ export default function ConfirmationModal({
}) {
const { chainId } = useWeb3React()
function WrappedOnDismissed() {
function WrappedOnDismissed(returnToPool = false) {
if (returnToPool && (history.location.pathname.match('/add') || history.location.pathname.match('/remove'))) {
history.push('/pool')
}
onDismiss()
}
......@@ -89,7 +94,7 @@ export default function ConfirmationModal({
View on Etherscan
</Text>
</Link>
<ButtonPrimary onClick={WrappedOnDismissed} style={{ margin: '20px 0' }}>
<ButtonPrimary onClick={() => WrappedOnDismissed(true)} style={{ margin: '20px 0' }}>
<Text fontWeight={500} fontSize={20}>
Close
</Text>
......@@ -109,3 +114,5 @@ export default function ConfirmationModal({
</Modal>
)
}
export default withRouter(ConfirmationModal)
import React, { useState, useEffect } from 'react'
import { withRouter } from 'react-router-dom'
import { Token, JSBI, WETH } from '@uniswap/sdk'
import Row from '../Row'
import TokenLogo from '../TokenLogo'
import SearchModal from '../SearchModal'
import AddLiquidity from '../../pages/Supply/AddLiquidity'
import { Text } from 'rebass'
import { Plus } from 'react-feather'
import { BlueCard } from '../Card'
import { TYPE, Link } from '../../theme'
import { AutoColumn, ColumnCenter } from '../Column'
import { ButtonPrimary, ButtonDropwdown, ButtonDropwdownLight } from '../Button'
import { usePair } from '../../contexts/Pairs'
import { useToken } from '../../contexts/Tokens'
import { useWeb3React } from '../../hooks'
const Fields = {
TOKEN0: 0,
TOKEN1: 1
}
function CreatePool({ history }) {
const { chainId } = useWeb3React()
const [showSearch, setShowSearch] = useState<boolean>(false)
const [activeField, setActiveField] = useState<number>(Fields.TOKEN0)
const [token0Address, setToken0Address] = useState<string>(WETH[chainId].address)
const [token1Address, setToken1Address] = useState<string>()
const token0: Token = useToken(token0Address)
const token1: Token = useToken(token1Address)
const [step, setStep] = useState<number>(1)
const pair = usePair(token0, token1)
const pairExists = // used to detect new exchange
pair && JSBI.notEqual(pair.reserve0.raw, JSBI.BigInt(0)) && JSBI.notEqual(pair.reserve1.raw, JSBI.BigInt(0))
useEffect(() => {
if (token0Address && token1Address && pair && !pairExists) {
setStep(2)
}
}, [pair, pairExists, token0Address, token1Address])
if (step === 2 && !pairExists) {
return <AddLiquidity token0={token0Address} token1={token1Address} step={true} />
} else
return (
<AutoColumn gap="20px">
<BlueCard>
<AutoColumn gap="10px">
<TYPE.blue>{'Step ' + step + '.'} </TYPE.blue>
{step === 1 && <TYPE.blue fontWeight={400}>Select or add your 2nd token to continue.</TYPE.blue>}
</AutoColumn>
</BlueCard>
<AutoColumn gap="24px">
{!token0Address ? (
<ButtonDropwdown
onClick={() => {
setShowSearch(true)
setActiveField(Fields.TOKEN0)
}}
>
<Text fontSize={20}>Select first token</Text>
</ButtonDropwdown>
) : (
<ButtonDropwdownLight
onClick={() => {
setShowSearch(true)
setActiveField(Fields.TOKEN0)
}}
>
<Row>
<TokenLogo address={token0Address} />
<Text fontWeight={500} fontSize={20} marginLeft={'12px'}>
{token0?.symbol}
</Text>
</Row>
</ButtonDropwdownLight>
)}
<ColumnCenter>
<Plus size="16" color="#888D9B" />
</ColumnCenter>
{!token1Address ? (
<ButtonDropwdown
onClick={() => {
setShowSearch(true)
setActiveField(Fields.TOKEN1)
}}
disabled={step !== 1}
>
<Text fontSize={20}>Select second token</Text>
</ButtonDropwdown>
) : (
<ButtonDropwdownLight
onClick={() => {
setShowSearch(true)
setActiveField(Fields.TOKEN1)
}}
>
<Row>
<TokenLogo address={token1Address} />
<Text fontWeight={500} fontSize={20} marginLeft={'12px'}>
{token1?.symbol}
</Text>
</Row>
</ButtonDropwdownLight>
)}
{pairExists ? (
<TYPE.body>
Pool already exists! Join the pool{' '}
<Link onClick={() => history.push('/add/' + token0Address + '-' + token1Address)}>here.</Link>
</TYPE.body>
) : (
<ButtonPrimary disabled={step !== 2}>
<Text fontWeight={500} fontSize={20}>
Create Pool
</Text>
</ButtonPrimary>
)}
</AutoColumn>
<SearchModal
isOpen={showSearch}
filterType="tokens"
onTokenSelect={address => {
activeField === Fields.TOKEN0 ? setToken0Address(address) : setToken1Address(address)
}}
onDismiss={() => {
setShowSearch(false)
}}
hiddenToken={activeField === Fields.TOKEN0 ? token1Address : token0Address}
/>
</AutoColumn>
)
}
export default withRouter(CreatePool)
......@@ -6,39 +6,36 @@ import { darken } from 'polished'
import TokenLogo from '../TokenLogo'
import DoubleLogo from '../DoubleLogo'
import SearchModal from '../SearchModal'
import { TYPE } from '../../theme'
import { Text } from 'rebass'
import { RowBetween } from '../Row'
import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg'
import { Input as NumericalInput } from '../NumericalInput'
import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg'
import { useWeb3React } from '../../hooks'
import { useTranslation } from 'react-i18next'
import { useAddressBalance } from '../../contexts/Balances'
const InputRow = styled.div`
${({ theme }) => theme.flexRowNoWrap}
align-items: center;
padding: 0.75rem 0.85rem 0.75rem;
padding: 0.75rem 0.5rem 0.75rem 1rem;
`
const CurrencySelect = styled.button`
align-items: center;
height: 2.2rem;
font-size: 20px;
font-family: 'Inter';
font-weight: 500;
background-color: ${({ selected, theme }) => (selected ? theme.bg1 : theme.blue1)};
color: ${({ selected, theme }) => (selected ? theme.text1 : theme.white)};
border-radius: 8px;
border-radius: 12px;
box-shadow: ${({ selected, theme }) => (selected ? 'none' : '0px 6px 10px rgba(0, 0, 0, 0.075)')};
/* padding: 0px; */
outline: none;
cursor: pointer;
user-select: none;
border: 1px solid ${({ selected, theme }) => (selected ? darken(0.1, theme.bg3) : darken(0.1, theme.blue1))};
border: none;
:focus,
:hover {
border: 1px solid ${({ selected, theme }) => (selected ? darken(0.2, theme.bg3) : darken(0.2, theme.blue1))};
background-color: ${({ selected, theme }) => (selected ? theme.bg2 : darken(0.05, theme.blue1))};
}
`
......@@ -49,11 +46,12 @@ const Aligner = styled.span`
`
const StyledDropDown = styled(DropDown)`
margin: 0 0.5rem 0 0.5rem;
margin: 0 0.25rem 0 0.5rem;
height: 35%;
path {
stroke: ${({ selected, theme }) => (selected ? theme.text1 : theme.white)};
stroke-width: 1.5px;
}
`
......@@ -61,45 +59,22 @@ const InputPanel = styled.div`
${({ theme }) => theme.flexColumnNoWrap}
position: relative;
border-radius: ${({ hideInput }) => (hideInput ? '8px' : '20px')};
background-color: ${({ theme }) => theme.bg1};
background-color: ${({ theme }) => theme.bg2};
z-index: 1;
`
const Container = styled.div`
border-radius: ${({ hideInput }) => (hideInput ? '8px' : '20px')};
border: 1px solid ${({ error, theme }) => (error ? theme.red1 : theme.bg2)};
background-color: ${({ theme }) => theme.bg1};
`
const LabelRow = styled.div`
${({ theme }) => theme.flexRowNoWrap}
align-items: center;
color: ${({ theme }) => theme.text3};
font-size: 0.75rem;
line-height: 1rem;
padding: 0.5rem 1rem 1rem 1rem;
span:hover {
cursor: pointer;
color: ${({ theme }) => darken(0.2, theme.text3)};
}
`
/* border: 1px solid ${({ error, theme }) => (error ? theme.red1 : theme.bg2)}; */
border: 1px solid ${({ theme }) => theme.bg2};
const ErrorSpan = styled.span`
color: ${({ error, theme }) => error && theme.red1};
:hover {
cursor: pointer;
color: ${({ error, theme }) => error && darken(0.1, theme.red1)};
}
background-color: ${({ theme }) => theme.bg1};
`
const StyledTokenName = styled.span`
margin: 0 0.25rem 0 0.75rem;
`
${({ active }) => (active ? ' margin: 0 0.25rem 0 0.75rem;' : ' margin: 0 0.25rem 0 0.25rem;')}
font-size: ${({ active }) => (active ? '20px' : '16px')};
const ClickableText = styled.div`
:hover {
cursor: pointer;
}
`
const StyledBalanceMax = styled.button`
......@@ -128,6 +103,7 @@ export default function CurrencyInputPanel({
onMax,
atMax,
error,
type = '',
urlAddedTokens = [], // used
onTokenSelection = null,
token = null,
......@@ -140,12 +116,9 @@ export default function CurrencyInputPanel({
showSendWithSwap = false
}) {
const { t } = useTranslation()
const { account } = useWeb3React()
const [modalOpen, setModalOpen] = useState(false)
const userTokenBalance = useAddressBalance(account, token)
return (
<InputPanel>
<Container error={!!error} hideInput={hideInput}>
......@@ -158,7 +131,9 @@ export default function CurrencyInputPanel({
onUserInput(field, val)
}}
/>
{!!token?.address && !atMax && <StyledBalanceMax onClick={onMax}>MAX</StyledBalanceMax>}
{!!token?.address && !atMax && type !== 'OUTPUT' && (
<StyledBalanceMax onClick={onMax}>MAX</StyledBalanceMax>
)}
{/* {renderUnlockButton()} */}
</>
)}
......@@ -182,25 +157,34 @@ export default function CurrencyInputPanel({
{pair?.token0.symbol}:{pair?.token1.symbol}
</StyledTokenName>
) : (
<StyledTokenName>{(token && token.symbol) || t('selectToken')}</StyledTokenName>
<StyledTokenName active={token && token.symbol}>
{(token && token.symbol) || t('selectToken')}
</StyledTokenName>
)}
{!disableTokenSelect && <StyledDropDown selected={!!token?.address} />}
</Aligner>
</CurrencySelect>
</InputRow>
{!hideBalance && !!token && (
{/* {!hideBalance && !!token && (
<LabelRow>
<RowBetween>
<Text>{'-'}</Text>
<Text fontSize={16} fontWeight={400}>
{'-'}
</Text>
{!!token?.address && type !== 'OUTPUT' && !atMax ? (
<MiniMax onClick={onMax}>MAX</MiniMax>
) : (
<Clear>Clear</Clear>
)}
<ErrorSpan data-tip={'Enter max'} error={!!error} onClick={() => {}}></ErrorSpan>
<ClickableText onClick={onMax}>
<ClickableText fontWeight={500} onClick={onMax}>
<TYPE.body>
Balance: {customBalance ? customBalance?.toSignificant(4) : userTokenBalance?.toSignificant(4)}
{customBalance ? customBalance?.toSignificant(4) : userTokenBalance?.toSignificant(4)} {token.symbol}
</TYPE.body>
</ClickableText>
</RowBetween>
</LabelRow>
)}
)} */}
</Container>
{!disableTokenSelect && (
<SearchModal
......
This diff is collapsed.
......@@ -3,30 +3,36 @@ import styled from 'styled-components'
import Row from '../Row'
import Menu from '../Menu'
import Logo from '../../assets/svg/logo.svg'
import Card, { YellowCard } from '../Card'
import Web3Status from '../Web3Status'
import { X } from 'react-feather'
import { Link } from '../../theme'
import { Text } from 'rebass'
import { AutoColumn } from '../Column'
import { YellowCard } from '../Card'
import Web3Status from '../Web3Status'
import { WETH } from '@uniswap/sdk'
import { isMobile } from 'react-device-detect'
import { useWeb3React } from '../../hooks'
import { useAddressBalance } from '../../contexts/Balances'
import { useWalletModalToggle, usePopups } from '../../contexts/Application'
import { useWalletModalToggle } from '../../contexts/Application'
import Logo from '../../assets/svg/logo.svg'
import Wordmark from '../../assets/svg/wordmark.svg'
const HeaderFrame = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
position: absolute;
padding: 0 10px;
width: calc(100% - 20px);
${({ theme }) => theme.mediaWidth.upToExtraSmall`
padding: 10px;
width: calc(100% - 20px);
`};
`
const HeaderElement = styled.div`
margin: 1.25rem;
display: flex;
min-width: 0;
display: flex;
......@@ -42,22 +48,22 @@ const Title = styled.div`
}
`
const TitleText = styled.div`
font-size: 24px;
font-weight: 700;
color: ${({ theme }) => theme.black};
margin-left: 12px;
const TitleText = styled(Row)`
width: fit-content;
white-space: nowrap;
${({ theme }) => theme.mediaWidth.upToExtraSmall`
display: none;
`};
`
const AccountElement = styled.div`
display: flex;
min-width: 0;
display: flex;
flex-direction: row;
align-items: center;
background-color: ${({ theme, active }) => (!active ? theme.white : theme.bg3)};
border: 1px solid ${({ theme }) => theme.bg3};
border-radius: 8px;
border-radius: 12px;
padding-left: ${({ active }) => (active ? '8px' : 0)};
white-space: nowrap;
......@@ -66,27 +72,21 @@ const AccountElement = styled.div`
}
`
const FixedPopupColumn = styled(AutoColumn)`
position: absolute;
top: 80px;
right: 20px
width: 380px;
`
const StyledClose = styled(X)`
position: absolute;
right: 10px;
const TestnetWrapper = styled.div`
white-space: nowrap;
width: fit-content;
margin-left: 10px;
:hover {
cursor: pointer;
}
${({ theme }) => theme.mediaWidth.upToSmall`
display: none;
`};
`
const Popup = styled(Card)`
z-index: 9999;
border-radius: 8px;
padding: 1rem;
background-color: white;
const NetworkCard = styled(YellowCard)`
width: fit-content;
margin-right: 10px;
border-radius: 12px;
padding: 8px 12px;
`
export default function Header() {
......@@ -95,8 +95,6 @@ export default function Header() {
const userEthBalance = useAddressBalance(account, WETH[chainId])
const toggleWalletModal = useWalletModalToggle()
const [activePopups, , removePopup] = usePopups()
return (
<HeaderFrame>
<HeaderElement>
......@@ -104,54 +102,35 @@ export default function Header() {
<Link id="link" href="https://uniswap.io">
<img src={Logo} alt="logo" />
</Link>
<Link id="link" href="https://uniswap.io">
<TitleText>Uniswap</TitleText>
</Link>
{!isMobile && (
<TitleText>
<Link id="link" href="https://uniswap.io">
<img style={{ marginLeft: '4px' }} src={Wordmark} alt="logo" />
</Link>
<p style={{ opacity: 0.6, marginLeft: '4px', fontSize: '16px' }}>{'/ Exchange'}</p>
</TitleText>
)}
</Title>
</HeaderElement>
<HeaderElement>
<TestnetWrapper>
{!isMobile && chainId === 4 && <NetworkCard>Rinkeby Testnet</NetworkCard>}
{!isMobile && chainId === 3 && <NetworkCard> Ropsten Testnet</NetworkCard>}
{!isMobile && chainId === 5 && <NetworkCard>Goerli Testnet</NetworkCard>}
{!isMobile && chainId === 42 && <NetworkCard>Kovan Testnet</NetworkCard>}
</TestnetWrapper>
<AccountElement active={!!account}>
{!isMobile && account ? (
{account ? (
<Row style={{ marginRight: '-1.25rem', paddingRight: '1.75rem' }}>
<Text fontWeight={500}> {userEthBalance && userEthBalance?.toFixed(4) + ' ETH'}</Text>
<Text fontWeight={400}> {userEthBalance && userEthBalance?.toFixed(4) + ' ETH'}</Text>
</Row>
) : (
''
)}
<Web3Status onClick={toggleWalletModal} />
</AccountElement>
{chainId === 4 && (
<YellowCard style={{ width: 'fit-content', marginLeft: '10px' }} padding={'6px'}>
Rinkeby Testnet
</YellowCard>
)}
{chainId === 3 && (
<YellowCard style={{ width: 'fit-content', marginLeft: '10px' }} padding={'6px'}>
Ropsten Testnet
</YellowCard>
)}
{chainId === 5 && (
<YellowCard style={{ width: 'fit-content', marginLeft: '10px' }} padding={'6px'}>
Goerli Testnet
</YellowCard>
)}
{chainId === 42 && (
<YellowCard style={{ width: 'fit-content', marginLeft: '10px' }} padding={'6px'}>
Kovan Testnet
</YellowCard>
)}
<Menu />
</HeaderElement>
<FixedPopupColumn gap="20px">
{activePopups.map(item => {
return (
<Popup key={item.key}>
<StyledClose color="#888D9B" onClick={() => removePopup(item.key)} />
{item.content}
</Popup>
)
})}
</FixedPopupColumn>
</HeaderFrame>
)
}
......@@ -36,8 +36,9 @@ const StyledMenuButton = styled.button`
}
svg {
width: 25px;
height: 24px;
margin-top: 2px;
/* width: 25px;
height: 24px; */
}
`
......@@ -65,11 +66,11 @@ const MenuFlyout = styled.span`
position: absolute;
top: 3rem;
right: 0rem;
z-index: 100;
`
const MenuItem = styled(Link)`
flex: 1;
/* text-align: right; */
padding: 0.5rem 0.5rem;
color: ${({ theme }) => theme.text3};
:hover {
......
......@@ -4,9 +4,10 @@ import { darken } from 'polished'
import { useTranslation } from 'react-i18next'
import { withRouter, NavLink, Link as HistoryLink } from 'react-router-dom'
import QuestionHelper from '../Question'
import { Hover } from '../../theme'
import { ArrowLeft } from 'react-feather'
import { RowBetween } from '../Row'
import QuestionHelper from '../Question'
import { useBodyKeyDown } from '../../hooks'
......@@ -31,7 +32,6 @@ const tabOrder = [
const Tabs = styled.div`
${({ theme }) => theme.flexRowNoWrap}
align-items: center;
height: 3rem;
border-radius: 3rem;
margin-bottom: 20px;
`
......@@ -44,7 +44,7 @@ const StyledNavLink = styled(NavLink).attrs({
${({ theme }) => theme.flexRowNoWrap}
align-items: center;
justify-content: center;
height: 2.5rem;
height: 3rem;
flex: 1 0 auto;
border-radius: 3rem;
outline: none;
......@@ -55,7 +55,7 @@ const StyledNavLink = styled(NavLink).attrs({
box-sizing: border-box;
&.${activeClassName} {
border-radius: 3rem;
border-radius: 12px;
box-sizing: border-box;
font-weight: 500;
color: ${({ theme }) => theme.black};
......@@ -99,15 +99,16 @@ function NavigationTabs({ location: { pathname }, history }) {
const adding = pathname.match('/add')
const removing = pathname.match('/remove')
const finding = pathname.match('/find')
const creating = pathname.match('/create')
return (
<>
{adding || removing ? (
<Tabs>
<RowBetween style={{ padding: '1rem' }}>
<HistoryLink to="/pool">
<Hover onClick={() => history.goBack()}>
<ArrowLink />
</HistoryLink>
</Hover>
<ActiveText>{adding ? 'Add' : 'Remove'} Liquidity</ActiveText>
<QuestionHelper text={'helper text'} />
</RowBetween>
......@@ -118,7 +119,17 @@ function NavigationTabs({ location: { pathname }, history }) {
<HistoryLink to="/pool">
<ArrowLink />
</HistoryLink>
<ActiveText>Find a Pool</ActiveText>
<ActiveText>Import Pool</ActiveText>
<QuestionHelper text={'helper text'} />
</RowBetween>
</Tabs>
) : creating ? (
<Tabs>
<RowBetween style={{ padding: '1rem' }}>
<HistoryLink to="/pool">
<ArrowLink />
</HistoryLink>
<ActiveText>Create Pool</ActiveText>
<QuestionHelper text={'helper text'} />
</RowBetween>
</Tabs>
......
......@@ -3,10 +3,11 @@ import styled from 'styled-components'
const StyledInput = styled.input`
color: ${({ error, theme }) => error && theme.red1};
background-color: ${({ theme }) => theme.bg1};
color: ${({ theme }) => theme.text1};
width: 0;
font-size: 20px;
font-size: 24px;
font-weight: 500;
font-family: 'Inter', sans-serif;
outline: none;
border: none;
flex: 1 1 auto;
......
import React, { useState } from 'react'
import React, { useState, useEffect } from 'react'
import { withRouter } from 'react-router-dom'
import { TokenAmount, JSBI, Token, Pair } from '@uniswap/sdk'
......@@ -14,11 +14,12 @@ import { LightCard } from '../Card'
import { AutoColumn, ColumnCenter } from '../Column'
import { ButtonPrimary, ButtonDropwdown, ButtonDropwdownLight } from '../Button'
import { usePair } from '../../contexts/Pairs'
import { useToken } from '../../contexts/Tokens'
import { usePopups } from '../../contexts/Application'
import { usePrevious } from '../../hooks'
import { useWeb3React } from '@web3-react/core'
import { useAddressBalance } from '../../contexts/Balances'
import { usePair, useAllPairs } from '../../contexts/Pairs'
function PoolFinder({ history }) {
const Fields = {
......@@ -44,21 +45,45 @@ function PoolFinder({ history }) {
const newPair: boolean = pair && JSBI.equal(pair.reserve0.raw, JSBI.BigInt(0))
const allowImport: boolean = position && JSBI.greaterThan(position.raw, JSBI.BigInt(0))
const allPairs = useAllPairs()
const pairCount = Object.keys(allPairs)?.length
const pairCountPrevious = usePrevious(pairCount)
const [newLiquidity, setNewLiquidity] = useState<boolean>(false) // check for unimported pair
// use previous ref to detect new pair added
useEffect(() => {
if (pairCount !== pairCountPrevious && pairCountPrevious) {
setNewLiquidity(true)
}
}, [pairCount, pairCountPrevious])
// reset the watcher if tokens change
useEffect(() => {
setNewLiquidity(false)
}, [token0, token1])
function endSearch() {
history.goBack() // return to previous page
addPopup(
<Row>
<DoubleTokenLogo a0={token0Address || ''} a1={token1Address || ''} margin={true} />
<Text color="grey">
UNI {token0?.symbol} / {token1?.symbol} pool imported.
</Text>
</Row>
)
newLiquidity &&
addPopup(
<AutoColumn gap={'10px'}>
<Text fontSize={20} fontWeight={500}>
Pool Imported
</Text>
<Row>
<DoubleTokenLogo a0={token0Address || ''} a1={token1Address || ''} margin={true} />
<Text fontSize={16} fotnWeight={500}>
UNI {token0?.symbol} / {token1?.symbol}
</Text>
</Row>
<Link>View on Uniswap Info.</Link>
</AutoColumn>
)
}
return (
<>
<AutoColumn gap="24px">
<AutoColumn gap="md">
{!token0Address ? (
<ButtonDropwdown
onClick={() => {
......@@ -111,9 +136,12 @@ function PoolFinder({ history }) {
</ButtonDropwdownLight>
)}
{allowImport && (
<ColumnCenter justify="center" style={{ backgroundColor: '#EBF4FF', padding: '8px', borderRadius: '12px' }}>
<ColumnCenter
justify="center"
style={{ backgroundColor: '#EBF4FF', padding: '12px 0px', borderRadius: '12px' }}
>
<Text textAlign="center" fontWeight={500} color="#2172E5">
Liquidity Found!
{newLiquidity ? 'Pool Found!' : 'Pool already imported.'}
</Text>
</ColumnCenter>
)}
......@@ -128,7 +156,7 @@ function PoolFinder({ history }) {
/>
) : (
<LightCard padding="45px">
<AutoColumn gap="8px" justify="center">
<AutoColumn gap="sm" justify="center">
<Text color="">No position found.</Text>
<Link
onClick={() => {
......@@ -142,14 +170,14 @@ function PoolFinder({ history }) {
)
) : newPair ? (
<LightCard padding="45px">
<AutoColumn gap="8px" justify="center">
<Text color="">No exchange found.</Text>
<AutoColumn gap="sm" justify="center">
<Text color="">No pool found.</Text>
<Link
onClick={() => {
history.push('/add/' + token0Address + '-' + token1Address)
}}
>
Create exchange instead.
Create pool instead.
</Link>
</AutoColumn>
</LightCard>
......@@ -163,7 +191,7 @@ function PoolFinder({ history }) {
<ButtonPrimary disabled={!allowImport} onClick={endSearch}>
<Text fontWeight={500} fontSize={20}>
Import
{newLiquidity ? 'Import' : 'Close'}
</Text>
</ButtonPrimary>
</AutoColumn>
......
import React from 'react'
import styled from 'styled-components'
import { useMediaLayout } from 'use-media'
import { X } from 'react-feather'
import { Text } from 'rebass'
import { TYPE } from '../../theme'
import { Hover } from '../../theme/components'
import { PinkCard } from '../Card'
import { ButtonPink } from '../Button'
import { usePopups } from '../../contexts/Application'
import { AutoColumn } from '../Column'
import { useMigrationMessageManager } from '../../contexts/LocalStorage'
const StyledClose = styled(X)`
position: absolute;
right: 10px;
top: 10px;
:hover {
cursor: pointer;
}
`
const MobilePopupWrapper = styled.div`
position: relative;
max-width: 100%;
height: ${({ height }) => height}
margin: ${({ height }) => (height ? '0 auto;' : 0)}
margin-bottom: ${({ height }) => (height ? '20px' : 0)}}
`
const MobilePopupInner = styled.div`
height: 99%;
box-sizing: border-box;
white-space: nowrap;
overflow-x: auto;
overflow-y: hidden;
display: flex;
flex-direction: row;
-webkit-overflow-scrolling: touch;
::-webkit-scrollbar {
display: none;
}
`
const FixedPopupColumn = styled(AutoColumn)`
position: absolute;
top: 80px;
right: 20px
width: 380px;
${({ theme }) => theme.mediaWidth.upToSmall`
display: none;
`};
`
const Popup = styled.div`
display: inline-block;
width: 100%;
height: 120px;
padding: 1em;
box-sizing: border-box;
background-color: white;
margin: 0 10px;
position: relative;
border-radius: 10px;
padding: 20px;
padding-right: 35px;
whitespace: normal;
${({ theme }) => theme.mediaWidth.upToSmall`
min-width: 290px;
`}
`
const MobileCardPink = styled(PinkCard)`
z-index: 2;
padding: 20px;
white-space: normal;
`
export default function App() {
// get all popups
const [activePopups, , removePopup] = usePopups()
// local storage reference to show message
const [showMessage, hideMigrationMessage] = useMigrationMessageManager()
// switch view settings on mobile
const isMobile = useMediaLayout({ maxWidth: '600px' })
if (!isMobile) {
return (
<FixedPopupColumn gap="20px">
{activePopups.map(item => {
return (
<Popup key={item.key}>
<StyledClose color="#888D9B" onClick={() => removePopup(item.key)} />
{item.content}
</Popup>
)
})}
{showMessage && (
<PinkCard padding="20px" style={{ zIndex: '2' }}>
<AutoColumn justify={'center'} gap={'20px'}>
<TYPE.largeHeader>Uniswap has upgraded.</TYPE.largeHeader>
<Text textAlign="center">Are you a liquidity provider? Upgrade now using the migration helper.</Text>
<ButtonPink width={'265px'}>Migrate your liquidity </ButtonPink>
<Hover onClick={() => hideMigrationMessage()}>
<Text textAlign="center">Dismiss</Text>
</Hover>
</AutoColumn>
</PinkCard>
)}
</FixedPopupColumn>
)
}
//mobile
else
return (
<MobilePopupWrapper height={activePopups?.length > 0 || showMessage ? 'fit-content' : 0}>
<MobilePopupInner>
{activePopups // reverse so new items up front
.slice(0)
.reverse()
.map(item => {
return (
<Popup key={item.key}>
<StyledClose color="#888D9B" onClick={() => removePopup(item.key)} />
{item.content}
</Popup>
)
})}
{showMessage && (
<MobileCardPink>
<AutoColumn justify={'center'} gap={'20px'}>
<Text>Uniswap has upgraded.</Text>
<Text textAlign="center">Are you a liquidity provider? Upgrade now using the migration helper.</Text>
<ButtonPink width={'265px'}>Migrate your liquidity </ButtonPink>
<Hover onClick={() => hideMigrationMessage()}>
<Text textAlign="center">Dismiss</Text>
</Hover>
</AutoColumn>
</MobileCardPink>
)}
</MobilePopupInner>
</MobilePopupWrapper>
)
}
......@@ -51,27 +51,32 @@ function PositionCard({ pairAddress, token0, token1, history, minimal = false, .
token0 &&
totalPoolTokens &&
userPoolBalance &&
pair &&
totalPoolTokens &&
pair.liquidityToken.equals(totalPoolTokens.token) &&
pair.getLiquidityValue(token0, totalPoolTokens, userPoolBalance, false)
const token1Deposited =
token1 &&
totalPoolTokens &&
userPoolBalance &&
totalPoolTokens &&
pair.liquidityToken.equals(totalPoolTokens.token) &&
pair.getLiquidityValue(token1, totalPoolTokens, userPoolBalance, false)
if (minimal) {
return (
<GreyCard {...rest}>
<AutoColumn gap="20px">
<AutoColumn gap="12px">
<FixedHeightRow>
<RowFixed>
<Text fontWeight={500} fontSize={20}>
Current Position
<Text fontWeight={500} fontSize={16}>
Your current position
</Text>
</RowFixed>
</FixedHeightRow>
<FixedHeightRow onClick={() => setShowMore(!showMore)}>
<RowFixed>
<DoubleLogo a0={token0?.address || ''} a1={token1?.address || ''} margin={true} size={24} />
<DoubleLogo a0={token0?.address || ''} a1={token1?.address || ''} margin={true} size={20} />
<Text fontWeight={500} fontSize={20}>
{token0?.symbol}:{token1?.symbol}
</Text>
......@@ -82,15 +87,15 @@ function PositionCard({ pairAddress, token0, token1, history, minimal = false, .
</Text>
</RowFixed>
</FixedHeightRow>
<AutoColumn gap="12px">
<AutoColumn gap="4px">
<FixedHeightRow>
<Text color="#888D9B" fontSize={16} fontWeight={500}>
<Text color="#888D9B" fontSize={14} fontWeight={500}>
{token0?.symbol}:
</Text>
{token0Deposited ? (
<RowFixed>
{!minimal && <TokenLogo address={token0?.address || ''} />}
<Text color="#888D9B" fontSize={16} fontWeight={500} marginLeft={'6px'}>
<Text color="#888D9B" fontSize={14} fontWeight={500} marginLeft={'6px'}>
{token0Deposited?.toFixed(8)}
</Text>
</RowFixed>
......@@ -99,13 +104,13 @@ function PositionCard({ pairAddress, token0, token1, history, minimal = false, .
)}
</FixedHeightRow>
<FixedHeightRow>
<Text color="#888D9B" fontSize={16} fontWeight={500}>
<Text color="#888D9B" fontSize={14} fontWeight={500}>
{token1?.symbol}:
</Text>
{token1Deposited ? (
<RowFixed>
{!minimal && <TokenLogo address={token1?.address || ''} />}
<Text color="#888D9B" fontSize={16} fontWeight={500} marginLeft={'6px'}>
<Text color="#888D9B" fontSize={14} fontWeight={500} marginLeft={'6px'}>
{token1Deposited?.toFixed(8)}
</Text>
</RowFixed>
......@@ -120,10 +125,10 @@ function PositionCard({ pairAddress, token0, token1, history, minimal = false, .
} else
return (
<HoverCard {...rest} onClick={() => setShowMore(!showMore)}>
<AutoColumn gap="20px">
<AutoColumn gap="12px">
<FixedHeightRow>
<RowFixed>
<DoubleLogo a0={token0?.address || ''} a1={token1?.address || ''} margin={true} size={24} />
<DoubleLogo a0={token0?.address || ''} a1={token1?.address || ''} margin={true} size={20} />
<Text fontWeight={500} fontSize={20}>
{token0?.symbol}:{token1?.symbol}
</Text>
......@@ -140,15 +145,18 @@ function PositionCard({ pairAddress, token0, token1, history, minimal = false, .
</RowFixed>
</FixedHeightRow>
{showMore && (
<AutoColumn gap="12px">
<AutoColumn gap="4px">
<FixedHeightRow>
<Text color="#888D9B" fontSize={16} fontWeight={500}>
{token0?.symbol}:
</Text>
<RowFixed>
{!minimal && <TokenLogo size="16px" style={{ marginRight: '4px' }} address={token0?.address || ''} />}
<Text color="#888D9B" fontSize={14} fontWeight={500}>
{token0?.symbol}:
</Text>
</RowFixed>
{token0Deposited ? (
<RowFixed>
{!minimal && <TokenLogo address={token0?.address || ''} />}
<Text color="#888D9B" fontSize={16} fontWeight={500} marginLeft={'6px'}>
<Text color="#888D9B" fontSize={14} fontWeight={500} marginLeft={'6px'}>
{token0Deposited?.toFixed(8)}
</Text>
</RowFixed>
......@@ -157,26 +165,26 @@ function PositionCard({ pairAddress, token0, token1, history, minimal = false, .
)}
</FixedHeightRow>
<FixedHeightRow>
<Text color="#888D9B" fontSize={16} fontWeight={500}>
{token1?.symbol}:
</Text>
<RowFixed>
{!minimal && <TokenLogo size="16px" style={{ marginRight: '4px' }} address={token1?.address || ''} />}
<Text color="#888D9B" fontSize={14} fontWeight={500}>
{token1?.symbol}:
</Text>
</RowFixed>
{token1Deposited ? (
<RowFixed>
{!minimal && <TokenLogo address={token1?.address || ''} />}
<Text color="#888D9B" fontSize={16} fontWeight={500} marginLeft={'6px'}>
{token1Deposited?.toFixed(8)}
</Text>
</RowFixed>
<Text color="#888D9B" fontSize={14} fontWeight={500} marginLeft={'6px'}>
{token1Deposited?.toFixed(8)}
</Text>
) : (
'-'
)}
</FixedHeightRow>
{!minimal && (
<FixedHeightRow>
<Text color="#888D9B" fontSize={16} fontWeight={500}>
<Text color="#888D9B" fontSize={14} fontWeight={500}>
Your pool share:
</Text>
<Text color="#888D9B" fontSize={16} fontWeight={500}>
<Text color="#888D9B" fontSize={14} fontWeight={500}>
{poolTokenPercentage ? poolTokenPercentage.toFixed(2) + '%' : '-'}
</Text>
</FixedHeightRow>
......
import styled from 'styled-components'
import { Box } from 'rebass/styled-components'
const Row = styled.div`
const Row = styled(Box)`
width: 100%;
display: flex;
padding: 0;
align-items: center;
align-items: ${({ align }) => align && align};
padding: ${({ padding }) => padding};
border: ${({ border }) => border};
border-radius: ${({ borderRadius }) => borderRadius};
`
export const RowBetween = styled(Row)`
......@@ -19,6 +24,7 @@ export const RowFlat = styled.div`
export const AutoRow = styled(Row)`
flex-wrap: wrap;
margin: -${({ gap }) => gap};
justify-content: ${({ justify }) => justify && justify};
& > * {
margin: ${({ gap }) => gap} !important;
......
......@@ -9,20 +9,25 @@ import { isMobile } from 'react-device-detect'
import { withRouter } from 'react-router-dom'
import { Link as StyledLink } from '../../theme/components'
import { Hover } from '../../theme'
import Modal from '../Modal'
import Circle from '../../assets/images/circle.svg'
import TokenLogo from '../TokenLogo'
import DoubleTokenLogo from '../DoubleLogo'
import Column, { AutoColumn } from '../Column'
import { Text } from 'rebass'
import { Spinner } from '../../theme'
import { LightCard } from '../Card'
import { ArrowLeft } from 'react-feather'
import { CloseIcon } from '../../theme/components'
import { ColumnCenter } from '../../components/Column'
import { Spinner, TYPE } from '../../theme'
import { ButtonSecondary } from '../Button'
import { RowBetween, RowFixed } from '../Row'
import { isAddress } from '../../utils'
import { useAllPairs } from '../../contexts/Pairs'
import { useWeb3React } from '../../hooks'
import { useSavedTokens } from '../../contexts/LocalStorage'
import { useAllBalances } from '../../contexts/Balances'
import { useTranslation } from 'react-i18next'
import { useToken, useAllTokens, INITIAL_TOKENS_CONTEXT } from '../../contexts/Tokens'
......@@ -100,7 +105,7 @@ const PaddedColumn = styled(AutoColumn)`
const PaddedItem = styled(RowBetween)`
padding: 4px 24px;
width: calc(100% - 48px);
/* width: calc(100% - 48px); */
height: 56px;
`
......@@ -148,6 +153,17 @@ function SearchModal({
const [activeFilter, setActiveFilter] = useState(FILTERS.BALANCES)
const [showTokenImport, setShowTokenImport] = useState(false)
const [, saveUserToken] = useSavedTokens()
// reset view on close
useEffect(() => {
if (!isOpen) {
setShowTokenImport(false)
}
}, [isOpen])
const tokenList = useMemo(() => {
return Object.keys(allTokens)
.sort((a, b) => {
......@@ -188,23 +204,35 @@ function SearchModal({
const filteredTokenList = useMemo(() => {
return tokenList.filter(tokenEntry => {
const urlAdded = urlAddedTokens && urlAddedTokens.hasOwnProperty(tokenEntry.address)
const customAdded =
tokenEntry.address !== 'ETH' &&
INITIAL_TOKENS_CONTEXT[chainId] &&
!INITIAL_TOKENS_CONTEXT[chainId].hasOwnProperty(tokenEntry.address) &&
!urlAdded
// if token import page dont show preset list, else show all
const include = !showTokenImport || (showTokenImport && customAdded && searchQuery !== '')
const inputIsAddress = searchQuery.slice(0, 2) === '0x'
const regexMatches = Object.keys(tokenEntry).map(tokenEntryKey => {
if (tokenEntryKey === 'address') {
return (
include &&
inputIsAddress &&
typeof tokenEntry[tokenEntryKey] === 'string' &&
!!tokenEntry[tokenEntryKey].match(new RegExp(escapeStringRegex(searchQuery), 'i'))
)
}
return (
include &&
typeof tokenEntry[tokenEntryKey] === 'string' &&
!!tokenEntry[tokenEntryKey].match(new RegExp(escapeStringRegex(searchQuery), 'i'))
)
})
return regexMatches.some(m => m)
})
}, [tokenList, searchQuery])
}, [tokenList, urlAddedTokens, chainId, showTokenImport, searchQuery])
function _onTokenSelect(address) {
setSearchQuery('')
......@@ -334,6 +362,7 @@ function SearchModal({
</>
)
}
if (!filteredTokenList.length) {
return <TokenModalInfo>{t('noToken')}</TokenModalInfo>
}
......@@ -348,16 +377,11 @@ function SearchModal({
const zeroBalance = balance && JSBI.equal(JSBI.BigInt(0), balance.raw)
// if token import page dont show preset list, else show all
return (
<MenuItem
key={address}
onClick={() =>
hiddenToken && hiddenToken === address
? () => {}
: zeroBalance
? _onTokenSelect(address, true)
: _onTokenSelect(address)
}
onClick={() => (hiddenToken && hiddenToken === address ? () => {} : _onTokenSelect(address))}
disabled={hiddenToken && hiddenToken === address}
>
<RowFixed>
......@@ -428,42 +452,108 @@ function SearchModal({
initialFocusRef={isMobile ? undefined : inputRef}
>
<TokenModal>
<PaddedColumn gap="20px">
<RowBetween>
<Text fontWeight={500} fontSize={16}>
{filterType === 'tokens' ? 'Select A Token' : 'Select A Pool'}
</Text>
<CloseIcon onClick={onDismiss} />
</RowBetween>
<Input
type={'text'}
placeholder={t('tokenSearchPlaceholder')}
value={searchQuery}
ref={inputRef}
onChange={onInput}
/>
<RowBetween>
<div>
{filterType !== 'tokens' && (
<Text>
Don't see a pool?{' '}
<StyledLink
{showTokenImport ? (
<PaddedColumn gap="20px">
<RowBetween>
<RowFixed>
<Hover>
<ArrowLeft
onClick={() => {
history.push('/find')
setShowTokenImport(false)
}}
>
Import it.
</StyledLink>
/>
</Hover>
<Text fontWeight={500} fontSize={16} marginLeft={'10px'}>
Import A Token
</Text>
</RowFixed>
<CloseIcon onClick={onDismiss} />
</RowBetween>
<TYPE.body style={{ marginTop: '40px' }}>
To import a custom token, paste the token address in the search bar.
</TYPE.body>
<Input
type={'text'}
placeholder={t('tokenSearchPlaceholder')}
value={searchQuery}
ref={inputRef}
onChange={onInput}
/>
<LightCard padding={filteredTokenList?.length === 0 ? '20px' : '0px'}>
{filteredTokenList?.length === 0 ? (
<AutoColumn gap="8px" justify="center">
<TYPE.body color="">No token found.</TYPE.body>
</AutoColumn>
) : (
renderTokenList()
)}
{filterType === 'tokens' && <Text>Token Symbol</Text>}
</div>
<div />
<Filter title="Your Balances" filter={FILTERS.BALANCES} />
</RowBetween>
</PaddedColumn>
<div style={{ width: '100%', height: '1px', backgroundColor: '#E1E1E1' }} />
<TokenList>{filterType === 'tokens' ? renderTokenList() : renderPairsList()}</TokenList>
</LightCard>
{filteredTokenList?.length > 0 && (
<RowBetween>
<ButtonSecondary
width="48%"
onClick={() => {
const newToken = filteredTokenList?.[0]
saveUserToken(newToken?.address)
}}
>
Save To Your List
</ButtonSecondary>
<ButtonSecondary width="48%" onClick={() => _onTokenSelect(filteredTokenList[0].address)}>
Import
</ButtonSecondary>
</RowBetween>
)}
</PaddedColumn>
) : (
<PaddedColumn gap="20px">
<RowBetween>
<Text fontWeight={500} fontSize={16}>
{filterType === 'tokens' ? 'Select A Token' : 'Select A Pool'}
</Text>
<CloseIcon onClick={onDismiss} />
</RowBetween>
<Input
type={'text'}
placeholder={t('tokenSearchPlaceholder')}
value={searchQuery}
ref={inputRef}
onChange={onInput}
/>
<RowBetween>
<div>
{filterType !== 'tokens' && (
<Text fontWeight={500}>
{!isMobile && 'Dont see a pool? '}
<StyledLink
onClick={() => {
history.push('/find')
}}
>
{!isMobile ? 'Import it.' : 'Import pool.'}
</StyledLink>
</Text>
)}
{filterType === 'tokens' && (
<Text fontWeight={500}>
{!isMobile && 'Dont see a token? '}
<StyledLink
onClick={() => {
setShowTokenImport(true)
}}
>
{!isMobile ? 'Import it.' : 'Import custom token.'}
</StyledLink>
</Text>
)}
</div>
<div />
<Filter title="Your Balances" filter={FILTERS.BALANCES} />
</RowBetween>
</PaddedColumn>
)}
{!showTokenImport && <div style={{ width: '100%', height: '1px', backgroundColor: '#E1E1E1' }} />}
{!showTokenImport && <TokenList>{filterType === 'tokens' ? renderTokenList() : renderPairsList()}</TokenList>}
</TokenModal>
</Modal>
)
......
......@@ -17,6 +17,7 @@ const Image = styled.img`
height: ${({ size }) => size};
background-color: white;
border-radius: 1rem;
box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.075);
`
const Emoji = styled.span`
......
......@@ -39,7 +39,6 @@ const Wrapper = styled.div`
margin: 0;
padding: 0;
width: 100%;
background-color: ${({ theme }) => theme.bg2};
`
const HeaderRow = styled.div`
......@@ -55,12 +54,14 @@ const HeaderRow = styled.div`
const ContentWrapper = styled.div`
background-color: ${({ theme }) => theme.bg2};
padding: 2rem;
border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px;
${({ theme }) => theme.mediaWidth.upToMedium`padding: 1rem`};
`
const UpperSection = styled.div`
position: relative;
background-color: ${({ theme }) => theme.bg1};
h5 {
margin: 0;
......
......@@ -2,7 +2,7 @@ import React from 'react'
import styled, { css } from 'styled-components'
import { useTranslation } from 'react-i18next'
import { useWeb3React, UnsupportedChainIdError } from '@web3-react/core'
import { darken } from 'polished'
import { darken, lighten } from 'polished'
import { Activity } from 'react-feather'
import { shortenAddress } from '../../utils'
......@@ -21,10 +21,10 @@ import Identicon from '../Identicon'
const Web3StatusGeneric = styled.button`
${({ theme }) => theme.flexRowNoWrap}
width: 100%;
font-size: 0.9rem;
/* font-size: 0.9rem; */
align-items: center;
padding: 0.5rem;
border-radius: 10px;
border-radius: 12px;
box-sizing: border-box;
cursor: pointer;
user-select: none;
......@@ -72,12 +72,12 @@ const Web3StatusConnect = styled(Web3StatusGeneric)`
`
const Web3StatusConnected = styled(Web3StatusGeneric)`
background-color: ${({ pending, theme }) => (pending ? theme.blue1 : theme.bg1)};
background-color: ${({ pending, theme }) => (pending ? theme.blue1 : theme.bg2)};
border: 1px solid ${({ pending, theme }) => (pending ? theme.blue1 : theme.bg3)};
color: ${({ pending, theme }) => (pending ? theme.white : theme.text3)};
font-weight: 400;
color: ${({ pending, theme }) => (pending ? theme.white : theme.text1)};
font-weight: 500;
:hover {
background-color: ${({ pending, theme }) => (pending ? darken(0.05, theme.blue1) : darken(0.05, theme.bg1))};
background-color: ${({ pending, theme }) => (pending ? darken(0.05, theme.blue1) : lighten(0.05, theme.bg2))};
:focus {
border: 1px solid ${({ pending, theme }) => (pending ? darken(0.1, theme.blue1) : darken(0.1, theme.bg3))};
......@@ -91,7 +91,7 @@ const Text = styled.p`
text-overflow: ellipsis;
white-space: nowrap;
margin: 0 0.5rem 0 0.25rem;
font-size: 0.83rem;
font-size: 1rem;
width: fit-content;
font-weight: 500;
`
......
import React, { createContext, useContext, useReducer, useMemo, useCallback, useEffect, useState } from 'react'
import React, { createContext, useContext, useReducer, useMemo, useCallback, useEffect } from 'react'
import { useWeb3React } from '../hooks'
import { safeAccess } from '../utils'
......@@ -7,6 +7,7 @@ const BLOCK_NUMBER = 'BLOCK_NUMBER'
const USD_PRICE = 'USD_PRICE'
const WALLET_MODAL_OPEN = 'WALLET_MODAL_OPEN'
const POPUP_LIST = 'POPUP_LIST'
const POPUP_KEY = 'POPUP_KEY'
const UPDATE_BLOCK_NUMBER = 'UPDATE_BLOCK_NUMBER'
const TOGGLE_WALLET_MODAL = 'TOGGLE_WALLET_MODAL'
......@@ -38,7 +39,7 @@ function reducer(state, { type, payload }) {
case ADD_POPUP: {
const { newList } = payload
return { ...state, [POPUP_LIST]: newList }
return { ...state, [POPUP_LIST]: newList, [POPUP_KEY]: state?.[POPUP_KEY] + 1 }
}
default: {
......@@ -52,6 +53,7 @@ export default function Provider({ children }) {
[BLOCK_NUMBER]: {},
[USD_PRICE]: {},
[POPUP_LIST]: [],
[POPUP_KEY]: 0,
[WALLET_MODAL_OPEN]: false
})
......@@ -142,8 +144,7 @@ export function useWalletModalToggle() {
export function usePopups() {
const [state, { setPopups }] = useApplicationContext()
const [index, setIndex] = useState(0)
const index = state[POPUP_KEY]
const currentPopups = state[POPUP_LIST]
function addPopup(content) {
......@@ -154,7 +155,6 @@ export function usePopups() {
}
currentPopups.push(newItem)
setPopups(currentPopups)
setIndex(index + 1)
}
function removePopup(key) {
......
import React, { createContext, useContext, useReducer, useMemo, useCallback, useEffect } from 'react'
import { useAllTokens } from './Tokens'
const UNISWAP = 'UNISWAP'
......@@ -7,12 +8,16 @@ const CURRENT_VERSION = 0
const LAST_SAVED = 'LAST_SAVED'
const BETA_MESSAGE_DISMISSED = 'BETA_MESSAGE_DISMISSED'
const MIGRATION_MESSAGE_DISMISSED = 'MIGRATION_MESSAGE_DISMISSED'
const DARK_MODE = 'DARK_MODE'
const TOKEN_LIST = 'TOKEN_LIST'
const UPDATABLE_KEYS = [BETA_MESSAGE_DISMISSED, DARK_MODE]
const UPDATABLE_KEYS = [BETA_MESSAGE_DISMISSED, MIGRATION_MESSAGE_DISMISSED, DARK_MODE]
const UPDATE_KEY = 'UPDATE_KEY'
const UPDATE_TOKEN_LIST = 'UPDATE_TOKEN_LIST'
const LocalStorageContext = createContext()
function useLocalStorageContext() {
......@@ -32,6 +37,16 @@ function reducer(state, { type, payload }) {
}
}
}
case UPDATE_TOKEN_LIST: {
const { tokenAddress, token } = payload
return {
...state,
[TOKEN_LIST]: {
...state?.[TOKEN_LIST],
[tokenAddress]: token
}
}
}
default: {
throw Error(`Unexpected action type in LocalStorageContext reducer: '${type}'.`)
}
......@@ -42,6 +57,7 @@ function init() {
const defaultLocalStorage = {
[VERSION]: CURRENT_VERSION,
[BETA_MESSAGE_DISMISSED]: false,
[MIGRATION_MESSAGE_DISMISSED]: false,
[DARK_MODE]: false
}
......@@ -65,8 +81,14 @@ export default function Provider({ children }) {
dispatch({ type: UPDATE_KEY, payload: { key, value } })
}, [])
const updateTokenList = useCallback((tokenAddress, token) => {
dispatch({ type: UPDATE_TOKEN_LIST, payload: { tokenAddress, token } })
}, [])
return (
<LocalStorageContext.Provider value={useMemo(() => [state, { updateKey }], [state, updateKey])}>
<LocalStorageContext.Provider
value={useMemo(() => [state, { updateKey, updateTokenList }], [state, updateKey, updateTokenList])}
>
{children}
</LocalStorageContext.Provider>
)
......@@ -92,6 +114,16 @@ export function useBetaMessageManager() {
return [!state[BETA_MESSAGE_DISMISSED], dismissBetaMessage]
}
export function useMigrationMessageManager() {
const [state, { updateKey }] = useLocalStorageContext()
const dismissMigrationMessage = useCallback(() => {
updateKey(MIGRATION_MESSAGE_DISMISSED, true)
}, [updateKey])
return [!state[MIGRATION_MESSAGE_DISMISSED], dismissMigrationMessage]
}
export function useDarkModeManager() {
const [state, { updateKey }] = useLocalStorageContext()
......@@ -106,3 +138,20 @@ export function useDarkModeManager() {
return [state[DARK_MODE], toggleDarkMode]
}
/**
* @todo is there a better place to store these? should we move into tokens context
*/
export function useSavedTokens() {
const [state, { updateTokenList }] = useLocalStorageContext()
const allTokens = useAllTokens()
const userList = state?.[TOKEN_LIST] || []
function addToken(tokenAddress) {
const token = allTokens?.[tokenAddress]
if (token) {
updateTokenList(token.address, token)
}
}
return [userList, addToken]
}
......@@ -4,6 +4,9 @@ import { useWeb3React, usePairContract } from '../hooks'
import { INITIAL_TOKENS_CONTEXT } from './Tokens'
import { ChainId, WETH, Token, TokenAmount, Pair, JSBI } from '@uniswap/sdk'
const ADDRESSES_KEY = 'ADDRESSES_KEY'
const ENTITIES_KEY = 'ENTITIES_KEY'
const UPDATE = 'UPDATE'
const UPDATE_PAIR_ENTITY = 'UPDATE_PAIR_ENTITY'
......@@ -29,14 +32,14 @@ const PAIR_MAP: {
...pairMap,
[tokens[0].chainId]: {
...pairMap?.[tokens[0].chainId],
addresses: {
...pairMap?.[tokens[0].chainId]?.['addresses'],
[ADDRESSES_KEY]: {
...pairMap?.[tokens[0].chainId]?.[ADDRESSES_KEY],
[tokens[0].address]: {
...pairMap?.[tokens[0].chainId]?.[tokens[0].address],
...pairMap?.[tokens[0].chainId]?.[ADDRESSES_KEY]?.[tokens[0].address],
[tokens[1].address]: Pair.getAddress(...tokens)
}
},
entities: {}
[ENTITIES_KEY]: {}
}
}
}, {})
......@@ -58,10 +61,10 @@ function reducer(state, { type, payload }) {
...state,
[tokensSorted[0].chainId]: {
...state?.[tokensSorted[0].chainId],
addresses: {
...state?.[tokensSorted[0].chainId]['addresses'],
[ADDRESSES_KEY]: {
...state?.[tokensSorted[0].chainId]?.[ADDRESSES_KEY],
[tokensSorted[0].address]: {
...state?.[tokensSorted[0].chainId]?.[tokensSorted[0].address],
...state?.[tokensSorted[0].chainId]?.[ADDRESSES_KEY]?.[tokensSorted[0].address],
[tokensSorted[1].address]: Pair.getAddress(tokensSorted[0], tokensSorted[1])
}
}
......@@ -74,8 +77,8 @@ function reducer(state, { type, payload }) {
...state,
[chainId]: {
...state?.[chainId],
entities: {
...state?.[chainId]?.['entities'],
[ENTITIES_KEY]: {
...state?.[chainId]?.[ENTITIES_KEY],
[pairAddress]: pair
}
}
......@@ -113,7 +116,7 @@ export function usePairAddress(tokenA?: Token, tokenB?: Token): string | undefin
const tokens: [Token, Token] = tokenA && tokenB && tokenA.sortsBefore(tokenB) ? [tokenA, tokenB] : [tokenB, tokenA]
const address = state?.[chainId]?.['addresses']?.[tokens[0]?.address]?.[tokens[1]?.address]
const address = state?.[chainId]?.[ADDRESSES_KEY]?.[tokens[0]?.address]?.[tokens[1]?.address]
useEffect(() => {
if (address === undefined && tokenA && tokenB) {
......@@ -130,7 +133,7 @@ export function usePair(tokenA?: Token, tokenB?: Token): Pair | undefined {
const [state, { updatePairEntity }] = usePairContext()
const address = usePairAddress(tokenA, tokenB)
const pair = state?.[chainId]?.['entities']?.[address]
const pair = state?.[chainId]?.[ENTITIES_KEY]?.[address]
const tokenAmountA = useAddressBalance(address, tokenA)
const tokenAmountB = useAddressBalance(address, tokenB)
......@@ -148,7 +151,7 @@ export function useAllPairs() {
const { chainId } = useWeb3React()
const [state] = usePairContext()
const allPairDetails = state?.[chainId]?.['addresses']
const allPairDetails = state?.[chainId]?.[ADDRESSES_KEY]
const allPairs = useMemo(() => {
if (!allPairDetails) {
......
......@@ -77,8 +77,8 @@ export function useRoute(tokenA: Token, tokenB: Token) {
const defaultPair = usePair(tokenA, tokenB)
// get token<->WETH pairs
const aToETH = usePair(tokenA && chainId && !tokenA.equals(WETH[chainId]) ? tokenA : null, WETH[chainId])
const bToETH = usePair(tokenB && chainId && !tokenB.equals(WETH[chainId]) ? tokenB : null, WETH[chainId])
const aToETH = usePair(tokenA && !tokenA.equals(WETH[chainId]) ? tokenA : null, WETH[chainId])
const bToETH = usePair(tokenB && !tokenB.equals(WETH[chainId]) ? tokenB : null, WETH[chainId])
// needs to route through WETH
const requiresHop =
......@@ -95,7 +95,7 @@ export function useRoute(tokenA: Token, tokenB: Token) {
requiresHop &&
aToETH &&
bToETH &&
// check there is liquidity in both pairs, possibly to reference empty pair
// check there is liquidity in both token<->ETH pairs
JSBI.notEqual(JSBI.BigInt(0), aToETH.reserve0.raw) &&
JSBI.notEqual(JSBI.BigInt(0), bToETH.reserve0.raw)
) {
......
......@@ -5,7 +5,7 @@ import { isAddress, getTokenName, getTokenSymbol, getTokenDecimals, safeAccess }
const UPDATE = 'UPDATE'
export const ALL_TOKENS = [
export let ALL_TOKENS = [
//Mainnet Tokens
WETH[ChainId.MAINNET],
......@@ -24,10 +24,22 @@ export const ALL_TOKENS = [
new Token(ChainId.ROPSTEN, '0xaD6D458402F60fD3Bd25163575031ACDce07538D', 18, 'DAI', 'Dai Stablecoin'),
//Goerli Tokens
WETH[ChainId.GÖRLI],
new Token(ChainId.GÖRLI, '0xaD6D458402F60fD3Bd25163575031ACDce07538D', 18, 'DAI', 'Dai Stablecoin')
WETH[ChainId.GÖRLI]
]
/**
* @todo is there a better way to load these upfront?
*/
// add any tokens from local storage
const savedList = window?.localStorage?.UNISWAP && JSON.parse(window?.localStorage?.UNISWAP)?.TOKEN_LIST
if (savedList) {
const newTokens = Object.keys(savedList).map(key => {
const token = savedList[key]
return new Token(token.chainId, token.address, token.decimals, token.symbol, token.name)
})
ALL_TOKENS = ALL_TOKENS.concat(newTokens)
}
// only meant to be used in exchanges.ts!
export const INITIAL_TOKENS_CONTEXT = ALL_TOKENS.reduce((tokenMap, token) => {
// ensure tokens are unique
......
import React, { Suspense, lazy, useState } from 'react'
import React, { Suspense, lazy } from 'react'
import styled from 'styled-components'
import { BrowserRouter, Redirect, Route, Switch } from 'react-router-dom'
import { Text } from 'rebass'
import Header from '../components/Header'
import NavigationTabs from '../components/NavigationTabs'
import Web3ReactManager from '../components/Web3ReactManager'
import { TYPE } from '../theme'
import { Hover } from '../theme/components'
import { AutoColumn } from '../components/Column'
import { PinkCard } from '../components/Card'
import { ButtonPink } from '../components/Button'
import Popups from '../components/Popups'
import { isAddress, getAllQueryParams } from '../utils'
const Swap = lazy(() => import('./Swap'))
......@@ -19,11 +15,13 @@ const Pool = lazy(() => import('./Supply'))
const Add = lazy(() => import('./Supply/AddLiquidity'))
const Remove = lazy(() => import('./Supply/RemoveLiquidity'))
const Find = lazy(() => import('../components/PoolFinder'))
const Create = lazy(() => import('../components/CreatePool'))
const AppWrapper = styled.div`
display: flex;
flex-flow: column;
align-items: flex-start;
overflow-x: hidden;
height: 100vh;
`
......@@ -37,34 +35,33 @@ const BodyWrapper = styled.div`
display: flex;
flex-direction: column;
width: 100%;
box-sizing: border-box;
justify-content: flex-start;
align-items: center;
flex: 1;
overflow: auto;
padding-top: 40px;
padding-top: 100px;
& > * {
max-width: calc(355px + 4rem);
width: 90%;
margin-bottom: 20px;
}
`
const Body = styled.div`
max-width: 355px;
width: 90%;
width: 100%;
background: ${({ theme }) => theme.bg1};
box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04),
0px 24px 32px rgba(0, 0, 0, 0.01);
border-radius: 20px;
padding: 2rem 2rem 1rem 2rem;
border-radius: 30px;
box-sizing: border-box;
padding: 1rem;
`
export default function App() {
const params = getAllQueryParams()
const [showMigrationMessage, toggleShowMigrationMessage] = useState(true)
return (
<>
<Suspense fallback={null}>
......@@ -73,18 +70,8 @@ export default function App() {
<Header />
</HeaderWrapper>
<BodyWrapper>
{showMigrationMessage && (
<PinkCard padding="20px">
<AutoColumn justify={'center'} gap={'20px'}>
<TYPE.largeHeader>Uniswap has upgraded.</TYPE.largeHeader>
<Text textAlign="center">Are you a liquidity provider? Upgrade now using the migration helper.</Text>
<ButtonPink width={'265px'}>Migrate your liquidity </ButtonPink>
<Hover onClick={() => toggleShowMigrationMessage(false)}>
<Text textAlign="center">Dismiss</Text>
</Hover>
</AutoColumn>
</PinkCard>
)}
<Popups />
<Body>
<Web3ReactManager>
<BrowserRouter>
......@@ -94,6 +81,7 @@ export default function App() {
<Switch>
<Route exact strict path="/" render={() => <Redirect to={{ pathname: '/swap' }} />} />
<Route exact strict path="/find" component={() => <Find params={params} />} />
<Route exact strict path="/create" component={() => <Create params={params} />} />
<Route exact strict path="/swap" component={() => <Swap params={params} />} />
<Route
exact
......@@ -136,8 +124,8 @@ export default function App() {
let t0
let t1
if (tokens) {
t0 = tokens[0] === 'ETH' ? 'ETH' : isAddress(tokens[0])
t1 = tokens[1] === 'ETH' ? 'ETH' : isAddress(tokens[1])
t0 = tokens?.[0] === 'ETH' ? 'ETH' : isAddress(tokens[0])
t1 = tokens?.[1] === 'ETH' ? 'ETH' : isAddress(tokens[1])
}
if (t0 && t1) {
return <Add params={params} token0={t0} token1={t1} />
......@@ -155,8 +143,8 @@ export default function App() {
let t0
let t1
if (tokens) {
t0 = tokens[0] === 'ETH' ? 'ETH' : isAddress(tokens[0])
t1 = tokens[1] === 'ETH' ? 'ETH' : isAddress(tokens[1])
t0 = tokens?.[0] === 'ETH' ? 'ETH' : isAddress(tokens[0])
t1 = tokens?.[1] === 'ETH' ? 'ETH' : isAddress(tokens[1])
}
if (t0 && t1) {
return <Remove params={params} token0={t0} token1={t1} />
......
......@@ -2,6 +2,6 @@ import React from 'react'
import ExchangePage from '../../components/ExchangePage'
export default function Send() {
return <ExchangePage sendingInput={true} />
export default function Send({ initialCurrency, params }) {
return <ExchangePage sendingInput={true} initialCurrency={initialCurrency} params={params} />
}
This diff is collapsed.
......@@ -42,7 +42,7 @@ const Wrapper = styled.div`
const FixedBottom = styled.div`
position: absolute;
bottom: -220px;
top: 100px;
width: 100%;
`
......@@ -694,32 +694,34 @@ export default function RemoveLiquidity({ token0, token1 }) {
</div>
</RowBetween>
</div>
<ButtonPrimary
onClick={() => {
setShowConfirm(true)
}}
disabled={!isValid}
>
<Text fontSize={20} fontWeight={500}>
{inputError
? inputError
: outputError
? outputError
: poolTokenError
? poolTokenError
: generalError
? generalError
: 'Remove'}
</Text>
</ButtonPrimary>
<FixedBottom>
<PositionCard
pairAddress={pair?.liquidityToken.address}
token0={pair?.token0}
token1={pair?.token1}
minimal={true}
/>
</FixedBottom>
<div style={{ position: 'relative' }}>
<ButtonPrimary
onClick={() => {
setShowConfirm(true)
}}
disabled={!isValid}
>
<Text fontSize={20} fontWeight={500}>
{inputError
? inputError
: outputError
? outputError
: poolTokenError
? poolTokenError
: generalError
? generalError
: 'Remove'}
</Text>
</ButtonPrimary>
<FixedBottom>
<PositionCard
pairAddress={pair?.liquidityToken.address}
token0={pair?.token0}
token1={pair?.token1}
minimal={true}
/>
</FixedBottom>
</div>
</AutoColumn>
</Wrapper>
)
......
......@@ -8,9 +8,10 @@ import SearchModal from '../../components/SearchModal'
import PositionCard from '../../components/PositionCard'
import { Link } from '../../theme'
import { Text } from 'rebass'
import { AutoColumn } from '../../components/Column'
import { RowBetween } from '../../components/Row'
import { ButtonPrimary } from '../../components/Button'
import { GreyCard } from '../../components/Card'
import { AutoColumn, ColumnCenter } from '../../components/Column'
import { useAllPairs } from '../../contexts/Pairs'
import { useWeb3React } from '@web3-react/core'
......@@ -19,7 +20,13 @@ import { useAllBalances, useAccountLPBalances } from '../../contexts/Balances'
const Positions = styled.div`
position: relative;
margin-top: 38px;
width: 100%;
`
const FixedBottom = styled.div`
position: absolute;
bottom: -80px;
width: 100%;
`
function Supply({ history }) {
......@@ -33,8 +40,6 @@ function Supply({ history }) {
// initiate listener for LP balances
useAccountLPBalances(account)
// console.log(allPairs)
const filteredExchangeList = Object.keys(allPairs)
.filter((pairAddress, i) => {
return (
......@@ -56,7 +61,7 @@ function Supply({ history }) {
})
return (
<>
<AutoColumn gap="lg" justify="center">
<ButtonPrimary
onClick={() => {
setShowPoolSearch(true)
......@@ -67,13 +72,13 @@ function Supply({ history }) {
<Positions>
<AutoColumn gap="20px">
{filteredExchangeList?.length !== 0 && (
<RowBetween>
<RowBetween padding={'0 8px'}>
<Text fontWeight={500}>Your Pooled Liquidity</Text>
<Question text="filler text" />
</RowBetween>
)}
{filteredExchangeList}
<AutoColumn justify="center">
<GreyCard style={{ textAlign: 'center', padding: '0.5rem 1.25rem 1rem 1.25rem' }}>
<Text color="#AEAEAE">
{filteredExchangeList?.length !== 0 ? `Don't see a pool you joined? ` : 'Already joined a pool?'}{' '}
<Link
......@@ -81,14 +86,21 @@ function Supply({ history }) {
history.push('/find')
}}
>
Find it.
Import it.
</Link>
</Text>
</AutoColumn>
</GreyCard>
</AutoColumn>
<FixedBottom>
<ColumnCenter>
<ButtonPrimary width="120px" padding="8px" borderRadius="10px" onClick={() => history.push('/create')}>
Create Pool
</ButtonPrimary>
</ColumnCenter>
</FixedBottom>
</Positions>
<SearchModal isOpen={showPoolSearch} onDismiss={() => setShowPoolSearch(false)} />
</>
</AutoColumn>
)
}
export default withRouter(Supply)
......@@ -2,5 +2,5 @@ import React from 'react'
import ExchangePage from '../../components/ExchangePage'
export default function Swap({ initialCurrency, params }) {
return <ExchangePage sendingInput={false} />
return <ExchangePage sendingInput={false} initialCurrency={initialCurrency} params={params} />
}
......@@ -8,6 +8,7 @@ import { Text } from 'rebass'
export * from './components'
const MEDIA_WIDTHS = {
upToExtraSmall: 500,
upToSmall: 600,
upToMedium: 960,
upToLarge: 1280
......@@ -77,6 +78,12 @@ const theme = darkMode => ({
yellow1: '#FFE270',
yellow2: '#F3841E',
grids: {
sm: 8,
md: 12,
lg: 24
},
//shadows
shadow1: darkMode ? '#000' : '#2F80ED',
......@@ -115,7 +122,7 @@ export const TYPE = {
</Text>
),
body: ({ children, ...rest }) => (
<Text fontWeight={500} fontSize={16} color={'#565A69'} {...rest}>
<Text fontWeight={400} fontSize={16} color={'#888D9B'} {...rest}>
{children}
</Text>
),
......@@ -153,7 +160,11 @@ export const TYPE = {
export const GlobalStyle = createGlobalStyle`
@import url('https://rsms.me/inter/inter.css');
html { font-family: 'Inter', sans-serif; }
html {
font-family: 'Inter', sans-serif;
letter-spacing: -0.018em;
font-feature-settings: 'cv01', 'cv02', 'cv03', 'cv04';
}
@supports (font-variation-settings: normal) {
html { font-family: 'Inter var', sans-serif; }
}
......
......@@ -56,6 +56,23 @@ export function getQueryParam(windowLocation, name) {
export function getAllQueryParams() {
let params = {}
params.inputTokenAddress = isAddress(getQueryParam(window.location, 'inputTokenAddress'))
? isAddress(getQueryParam(window.location, 'inputTokenAddress'))
: ''
params.outputTokenAddress = isAddress(getQueryParam(window.location, 'outputTokenAddress'))
? isAddress(getQueryParam(window.location, 'outputTokenAddress'))
: ''
params.inputTokenAmount = !isNaN(getQueryParam(window.location, 'inputTokenAmount'))
? getQueryParam(window.location, 'inputTokenAmount')
: ''
params.outputTokenAmount = !isNaN(getQueryParam(window.location, 'outputTokenAmount'))
? getQueryParam(window.location, 'outputTokenAmount')
: ''
return params
}
......
......@@ -15441,6 +15441,11 @@ usb@^1.6.0:
nan "2.13.2"
prebuild-install "^5.3.3"
use-media@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/use-media/-/use-media-1.4.0.tgz#e777bf1f382a7aacabbd1f9ce3da2b62e58b2a98"
integrity sha512-XsgyUAf3nhzZmEfhc5MqLHwyaPjs78bgytpVJ/xDl0TF4Bptf3vEpBNBBT/EIKOmsOc8UbuECq3mrP3mt1QANA==
use@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
......
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