Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b57059353 | ||
|
|
6926f9a4ae | ||
|
|
7dec580944 | ||
|
|
5cf95680ef | ||
|
|
f8d6bab4ae | ||
|
|
c9721c42bf | ||
|
|
4414134bb2 | ||
|
|
44ba54e44a | ||
|
|
9ec3109f72 | ||
|
|
e75793676a | ||
|
|
32006ded21 | ||
|
|
d4f1c579d8 | ||
|
|
95f3541807 | ||
|
|
da4ca73a1d | ||
|
|
e75bf8d003 | ||
|
|
236f68a459 | ||
|
|
9f07baaad2 | ||
|
|
c75464e1aa | ||
|
|
bc80585bb4 | ||
|
|
ad45b2b7bb | ||
|
|
63ac89e9f3 | ||
|
|
1b6ae0d3db | ||
|
|
7d67819604 | ||
|
|
7b9b332c42 |
2
.env
2
.env
@@ -1,2 +1,2 @@
|
||||
REACT_APP_CHAIN_ID="1"
|
||||
REACT_APP_NETWORK_URL="https://mainnet.infura.io/v3/b8800ce81b8c451698081d269b86692b"
|
||||
REACT_APP_NETWORK_URL="https://mainnet.infura.io/v3/acb7e55995d04c49bfb52b7141599467"
|
||||
@@ -1,5 +1,5 @@
|
||||
REACT_APP_CHAIN_ID="1"
|
||||
REACT_APP_NETWORK_URL="https://mainnet.infura.io/v3/2acb2baa4c06402792e0c701a3697d10"
|
||||
REACT_APP_NETWORK_URL="https://mainnet.infura.io/v3/febcb10ca2754433a61e0805bc6c047d"
|
||||
REACT_APP_PORTIS_ID="c0e2bf01-4b08-4fd5-ac7b-8e26b58cd236"
|
||||
REACT_APP_FORTMATIC_KEY="pk_live_F937DF033A1666BF"
|
||||
REACT_APP_GOOGLE_ANALYTICS_ID="UA-128182339-4"
|
||||
|
||||
78
.github/workflows/release.yaml
vendored
78
.github/workflows/release.yaml
vendored
@@ -1,36 +1,49 @@
|
||||
name: Release
|
||||
# every morning
|
||||
on:
|
||||
# every morning
|
||||
schedule:
|
||||
- cron: '0 12 * * *'
|
||||
|
||||
# releases are triggered on changes to this file
|
||||
push:
|
||||
branches:
|
||||
- v2
|
||||
paths:
|
||||
- '.github/workflows/release.yaml'
|
||||
|
||||
jobs:
|
||||
create-release:
|
||||
name: Create Release
|
||||
bump_version:
|
||||
name: Bump Version
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
new_tag: ${{ steps.github_tag_action.outputs.new_tag }}
|
||||
changelog: ${{ steps.github_tag_action.outputs.changelog }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
|
||||
- name: Bump version and push tag
|
||||
id: bump_version
|
||||
uses: mathieudutour/github-tag-action@v4
|
||||
id: github_tag_action
|
||||
uses: mathieudutour/github-tag-action@v4.3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
release_branches: .*
|
||||
|
||||
- name: Cancel this build if no new commits
|
||||
if: ${{ steps.bump_version.outputs.new_tag == null }}
|
||||
uses: andymckay/cancel-action@0.2
|
||||
create_release:
|
||||
name: Create Release
|
||||
runs-on: ubuntu-latest
|
||||
needs: bump_version
|
||||
if: ${{ needs.bump_version.outputs.new_tag != null }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '12'
|
||||
|
||||
- name: Install yarn
|
||||
run: npm install -g yarn
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn
|
||||
run: yarn install --ignore-scripts --frozen-lockfile
|
||||
|
||||
- name: Build the IPFS bundle
|
||||
run: yarn ipfs-build
|
||||
@@ -39,14 +52,26 @@ jobs:
|
||||
id: upload
|
||||
uses: anantaramdas/ipfs-pinata-deploy-action@v1.5.2
|
||||
with:
|
||||
pin-name: Uniswap ${{ steps.bump_version.outputs.new_tag }}
|
||||
pin-name: Uniswap ${{ needs.bump_version.outputs.new_tag }}
|
||||
path: './build'
|
||||
pinata-api-key: ${{ secrets.PINATA_API_KEY }}
|
||||
pinata-secret-api-key: ${{ secrets.PINATA_API_SECRET_KEY }}
|
||||
|
||||
- name: Convert CIDv0 to CIDv1
|
||||
id: convert_cidv0
|
||||
uses: uniswap/convert-cidv0-cidv1@v1.0.0
|
||||
with:
|
||||
cidv0: ${{ steps.upload.outputs.hash }}
|
||||
|
||||
- name: Update DNS with new IPFS hash
|
||||
id: update_dns
|
||||
run: npx vercel --token ${{ secrets.VERCEL_TOKEN }} --scope uniswap dns add uniswap.org _dnslink.app TXT "dnslink=/ipfs/${{ steps.upload.outputs.hash }}"
|
||||
uses: uniswap/replace-vercel-dns-records@v1.0.0
|
||||
with:
|
||||
domain: 'uniswap.org'
|
||||
subdomain: '_dnslink.app'
|
||||
record-type: 'TXT'
|
||||
value: dnslink=/ipfs/${{ steps.upload.outputs.hash }}
|
||||
token: ${{ secrets.VERCEL_TOKEN }}
|
||||
team-name: 'uniswap'
|
||||
|
||||
- name: Create GitHub Release
|
||||
id: create_release
|
||||
@@ -54,26 +79,27 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ steps.bump_version.outputs.new_tag }}
|
||||
release_name: Release ${{ steps.bump_version.outputs.new_tag }}
|
||||
tag_name: ${{ needs.bump_version.outputs.new_tag }}
|
||||
release_name: Release ${{ needs.bump_version.outputs.new_tag }}
|
||||
body: |
|
||||
Release built from commit
|
||||
[`${{ github.sha }}`](https://github.com/Uniswap/uniswap-frontend/tree/${{ github.sha }})
|
||||
Release built from commit [`${{ github.sha }}`](https://github.com/Uniswap/uniswap-frontend/tree/${{ github.sha }})
|
||||
|
||||
The IPFS hash of the bundle is `${{ steps.upload.outputs.hash }}`
|
||||
The IPFS hash of the bundle is:
|
||||
- CIDv0: `${{ steps.upload.outputs.hash }}`
|
||||
- CIDv1: `${{ steps.convert_cidv0.outputs.cidv1 }}`
|
||||
|
||||
Uniswap uses [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage)
|
||||
to store your settings.
|
||||
**Beware** that other sites you access via the same IPFS gateway can read and modify your settings on
|
||||
Uniswap without your permission.
|
||||
Uniswap uses [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) to store your settings.
|
||||
**Beware** that other sites you access via the _same_ IPFS gateway can read and modify your settings on Uniswap without your permission.
|
||||
You can avoid this issue by using a subdomain IPFS gateway. The preferred gateway URLs below utilize the CIDv1 of the release in the subdomain, and are relatively safer.
|
||||
|
||||
Preferred URLs:
|
||||
- https://${{ steps.convert_cidv0.outputs.cidv1 }}.ipfs.dweb.link/
|
||||
- https://${{ steps.convert_cidv0.outputs.cidv1 }}.cf-ipfs.com/
|
||||
- [ipfs://${{ steps.upload.outputs.hash }}/](ipfs://${{ steps.upload.outputs.hash }}/)
|
||||
- https://dweb.link/ipfs/${{ steps.upload.outputs.hash }}/
|
||||
|
||||
Other IPFS gateways:
|
||||
- https://cloudflare-ipfs.com/ipfs/${{ steps.upload.outputs.hash }}/
|
||||
- https://ipfs.infura.io/ipfs/${{ steps.upload.outputs.hash }}/
|
||||
- https://ipfs.io/ipfs/${{ steps.upload.outputs.hash }}/
|
||||
|
||||
${{ steps.bump_version.outputs.changelog }}
|
||||
${{ needs.bump_version.outputs.changelog }}
|
||||
6
.github/workflows/tests.yaml
vendored
6
.github/workflows/tests.yaml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
- run: yarn
|
||||
- run: yarn install
|
||||
- run: yarn integration-test
|
||||
|
||||
unit-tests:
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
- run: yarn
|
||||
- run: yarn install --ignore-scripts --frozen-lockfile
|
||||
- run: yarn test
|
||||
|
||||
lint:
|
||||
@@ -70,6 +70,6 @@ jobs:
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
- run: yarn
|
||||
- run: yarn install --ignore-scripts --frozen-lockfile
|
||||
- run: yarn lint
|
||||
|
||||
|
||||
11
README.md
11
README.md
@@ -1,9 +1,7 @@
|
||||
# Uniswap Frontend
|
||||
|
||||
[](https://app.netlify.com/sites/uniswap/deploys)
|
||||
[](https://github.com/Uniswap/uniswap-frontend/actions?query=workflow%3ATests)
|
||||
[](https://github.com/Uniswap/uniswap-frontend/actions?query=workflow%3ATests)
|
||||
[](https://prettier.io/)
|
||||
[](https://github.com/Uniswap/uniswap-frontend/actions?query=workflow%3ARelease)
|
||||
|
||||
An open source interface for Uniswap -- a protocol for decentralized exchange of Ethereum tokens.
|
||||
|
||||
@@ -17,10 +15,9 @@ An open source interface for Uniswap -- a protocol for decentralized exchange of
|
||||
|
||||
## Accessing the frontend
|
||||
|
||||
The front end is deployed to IPFS as well as to [uniswap.exchange](https://uniswap.exchange).
|
||||
|
||||
To access the front end via IPFS, use a link from the
|
||||
[latest release](https://github.com/Uniswap/uniswap-frontend/releases/latest).
|
||||
To access the front end, use an IPFS gateway link from the
|
||||
[latest release](https://github.com/Uniswap/uniswap-frontend/releases/latest)
|
||||
or visit [uniswap.exchange](https://uniswap.exchange).
|
||||
|
||||
## Development
|
||||
|
||||
|
||||
@@ -71,10 +71,9 @@ Cypress.Commands.overwrite('visit', (original, url, options) => {
|
||||
...options,
|
||||
onBeforeLoad(win) {
|
||||
options && options.onBeforeLoad && options.onBeforeLoad(win)
|
||||
const provider = new JsonRpcProvider('https://rinkeby.infura.io/v3/b8800ce81b8c451698081d269b86692b', 4)
|
||||
const provider = new JsonRpcProvider('https://rinkeby.infura.io/v3/acb7e55995d04c49bfb52b7141599467', 4)
|
||||
const signer = new Wallet(PRIVATE_KEY_TEST_NEVER_USE, provider)
|
||||
const bridge = new CustomizedBridge(signer, provider)
|
||||
win.ethereum = bridge
|
||||
win.ethereum = new CustomizedBridge(signer, provider)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
"@material-ui/core": "^4.9.5",
|
||||
"@mycrypto/eth-scan": "^2.1.0",
|
||||
"@popperjs/core": "^2.4.0",
|
||||
"@reach/dialog": "^0.2.8",
|
||||
"@reach/dialog": "^0.10.3",
|
||||
"@reach/portal": "^0.10.3",
|
||||
"@reduxjs/toolkit": "^1.3.5",
|
||||
"@types/jest": "^25.2.1",
|
||||
"@types/lodash.flatmap": "^4.5.6",
|
||||
"@types/node": "^13.13.5",
|
||||
"@types/qs": "^6.9.2",
|
||||
"@types/react": "^16.9.34",
|
||||
@@ -54,6 +56,7 @@
|
||||
"i18next-browser-languagedetector": "^3.0.1",
|
||||
"i18next-xhr-backend": "^2.0.1",
|
||||
"jazzicon": "^1.5.0",
|
||||
"lodash.flatmap": "^4.5.0",
|
||||
"polished": "^3.3.2",
|
||||
"prettier": "^1.17.0",
|
||||
"qrcode.react": "^0.9.3",
|
||||
|
||||
@@ -11,7 +11,7 @@ import { useGesture } from 'react-use-gesture'
|
||||
|
||||
// errors emitted, fix with https://github.com/styled-components/styled-components/pull/3006
|
||||
const AnimatedDialogOverlay = animated(DialogOverlay)
|
||||
const StyledDialogOverlay = styled(AnimatedDialogOverlay)`
|
||||
const StyledDialogOverlay = styled(AnimatedDialogOverlay)<{ mobile: boolean }>`
|
||||
&[data-reach-dialog-overlay] {
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
@@ -95,7 +95,7 @@ interface ModalProps {
|
||||
onDismiss: () => void
|
||||
minHeight?: number | false
|
||||
maxHeight?: number
|
||||
initialFocusRef?: React.Ref<any>
|
||||
initialFocusRef?: React.RefObject<any>
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ export default function Modal({
|
||||
style={props}
|
||||
onDismiss={onDismiss}
|
||||
initialFocusRef={initialFocusRef}
|
||||
mobile={isMobile}
|
||||
mobile={true}
|
||||
>
|
||||
<Spring // animation for entrance and exit
|
||||
from={{
|
||||
@@ -191,15 +191,9 @@ export default function Modal({
|
||||
style={props}
|
||||
onDismiss={onDismiss}
|
||||
initialFocusRef={initialFocusRef}
|
||||
mobile={isMobile ? isMobile : undefined}
|
||||
mobile={false}
|
||||
>
|
||||
<StyledDialogContent
|
||||
hidden={true}
|
||||
minHeight={minHeight}
|
||||
maxHeight={maxHeight}
|
||||
isOpen={isOpen}
|
||||
mobile={isMobile ? isMobile : undefined}
|
||||
>
|
||||
<StyledDialogContent hidden={true} minHeight={minHeight} maxHeight={maxHeight} isOpen={isOpen}>
|
||||
<HiddenCloseButton onClick={onDismiss} />
|
||||
{children}
|
||||
</StyledDialogContent>
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Placement } from '@popperjs/core'
|
||||
import { transparentize } from 'polished'
|
||||
import React, { useState } from 'react'
|
||||
import { createPortal } from 'react-dom'
|
||||
import { usePopper } from 'react-popper'
|
||||
import styled, { keyframes } from 'styled-components'
|
||||
import useInterval from '../../hooks/useInterval'
|
||||
import Portal from '@reach/portal'
|
||||
|
||||
const fadeIn = keyframes`
|
||||
from {
|
||||
@@ -26,7 +27,6 @@ const fadeOut = keyframes`
|
||||
`
|
||||
|
||||
const PopoverContainer = styled.div<{ show: boolean }>`
|
||||
position: relative;
|
||||
z-index: 9999;
|
||||
|
||||
visibility: ${props => (!props.show ? 'hidden' : 'visible')};
|
||||
@@ -45,7 +45,6 @@ const ReferenceElement = styled.div`
|
||||
`
|
||||
|
||||
const Arrow = styled.div`
|
||||
position: absolute;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
z-index: 9998;
|
||||
@@ -98,42 +97,39 @@ const Arrow = styled.div`
|
||||
|
||||
export interface PopoverProps {
|
||||
content: React.ReactNode
|
||||
showPopup: boolean
|
||||
show: boolean
|
||||
children: React.ReactNode
|
||||
placement?: Placement
|
||||
}
|
||||
|
||||
export default function Popover({ content, showPopup, children }: PopoverProps) {
|
||||
export default function Popover({ content, show, children, placement = 'auto' }: PopoverProps) {
|
||||
const [referenceElement, setReferenceElement] = useState<HTMLDivElement>(null)
|
||||
const [popperElement, setPopperElement] = useState<HTMLDivElement>(null)
|
||||
const [arrowElement, setArrowElement] = useState<HTMLDivElement>(null)
|
||||
const { styles, update, attributes } = usePopper(referenceElement, popperElement, {
|
||||
placement: 'auto',
|
||||
placement,
|
||||
strategy: 'fixed',
|
||||
modifiers: [
|
||||
{ name: 'offset', options: { offset: [8, 8] } },
|
||||
{ name: 'arrow', options: { element: arrowElement } }
|
||||
]
|
||||
})
|
||||
|
||||
const portal = createPortal(
|
||||
<PopoverContainer show={showPopup} ref={setPopperElement} style={styles.popper} {...attributes.popper}>
|
||||
{content}
|
||||
<Arrow
|
||||
className={`arrow-${attributes.popper?.['data-popper-placement'] ?? ''}`}
|
||||
ref={setArrowElement}
|
||||
style={styles.arrow}
|
||||
{...attributes.arrow}
|
||||
/>
|
||||
</PopoverContainer>,
|
||||
document.getElementById('popover-container')
|
||||
)
|
||||
|
||||
useInterval(update, showPopup ? 100 : null)
|
||||
useInterval(update, show ? 100 : null)
|
||||
|
||||
return (
|
||||
<>
|
||||
<ReferenceElement ref={setReferenceElement}>{children}</ReferenceElement>
|
||||
{portal}
|
||||
<Portal>
|
||||
<PopoverContainer show={show} ref={setPopperElement} style={styles.popper} {...attributes.popper}>
|
||||
{content}
|
||||
<Arrow
|
||||
className={`arrow-${attributes.popper?.['data-popper-placement'] ?? ''}`}
|
||||
ref={setArrowElement}
|
||||
style={styles.arrow}
|
||||
{...attributes.arrow}
|
||||
/>
|
||||
</PopoverContainer>
|
||||
</Portal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react'
|
||||
import React, { useCallback, useState } from 'react'
|
||||
import { HelpCircle as Question } from 'react-feather'
|
||||
import styled from 'styled-components'
|
||||
import Tooltip from '../Tooltip'
|
||||
@@ -23,22 +23,15 @@ const QuestionWrapper = styled.div`
|
||||
`
|
||||
|
||||
export default function QuestionHelper({ text, disabled }: { text: string; disabled?: boolean }) {
|
||||
const [showPopup, setShowPopup] = useState<boolean>(false)
|
||||
const [show, setShow] = useState<boolean>(false)
|
||||
|
||||
const open = useCallback(() => setShow(true), [setShow])
|
||||
const close = useCallback(() => setShow(false), [setShow])
|
||||
|
||||
return (
|
||||
<span style={{ marginLeft: 4 }}>
|
||||
<Tooltip text={text} showPopup={showPopup && !disabled}>
|
||||
<QuestionWrapper
|
||||
onClick={() => {
|
||||
setShowPopup(true)
|
||||
}}
|
||||
onMouseEnter={() => {
|
||||
setShowPopup(true)
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
setShowPopup(false)
|
||||
}}
|
||||
>
|
||||
<Tooltip text={text} show={show && !disabled}>
|
||||
<QuestionWrapper onClick={open} onMouseEnter={open} onMouseLeave={close}>
|
||||
<Question size={16} />
|
||||
</QuestionWrapper>
|
||||
</Tooltip>
|
||||
|
||||
@@ -18,19 +18,14 @@ export const FilterWrapper = styled(RowFixed)`
|
||||
`
|
||||
|
||||
export default function SortButton({
|
||||
title,
|
||||
toggleSortOrder,
|
||||
ascending
|
||||
}: {
|
||||
title: string
|
||||
toggleSortOrder: () => void
|
||||
ascending: boolean
|
||||
}) {
|
||||
return (
|
||||
<FilterWrapper onClick={toggleSortOrder}>
|
||||
<Text fontSize={14} fontWeight={500}>
|
||||
{title}
|
||||
</Text>
|
||||
<Text fontSize={14} fontWeight={500}>
|
||||
{ascending ? '↑' : '↓'}
|
||||
</Text>
|
||||
|
||||
@@ -155,7 +155,8 @@ function SearchModal({
|
||||
</RowBetween>
|
||||
<Tooltip
|
||||
text="Import any token into your list by pasting the token address into the search field."
|
||||
showPopup={tooltipOpen}
|
||||
show={tooltipOpen}
|
||||
placement="bottom"
|
||||
>
|
||||
<SearchInput
|
||||
type={'text'}
|
||||
@@ -175,11 +176,7 @@ function SearchModal({
|
||||
{isTokenView ? 'Token Name' : 'Pool Name'}
|
||||
</Text>
|
||||
{isTokenView && (
|
||||
<SortButton
|
||||
ascending={invertSearchOrder}
|
||||
toggleSortOrder={() => setInvertSearchOrder(iso => !iso)}
|
||||
title="Your Balances"
|
||||
/>
|
||||
<SortButton ascending={invertSearchOrder} toggleSortOrder={() => setInvertSearchOrder(iso => !iso)} />
|
||||
)}
|
||||
</RowBetween>
|
||||
</PaddedColumn>
|
||||
@@ -210,7 +207,7 @@ function SearchModal({
|
||||
<div>
|
||||
{isTokenView ? (
|
||||
<Text fontWeight={500} color={theme.text2} fontSize={14}>
|
||||
<StyledLink onClick={openTooltip}>Having trouble importing a token?</StyledLink>
|
||||
<StyledLink onClick={openTooltip}>Having trouble finding a token?</StyledLink>
|
||||
</Text>
|
||||
) : (
|
||||
<Text fontWeight={500}>
|
||||
|
||||
@@ -13,6 +13,7 @@ import { RowBetween, RowFixed } from '../Row'
|
||||
import SlippageTabs, { SlippageTabsProps } from '../SlippageTabs'
|
||||
import FormattedPriceImpact from './FormattedPriceImpact'
|
||||
import TokenLogo from '../TokenLogo'
|
||||
import flatMap from 'lodash.flatmap'
|
||||
|
||||
export interface AdvancedSwapDetailsProps extends SlippageTabsProps {
|
||||
trade: Trade
|
||||
@@ -109,27 +110,28 @@ export function AdvancedSwapDetails({ trade, onDismiss, ...slippageTabProps }: A
|
||||
justifyContent="space-evenly"
|
||||
alignItems="center"
|
||||
>
|
||||
{trade.route.path
|
||||
{flatMap(
|
||||
trade.route.path,
|
||||
// add a null in-between each item
|
||||
.flatMap((token, i, array) => {
|
||||
(token, i, array) => {
|
||||
const lastItem = i === array.length - 1
|
||||
return lastItem ? [token] : [token, null]
|
||||
})
|
||||
.map((token, i) => {
|
||||
// use null as an indicator to insert chevrons
|
||||
if (token === null) {
|
||||
return <ChevronRight key={i} color={theme.text2} />
|
||||
} else {
|
||||
return (
|
||||
<Flex my="0.5rem" alignItems="center" key={token.address} style={{ flexShrink: 0 }}>
|
||||
<TokenLogo address={token.address} size="1.5rem" />
|
||||
<TYPE.black fontSize={14} color={theme.text1} ml="0.5rem">
|
||||
{token.symbol}
|
||||
</TYPE.black>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
})}
|
||||
}
|
||||
).map((token, i) => {
|
||||
// use null as an indicator to insert chevrons
|
||||
if (token === null) {
|
||||
return <ChevronRight key={i} color={theme.text2} />
|
||||
} else {
|
||||
return (
|
||||
<Flex my="0.5rem" alignItems="center" key={token.address} style={{ flexShrink: 0 }}>
|
||||
<TokenLogo address={token.address} size="1.5rem" />
|
||||
<TYPE.black fontSize={14} color={theme.text1} ml="0.5rem">
|
||||
{token.symbol}
|
||||
</TYPE.black>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
})}
|
||||
</Flex>
|
||||
</AutoColumn>
|
||||
)}
|
||||
|
||||
@@ -16,6 +16,7 @@ export default function useInterval(callback: () => void, delay: null | number)
|
||||
}
|
||||
|
||||
if (delay !== null) {
|
||||
tick()
|
||||
const id = setInterval(tick, delay)
|
||||
return () => clearInterval(id)
|
||||
}
|
||||
|
||||
20
src/hooks/useIsWindowVisible.ts
Normal file
20
src/hooks/useIsWindowVisible.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
|
||||
/**
|
||||
* Returns whether the window is currently visible to the user.
|
||||
*/
|
||||
export default function useIsWindowVisible(): boolean {
|
||||
const [focused, setFocused] = useState<boolean>(true)
|
||||
const listener = useCallback(() => {
|
||||
setFocused(document.visibilityState !== 'hidden')
|
||||
}, [setFocused])
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener('visibilitychange', listener)
|
||||
return () => {
|
||||
document.removeEventListener('visibilitychange', listener)
|
||||
}
|
||||
}, [listener])
|
||||
|
||||
return focused
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useDebounce, useActiveWeb3React } from '../../hooks'
|
||||
import useIsWindowVisible from '../../hooks/useIsWindowVisible'
|
||||
import { updateBlockNumber } from './actions'
|
||||
import { useDispatch } from 'react-redux'
|
||||
|
||||
@@ -7,6 +8,7 @@ export default function Updater() {
|
||||
const { library, chainId } = useActiveWeb3React()
|
||||
const dispatch = useDispatch()
|
||||
|
||||
const windowVisible = useIsWindowVisible()
|
||||
const [maxBlockNumber, setMaxBlockNumber] = useState<number | null>(null)
|
||||
// because blocks arrive in bunches with longer polling periods, we just want
|
||||
// to process the latest one.
|
||||
@@ -38,8 +40,10 @@ export default function Updater() {
|
||||
|
||||
useEffect(() => {
|
||||
if (!chainId || !debouncedMaxBlockNumber) return
|
||||
dispatch(updateBlockNumber({ chainId, blockNumber: debouncedMaxBlockNumber }))
|
||||
}, [chainId, debouncedMaxBlockNumber, dispatch])
|
||||
if (windowVisible) {
|
||||
dispatch(updateBlockNumber({ chainId, blockNumber: debouncedMaxBlockNumber }))
|
||||
}
|
||||
}, [chainId, debouncedMaxBlockNumber, windowVisible, dispatch])
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
SerializedToken,
|
||||
updateUserDarkMode
|
||||
} from './actions'
|
||||
import flatMap from 'lodash.flatmap'
|
||||
|
||||
function serializeToken(token: Token): SerializedToken {
|
||||
return {
|
||||
@@ -165,10 +166,11 @@ export function useAllDummyPairs(): Pair[] {
|
||||
|
||||
const generatedPairs: Pair[] = useMemo(
|
||||
() =>
|
||||
Object.values(tokens)
|
||||
// select only tokens on the current chain
|
||||
.filter(token => token.chainId === chainId)
|
||||
.flatMap(token => {
|
||||
flatMap(
|
||||
Object.values(tokens)
|
||||
// select only tokens on the current chain
|
||||
.filter(token => token.chainId === chainId),
|
||||
token => {
|
||||
// for each token on the current chain,
|
||||
return (
|
||||
bases
|
||||
@@ -184,7 +186,8 @@ export function useAllDummyPairs(): Pair[] {
|
||||
})
|
||||
.filter(pair => !!pair) as Pair[]
|
||||
)
|
||||
}),
|
||||
}
|
||||
),
|
||||
[tokens, chainId]
|
||||
)
|
||||
|
||||
|
||||
139
yarn.lock
139
yarn.lock
@@ -2385,33 +2385,34 @@
|
||||
penpal "3.0.7"
|
||||
pocket-js-core "0.0.3"
|
||||
|
||||
"@reach/component-component@^0.1.3":
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@reach/component-component/-/component-component-0.1.3.tgz#5d156319572dc38995b246f81878bc2577c517e5"
|
||||
integrity sha512-a1USH7L3bEfDdPN4iNZGvMEFuBfkdG+QNybeyDv8RloVFgZYRoM+KGXyy2KOfEnTUM8QWDRSROwaL3+ts5Angg==
|
||||
|
||||
"@reach/dialog@^0.2.8":
|
||||
version "0.2.9"
|
||||
resolved "https://registry.yarnpkg.com/@reach/dialog/-/dialog-0.2.9.tgz#6375ec4adc1e22838aeede15f57d5eb5ac0e571c"
|
||||
integrity sha512-4plyTRt2X4bB9A5fDFXH0bxb4aipLyAuRVMpOuA1RekFgvkxFn65em2CWYSzRsVf3aTQ2cEnYET4a5H2Qu8a5Q==
|
||||
"@reach/dialog@^0.10.3":
|
||||
version "0.10.3"
|
||||
resolved "https://registry.yarnpkg.com/@reach/dialog/-/dialog-0.10.3.tgz#ba789809c3b194fff79d3bcb4a583c58e03edb83"
|
||||
integrity sha512-RMpUHNjRQhkjGzKt9/oLmDhwUBikW3JbEzgzZngq5MGY5kWRPwYInLDkEA8We4E43AbBsl5J/PRzQha9V+EEXw==
|
||||
dependencies:
|
||||
"@reach/component-component" "^0.1.3"
|
||||
"@reach/portal" "^0.2.1"
|
||||
"@reach/utils" "^0.2.3"
|
||||
react-focus-lock "^1.17.7"
|
||||
react-remove-scroll "^1.0.2"
|
||||
"@reach/portal" "^0.10.3"
|
||||
"@reach/utils" "^0.10.3"
|
||||
prop-types "^15.7.2"
|
||||
react-focus-lock "^2.3.1"
|
||||
react-remove-scroll "^2.3.0"
|
||||
tslib "^1.11.2"
|
||||
|
||||
"@reach/portal@^0.2.1":
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@reach/portal/-/portal-0.2.1.tgz#07720b999e0063a9e179c14dbdc60fd991cfc9fa"
|
||||
integrity sha512-pUQ0EtCcYm4ormEjJmdk4uzZCxOpaRHB8FDKJXy6q6GqRqQwZ4lAT1f2Tvw0DAmULmyZTpe1/heXY27Tdnct+Q==
|
||||
"@reach/portal@^0.10.3":
|
||||
version "0.10.3"
|
||||
resolved "https://registry.yarnpkg.com/@reach/portal/-/portal-0.10.3.tgz#2eb408cc246d3eabbbf3b47ca4dc9c381cdb1d88"
|
||||
integrity sha512-t8c+jtDxMLSPRGg93sQd2s6dDNilh5/qdrwmx88ki7l9h8oIXqMxPP3kSkOqZ9cbVR0b2A68PfMhCDOwMGvkoQ==
|
||||
dependencies:
|
||||
"@reach/component-component" "^0.1.3"
|
||||
"@reach/utils" "^0.10.3"
|
||||
tslib "^1.11.2"
|
||||
|
||||
"@reach/utils@^0.2.3":
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.2.3.tgz#820f6a6af4301b4c5065cfc04bb89e6a3d1d723f"
|
||||
integrity sha512-zM9rA8jDchr05giMhL95dPeYkK67cBQnIhCVrOKKqgWGsv+2GE/HZqeptvU4zqs0BvIqsThwov+YxVNVh5csTQ==
|
||||
"@reach/utils@^0.10.3":
|
||||
version "0.10.3"
|
||||
resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.10.3.tgz#e30f9b172d131161953df7dd01553c57ca4e78f8"
|
||||
integrity sha512-LoIZSfVAJMA+DnzAMCMfc/wAM39iKT8BQQ9gI1FODpxd8nPFP4cKisMuRXImh2/iVtG2Z6NzzCNgceJSrywqFQ==
|
||||
dependencies:
|
||||
"@types/warning" "^3.0.0"
|
||||
tslib "^1.11.2"
|
||||
warning "^4.0.3"
|
||||
|
||||
"@reduxjs/toolkit@^1.3.5":
|
||||
version "1.3.5"
|
||||
@@ -2817,6 +2818,18 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339"
|
||||
integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==
|
||||
|
||||
"@types/lodash.flatmap@^4.5.6":
|
||||
version "4.5.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash.flatmap/-/lodash.flatmap-4.5.6.tgz#5f1ea80cebe403f0fbfcc1b5ad75cd09dd8b5785"
|
||||
integrity sha512-ELNrUL9q+MB7AACaHivWIsKDFDgYhHE3/svXhqvDJgONtn2c467Cy87nEb7CEDvfaGCPv91lPaW596I8s5oiNQ==
|
||||
dependencies:
|
||||
"@types/lodash" "*"
|
||||
|
||||
"@types/lodash@*":
|
||||
version "4.14.153"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.153.tgz#5cb7dded0649f1df97938ac5ffc4f134e9e9df98"
|
||||
integrity sha512-lYniGRiRfZf2gGAR9cfRC3Pi5+Q1ziJCKqPmjZocigrSJUVPWf7st1BtSJ8JOeK0FLXVndQ1IjUjTco9CXGo/Q==
|
||||
|
||||
"@types/lodash@4.14.149":
|
||||
version "4.14.149"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.149.tgz#1342d63d948c6062838fbf961012f74d4e638440"
|
||||
@@ -3024,6 +3037,11 @@
|
||||
dependencies:
|
||||
pretty-format "^25.1.0"
|
||||
|
||||
"@types/warning@^3.0.0":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.0.tgz#0d2501268ad8f9962b740d387c4654f5f8e23e52"
|
||||
integrity sha1-DSUBJorY+ZYrdA04fEZU9fjiPlI=
|
||||
|
||||
"@types/web3-provider-engine@^14.0.0":
|
||||
version "14.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/web3-provider-engine/-/web3-provider-engine-14.0.0.tgz#43adc3b39dc9812b82aef8cd2d66577665ad59b0"
|
||||
@@ -8616,7 +8634,7 @@ flush-write-stream@^1.0.0, flush-write-stream@^1.0.2:
|
||||
inherits "^2.0.3"
|
||||
readable-stream "^2.3.6"
|
||||
|
||||
focus-lock@^0.6.3:
|
||||
focus-lock@^0.6.7:
|
||||
version "0.6.8"
|
||||
resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.6.8.tgz#61985fadfa92f02f2ee1d90bc738efaf7f3c9f46"
|
||||
integrity sha512-vkHTluRCoq9FcsrldC0ulQHiyBYgVJB2CX53I8r0nTC6KnEij7Of0jpBspjt3/CuNb6fyoj3aOh9J2HgQUM0og==
|
||||
@@ -8891,6 +8909,11 @@ get-caller-file@^2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||
|
||||
get-nonce@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3"
|
||||
integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==
|
||||
|
||||
get-own-enumerable-property-symbols@^3.0.0:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664"
|
||||
@@ -14402,7 +14425,7 @@ react-app-polyfill@^1.0.6:
|
||||
regenerator-runtime "^0.13.3"
|
||||
whatwg-fetch "^3.0.0"
|
||||
|
||||
react-clientside-effect@^1.2.0:
|
||||
react-clientside-effect@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/react-clientside-effect/-/react-clientside-effect-1.2.2.tgz#6212fb0e07b204e714581dd51992603d1accc837"
|
||||
integrity sha512-nRmoyxeok5PBO6ytPvSjKp9xwXg9xagoTK1mMjwnQxqM9Hd7MNPl+LS1bOSOe+CV2+4fnEquc7H/S8QD3q697A==
|
||||
@@ -14473,15 +14496,17 @@ react-feather@^2.0.8:
|
||||
dependencies:
|
||||
prop-types "^15.7.2"
|
||||
|
||||
react-focus-lock@^1.17.7:
|
||||
version "1.19.1"
|
||||
resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-1.19.1.tgz#2f3429793edaefe2d077121f973ce5a3c7a0651a"
|
||||
integrity sha512-TPpfiack1/nF4uttySfpxPk4rGZTLXlaZl7ncZg/ELAk24Iq2B1UUaUioID8H8dneUXqznT83JTNDHDj+kwryw==
|
||||
react-focus-lock@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.3.1.tgz#9d5d85899773609c7eefa4fc54fff6a0f5f2fc47"
|
||||
integrity sha512-j15cWLPzH0gOmRrUg01C09Peu8qbcdVqr6Bjyfxj80cNZmH+idk/bNBYEDSmkAtwkXI+xEYWSmHYqtaQhZ8iUQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.0.0"
|
||||
focus-lock "^0.6.3"
|
||||
focus-lock "^0.6.7"
|
||||
prop-types "^15.6.2"
|
||||
react-clientside-effect "^1.2.0"
|
||||
react-clientside-effect "^1.2.2"
|
||||
use-callback-ref "^1.2.1"
|
||||
use-sidecar "^1.0.1"
|
||||
|
||||
react-ga@^2.5.7:
|
||||
version "2.7.0"
|
||||
@@ -14520,21 +14545,24 @@ react-redux@^7.2.0:
|
||||
prop-types "^15.7.2"
|
||||
react-is "^16.9.0"
|
||||
|
||||
react-remove-scroll-bar@^1.1.5:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-1.2.0.tgz#07250b2bc581f56315759c454c9b159dd04ba49d"
|
||||
integrity sha512-8xSYR6xgW8QW65k38qB1Sh6ouTRjZ7BEteepR9tACd1rSaRyVYWabFxYLNOr4l1blZlqb81GEmDpUoPm7LsUTA==
|
||||
react-remove-scroll-bar@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.1.0.tgz#edafe9b42a42c0dad9bdd10712772a1f9a39d7b9"
|
||||
integrity sha512-5X5Y5YIPjIPrAoMJxf6Pfa7RLNGCgwZ95TdnVPgPuMftRfO8DaC7F4KP1b5eiO8hHbe7u+wZNDbYN5WUTpv7+g==
|
||||
dependencies:
|
||||
react-style-singleton "^1.1.0"
|
||||
react-style-singleton "^2.1.0"
|
||||
tslib "^1.0.0"
|
||||
|
||||
react-remove-scroll@^1.0.2:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-1.0.8.tgz#a5aadc56368345a51ba524582c842a773849f609"
|
||||
integrity sha512-AS6gFBO6T2CP0TgmDjq3Ip0Fz1HKyv+lzNrQAkJBSWGyOYaMWLMDy77mQJ7qEyy6fK0pI+Cz5x3X81/ux6SBew==
|
||||
react-remove-scroll@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.3.0.tgz#3af06fe2f7130500704b676cdef94452c08fe593"
|
||||
integrity sha512-UqVimLeAe+5EHXKfsca081hAkzg3WuDmoT9cayjBegd6UZVhlTEchleNp9J4TMGkb/ftLve7ARB5Wph+HJ7A5g==
|
||||
dependencies:
|
||||
react-remove-scroll-bar "^1.1.5"
|
||||
react-remove-scroll-bar "^2.1.0"
|
||||
react-style-singleton "^2.1.0"
|
||||
tslib "^1.0.0"
|
||||
use-callback-ref "^1.2.3"
|
||||
use-sidecar "^1.0.1"
|
||||
|
||||
react-router-dom@^5.0.0:
|
||||
version "5.1.2"
|
||||
@@ -14633,11 +14661,12 @@ react-spring@^8.0.27:
|
||||
"@babel/runtime" "^7.3.1"
|
||||
prop-types "^15.5.8"
|
||||
|
||||
react-style-singleton@^1.1.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-1.1.1.tgz#b2b698765519da812b80f55ab3c5fc5d849a2e63"
|
||||
integrity sha512-0JD+XC5veR3oxf7GzIXipr89sM8R3rWnOR/gpzIV0DnoRBrcTvvkqyMu9icDYqM/6CWJhYcH5Jdy6Nim7PmoTQ==
|
||||
react-style-singleton@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.1.0.tgz#7396885332e9729957f9df51f08cadbfc164e1c4"
|
||||
integrity sha512-DH4ED+YABC1dhvSDYGGreAHmfuTXj6+ezT3CmHoqIEfxNgEYfIMoOtmbRp42JsUst3IPqBTDL+8r4TF7EWhIHw==
|
||||
dependencies:
|
||||
get-nonce "^1.0.0"
|
||||
invariant "^2.2.4"
|
||||
tslib "^1.0.0"
|
||||
|
||||
@@ -16873,6 +16902,11 @@ tslib@^1.0.0, tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0:
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.2.tgz#9c79d83272c9a7aaf166f73915c9667ecdde3cc9"
|
||||
integrity sha512-tTSkux6IGPnUGUd1XAZHcpu85MOkIl5zX49pO+jfsie3eP0B6pyhOlLXm3cAC6T7s+euSDDUUV+Acop5WmtkVg==
|
||||
|
||||
tslib@^1.11.2, tslib@^1.9.3:
|
||||
version "1.13.0"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043"
|
||||
integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==
|
||||
|
||||
tsutils@^3.17.1:
|
||||
version "3.17.1"
|
||||
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"
|
||||
@@ -17215,11 +17249,24 @@ usb@^1.6.0:
|
||||
nan "2.13.2"
|
||||
prebuild-install "^5.3.3"
|
||||
|
||||
use-callback-ref@^1.2.1, use-callback-ref@^1.2.3:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.2.3.tgz#9f939dfb5740807bbf9dd79cdd4e99d27e827756"
|
||||
integrity sha512-DPBPh1i2adCZoIArRlTuKRy7yue7QogtEnfv0AKrWsY+GA+4EKe37zhRDouNnyWMoNQFYZZRF+2dLHsWE4YvJA==
|
||||
|
||||
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-sidecar@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.0.2.tgz#e72f582a75842f7de4ef8becd6235a4720ad8af6"
|
||||
integrity sha512-287RZny6m5KNMTb/Kq9gmjafi7lQL0YHO1lYolU6+tY1h9+Z3uCtkJJ3OSOq3INwYf2hBryCcDh4520AhJibMA==
|
||||
dependencies:
|
||||
detect-node "^2.0.4"
|
||||
tslib "^1.9.3"
|
||||
|
||||
use@^3.1.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
|
||||
@@ -17450,7 +17497,7 @@ walletlink@^2.0.2:
|
||||
preact "^10.3.3"
|
||||
rxjs "^6.5.4"
|
||||
|
||||
warning@^4.0.2:
|
||||
warning@^4.0.2, warning@^4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"
|
||||
integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==
|
||||
|
||||
Reference in New Issue
Block a user