Introduce redux for one of the state stores (#742)
* Introduce redux for one of the state stores * Remove unused state * Clean up hooks * Add types for react-redux and fix error from any type on useSelector * Strongly type the web3 provider * Make the popup content into a POJO * Lint errors * Clean up method call * Fix lint error * Fix lint error * Lint
This commit is contained in:
parent
ea015d16f2
commit
6da8e2c84d
3
.gitignore
vendored
3
.gitignore
vendored
@ -30,4 +30,5 @@ notes.txt
|
|||||||
package-lock.json
|
package-lock.json
|
||||||
|
|
||||||
cypress/videos
|
cypress/videos
|
||||||
cypress/screenshots
|
cypress/screenshots
|
||||||
|
cypress/fixtures/example.json
|
@ -15,6 +15,7 @@
|
|||||||
"@material-ui/core": "^4.9.5",
|
"@material-ui/core": "^4.9.5",
|
||||||
"@reach/dialog": "^0.2.8",
|
"@reach/dialog": "^0.2.8",
|
||||||
"@reach/tooltip": "^0.2.0",
|
"@reach/tooltip": "^0.2.0",
|
||||||
|
"@reduxjs/toolkit": "^1.3.5",
|
||||||
"@uniswap/sdk": "^2.0.3",
|
"@uniswap/sdk": "^2.0.3",
|
||||||
"@uniswap/v2-core": "1.0.0",
|
"@uniswap/v2-core": "1.0.0",
|
||||||
"@uniswap/v2-periphery": "1.0.0-beta.0",
|
"@uniswap/v2-periphery": "1.0.0-beta.0",
|
||||||
@ -41,6 +42,7 @@
|
|||||||
"react-feather": "^2.0.8",
|
"react-feather": "^2.0.8",
|
||||||
"react-ga": "^2.5.7",
|
"react-ga": "^2.5.7",
|
||||||
"react-i18next": "^10.7.0",
|
"react-i18next": "^10.7.0",
|
||||||
|
"react-redux": "^7.2.0",
|
||||||
"react-router-dom": "^5.0.0",
|
"react-router-dom": "^5.0.0",
|
||||||
"react-scripts": "^3.4.1",
|
"react-scripts": "^3.4.1",
|
||||||
"react-spring": "^8.0.27",
|
"react-spring": "^8.0.27",
|
||||||
@ -55,6 +57,7 @@
|
|||||||
"@types/node": "^13.13.5",
|
"@types/node": "^13.13.5",
|
||||||
"@types/react": "^16.9.34",
|
"@types/react": "^16.9.34",
|
||||||
"@types/react-dom": "^16.9.7",
|
"@types/react-dom": "^16.9.7",
|
||||||
|
"@types/react-redux": "^7.1.8",
|
||||||
"@types/react-router-dom": "^5.0.0",
|
"@types/react-router-dom": "^5.0.0",
|
||||||
"@types/rebass": "^4.0.5",
|
"@types/rebass": "^4.0.5",
|
||||||
"@types/styled-components": "^4.2.0",
|
"@types/styled-components": "^4.2.0",
|
||||||
|
@ -7,6 +7,7 @@ import { withRouter, RouteComponentProps } from 'react-router-dom'
|
|||||||
import { BigNumber } from '@ethersproject/bignumber'
|
import { BigNumber } from '@ethersproject/bignumber'
|
||||||
import { MaxUint256 } from '@ethersproject/constants'
|
import { MaxUint256 } from '@ethersproject/constants'
|
||||||
import { Contract } from '@ethersproject/contracts'
|
import { Contract } from '@ethersproject/contracts'
|
||||||
|
import { useUserAdvanced } from '../../state/application/hooks'
|
||||||
import { Field, SwapAction, useSwapStateReducer } from './swap-store'
|
import { Field, SwapAction, useSwapStateReducer } from './swap-store'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import Card, { BlueCard, GreyCard, YellowCard } from '../../components/Card'
|
import Card, { BlueCard, GreyCard, YellowCard } from '../../components/Card'
|
||||||
@ -14,7 +15,6 @@ import { AutoColumn, ColumnCenter } from '../../components/Column'
|
|||||||
import { AutoRow, RowBetween, RowFixed } from '../Row'
|
import { AutoRow, RowBetween, RowFixed } from '../Row'
|
||||||
import { ROUTER_ADDRESS } from '../../constants'
|
import { ROUTER_ADDRESS } from '../../constants'
|
||||||
import { useTokenAllowance } from '../../data/Allowances'
|
import { useTokenAllowance } from '../../data/Allowances'
|
||||||
import { useUserAdvanced } from '../../contexts/Application'
|
|
||||||
import { useAddressBalance, useAllBalances } from '../../contexts/Balances'
|
import { useAddressBalance, useAllBalances } from '../../contexts/Balances'
|
||||||
import { useLocalStorageTokens } from '../../contexts/LocalStorage'
|
import { useLocalStorageTokens } from '../../contexts/LocalStorage'
|
||||||
import { usePair } from '../../data/Reserves'
|
import { usePair } from '../../data/Reserves'
|
||||||
|
@ -3,8 +3,14 @@ import styled, { ThemeContext } from 'styled-components'
|
|||||||
import { useMediaLayout } from 'use-media'
|
import { useMediaLayout } from 'use-media'
|
||||||
|
|
||||||
import { X } from 'react-feather'
|
import { X } from 'react-feather'
|
||||||
import { usePopups } from '../../contexts/Application'
|
import { PopupContent } from '../../state/application/actions'
|
||||||
|
import { usePopups } from '../../state/application/hooks'
|
||||||
|
import { Link } from '../../theme'
|
||||||
import { AutoColumn } from '../Column'
|
import { AutoColumn } from '../Column'
|
||||||
|
import DoubleTokenLogo from '../DoubleLogo'
|
||||||
|
import Row from '../Row'
|
||||||
|
import TxnPopup from '../TxnPopup'
|
||||||
|
import { Text } from 'rebass'
|
||||||
|
|
||||||
const StyledClose = styled(X)`
|
const StyledClose = styled(X)`
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -66,6 +72,33 @@ const Popup = styled.div`
|
|||||||
`}
|
`}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
function PopupItem({ content, popKey }: { content: PopupContent; popKey: string }) {
|
||||||
|
if ('txn' in content) {
|
||||||
|
const {
|
||||||
|
txn: { hash, success, summary }
|
||||||
|
} = content
|
||||||
|
return <TxnPopup popKey={popKey} hash={hash} success={success} summary={summary} />
|
||||||
|
} else if ('poolAdded' in content) {
|
||||||
|
const {
|
||||||
|
poolAdded: { token0, token1 }
|
||||||
|
} = content
|
||||||
|
return (
|
||||||
|
<AutoColumn gap={'10px'}>
|
||||||
|
<Text fontSize={20} fontWeight={500}>
|
||||||
|
Pool Imported
|
||||||
|
</Text>
|
||||||
|
<Row>
|
||||||
|
<DoubleTokenLogo a0={token0?.address ?? ''} a1={token1?.address ?? ''} margin={true} />
|
||||||
|
<Text fontSize={16} fontWeight={500}>
|
||||||
|
UNI {token0?.symbol} / {token1?.symbol}
|
||||||
|
</Text>
|
||||||
|
</Row>
|
||||||
|
<Link>View on Uniswap Info.</Link>
|
||||||
|
</AutoColumn>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const theme = useContext(ThemeContext)
|
const theme = useContext(ThemeContext)
|
||||||
// get all popups
|
// get all popups
|
||||||
@ -81,7 +114,7 @@ export default function App() {
|
|||||||
return (
|
return (
|
||||||
<Popup key={item.key}>
|
<Popup key={item.key}>
|
||||||
<StyledClose color={theme.text2} onClick={() => removePopup(item.key)} />
|
<StyledClose color={theme.text2} onClick={() => removePopup(item.key)} />
|
||||||
{React.cloneElement(item.content, { popKey: item.key })}
|
<PopupItem content={item.content} popKey={item.key} />
|
||||||
</Popup>
|
</Popup>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
@ -100,7 +133,7 @@ export default function App() {
|
|||||||
return (
|
return (
|
||||||
<Popup key={item.key}>
|
<Popup key={item.key}>
|
||||||
<StyledClose color={theme.text2} onClick={() => removePopup(item.key)} />
|
<StyledClose color={theme.text2} onClick={() => removePopup(item.key)} />
|
||||||
{React.cloneElement(item.content, { popKey: item.key })}
|
<PopupItem content={item.content} popKey={item.key} />
|
||||||
</Popup>
|
</Popup>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
@ -3,10 +3,10 @@ import React, { useState } from 'react'
|
|||||||
import { AlertCircle, CheckCircle } from 'react-feather'
|
import { AlertCircle, CheckCircle } from 'react-feather'
|
||||||
|
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { usePopups } from '../../contexts/Application'
|
|
||||||
|
|
||||||
import { useWeb3React } from '../../hooks'
|
import { useWeb3React } from '../../hooks'
|
||||||
import useInterval from '../../hooks/useInterval'
|
import useInterval from '../../hooks/useInterval'
|
||||||
|
import { usePopups } from '../../state/application/hooks'
|
||||||
import { TYPE } from '../../theme'
|
import { TYPE } from '../../theme'
|
||||||
|
|
||||||
import { Link } from '../../theme/components'
|
import { Link } from '../../theme/components'
|
||||||
@ -35,7 +35,7 @@ export default function TxnPopup({
|
|||||||
hash: string
|
hash: string
|
||||||
success?: boolean
|
success?: boolean
|
||||||
summary?: string
|
summary?: string
|
||||||
popKey?: number
|
popKey?: string
|
||||||
}) {
|
}) {
|
||||||
const { chainId } = useWeb3React()
|
const { chainId } = useWeb3React()
|
||||||
const [count, setCount] = useState(1)
|
const [count, setCount] = useState(1)
|
||||||
|
@ -4,6 +4,7 @@ import styled from 'styled-components'
|
|||||||
import { isMobile } from 'react-device-detect'
|
import { isMobile } from 'react-device-detect'
|
||||||
import { useWeb3React, UnsupportedChainIdError } from '@web3-react/core'
|
import { useWeb3React, UnsupportedChainIdError } from '@web3-react/core'
|
||||||
import { URI_AVAILABLE } from '@web3-react/walletconnect-connector'
|
import { URI_AVAILABLE } from '@web3-react/walletconnect-connector'
|
||||||
|
import { useWalletModalOpen, useWalletModalToggle } from '../../state/application/hooks'
|
||||||
|
|
||||||
import Modal from '../Modal'
|
import Modal from '../Modal'
|
||||||
import AccountDetails from '../AccountDetails'
|
import AccountDetails from '../AccountDetails'
|
||||||
@ -15,7 +16,6 @@ import { Link } from '../../theme'
|
|||||||
import MetamaskIcon from '../../assets/images/metamask.png'
|
import MetamaskIcon from '../../assets/images/metamask.png'
|
||||||
import { ReactComponent as Close } from '../../assets/images/x.svg'
|
import { ReactComponent as Close } from '../../assets/images/x.svg'
|
||||||
import { injected, walletconnect, fortmatic, portis } from '../../connectors'
|
import { injected, walletconnect, fortmatic, portis } from '../../connectors'
|
||||||
import { useWalletModalToggle, useWalletModalOpen } from '../../contexts/Application'
|
|
||||||
import { OVERLAY_READY } from '../../connectors/Fortmatic'
|
import { OVERLAY_READY } from '../../connectors/Fortmatic'
|
||||||
|
|
||||||
const CloseIcon = styled.div`
|
const CloseIcon = styled.div`
|
||||||
|
@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next'
|
|||||||
import { useWeb3React, UnsupportedChainIdError } from '@web3-react/core'
|
import { useWeb3React, UnsupportedChainIdError } from '@web3-react/core'
|
||||||
import { darken, lighten } from 'polished'
|
import { darken, lighten } from 'polished'
|
||||||
import { Activity } from 'react-feather'
|
import { Activity } from 'react-feather'
|
||||||
|
import { useWalletModalToggle } from '../../state/application/hooks'
|
||||||
|
|
||||||
import Identicon from '../Identicon'
|
import Identicon from '../Identicon'
|
||||||
import PortisIcon from '../../assets/images/portisIcon.png'
|
import PortisIcon from '../../assets/images/portisIcon.png'
|
||||||
@ -21,7 +22,6 @@ import { useENSName } from '../../hooks'
|
|||||||
import { shortenAddress } from '../../utils'
|
import { shortenAddress } from '../../utils'
|
||||||
import { useAllTransactions } from '../../contexts/Transactions'
|
import { useAllTransactions } from '../../contexts/Transactions'
|
||||||
import { NetworkContextName } from '../../constants'
|
import { NetworkContextName } from '../../constants'
|
||||||
import { useWalletModalToggle } from '../../contexts/Application'
|
|
||||||
import { injected, walletconnect, walletlink, fortmatic, portis } from '../../connectors'
|
import { injected, walletconnect, walletlink, fortmatic, portis } from '../../connectors'
|
||||||
|
|
||||||
const SpinnerWrapper = styled(Spinner)`
|
const SpinnerWrapper = styled(Spinner)`
|
||||||
|
@ -1,226 +0,0 @@
|
|||||||
import React, { createContext, useContext, useReducer, useMemo, useCallback, useEffect } from 'react'
|
|
||||||
|
|
||||||
import { useWeb3React } from '../hooks'
|
|
||||||
|
|
||||||
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'
|
|
||||||
|
|
||||||
const ADD_POPUP = 'ADD_POPUP'
|
|
||||||
const USER_ADVANCED = 'USER_ADVANCED'
|
|
||||||
const TOGGLE_USER_ADVANCED = 'TOGGLE_USER_ADVANCED'
|
|
||||||
|
|
||||||
interface ApplicationState {
|
|
||||||
BLOCK_NUMBER: {}
|
|
||||||
USD_PRICE: {}
|
|
||||||
POPUP_LIST: Array<{ key: number; show: boolean; content: React.ReactElement }>
|
|
||||||
POPUP_KEY: number
|
|
||||||
WALLET_MODAL_OPEN: boolean
|
|
||||||
USER_ADVANCED: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
const ApplicationContext = createContext<[ApplicationState, { [updater: string]: (...args: any[]) => void }]>([
|
|
||||||
{
|
|
||||||
[BLOCK_NUMBER]: {},
|
|
||||||
[USD_PRICE]: {},
|
|
||||||
[POPUP_LIST]: [],
|
|
||||||
[POPUP_KEY]: 0,
|
|
||||||
[WALLET_MODAL_OPEN]: false,
|
|
||||||
[USER_ADVANCED]: false
|
|
||||||
},
|
|
||||||
{}
|
|
||||||
])
|
|
||||||
|
|
||||||
function useApplicationContext() {
|
|
||||||
return useContext(ApplicationContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
function reducer(state: ApplicationState, { type, payload }): ApplicationState {
|
|
||||||
switch (type) {
|
|
||||||
case UPDATE_BLOCK_NUMBER: {
|
|
||||||
const { networkId, blockNumber } = payload
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
[BLOCK_NUMBER]: {
|
|
||||||
...state?.[BLOCK_NUMBER],
|
|
||||||
[networkId]: blockNumber
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case TOGGLE_WALLET_MODAL: {
|
|
||||||
return { ...state, [WALLET_MODAL_OPEN]: !state[WALLET_MODAL_OPEN] }
|
|
||||||
}
|
|
||||||
|
|
||||||
case TOGGLE_USER_ADVANCED: {
|
|
||||||
return { ...state, [USER_ADVANCED]: !state[USER_ADVANCED] }
|
|
||||||
}
|
|
||||||
|
|
||||||
case ADD_POPUP: {
|
|
||||||
const { newList } = payload
|
|
||||||
return { ...state, [POPUP_LIST]: newList, [POPUP_KEY]: state?.[POPUP_KEY] + 1 }
|
|
||||||
}
|
|
||||||
|
|
||||||
default: {
|
|
||||||
throw Error(`Unexpected action type in ApplicationContext reducer: '${type}'.`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Provider({ children }: { children: React.ReactNode }) {
|
|
||||||
const [state, dispatch] = useReducer(reducer, {
|
|
||||||
[BLOCK_NUMBER]: {},
|
|
||||||
[USD_PRICE]: {},
|
|
||||||
[POPUP_LIST]: [],
|
|
||||||
[POPUP_KEY]: 0,
|
|
||||||
[WALLET_MODAL_OPEN]: false,
|
|
||||||
[USER_ADVANCED]: false
|
|
||||||
})
|
|
||||||
|
|
||||||
const updateBlockNumber = useCallback(
|
|
||||||
(networkId, blockNumber) => {
|
|
||||||
dispatch({ type: UPDATE_BLOCK_NUMBER, payload: { networkId, blockNumber } })
|
|
||||||
},
|
|
||||||
[dispatch]
|
|
||||||
)
|
|
||||||
|
|
||||||
const toggleWalletModal = useCallback(() => {
|
|
||||||
dispatch({ type: TOGGLE_WALLET_MODAL, payload: null })
|
|
||||||
}, [dispatch])
|
|
||||||
|
|
||||||
const toggleUserAdvanced = useCallback(() => {
|
|
||||||
dispatch({ type: TOGGLE_USER_ADVANCED, payload: null })
|
|
||||||
}, [dispatch])
|
|
||||||
|
|
||||||
const setPopups = useCallback(
|
|
||||||
newList => {
|
|
||||||
dispatch({ type: ADD_POPUP, payload: { newList } })
|
|
||||||
},
|
|
||||||
[dispatch]
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ApplicationContext.Provider
|
|
||||||
value={useMemo(() => [state, { updateBlockNumber, toggleWalletModal, toggleUserAdvanced, setPopups }], [
|
|
||||||
state,
|
|
||||||
updateBlockNumber,
|
|
||||||
toggleWalletModal,
|
|
||||||
toggleUserAdvanced,
|
|
||||||
setPopups
|
|
||||||
])}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</ApplicationContext.Provider>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function Updater() {
|
|
||||||
const { library, chainId } = useWeb3React()
|
|
||||||
|
|
||||||
const [, { updateBlockNumber }] = useApplicationContext()
|
|
||||||
|
|
||||||
// update block number
|
|
||||||
useEffect(() => {
|
|
||||||
if (library) {
|
|
||||||
let stale = false
|
|
||||||
|
|
||||||
const update = () => {
|
|
||||||
library
|
|
||||||
.getBlockNumber()
|
|
||||||
.then(blockNumber => {
|
|
||||||
if (!stale) {
|
|
||||||
updateBlockNumber(chainId, blockNumber)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
if (!stale) {
|
|
||||||
updateBlockNumber(chainId, null)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
update()
|
|
||||||
library.on('block', update)
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
stale = true
|
|
||||||
library.removeListener('block', update)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [chainId, library, updateBlockNumber])
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useBlockNumber() {
|
|
||||||
const { chainId } = useWeb3React()
|
|
||||||
|
|
||||||
const [state] = useApplicationContext()
|
|
||||||
|
|
||||||
return state?.[BLOCK_NUMBER]?.[chainId]
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useWalletModalOpen() {
|
|
||||||
const [state] = useApplicationContext()
|
|
||||||
|
|
||||||
return state[WALLET_MODAL_OPEN]
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useWalletModalToggle() {
|
|
||||||
const [, { toggleWalletModal }] = useApplicationContext()
|
|
||||||
|
|
||||||
return toggleWalletModal
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useUserAdvanced() {
|
|
||||||
const [state] = useApplicationContext()
|
|
||||||
|
|
||||||
return state[USER_ADVANCED]
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useToggleUserAdvanced() {
|
|
||||||
const [, { toggleUserAdvanced }] = useApplicationContext()
|
|
||||||
return toggleUserAdvanced
|
|
||||||
}
|
|
||||||
|
|
||||||
export function usePopups(): [
|
|
||||||
ApplicationState['POPUP_LIST'],
|
|
||||||
(content: React.ReactElement) => void,
|
|
||||||
(key: number) => void
|
|
||||||
] {
|
|
||||||
const [state, { setPopups }] = useApplicationContext()
|
|
||||||
|
|
||||||
const index = state[POPUP_KEY]
|
|
||||||
const currentPopups = state[POPUP_LIST]
|
|
||||||
|
|
||||||
function addPopup(content: React.ReactElement): void {
|
|
||||||
const newItem = {
|
|
||||||
show: true,
|
|
||||||
key: index,
|
|
||||||
content: content
|
|
||||||
}
|
|
||||||
currentPopups.push(newItem)
|
|
||||||
setPopups(currentPopups)
|
|
||||||
}
|
|
||||||
|
|
||||||
function removePopup(key: number): void {
|
|
||||||
currentPopups.map(item => {
|
|
||||||
if (key === item.key) {
|
|
||||||
item.show = false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
setPopups(currentPopups)
|
|
||||||
}
|
|
||||||
|
|
||||||
const activePopups = currentPopups.filter(item => {
|
|
||||||
return item.show
|
|
||||||
})
|
|
||||||
|
|
||||||
return [activePopups, addPopup, removePopup]
|
|
||||||
}
|
|
@ -1,8 +1,8 @@
|
|||||||
import React, { createContext, useContext, useReducer, useRef, useMemo, useCallback, useEffect, ReactNode } from 'react'
|
import React, { createContext, useContext, useReducer, useRef, useMemo, useCallback, useEffect, ReactNode } from 'react'
|
||||||
import { TokenAmount, Token, JSBI, WETH } from '@uniswap/sdk'
|
import { TokenAmount, Token, JSBI, WETH } from '@uniswap/sdk'
|
||||||
|
import { useBlockNumber } from '../state/application/hooks'
|
||||||
|
|
||||||
import { useAllTokens } from './Tokens'
|
import { useAllTokens } from './Tokens'
|
||||||
import { useBlockNumber } from './Application'
|
|
||||||
import { useWeb3React, useDebounce } from '../hooks'
|
import { useWeb3React, useDebounce } from '../hooks'
|
||||||
|
|
||||||
import { getEtherBalance, getTokenBalance, isAddress } from '../utils'
|
import { getEtherBalance, getTokenBalance, isAddress } from '../utils'
|
||||||
@ -158,28 +158,46 @@ function useBalancesContext() {
|
|||||||
export default function Provider({ children }: { children: ReactNode }) {
|
export default function Provider({ children }: { children: ReactNode }) {
|
||||||
const [state, dispatch] = useReducer(reducer, undefined, initialize)
|
const [state, dispatch] = useReducer(reducer, undefined, initialize)
|
||||||
|
|
||||||
const startListening = useCallback((chainId, address, tokenAddress) => {
|
const startListening = useCallback(
|
||||||
dispatch({ type: Action.START_LISTENING, payload: { chainId, address, tokenAddress } })
|
(chainId, address, tokenAddress) => {
|
||||||
}, [])
|
dispatch({ type: Action.START_LISTENING, payload: { chainId, address, tokenAddress } })
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
)
|
||||||
|
|
||||||
const stopListening = useCallback((chainId, address, tokenAddress) => {
|
const stopListening = useCallback(
|
||||||
dispatch({ type: Action.STOP_LISTENING, payload: { chainId, address, tokenAddress } })
|
(chainId, address, tokenAddress) => {
|
||||||
}, [])
|
dispatch({ type: Action.STOP_LISTENING, payload: { chainId, address, tokenAddress } })
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
)
|
||||||
|
|
||||||
const update = useCallback((chainId, address, tokenAddress, value, blockNumber) => {
|
const update = useCallback(
|
||||||
dispatch({ type: Action.UPDATE, payload: { chainId, address, tokenAddress, value, blockNumber } })
|
(chainId, address, tokenAddress, value, blockNumber) => {
|
||||||
}, [])
|
dispatch({ type: Action.UPDATE, payload: { chainId, address, tokenAddress, value, blockNumber } })
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
)
|
||||||
|
|
||||||
const batchUpdateAccount = useCallback((chainId, address, tokenAddresses, values, blockNumber) => {
|
const batchUpdateAccount = useCallback(
|
||||||
dispatch({ type: Action.BATCH_UPDATE_ACCOUNT, payload: { chainId, address, tokenAddresses, values, blockNumber } })
|
(chainId, address, tokenAddresses, values, blockNumber) => {
|
||||||
}, [])
|
dispatch({
|
||||||
|
type: Action.BATCH_UPDATE_ACCOUNT,
|
||||||
|
payload: { chainId, address, tokenAddresses, values, blockNumber }
|
||||||
|
})
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
)
|
||||||
|
|
||||||
const batchUpdateExchanges = useCallback((chainId, pairAddresses, tokenAddresses, values, blockNumber) => {
|
const batchUpdateExchanges = useCallback(
|
||||||
dispatch({
|
(chainId, pairAddresses, tokenAddresses, values, blockNumber) => {
|
||||||
type: Action.BATCH_UPDATE_EXCHANGES,
|
dispatch({
|
||||||
payload: { chainId, pairAddresses, tokenAddresses, values, blockNumber }
|
type: Action.BATCH_UPDATE_EXCHANGES,
|
||||||
})
|
payload: { chainId, pairAddresses, tokenAddresses, values, blockNumber }
|
||||||
}, [])
|
})
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BalancesContext.Provider
|
<BalancesContext.Provider
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import React, { createContext, useContext, useReducer, useMemo, useCallback, useEffect } from 'react'
|
import React, { createContext, useContext, useReducer, useMemo, useCallback, useEffect } from 'react'
|
||||||
|
|
||||||
import TxnPopup from '../components/TxnPopup'
|
|
||||||
|
|
||||||
import { useWeb3React } from '../hooks'
|
import { useWeb3React } from '../hooks'
|
||||||
import { useBlockNumber, usePopups } from './Application'
|
import { useBlockNumber, usePopups } from '../state/application/hooks'
|
||||||
|
|
||||||
const ADD = 'ADD'
|
const ADD = 'ADD'
|
||||||
const CHECK = 'CHECK'
|
const CHECK = 'CHECK'
|
||||||
@ -140,23 +138,17 @@ export function Updater() {
|
|||||||
finalize(chainId, hash, receipt)
|
finalize(chainId, hash, receipt)
|
||||||
// add success or failure popup
|
// add success or failure popup
|
||||||
if (receipt.status === 1) {
|
if (receipt.status === 1) {
|
||||||
addPopup(
|
addPopup({
|
||||||
<TxnPopup
|
txn: {
|
||||||
popKey={1}
|
hash,
|
||||||
hash={hash}
|
success: true,
|
||||||
success={true}
|
summary: allTransactions[hash]?.response?.summary
|
||||||
summary={allTransactions[hash]?.response?.summary}
|
}
|
||||||
/>
|
})
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
addPopup(
|
addPopup({
|
||||||
<TxnPopup
|
txn: { hash, success: false, summary: allTransactions[hash]?.response?.summary }
|
||||||
popKey={2}
|
})
|
||||||
hash={hash}
|
|
||||||
success={false}
|
|
||||||
summary={allTransactions[hash]?.response?.summary}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { Web3Provider } from '@ethersproject/providers'
|
||||||
import { useState, useMemo, useCallback, useEffect, useRef } from 'react'
|
import { useState, useMemo, useCallback, useEffect, useRef } from 'react'
|
||||||
import { useWeb3React as useWeb3ReactCore } from '@web3-react/core'
|
import { useWeb3React as useWeb3ReactCore } from '@web3-react/core'
|
||||||
import { isMobile } from 'react-device-detect'
|
import { isMobile } from 'react-device-detect'
|
||||||
@ -9,8 +10,8 @@ import { NetworkContextName } from '../constants'
|
|||||||
import { getContract, getExchangeContract, isAddress } from '../utils'
|
import { getContract, getExchangeContract, isAddress } from '../utils'
|
||||||
|
|
||||||
export function useWeb3React() {
|
export function useWeb3React() {
|
||||||
const context = useWeb3ReactCore()
|
const context = useWeb3ReactCore<Web3Provider>()
|
||||||
const contextNetwork = useWeb3ReactCore(NetworkContextName)
|
const contextNetwork = useWeb3ReactCore<Web3Provider>(NetworkContextName)
|
||||||
return context.active ? context : contextNetwork
|
return context.active ? context : contextNetwork
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,14 +3,16 @@ import ReactDOM from 'react-dom'
|
|||||||
import ReactGA from 'react-ga'
|
import ReactGA from 'react-ga'
|
||||||
import { Web3ReactProvider, createWeb3ReactRoot } from '@web3-react/core'
|
import { Web3ReactProvider, createWeb3ReactRoot } from '@web3-react/core'
|
||||||
import { Web3Provider } from '@ethersproject/providers'
|
import { Web3Provider } from '@ethersproject/providers'
|
||||||
|
import { Provider } from 'react-redux'
|
||||||
|
|
||||||
import { NetworkContextName } from './constants'
|
import { NetworkContextName } from './constants'
|
||||||
import { isMobile } from 'react-device-detect'
|
import { isMobile } from 'react-device-detect'
|
||||||
import LocalStorageContextProvider, { Updater as LocalStorageContextUpdater } from './contexts/LocalStorage'
|
import LocalStorageContextProvider, { Updater as LocalStorageContextUpdater } from './contexts/LocalStorage'
|
||||||
import ApplicationContextProvider, { Updater as ApplicationContextUpdater } from './contexts/Application'
|
|
||||||
import TransactionContextProvider, { Updater as TransactionContextUpdater } from './contexts/Transactions'
|
import TransactionContextProvider, { Updater as TransactionContextUpdater } from './contexts/Transactions'
|
||||||
import BalancesContextProvider, { Updater as BalancesContextUpdater } from './contexts/Balances'
|
import BalancesContextProvider, { Updater as BalancesContextUpdater } from './contexts/Balances'
|
||||||
import App from './pages/App'
|
import App from './pages/App'
|
||||||
|
import store from './state'
|
||||||
|
import { Updater as ApplicationContextUpdater } from './state/application/updater'
|
||||||
import ThemeProvider, { FixedGlobalStyle, ThemedGlobalStyle } from './theme'
|
import ThemeProvider, { FixedGlobalStyle, ThemedGlobalStyle } from './theme'
|
||||||
import './i18n'
|
import './i18n'
|
||||||
|
|
||||||
@ -36,11 +38,9 @@ ReactGA.pageview(window.location.pathname + window.location.search)
|
|||||||
function ContextProviders({ children }: { children: React.ReactNode }) {
|
function ContextProviders({ children }: { children: React.ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<LocalStorageContextProvider>
|
<LocalStorageContextProvider>
|
||||||
<ApplicationContextProvider>
|
<TransactionContextProvider>
|
||||||
<TransactionContextProvider>
|
<BalancesContextProvider>{children}</BalancesContextProvider>
|
||||||
<BalancesContextProvider>{children}</BalancesContextProvider>
|
</TransactionContextProvider>
|
||||||
</TransactionContextProvider>
|
|
||||||
</ApplicationContextProvider>
|
|
||||||
</LocalStorageContextProvider>
|
</LocalStorageContextProvider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -61,15 +61,17 @@ ReactDOM.render(
|
|||||||
<FixedGlobalStyle />
|
<FixedGlobalStyle />
|
||||||
<Web3ReactProvider getLibrary={getLibrary}>
|
<Web3ReactProvider getLibrary={getLibrary}>
|
||||||
<Web3ProviderNetwork getLibrary={getLibrary}>
|
<Web3ProviderNetwork getLibrary={getLibrary}>
|
||||||
<ContextProviders>
|
<Provider store={store}>
|
||||||
<Updaters />
|
<ContextProviders>
|
||||||
<ThemeProvider>
|
<Updaters />
|
||||||
<>
|
<ThemeProvider>
|
||||||
<ThemedGlobalStyle />
|
<>
|
||||||
<App />
|
<ThemedGlobalStyle />
|
||||||
</>
|
<App />
|
||||||
</ThemeProvider>
|
</>
|
||||||
</ContextProviders>
|
</ThemeProvider>
|
||||||
|
</ContextProviders>
|
||||||
|
</Provider>
|
||||||
</Web3ProviderNetwork>
|
</Web3ProviderNetwork>
|
||||||
</Web3ReactProvider>
|
</Web3ReactProvider>
|
||||||
</>,
|
</>,
|
||||||
|
28
src/state/application/actions.ts
Normal file
28
src/state/application/actions.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { createAction } from '@reduxjs/toolkit'
|
||||||
|
|
||||||
|
export type PopupContent =
|
||||||
|
| {
|
||||||
|
txn: {
|
||||||
|
hash: string
|
||||||
|
success?: boolean
|
||||||
|
summary?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
poolAdded: {
|
||||||
|
token0?: {
|
||||||
|
address?: string
|
||||||
|
symbol?: string
|
||||||
|
}
|
||||||
|
token1: {
|
||||||
|
address?: string
|
||||||
|
symbol?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const updateBlockNumber = createAction<{ networkId: number; blockNumber: number | null }>('updateBlockNumber')
|
||||||
|
export const toggleWalletModal = createAction<void>('toggleWalletModal')
|
||||||
|
export const toggleUserAdvanced = createAction<void>('toggleUserAdvanced')
|
||||||
|
export const addPopup = createAction<{ content: PopupContent }>('addPopup')
|
||||||
|
export const removePopup = createAction<{ key: string }>('removePopup')
|
49
src/state/application/hooks.ts
Normal file
49
src/state/application/hooks.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { useCallback } from 'react'
|
||||||
|
import { useWeb3React } from '../../hooks'
|
||||||
|
import { addPopup, PopupContent, removePopup, toggleWalletModal } from './actions'
|
||||||
|
import { useSelector, useDispatch } from 'react-redux'
|
||||||
|
import { AppState } from '../index'
|
||||||
|
|
||||||
|
export function useBlockNumber() {
|
||||||
|
const { chainId } = useWeb3React()
|
||||||
|
|
||||||
|
return useSelector((state: AppState) => state.application.blockNumber[chainId])
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useWalletModalOpen() {
|
||||||
|
return useSelector((state: AppState) => state.application.walletModalOpen)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useWalletModalToggle() {
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
return useCallback(() => dispatch(toggleWalletModal()), [dispatch])
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useUserAdvanced() {
|
||||||
|
return useSelector((state: AppState) => state.application.userAdvanced)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function usePopups(): [
|
||||||
|
AppState['application']['popupList'],
|
||||||
|
(content: PopupContent) => void,
|
||||||
|
(key: string) => void
|
||||||
|
] {
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
const activePopups = useSelector((state: AppState) => state.application.popupList.filter(item => item.show))
|
||||||
|
|
||||||
|
const wrappedAddPopup = useCallback(
|
||||||
|
(content: PopupContent) => {
|
||||||
|
dispatch(addPopup({ content }))
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
)
|
||||||
|
|
||||||
|
const wrappedRemovePopup = useCallback(
|
||||||
|
(key: string) => {
|
||||||
|
dispatch(removePopup({ key }))
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
)
|
||||||
|
|
||||||
|
return [activePopups, wrappedAddPopup, wrappedRemovePopup]
|
||||||
|
}
|
53
src/state/application/reducer.ts
Normal file
53
src/state/application/reducer.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import { createReducer, nanoid } from '@reduxjs/toolkit'
|
||||||
|
import {
|
||||||
|
addPopup,
|
||||||
|
PopupContent,
|
||||||
|
removePopup,
|
||||||
|
toggleUserAdvanced,
|
||||||
|
toggleWalletModal,
|
||||||
|
updateBlockNumber
|
||||||
|
} from './actions'
|
||||||
|
|
||||||
|
type PopupList = Array<{ key: string; show: boolean; content: PopupContent }>
|
||||||
|
|
||||||
|
interface ApplicationState {
|
||||||
|
blockNumber: { [chainId: number]: number }
|
||||||
|
popupList: PopupList
|
||||||
|
walletModalOpen: boolean
|
||||||
|
userAdvanced: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState: ApplicationState = {
|
||||||
|
blockNumber: {},
|
||||||
|
popupList: [],
|
||||||
|
walletModalOpen: false,
|
||||||
|
userAdvanced: false
|
||||||
|
}
|
||||||
|
|
||||||
|
export default createReducer(initialState, builder =>
|
||||||
|
builder
|
||||||
|
.addCase(updateBlockNumber, (state, action) => {
|
||||||
|
const { networkId, blockNumber } = action.payload
|
||||||
|
state.blockNumber[networkId] = blockNumber
|
||||||
|
})
|
||||||
|
.addCase(toggleUserAdvanced, state => {
|
||||||
|
state.userAdvanced = !state.userAdvanced
|
||||||
|
})
|
||||||
|
.addCase(toggleWalletModal, state => {
|
||||||
|
state.walletModalOpen = !state.walletModalOpen
|
||||||
|
})
|
||||||
|
.addCase(addPopup, (state, { payload: { content } }) => {
|
||||||
|
state.popupList.push({
|
||||||
|
key: nanoid(),
|
||||||
|
show: true,
|
||||||
|
content
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.addCase(removePopup, (state, { payload: { key } }) => {
|
||||||
|
state.popupList.forEach(p => {
|
||||||
|
if (p.key === key) {
|
||||||
|
p.show = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
41
src/state/application/updater.ts
Normal file
41
src/state/application/updater.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { useEffect } from 'react'
|
||||||
|
import { useWeb3React } from '../../hooks'
|
||||||
|
import { updateBlockNumber } from './actions'
|
||||||
|
import { useDispatch } from 'react-redux'
|
||||||
|
|
||||||
|
export function Updater() {
|
||||||
|
const { library, chainId } = useWeb3React()
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
|
||||||
|
// update block number
|
||||||
|
useEffect(() => {
|
||||||
|
if (library) {
|
||||||
|
let stale = false
|
||||||
|
|
||||||
|
const update = () => {
|
||||||
|
library
|
||||||
|
.getBlockNumber()
|
||||||
|
.then(blockNumber => {
|
||||||
|
if (!stale) {
|
||||||
|
dispatch(updateBlockNumber({ networkId: chainId, blockNumber }))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
if (!stale) {
|
||||||
|
dispatch(updateBlockNumber({ networkId: chainId, blockNumber: null }))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
update()
|
||||||
|
library.on('block', update)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
stale = true
|
||||||
|
library.removeListener('block', update)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [dispatch, chainId, library])
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
13
src/state/index.ts
Normal file
13
src/state/index.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { configureStore } from '@reduxjs/toolkit'
|
||||||
|
import application from './application/reducer'
|
||||||
|
|
||||||
|
const store = configureStore({
|
||||||
|
reducer: {
|
||||||
|
application
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export default store
|
||||||
|
|
||||||
|
export type AppState = ReturnType<typeof store.getState>
|
||||||
|
export type AppDispatch = typeof store.dispatch
|
60
yarn.lock
60
yarn.lock
@ -2074,6 +2074,16 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@reach/visually-hidden/-/visually-hidden-0.1.4.tgz#0dc4ecedf523004337214187db70a46183bd945b"
|
resolved "https://registry.yarnpkg.com/@reach/visually-hidden/-/visually-hidden-0.1.4.tgz#0dc4ecedf523004337214187db70a46183bd945b"
|
||||||
integrity sha512-QHbzXjflSlCvDd6vJwdwx16mSB+vUCCQMiU/wK/CgVNPibtpEiIbisyxkpZc55DyDFNUIqP91rSUsNae+ogGDQ==
|
integrity sha512-QHbzXjflSlCvDd6vJwdwx16mSB+vUCCQMiU/wK/CgVNPibtpEiIbisyxkpZc55DyDFNUIqP91rSUsNae+ogGDQ==
|
||||||
|
|
||||||
|
"@reduxjs/toolkit@^1.3.5":
|
||||||
|
version "1.3.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-1.3.5.tgz#37c1ab6de9aa66f95bab25a8e9bd9d8ec3b7b80c"
|
||||||
|
integrity sha512-QVqI2T6kwT/3CVdCa6KjUDdEz9YY1eCLQVcRZamiaOAcKI7kkJSh2P0GjaaKXTjIFy0u9sWCXjzifPJNGoXjlw==
|
||||||
|
dependencies:
|
||||||
|
immer "^6.0.1"
|
||||||
|
redux "^4.0.0"
|
||||||
|
redux-thunk "^2.3.0"
|
||||||
|
reselect "^4.0.0"
|
||||||
|
|
||||||
"@samverschueren/stream-to-observable@^0.3.0":
|
"@samverschueren/stream-to-observable@^0.3.0":
|
||||||
version "0.3.0"
|
version "0.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f"
|
resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f"
|
||||||
@ -2413,7 +2423,7 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.5.tgz#527d20ef68571a4af02ed74350164e7a67544860"
|
resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.5.tgz#527d20ef68571a4af02ed74350164e7a67544860"
|
||||||
integrity sha512-wLD/Aq2VggCJXSjxEwrMafIP51Z+13H78nXIX0ABEuIGhmB5sNGbR113MOKo+yfw+RDo1ZU3DM6yfnnRF/+ouw==
|
integrity sha512-wLD/Aq2VggCJXSjxEwrMafIP51Z+13H78nXIX0ABEuIGhmB5sNGbR113MOKo+yfw+RDo1ZU3DM6yfnnRF/+ouw==
|
||||||
|
|
||||||
"@types/hoist-non-react-statics@*":
|
"@types/hoist-non-react-statics@*", "@types/hoist-non-react-statics@^3.3.0":
|
||||||
version "3.3.1"
|
version "3.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
|
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
|
||||||
integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
|
integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
|
||||||
@ -2527,6 +2537,16 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/react" "*"
|
"@types/react" "*"
|
||||||
|
|
||||||
|
"@types/react-redux@^7.1.8":
|
||||||
|
version "7.1.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.8.tgz#3631feb559f7858d6ad9eea1d6ef41fa64fe7205"
|
||||||
|
integrity sha512-kpplH7Wg2SYU00sZVT98WBN0ou6QKrYcShRaW+5Vpe5l7bluKWJbWmAL+ieiso07OQzpcP5i1PeY3690640ZWg==
|
||||||
|
dependencies:
|
||||||
|
"@types/hoist-non-react-statics" "^3.3.0"
|
||||||
|
"@types/react" "*"
|
||||||
|
hoist-non-react-statics "^3.3.0"
|
||||||
|
redux "^4.0.0"
|
||||||
|
|
||||||
"@types/react-router-dom@^5.0.0":
|
"@types/react-router-dom@^5.0.0":
|
||||||
version "5.1.5"
|
version "5.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.5.tgz#7c334a2ea785dbad2b2dcdd83d2cf3d9973da090"
|
resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.5.tgz#7c334a2ea785dbad2b2dcdd83d2cf3d9973da090"
|
||||||
@ -9216,6 +9236,11 @@ immer@1.10.0:
|
|||||||
resolved "https://registry.yarnpkg.com/immer/-/immer-1.10.0.tgz#bad67605ba9c810275d91e1c2a47d4582e98286d"
|
resolved "https://registry.yarnpkg.com/immer/-/immer-1.10.0.tgz#bad67605ba9c810275d91e1c2a47d4582e98286d"
|
||||||
integrity sha512-O3sR1/opvCDGLEVcvrGTMtLac8GJ5IwZC4puPrLuRj3l7ICKvkmA0vGuU9OW8mV9WIBRnaxp5GJh9IEAaNOoYg==
|
integrity sha512-O3sR1/opvCDGLEVcvrGTMtLac8GJ5IwZC4puPrLuRj3l7ICKvkmA0vGuU9OW8mV9WIBRnaxp5GJh9IEAaNOoYg==
|
||||||
|
|
||||||
|
immer@^6.0.1:
|
||||||
|
version "6.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/immer/-/immer-6.0.5.tgz#77187d13b71c6cee40dde3b8e87a50a7a636d630"
|
||||||
|
integrity sha512-Q2wd90qrgFieIpLzAO2q9NLEdmyp/sr76Ml4Vm5peUKgyTa2CQa3ey8zuzwSKOlKH7grCeGBGUcLLVCVW1aguA==
|
||||||
|
|
||||||
import-cwd@^2.0.0:
|
import-cwd@^2.0.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9"
|
resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9"
|
||||||
@ -13993,11 +14018,22 @@ react-i18next@^10.7.0:
|
|||||||
"@babel/runtime" "^7.3.1"
|
"@babel/runtime" "^7.3.1"
|
||||||
html-parse-stringify2 "2.0.1"
|
html-parse-stringify2 "2.0.1"
|
||||||
|
|
||||||
react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1, react-is@^16.8.4:
|
react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.9.0:
|
||||||
version "16.13.1"
|
version "16.13.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||||
|
|
||||||
|
react-redux@^7.2.0:
|
||||||
|
version "7.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.0.tgz#f970f62192b3981642fec46fd0db18a074fe879d"
|
||||||
|
integrity sha512-EvCAZYGfOLqwV7gh849xy9/pt55rJXPwmYvI4lilPM5rUT/1NxuuN59ipdBksRVSvz0KInbPnp4IfoXJXCqiDA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.5.5"
|
||||||
|
hoist-non-react-statics "^3.3.0"
|
||||||
|
loose-envify "^1.4.0"
|
||||||
|
prop-types "^15.7.2"
|
||||||
|
react-is "^16.9.0"
|
||||||
|
|
||||||
react-remove-scroll-bar@^1.1.5:
|
react-remove-scroll-bar@^1.1.5:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-1.2.0.tgz#07250b2bc581f56315759c454c9b159dd04ba49d"
|
resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-1.2.0.tgz#07250b2bc581f56315759c454c9b159dd04ba49d"
|
||||||
@ -14280,6 +14316,19 @@ recursive-readdir@2.2.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
minimatch "3.0.4"
|
minimatch "3.0.4"
|
||||||
|
|
||||||
|
redux-thunk@^2.3.0:
|
||||||
|
version "2.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622"
|
||||||
|
integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==
|
||||||
|
|
||||||
|
redux@^4.0.0:
|
||||||
|
version "4.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f"
|
||||||
|
integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==
|
||||||
|
dependencies:
|
||||||
|
loose-envify "^1.4.0"
|
||||||
|
symbol-observable "^1.2.0"
|
||||||
|
|
||||||
reflexbox@^4.0.6:
|
reflexbox@^4.0.6:
|
||||||
version "4.0.6"
|
version "4.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/reflexbox/-/reflexbox-4.0.6.tgz#fc756d2cc1ca493baf9b96bb27dd640ad8154cf1"
|
resolved "https://registry.yarnpkg.com/reflexbox/-/reflexbox-4.0.6.tgz#fc756d2cc1ca493baf9b96bb27dd640ad8154cf1"
|
||||||
@ -14564,6 +14613,11 @@ requires-port@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
||||||
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
|
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
|
||||||
|
|
||||||
|
reselect@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7"
|
||||||
|
integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA==
|
||||||
|
|
||||||
resolve-cwd@^2.0.0:
|
resolve-cwd@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
|
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
|
||||||
@ -15938,7 +15992,7 @@ swr@0.1.18:
|
|||||||
dependencies:
|
dependencies:
|
||||||
fast-deep-equal "2.0.1"
|
fast-deep-equal "2.0.1"
|
||||||
|
|
||||||
symbol-observable@^1.1.0:
|
symbol-observable@^1.1.0, symbol-observable@^1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
|
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
|
||||||
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
|
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
|
||||||
|
Loading…
Reference in New Issue
Block a user