Commit 2f0e2fb2 authored by Noah Zinsmeister's avatar Noah Zinsmeister Committed by GitHub

Beta cleanup (#285)

* improve context logic

* fix font-variant

* add dependencies for later

* fix icon
parent 8f2c347d
{
"extends": "react-app"
}
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
"homepage": ".", "homepage": ".",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@reach/tooltip": "^0.2.0",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"escape-string-regexp": "^2.0.0", "escape-string-regexp": "^2.0.0",
"ethers": "^4.0.27", "ethers": "^4.0.27",
...@@ -12,15 +13,16 @@ ...@@ -12,15 +13,16 @@
"i18next-browser-languagedetector": "^3.0.1", "i18next-browser-languagedetector": "^3.0.1",
"i18next-xhr-backend": "^2.0.1", "i18next-xhr-backend": "^2.0.1",
"jazzicon": "^1.5.0", "jazzicon": "^1.5.0",
"lodash.merge": "^4.6.1",
"node-sass": "^4.11.0", "node-sass": "^4.11.0",
"react": "^16.8.6", "react": "^16.8.6",
"react-aria-modal": "^4.0.0",
"react-dom": "^16.8.6", "react-dom": "^16.8.6",
"react-ga": "^2.5.7", "react-ga": "^2.5.7",
"react-i18next": "^10.7.0", "react-i18next": "^10.7.0",
"react-router-dom": "^5.0.0", "react-router-dom": "^5.0.0",
"react-scripts": "^3.0.0", "react-scripts": "^3.0.1",
"react-transition-group": "1.x", "react-transition-group": "1.x",
"styled-components": "^4.2.0",
"ua-parser-js": "^0.7.18", "ua-parser-js": "^0.7.18",
"web3-react": "^5.0.4" "web3-react": "^5.0.4"
}, },
...@@ -40,14 +42,23 @@ ...@@ -40,14 +42,23 @@
"check:format": "yarn format:base --check", "check:format": "yarn format:base --check",
"check:all": "yarn check:lint && yarn check:format" "check:all": "yarn check:lint && yarn check:format"
}, },
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"license": "GPL-3.0-or-later", "license": "GPL-3.0-or-later",
"devDependencies": { "devDependencies": {
"prettier": "^1.17.0" "prettier": "^1.17.0"
}, }
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
} }
...@@ -11,8 +11,8 @@ import { isAddress, calculateGasMargin } from '../../utils' ...@@ -11,8 +11,8 @@ import { isAddress, calculateGasMargin } from '../../utils'
import Modal from '../Modal' import Modal from '../Modal'
import TokenLogo from '../TokenLogo' import TokenLogo from '../TokenLogo'
import SearchIcon from '../../assets/images/magnifying-glass.svg' import SearchIcon from '../../assets/images/magnifying-glass.svg'
import { useTokenDetails, useAllTokenDetails } from '../../contexts/Static' import { useTransactionAdder, usePendingApproval } from '../../contexts/Transactions'
import { useTransactionContext, usePendingApproval } from '../../contexts/Transaction' import { useTokenDetails, useAllTokenDetails } from '../../contexts/Tokens'
import './currency-panel.scss' import './currency-panel.scss'
...@@ -43,7 +43,7 @@ export default function CurrencyInputPanel({ ...@@ -43,7 +43,7 @@ export default function CurrencyInputPanel({
const pendingApproval = usePendingApproval(selectedTokenAddress) const pendingApproval = usePendingApproval(selectedTokenAddress)
const { addTransaction } = useTransactionContext() const addTransaction = useTransactionAdder()
const inputRef = useRef() const inputRef = useRef()
const allTokens = useAllTokenDetails() const allTokens = useAllTokenDetails()
...@@ -74,7 +74,7 @@ export default function CurrencyInputPanel({ ...@@ -74,7 +74,7 @@ export default function CurrencyInputPanel({
gasLimit: calculateGasMargin(estimatedGas, GAS_MARGIN) gasLimit: calculateGasMargin(estimatedGas, GAS_MARGIN)
}) })
.then(response => { .then(response => {
addTransaction(response.hash, response) addTransaction(response)
}) })
}} }}
> >
......
...@@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next' ...@@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next'
import { useBodyKeyDown } from '../../hooks' import { useBodyKeyDown } from '../../hooks'
import './navigation-tabs.scss' import './navigation-tabs.scss'
import { useApplicationContext } from '../../contexts/Application' import { useBetaMessageManager } from '../../contexts/Application'
const tabOrder = [ const tabOrder = [
{ {
...@@ -28,7 +28,7 @@ const tabOrder = [ ...@@ -28,7 +28,7 @@ const tabOrder = [
function NavigationTabs({ location: { pathname }, history }) { function NavigationTabs({ location: { pathname }, history }) {
const { t } = useTranslation() const { t } = useTranslation()
const { showBetaMessage, dismissBetaMessage } = useApplicationContext() const [showBetaMessage, dismissBetaMessage] = useBetaMessageManager()
const navigate = useCallback( const navigate = useCallback(
direction => { direction => {
......
...@@ -7,7 +7,7 @@ import { useTranslation } from 'react-i18next' ...@@ -7,7 +7,7 @@ import { useTranslation } from 'react-i18next'
import { ethers } from 'ethers' import { ethers } from 'ethers'
import Modal from '../Modal' import Modal from '../Modal'
import { useAllTransactions } from '../../contexts/Transaction' import { useAllTransactions } from '../../contexts/Transactions'
import './web3-status.scss' import './web3-status.scss'
...@@ -116,7 +116,15 @@ export default function Web3Status() { ...@@ -116,7 +116,15 @@ export default function Web3Status() {
return return
} else { } else {
el.innerHTML = '' el.innerHTML = ''
el.appendChild(Jazzicon(16, parseInt(account.slice(2), 16))) el.appendChild(
Jazzicon(
16,
ethers.utils
.bigNumberify(account)
.mod(Number.MAX_SAFE_INTEGER)
.toNumber()
)
)
} }
}} }}
/> />
......
import React, { createContext, useContext, useReducer, useCallback, useMemo, useEffect } from 'react'
import { useWeb3Context } from 'web3-react'
import { safeAccess, isAddress, getTokenAllowance } from '../utils'
import { useBlockNumber } from './Application'
const UPDATE = 'UPDATE'
const AllowancesContext = createContext()
function useAllowancesContext() {
return useContext(AllowancesContext)
}
function reducer(state, { type, payload }) {
switch (type) {
case UPDATE: {
const { networkId, address, tokenAddress, spenderAddress, value, blockNumber } = payload
return {
...state,
[networkId]: {
...(safeAccess(state, [networkId]) || {}),
[address]: {
...(safeAccess(state, [networkId, address]) || {}),
[tokenAddress]: {
...(safeAccess(state, [networkId, address, tokenAddress]) || {}),
[spenderAddress]: {
value,
blockNumber
}
}
}
}
}
}
default: {
throw Error(`Unexpected action type in AllowancesContext reducer: '${type}'.`)
}
}
}
export default function Provider({ children }) {
const [state, dispatch] = useReducer(reducer, {})
const update = useCallback((networkId, address, tokenAddress, spenderAddress, value, blockNumber) => {
dispatch({ type: UPDATE, payload: { networkId, address, tokenAddress, spenderAddress, value, blockNumber } })
}, [])
const contextValue = useMemo(() => [state, { update }], [state, update])
return <AllowancesContext.Provider value={contextValue}>{children}</AllowancesContext.Provider>
}
export function useAddressAllowance(address, tokenAddress, spenderAddress) {
const { networkId, library } = useWeb3Context()
const globalBlockNumber = useBlockNumber()
const [state, { update }] = useAllowancesContext()
const { value, blockNumber } = safeAccess(state, [networkId, address, tokenAddress, spenderAddress]) || {}
useEffect(() => {
if (
isAddress(address) &&
isAddress(tokenAddress) &&
isAddress(spenderAddress) &&
(value === undefined || blockNumber !== globalBlockNumber) &&
(networkId || networkId === 0) &&
library
) {
let stale = false
getTokenAllowance(address, tokenAddress, spenderAddress, library)
.then(value => {
if (!stale) {
update(networkId, address, tokenAddress, spenderAddress, value, globalBlockNumber)
}
})
.catch(() => {
if (!stale) {
update(networkId, address, tokenAddress, spenderAddress, null, globalBlockNumber)
}
})
return () => {
stale = true
}
}
}, [address, tokenAddress, spenderAddress, value, blockNumber, globalBlockNumber, networkId, library, update])
return value
}
import React, { Component, createContext, useContext, useEffect } from 'react' import React, { createContext, useContext, useReducer, useCallback, useMemo, useEffect } from 'react'
import { useWeb3Context } from 'web3-react' import { useWeb3Context } from 'web3-react'
import { safeAccess } from '../utils'
import { useBlockEffect } from '../hooks' const SHOW_BETA_MESSAGE = 'SHOW_BETA_MESSAGE'
const BLOCK_NUMBERS = 'BLOCK_NUMBERS'
const DISMISS_BETA_MESSAGE = 'DISMISS_BETA_MESSAGE'
const UPDATE_BLOCK_NUMBER = 'UPDATE_BLOCK_NUMBER'
const ApplicationContext = createContext() const ApplicationContext = createContext()
export default class Provider extends Component { function useApplicationContext() {
constructor(props) { return useContext(ApplicationContext)
super(props) }
this.dismissBetaMessage = () => { function reducer(state, { type, payload }) {
this.setState({ showBetaMessage: false }) switch (type) {
case DISMISS_BETA_MESSAGE: {
return {
...state,
[SHOW_BETA_MESSAGE]: false
}
} }
case UPDATE_BLOCK_NUMBER: {
this.updateBlockNumber = blockNumber => { const { networkId, blockNumber } = payload
this.setState({ blockNumber }) return {
...state,
[BLOCK_NUMBERS]: {
...(safeAccess(state, [BLOCK_NUMBERS]) || {}),
[networkId]: blockNumber
}
}
} }
default: {
this.state = { throw Error(`Unexpected action type in ApplicationContext reducer: '${type}'.`)
showBetaMessage: true,
dismissBetaMessage: this.dismissBetaMessage,
blockNumber: undefined,
updateBlockNumber: this.updateBlockNumber
} }
} }
render() {
return <ApplicationContext.Provider value={this.state}>{this.props.children}</ApplicationContext.Provider>
}
} }
export function useApplicationContext() { export default function Provider({ children }) {
return useContext(ApplicationContext) const [state, dispatch] = useReducer(reducer, {
[SHOW_BETA_MESSAGE]: true,
[BLOCK_NUMBERS]: {}
})
const dismissBetaMessage = useCallback(() => {
dispatch({ type: DISMISS_BETA_MESSAGE })
}, [])
const updateBlockNumber = useCallback((networkId, blockNumber) => {
dispatch({ type: UPDATE_BLOCK_NUMBER, payload: { networkId, blockNumber } })
}, [])
const contextValue = useMemo(() => [state, { dismissBetaMessage, updateBlockNumber }], [
state,
dismissBetaMessage,
updateBlockNumber
])
return <ApplicationContext.Provider value={contextValue}>{children}</ApplicationContext.Provider>
} }
export function Updater() { export function Updater() {
const { library } = useWeb3Context() const { networkId, library } = useWeb3Context()
const { updateBlockNumber } = useApplicationContext()
const [, { updateBlockNumber }] = useApplicationContext()
// fetch the block number once on load...
useEffect(() => { useEffect(() => {
if (library) { if ((networkId || networkId === 0) && library) {
let stale = false let stale = false
library function update() {
.getBlockNumber() library
.then(blockNumber => { .getBlockNumber()
if (!stale) { .then(blockNumber => {
updateBlockNumber(blockNumber) if (!stale) {
} updateBlockNumber(networkId, blockNumber)
}) }
.catch(() => { })
if (!stale) { .catch(() => {
updateBlockNumber(null) if (!stale) {
} updateBlockNumber(networkId, null)
}) }
})
}
update()
library.on('block', update)
return () => { return () => {
stale = true stale = true
// this clears block number on network change because the library has changed library.removeListener('block', update)
updateBlockNumber(undefined)
} }
} }
}, [library, updateBlockNumber]) }, [networkId, library, updateBlockNumber])
// ...and every block...
useBlockEffect(updateBlockNumber)
return null return null
} }
export function useBetaMessageManager() {
const [state, { dismissBetaMessage }] = useApplicationContext()
return [safeAccess(state, [SHOW_BETA_MESSAGE]), dismissBetaMessage]
}
export function useBlockNumber() { export function useBlockNumber() {
const { blockNumber } = useApplicationContext() const { networkId } = useWeb3Context()
return blockNumber
const [state] = useApplicationContext()
return safeAccess(state, [BLOCK_NUMBERS, networkId])
} }
import React, { createContext, useContext, useReducer, useCallback, useMemo, useEffect } from 'react'
import { useWeb3Context } from 'web3-react'
import { safeAccess, isAddress, getEtherBalance, getTokenBalance } from '../utils'
import { useBlockNumber } from './Application'
import { useTokenDetails } from './Tokens'
const UPDATE = 'UPDATE'
const BalancesContext = createContext()
function useBalancesContext() {
return useContext(BalancesContext)
}
function reducer(state, { type, payload }) {
switch (type) {
case UPDATE: {
const { networkId, address, tokenAddress, value, blockNumber } = payload
return {
...state,
[networkId]: {
...(safeAccess(state, [networkId]) || {}),
[address]: {
...(safeAccess(state, [networkId, address]) || {}),
[tokenAddress]: {
value,
blockNumber
}
}
}
}
}
default: {
throw Error(`Unexpected action type in BalancesContext reducer: '${type}'.`)
}
}
}
export default function Provider({ children }) {
const [state, dispatch] = useReducer(reducer, {})
const update = useCallback((networkId, address, tokenAddress, value, blockNumber) => {
dispatch({ type: UPDATE, payload: { networkId, address, tokenAddress, value, blockNumber } })
}, [])
const contextValue = useMemo(() => [state, { update }], [state, update])
return <BalancesContext.Provider value={contextValue}>{children}</BalancesContext.Provider>
}
export function useAddressBalance(address, tokenAddress) {
const { networkId, library } = useWeb3Context()
const globalBlockNumber = useBlockNumber()
const [state, { update }] = useBalancesContext()
const { value, blockNumber } = safeAccess(state, [networkId, address, tokenAddress]) || {}
useEffect(() => {
if (
isAddress(address) &&
(tokenAddress === 'ETH' || isAddress(tokenAddress)) &&
(value === undefined || blockNumber !== globalBlockNumber) &&
(networkId || networkId === 0) &&
library
) {
let stale = false
;(tokenAddress === 'ETH' ? getEtherBalance(address, library) : getTokenBalance(tokenAddress, address, library))
.then(value => {
if (!stale) {
update(networkId, address, tokenAddress, value, globalBlockNumber)
}
})
.catch(e => {
if (!stale) {
update(networkId, address, tokenAddress, null, globalBlockNumber)
}
})
return () => {
stale = true
}
}
}, [address, tokenAddress, value, blockNumber, globalBlockNumber, networkId, library, update])
return value
}
export function useExchangeReserves(tokenAddress) {
const { exchangeAddress } = useTokenDetails(tokenAddress)
const reserveETH = useAddressBalance(exchangeAddress, 'ETH')
const reserveToken = useAddressBalance(exchangeAddress, tokenAddress)
return { reserveETH, reserveToken }
}
import React, { Component, createContext, useContext, useEffect } from 'react'
import { useWeb3Context } from 'web3-react'
import merge from 'lodash.merge'
import { getEtherBalance, getTokenBalance, getTokenAllowance, isAddress } from '../utils'
import { useBlockNumber } from './Application'
import { useTokenDetails } from './Static'
// define constants
const BALANCE = 'balance'
const ALLOWANCE = 'allowance'
// node creation
function createAddressValueNode(name, value, blockNumber) {
return { [name]: value, blockNumber }
}
// tree creation
function createAddressBalanceTree(address, tokenAddress, value, blockNumber) {
return { [address]: { [tokenAddress]: createAddressValueNode(BALANCE, value, blockNumber) } }
}
function createAddressAllowanceTree(address, tokenAddress, spenderAddress, value, blockNumber) {
return {
[address]: { [tokenAddress]: { [spenderAddress]: createAddressValueNode(ALLOWANCE, value, blockNumber) } }
}
}
// create contexts
const AddressBalanceContext = createContext()
const AddressAllowanceContext = createContext()
// define providers
class AddressBalanceContextProvider extends Component {
constructor(props) {
super(props)
this.getValue = (address, tokenAddress) => {
return this.state[BALANCE][address] && this.state[BALANCE][address][tokenAddress]
? this.state[BALANCE][address][tokenAddress]
: createAddressValueNode(BALANCE)
}
this.updateValue = (address, tokenAddress, value, blockNumber) => {
this.setState(state => ({
[BALANCE]: merge(state[BALANCE], createAddressBalanceTree(address, tokenAddress, value, blockNumber))
}))
}
this.clearValues = () => {
this.setState({ [BALANCE]: {} })
}
this.state = {
[BALANCE]: {},
getValue: this.getValue,
updateValue: this.updateValue,
clearValues: this.clearValues
}
}
render() {
return <AddressBalanceContext.Provider value={this.state}>{this.props.children}</AddressBalanceContext.Provider>
}
}
class AddressAllowanceContextProvider extends Component {
constructor(props) {
super(props)
this.getValue = (address, tokenAddress, spenderAddress) => {
return this.state[ALLOWANCE][address] &&
this.state[ALLOWANCE][address][tokenAddress] &&
this.state[ALLOWANCE][address][tokenAddress][spenderAddress]
? this.state[ALLOWANCE][address][tokenAddress][spenderAddress]
: createAddressValueNode(ALLOWANCE)
}
this.updateValue = (address, tokenAddress, spenderAddress, value, blockNumber) => {
this.setState(state => ({
[ALLOWANCE]: merge(
state[ALLOWANCE],
createAddressAllowanceTree(address, tokenAddress, spenderAddress, value, blockNumber)
)
}))
}
this.clearValues = () => {
this.setState({ [ALLOWANCE]: {} })
}
this.state = {
[ALLOWANCE]: {},
getValue: this.getValue,
updateValue: this.updateValue,
clearValues: this.clearValues
}
}
render() {
return <AddressAllowanceContext.Provider value={this.state}>{this.props.children}</AddressAllowanceContext.Provider>
}
}
export default function Provider({ children }) {
return (
<AddressBalanceContextProvider>
<AddressAllowanceContextProvider>{children}</AddressAllowanceContextProvider>
</AddressBalanceContextProvider>
)
}
// define useContext wrappers
function useAddressBalanceContext() {
return useContext(AddressBalanceContext)
}
function useAddressAllowanceContext() {
return useContext(AddressAllowanceContext)
}
export function Updater() {
const { networkId } = useWeb3Context()
const { clearValues: clearValuesBalance } = useAddressBalanceContext()
const { clearValues: clearValuesAllowance } = useAddressAllowanceContext()
useEffect(() => {
return () => {
clearValuesBalance()
clearValuesAllowance()
}
}, [clearValuesBalance, clearValuesAllowance, networkId])
return null
}
// define custom hooks
export function useAddressBalance(address, tokenAddress) {
const { library } = useWeb3Context()
const globalBlockNumber = useBlockNumber()
const { getValue, updateValue } = useAddressBalanceContext()
const { [BALANCE]: balance, blockNumber: balanceUpdatedBlockNumber } = getValue(address, tokenAddress)
useEffect(() => {
// gate this entire effect by checking that the inputs are valid
if (isAddress(address) && (tokenAddress === 'ETH' || isAddress(tokenAddress))) {
// if they are, and the balance is undefined or stale, fetch it
if (balance === undefined || balanceUpdatedBlockNumber !== globalBlockNumber) {
let stale = false
;(tokenAddress === 'ETH' ? getEtherBalance(address, library) : getTokenBalance(tokenAddress, address, library))
.then(value => {
if (!stale) {
updateValue(address, tokenAddress, value, globalBlockNumber)
}
})
.catch(() => {
if (!stale) {
updateValue(address, tokenAddress, null, globalBlockNumber)
}
})
return () => {
stale = true
}
}
}
}, [address, tokenAddress, balance, balanceUpdatedBlockNumber, globalBlockNumber, library, updateValue])
return balance
}
export function useAddressAllowance(address, tokenAddress, spenderAddress) {
const { library } = useWeb3Context()
const globalBlockNumber = useBlockNumber()
const { getValue, updateValue } = useAddressAllowanceContext()
const { [ALLOWANCE]: allowance, blockNumber: allowanceUpdatedBlockNumber } = getValue(
address,
tokenAddress,
spenderAddress
)
useEffect(() => {
// gate this entire effect by checking that the inputs are valid
if (isAddress(address) && isAddress(tokenAddress) && isAddress(spenderAddress)) {
// if they are, and the balance is undefined or stale, fetch it
if (allowance === undefined || allowanceUpdatedBlockNumber !== globalBlockNumber) {
let stale = false
getTokenAllowance(address, tokenAddress, spenderAddress, library)
.then(value => {
if (!stale) {
updateValue(address, tokenAddress, spenderAddress, value, globalBlockNumber)
}
})
.catch(() => {
if (!stale) {
updateValue(address, tokenAddress, spenderAddress, null, globalBlockNumber)
}
})
return () => {
stale = true
}
}
}
}, [
address,
tokenAddress,
spenderAddress,
allowance,
allowanceUpdatedBlockNumber,
globalBlockNumber,
library,
updateValue
])
return allowance
}
export function useExchangeReserves(tokenAddress) {
const { exchangeAddress } = useTokenDetails(tokenAddress)
const reserveETH = useAddressBalance(exchangeAddress, 'ETH')
const reserveToken = useAddressBalance(exchangeAddress, tokenAddress)
return { reserveETH, reserveToken }
}
import React, { Component, createContext, useContext, useEffect } from 'react'
import { useWeb3Context } from 'web3-react'
import { ethers } from 'ethers'
import merge from 'lodash.merge'
import { isAddress, getTokenName, getTokenSymbol, getTokenDecimals, getTokenExchangeAddressFromFactory } from '../utils'
// define constants
const TOKEN_DETAIL = 'tokenDetail'
const NAME = 'name'
const SYMBOL = 'symbol'
const DECIMALS = 'decimals'
const EXCHANGE_ADDRESS = 'exchangeAddress'
const TOKEN_DETAILS_MAINNET = {
ETH: {
[NAME]: 'Ethereum',
[SYMBOL]: 'ETH',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: null
},
'0x960b236A07cf122663c4303350609A66A7B288C0': {
[NAME]: 'Aragon Network Token',
[SYMBOL]: 'ANT',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x077d52B047735976dfdA76feF74d4d988AC25196'
},
'0x0D8775F648430679A709E98d2b0Cb6250d2887EF': {
[NAME]: 'Basic Attention Token',
[SYMBOL]: 'BAT',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x2E642b8D59B45a1D8c5aEf716A84FF44ea665914'
},
'0x107c4504cd79C5d2696Ea0030a8dD4e92601B82e': {
[NAME]: 'Bloom Token',
[SYMBOL]: 'BLT',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x0E6A53B13688018A3df8C69f99aFB19A3068D04f'
},
'0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C': {
[NAME]: 'Bancor Network Token',
[SYMBOL]: 'BNT',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x87d80DBD37E551F58680B4217b23aF6a752DA83F'
},
'0x26E75307Fc0C021472fEb8F727839531F112f317': {
[NAME]: 'Crypto20',
[SYMBOL]: 'C20',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xF7B5A4b934658025390ff69dB302BC7F2AC4a542'
},
'0x41e5560054824eA6B0732E656E3Ad64E20e94E45': {
[NAME]: 'Civic',
[SYMBOL]: 'CVC',
[DECIMALS]: 8,
[EXCHANGE_ADDRESS]: '0x1C6c712b1F4a7c263B1DBd8F97fb447c945d3b9a'
},
'0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359': {
[NAME]: 'Dai Stablecoin v1.0',
[SYMBOL]: 'DAI',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x09cabEC1eAd1c0Ba254B09efb3EE13841712bE14'
},
'0x4f3AfEC4E5a3F2A6a1A411DEF7D7dFe50eE057bF': {
[NAME]: 'Digix Gold Token',
[SYMBOL]: 'DGX',
[DECIMALS]: 9,
[EXCHANGE_ADDRESS]: '0xb92dE8B30584392Af27726D5ce04Ef3c4e5c9924'
},
'0x4946Fcea7C692606e8908002e55A582af44AC121': {
[NAME]: 'FOAM Token',
[SYMBOL]: 'FOAM',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xf79cb3BEA83BD502737586A6E8B133c378FD1fF2'
},
'0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b': {
[NAME]: 'FunFair',
[SYMBOL]: 'FUN',
[DECIMALS]: 8,
[EXCHANGE_ADDRESS]: '0x60a87cC7Fca7E53867facB79DA73181B1bB4238B'
},
'0x6810e776880C02933D47DB1b9fc05908e5386b96': {
[NAME]: 'Gnosis Token',
[SYMBOL]: 'GNO',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xe8e45431b93215566BA923a7E611B7342Ea954DF'
},
'0x12B19D3e2ccc14Da04FAe33e63652ce469b3F2FD': {
[NAME]: 'GRID Token',
[SYMBOL]: 'GRID',
[DECIMALS]: 12,
[EXCHANGE_ADDRESS]: '0x4B17685b330307C751B47f33890c8398dF4Fe407'
},
'0x056Fd409E1d7A124BD7017459dFEa2F387b6d5Cd': {
[NAME]: 'Gemini dollar',
[SYMBOL]: 'GUSD',
[DECIMALS]: 2,
[EXCHANGE_ADDRESS]: '0xD883264737Ed969d2696eE4B4cAF529c2Fc2A141'
},
'0x818Fc6C2Ec5986bc6E2CBf00939d90556aB12ce5': {
[NAME]: 'Kin',
[SYMBOL]: 'KIN',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xb7520a5F8c832c573d6BD0Df955fC5c9b72400F7'
},
'0xdd974D5C2e2928deA5F71b9825b8b646686BD200': {
[NAME]: 'Kyber Network Crystal',
[SYMBOL]: 'KNC',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x49c4f9bc14884f6210F28342ceD592A633801a8b'
},
'0x514910771AF9Ca656af840dff83E8264EcF986CA': {
[NAME]: 'ChainLink Token',
[SYMBOL]: 'LINK',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xF173214C720f58E03e194085B1DB28B50aCDeeaD'
},
'0x6c6EE5e31d828De241282B9606C8e98Ea48526E2': {
[NAME]: 'HoloToken',
[SYMBOL]: 'HOT',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xd4777E164c6C683E10593E08760B803D58529a8E'
},
'0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0': {
[NAME]: 'LoomToken',
[SYMBOL]: 'LOOM',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x417CB32bc991fBbDCaE230C7c4771CC0D69daA6b'
},
'0x58b6A8A3302369DAEc383334672404Ee733aB239': {
[NAME]: 'Livepeer Token',
[SYMBOL]: 'LPT',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xc4a1C45D5546029Fd57128483aE65b56124BFA6A'
},
'0x0F5D2fB29fb7d3CFeE444a200298f468908cC942': {
[NAME]: 'Decentraland MANA',
[SYMBOL]: 'MANA',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xC6581Ce3A005e2801c1e0903281BBd318eC5B5C2'
},
'0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2': {
[NAME]: 'Maker',
[SYMBOL]: 'MKR',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x2C4Bd064b998838076fa341A83d007FC2FA50957'
},
'0xB62132e35a6c13ee1EE0f84dC5d40bad8d815206': {
[NAME]: 'Nexo',
[SYMBOL]: 'NEXO',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x069C97DBA948175D10af4b2414969e0B88d44669'
},
'0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671': {
[NAME]: 'Numeraire',
[SYMBOL]: 'NMR',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x2Bf5A5bA29E60682fC56B2Fcf9cE07Bef4F6196f'
},
'0x8E870D67F660D95d5be530380D0eC0bd388289E1': {
[NAME]: 'PAX',
[SYMBOL]: 'PAX',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xC040d51b07Aea5d94a89Bc21E8078B77366Fc6C7'
},
'0x6758B7d441a9739b98552B373703d8d3d14f9e62': {
[NAME]: 'POA ERC20 on Foundation',
[SYMBOL]: 'POA20',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xA2E6B3EF205FeAEe475937c4883b24E6eB717eeF'
},
'0x687BfC3E73f6af55F0CccA8450114D107E781a0e': {
[NAME]: 'QChi',
[SYMBOL]: 'QCH',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x755899F0540c3548b99E68C59AdB0f15d2695188'
},
'0x255Aa6DF07540Cb5d3d297f0D0D4D84cb52bc8e6': {
[NAME]: 'Raiden Token',
[SYMBOL]: 'RDN',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x7D03CeCb36820b4666F45E1b4cA2538724Db271C'
},
'0x408e41876cCCDC0F92210600ef50372656052a38': {
[NAME]: 'Republic Token',
[SYMBOL]: 'REN',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x43892992B0b102459E895B88601Bb2C76736942c'
},
'0x1985365e9f78359a9B6AD760e32412f4a445E862': {
[NAME]: 'Reputation',
[SYMBOL]: 'REP',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x48B04d2A05B6B604d8d5223Fd1984f191DED51af'
},
'0x168296bb09e24A88805CB9c33356536B980D3fC5': {
[NAME]: 'RHOC',
[SYMBOL]: 'RHOC',
[DECIMALS]: 8,
[EXCHANGE_ADDRESS]: '0x394e524b47A3AB3D3327f7fF6629dC378c1494a3'
},
'0x607F4C5BB672230e8672085532f7e901544a7375': {
[NAME]: 'iEx.ec Network Token',
[SYMBOL]: 'RLC',
[DECIMALS]: 9,
[EXCHANGE_ADDRESS]: '0xA825CAE02B310E9901b4776806CE25db520c8642'
},
'0x4156D3342D5c385a87D264F90653733592000581': {
[NAME]: 'Salt',
[SYMBOL]: 'SALT',
[DECIMALS]: 8,
[EXCHANGE_ADDRESS]: '0xC0C59cDe851bfcbdddD3377EC10ea54A18Efb937'
},
'0x744d70FDBE2Ba4CF95131626614a1763DF805B9E': {
[NAME]: 'Status Network Token',
[SYMBOL]: 'SNT',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x1aEC8F11A7E78dC22477e91Ed924Fab46e3A88Fd'
},
'0x3772f9716Cf6D7a09edE3587738AA2af5577483a': {
[NAME]: 'Synthetix Network Token',
[SYMBOL]: 'SNX',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x5d8888a212d033cff5F2e0AC24ad91A5495bAD62'
},
'0x42d6622deCe394b54999Fbd73D108123806f6a18': {
[NAME]: 'SPANK',
[SYMBOL]: 'SPANK',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x4e395304655F0796bc3bc63709DB72173b9DdF98'
},
'0x0cbe2df57ca9191b64a7af3baa3f946fa7df2f25': {
[NAME]: 'Synth sUSD',
[SYMBOL]: 'sUSD',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xA1ECDcca26150cF69090280eE2EE32347C238c7b'
},
'0xaAAf91D9b90dF800Df4F55c205fd6989c977E73a': {
[NAME]: 'Monolith TKN',
[SYMBOL]: 'TKN',
[DECIMALS]: 8,
[EXCHANGE_ADDRESS]: '0xb6cFBf322db47D39331E306005DC7E5e6549942B'
},
'0x8dd5fbCe2F6a956C3022bA3663759011Dd51e73E': {
[NAME]: 'TrueUSD',
[SYMBOL]: 'TUSD',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x4F30E682D0541eAC91748bd38A648d759261b8f3'
},
'0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': {
[NAME]: 'USD//C',
[SYMBOL]: 'USDC',
[DECIMALS]: 6,
[EXCHANGE_ADDRESS]: '0x97deC872013f6B5fB443861090ad931542878126'
},
'0x8f3470A7388c05eE4e7AF3d01D8C722b0FF52374': {
[NAME]: 'Veritaseum',
[SYMBOL]: 'VERI',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x17e5BF07D696eaf0d14caA4B44ff8A1E17B34de3'
},
'0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599': {
[NAME]: 'Wrapped BTC',
[SYMBOL]: 'WBTC',
[DECIMALS]: 8,
[EXCHANGE_ADDRESS]: '0x4d2f5cFbA55AE412221182D8475bC85799A5644b'
},
'0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': {
[NAME]: 'Wrapped Ether',
[SYMBOL]: 'WETH',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xA2881A90Bf33F03E7a3f803765Cd2ED5c8928dFb'
},
'0xB4272071eCAdd69d933AdcD19cA99fe80664fc08': {
[NAME]: 'CryptoFranc',
[SYMBOL]: 'XCHF',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x8dE0d002DC83478f479dC31F76cB0a8aa7CcEa17'
},
'0x05f4a42e251f2d52b8ed15E9FEdAacFcEF1FAD27': {
[NAME]: 'Zilliqa',
[SYMBOL]: 'ZIL',
[DECIMALS]: 12,
[EXCHANGE_ADDRESS]: '0x7dc095A5CF7D6208CC680fA9866F80a53911041a'
},
'0xE41d2489571d322189246DaFA5ebDe1F4699F498': {
[NAME]: '0x Protocol Token',
[SYMBOL]: 'ZRX',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xaE76c84C9262Cdb9abc0C2c8888e62Db8E22A0bF'
}
}
const TOKEN_DETAILS = {
1: TOKEN_DETAILS_MAINNET
}
// node creation
function createTokenDetailNode(name, symbol, decimals, exchangeAddress) {
return { [NAME]: name, [SYMBOL]: symbol, [DECIMALS]: decimals, [EXCHANGE_ADDRESS]: exchangeAddress }
}
// tree creation
function createTokenDetailTree(tokenAddress, name, symbol, decimals, exchangeAddress) {
return { [tokenAddress]: createTokenDetailNode(name, symbol, decimals, exchangeAddress) }
}
// create contexts
const TokenDetailsContext = createContext()
// define providers
function getTokenDetails(tokenAddress, networkId, library) {
const namePromise = getTokenName(tokenAddress, library).catch(() => null)
const symbolPromise = getTokenSymbol(tokenAddress, library).catch(() => null)
const decimalsPromise = getTokenDecimals(tokenAddress, library).catch(() => null)
const exchangeAddressPromise = getTokenExchangeAddressFromFactory(tokenAddress, networkId, library).catch(() => null)
return Promise.all([namePromise, symbolPromise, decimalsPromise, exchangeAddressPromise])
}
export default class Provider extends Component {
constructor(props) {
super(props)
this.initializeValues = networkId => {
this.setState({ [TOKEN_DETAIL]: TOKEN_DETAILS[networkId] || {} })
}
this.getValue = tokenAddress => {
return this.state[TOKEN_DETAIL][tokenAddress] || createTokenDetailNode()
}
this.getValues = () => {
return this.state[TOKEN_DETAIL]
}
this.updateValue = (tokenAddress, name, symbol, decimals, exchangeAddress) => {
this.setState(state => ({
[TOKEN_DETAIL]: merge(
state[TOKEN_DETAIL],
createTokenDetailTree(tokenAddress, name, symbol, decimals, exchangeAddress, true)
)
}))
}
this.forceUpdateValue = (tokenAddress, networkId, library) => {
getTokenDetails(tokenAddress, networkId, library).then(([name, symbol, decimals, exchangeAddress]) => {
this.updateValue(tokenAddress, name, symbol, decimals, exchangeAddress)
})
}
this.state = {
[TOKEN_DETAIL]: {},
initializeValues: this.initializeValues,
getValue: this.getValue,
getValues: this.getValues,
updateValue: this.updateValue,
forceUpdateValue: this.forceUpdateValue
}
}
render() {
return <TokenDetailsContext.Provider value={this.state}>{this.props.children}</TokenDetailsContext.Provider>
}
}
// define useContext wrappers
export function useTokenDetailsContext() {
return useContext(TokenDetailsContext)
}
// define custom hooks
export function Updater() {
const { networkId } = useWeb3Context()
const { initializeValues } = useTokenDetailsContext()
useEffect(() => {
if (networkId) {
initializeValues(networkId)
}
return () => {
initializeValues()
}
}, [initializeValues, networkId])
return null
}
export function useTokenDetails(tokenAddress) {
const { networkId, library } = useWeb3Context()
const { getValue, updateValue } = useTokenDetailsContext()
const { [NAME]: name, [SYMBOL]: symbol, [DECIMALS]: decimals, [EXCHANGE_ADDRESS]: exchangeAddress } = getValue(
tokenAddress
)
useEffect(() => {
if (isAddress(tokenAddress)) {
getTokenDetails(tokenAddress, networkId, library).then(([name, symbol, decimals, exchangeAddress]) => {
updateValue(tokenAddress, name, symbol, decimals, exchangeAddress)
})
}
}, [tokenAddress, networkId, library, updateValue])
return { name, symbol, decimals, exchangeAddress }
}
export function useAllTokenDetails(requireExchange = true) {
const { getValues } = useTokenDetailsContext()
const allTokenDetails = getValues()
return requireExchange
? Object.keys(allTokenDetails)
.filter(
k =>
k === 'ETH' ||
(allTokenDetails[k][EXCHANGE_ADDRESS] &&
allTokenDetails[k][EXCHANGE_ADDRESS] !== ethers.constants.AddressZero)
)
.reduce((o, k) => {
o[k] = allTokenDetails[k]
return o
}, {})
: allTokenDetails
}
import React, { createContext, useContext, useReducer, useCallback, useMemo, useEffect } from 'react'
import { useWeb3Context } from 'web3-react'
import { ethers } from 'ethers'
import {
isAddress,
getTokenName,
getTokenSymbol,
getTokenDecimals,
getTokenExchangeAddressFromFactory,
safeAccess
} from '../utils'
const NAME = 'name'
const SYMBOL = 'symbol'
const DECIMALS = 'decimals'
const EXCHANGE_ADDRESS = 'exchangeAddress'
const UPDATE = 'UPDATE'
const INITIAL_TOKENS_CONTEXT = {
1: {
ETH: {
[NAME]: 'Ethereum',
[SYMBOL]: 'ETH',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: null
},
'0x960b236A07cf122663c4303350609A66A7B288C0': {
[NAME]: 'Aragon Network Token',
[SYMBOL]: 'ANT',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x077d52B047735976dfdA76feF74d4d988AC25196'
},
'0x0D8775F648430679A709E98d2b0Cb6250d2887EF': {
[NAME]: 'Basic Attention Token',
[SYMBOL]: 'BAT',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x2E642b8D59B45a1D8c5aEf716A84FF44ea665914'
},
'0x107c4504cd79C5d2696Ea0030a8dD4e92601B82e': {
[NAME]: 'Bloom Token',
[SYMBOL]: 'BLT',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x0E6A53B13688018A3df8C69f99aFB19A3068D04f'
},
'0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C': {
[NAME]: 'Bancor Network Token',
[SYMBOL]: 'BNT',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x87d80DBD37E551F58680B4217b23aF6a752DA83F'
},
'0x26E75307Fc0C021472fEb8F727839531F112f317': {
[NAME]: 'Crypto20',
[SYMBOL]: 'C20',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xF7B5A4b934658025390ff69dB302BC7F2AC4a542'
},
'0x41e5560054824eA6B0732E656E3Ad64E20e94E45': {
[NAME]: 'Civic',
[SYMBOL]: 'CVC',
[DECIMALS]: 8,
[EXCHANGE_ADDRESS]: '0x1C6c712b1F4a7c263B1DBd8F97fb447c945d3b9a'
},
'0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359': {
[NAME]: 'Dai Stablecoin v1.0',
[SYMBOL]: 'DAI',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x09cabEC1eAd1c0Ba254B09efb3EE13841712bE14'
},
'0x4f3AfEC4E5a3F2A6a1A411DEF7D7dFe50eE057bF': {
[NAME]: 'Digix Gold Token',
[SYMBOL]: 'DGX',
[DECIMALS]: 9,
[EXCHANGE_ADDRESS]: '0xb92dE8B30584392Af27726D5ce04Ef3c4e5c9924'
},
'0x4946Fcea7C692606e8908002e55A582af44AC121': {
[NAME]: 'FOAM Token',
[SYMBOL]: 'FOAM',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xf79cb3BEA83BD502737586A6E8B133c378FD1fF2'
},
'0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b': {
[NAME]: 'FunFair',
[SYMBOL]: 'FUN',
[DECIMALS]: 8,
[EXCHANGE_ADDRESS]: '0x60a87cC7Fca7E53867facB79DA73181B1bB4238B'
},
'0x6810e776880C02933D47DB1b9fc05908e5386b96': {
[NAME]: 'Gnosis Token',
[SYMBOL]: 'GNO',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xe8e45431b93215566BA923a7E611B7342Ea954DF'
},
'0x12B19D3e2ccc14Da04FAe33e63652ce469b3F2FD': {
[NAME]: 'GRID Token',
[SYMBOL]: 'GRID',
[DECIMALS]: 12,
[EXCHANGE_ADDRESS]: '0x4B17685b330307C751B47f33890c8398dF4Fe407'
},
'0x056Fd409E1d7A124BD7017459dFEa2F387b6d5Cd': {
[NAME]: 'Gemini dollar',
[SYMBOL]: 'GUSD',
[DECIMALS]: 2,
[EXCHANGE_ADDRESS]: '0xD883264737Ed969d2696eE4B4cAF529c2Fc2A141'
},
'0x818Fc6C2Ec5986bc6E2CBf00939d90556aB12ce5': {
[NAME]: 'Kin',
[SYMBOL]: 'KIN',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xb7520a5F8c832c573d6BD0Df955fC5c9b72400F7'
},
'0xdd974D5C2e2928deA5F71b9825b8b646686BD200': {
[NAME]: 'Kyber Network Crystal',
[SYMBOL]: 'KNC',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x49c4f9bc14884f6210F28342ceD592A633801a8b'
},
'0x514910771AF9Ca656af840dff83E8264EcF986CA': {
[NAME]: 'ChainLink Token',
[SYMBOL]: 'LINK',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xF173214C720f58E03e194085B1DB28B50aCDeeaD'
},
'0x6c6EE5e31d828De241282B9606C8e98Ea48526E2': {
[NAME]: 'HoloToken',
[SYMBOL]: 'HOT',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xd4777E164c6C683E10593E08760B803D58529a8E'
},
'0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0': {
[NAME]: 'LoomToken',
[SYMBOL]: 'LOOM',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x417CB32bc991fBbDCaE230C7c4771CC0D69daA6b'
},
'0x58b6A8A3302369DAEc383334672404Ee733aB239': {
[NAME]: 'Livepeer Token',
[SYMBOL]: 'LPT',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xc4a1C45D5546029Fd57128483aE65b56124BFA6A'
},
'0x0F5D2fB29fb7d3CFeE444a200298f468908cC942': {
[NAME]: 'Decentraland MANA',
[SYMBOL]: 'MANA',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xC6581Ce3A005e2801c1e0903281BBd318eC5B5C2'
},
'0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2': {
[NAME]: 'Maker',
[SYMBOL]: 'MKR',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x2C4Bd064b998838076fa341A83d007FC2FA50957'
},
'0xB62132e35a6c13ee1EE0f84dC5d40bad8d815206': {
[NAME]: 'Nexo',
[SYMBOL]: 'NEXO',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x069C97DBA948175D10af4b2414969e0B88d44669'
},
'0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671': {
[NAME]: 'Numeraire',
[SYMBOL]: 'NMR',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x2Bf5A5bA29E60682fC56B2Fcf9cE07Bef4F6196f'
},
'0x8E870D67F660D95d5be530380D0eC0bd388289E1': {
[NAME]: 'PAX',
[SYMBOL]: 'PAX',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xC040d51b07Aea5d94a89Bc21E8078B77366Fc6C7'
},
'0x6758B7d441a9739b98552B373703d8d3d14f9e62': {
[NAME]: 'POA ERC20 on Foundation',
[SYMBOL]: 'POA20',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xA2E6B3EF205FeAEe475937c4883b24E6eB717eeF'
},
'0x687BfC3E73f6af55F0CccA8450114D107E781a0e': {
[NAME]: 'QChi',
[SYMBOL]: 'QCH',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x755899F0540c3548b99E68C59AdB0f15d2695188'
},
'0x255Aa6DF07540Cb5d3d297f0D0D4D84cb52bc8e6': {
[NAME]: 'Raiden Token',
[SYMBOL]: 'RDN',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x7D03CeCb36820b4666F45E1b4cA2538724Db271C'
},
'0x408e41876cCCDC0F92210600ef50372656052a38': {
[NAME]: 'Republic Token',
[SYMBOL]: 'REN',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x43892992B0b102459E895B88601Bb2C76736942c'
},
'0x1985365e9f78359a9B6AD760e32412f4a445E862': {
[NAME]: 'Reputation',
[SYMBOL]: 'REP',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x48B04d2A05B6B604d8d5223Fd1984f191DED51af'
},
'0x168296bb09e24A88805CB9c33356536B980D3fC5': {
[NAME]: 'RHOC',
[SYMBOL]: 'RHOC',
[DECIMALS]: 8,
[EXCHANGE_ADDRESS]: '0x394e524b47A3AB3D3327f7fF6629dC378c1494a3'
},
'0x607F4C5BB672230e8672085532f7e901544a7375': {
[NAME]: 'iEx.ec Network Token',
[SYMBOL]: 'RLC',
[DECIMALS]: 9,
[EXCHANGE_ADDRESS]: '0xA825CAE02B310E9901b4776806CE25db520c8642'
},
'0x4156D3342D5c385a87D264F90653733592000581': {
[NAME]: 'Salt',
[SYMBOL]: 'SALT',
[DECIMALS]: 8,
[EXCHANGE_ADDRESS]: '0xC0C59cDe851bfcbdddD3377EC10ea54A18Efb937'
},
'0x744d70FDBE2Ba4CF95131626614a1763DF805B9E': {
[NAME]: 'Status Network Token',
[SYMBOL]: 'SNT',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x1aEC8F11A7E78dC22477e91Ed924Fab46e3A88Fd'
},
'0x3772f9716Cf6D7a09edE3587738AA2af5577483a': {
[NAME]: 'Synthetix Network Token',
[SYMBOL]: 'SNX',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x5d8888a212d033cff5F2e0AC24ad91A5495bAD62'
},
'0x42d6622deCe394b54999Fbd73D108123806f6a18': {
[NAME]: 'SPANK',
[SYMBOL]: 'SPANK',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x4e395304655F0796bc3bc63709DB72173b9DdF98'
},
'0x0cbe2df57ca9191b64a7af3baa3f946fa7df2f25': {
[NAME]: 'Synth sUSD',
[SYMBOL]: 'sUSD',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xA1ECDcca26150cF69090280eE2EE32347C238c7b'
},
'0xaAAf91D9b90dF800Df4F55c205fd6989c977E73a': {
[NAME]: 'Monolith TKN',
[SYMBOL]: 'TKN',
[DECIMALS]: 8,
[EXCHANGE_ADDRESS]: '0xb6cFBf322db47D39331E306005DC7E5e6549942B'
},
'0x8dd5fbCe2F6a956C3022bA3663759011Dd51e73E': {
[NAME]: 'TrueUSD',
[SYMBOL]: 'TUSD',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x4F30E682D0541eAC91748bd38A648d759261b8f3'
},
'0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': {
[NAME]: 'USD//C',
[SYMBOL]: 'USDC',
[DECIMALS]: 6,
[EXCHANGE_ADDRESS]: '0x97deC872013f6B5fB443861090ad931542878126'
},
'0x8f3470A7388c05eE4e7AF3d01D8C722b0FF52374': {
[NAME]: 'Veritaseum',
[SYMBOL]: 'VERI',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x17e5BF07D696eaf0d14caA4B44ff8A1E17B34de3'
},
'0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599': {
[NAME]: 'Wrapped BTC',
[SYMBOL]: 'WBTC',
[DECIMALS]: 8,
[EXCHANGE_ADDRESS]: '0x4d2f5cFbA55AE412221182D8475bC85799A5644b'
},
'0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': {
[NAME]: 'Wrapped Ether',
[SYMBOL]: 'WETH',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xA2881A90Bf33F03E7a3f803765Cd2ED5c8928dFb'
},
'0xB4272071eCAdd69d933AdcD19cA99fe80664fc08': {
[NAME]: 'CryptoFranc',
[SYMBOL]: 'XCHF',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x8dE0d002DC83478f479dC31F76cB0a8aa7CcEa17'
},
'0x05f4a42e251f2d52b8ed15E9FEdAacFcEF1FAD27': {
[NAME]: 'Zilliqa',
[SYMBOL]: 'ZIL',
[DECIMALS]: 12,
[EXCHANGE_ADDRESS]: '0x7dc095A5CF7D6208CC680fA9866F80a53911041a'
},
'0xE41d2489571d322189246DaFA5ebDe1F4699F498': {
[NAME]: '0x Protocol Token',
[SYMBOL]: 'ZRX',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xaE76c84C9262Cdb9abc0C2c8888e62Db8E22A0bF'
}
}
}
const TokensContext = createContext()
function useTokensContext() {
return useContext(TokensContext)
}
function reducer(state, { type, payload }) {
switch (type) {
case UPDATE: {
const { networkId, tokenAddress, name, symbol, decimals, exchangeAddress } = payload
return {
...state,
[networkId]: {
...(safeAccess(state, [networkId]) || {}),
[tokenAddress]: {
[NAME]: name,
[SYMBOL]: symbol,
[DECIMALS]: decimals,
[EXCHANGE_ADDRESS]: exchangeAddress
}
}
}
}
default: {
throw Error(`Unexpected action type in TokensContext reducer: '${type}'.`)
}
}
}
export default function Provider({ children }) {
const [state, dispatch] = useReducer(reducer, INITIAL_TOKENS_CONTEXT)
const update = useCallback((networkId, tokenAddress, name, symbol, decimals, exchangeAddress) => {
dispatch({ type: UPDATE, payload: { networkId, tokenAddress, name, symbol, decimals, exchangeAddress } })
}, [])
const contextValue = useMemo(() => [state, { update }], [state, update])
return <TokensContext.Provider value={contextValue}>{children}</TokensContext.Provider>
}
export function useTokenDetails(tokenAddress) {
const { networkId, library } = useWeb3Context()
const [state, { update }] = useTokensContext()
const { [NAME]: name, [SYMBOL]: symbol, [DECIMALS]: decimals, [EXCHANGE_ADDRESS]: exchangeAddress } =
safeAccess(state, [networkId, tokenAddress]) || {}
useEffect(() => {
if (
isAddress(tokenAddress) &&
(name === undefined || symbol === undefined || decimals === undefined || exchangeAddress === undefined) &&
(networkId || networkId === 0) &&
library
) {
let stale = false
const namePromise = getTokenName(tokenAddress, library).catch(() => null)
const symbolPromise = getTokenSymbol(tokenAddress, library).catch(() => null)
const decimalsPromise = getTokenDecimals(tokenAddress, library).catch(() => null)
const exchangeAddressPromise = getTokenExchangeAddressFromFactory(tokenAddress, networkId, library).catch(
() => null
)
Promise.all([namePromise, symbolPromise, decimalsPromise, exchangeAddressPromise]).then(
([resolvedName, resolvedSymbol, resolvedDecimals, resolvedExchangeAddress]) => {
if (!stale) {
update(networkId, tokenAddress, resolvedName, resolvedSymbol, resolvedDecimals, resolvedExchangeAddress)
}
}
)
return () => {
stale = true
}
}
}, [tokenAddress, name, symbol, decimals, exchangeAddress, networkId, library, update])
return { name, symbol, decimals, exchangeAddress }
}
export function useAllTokenDetails(requireExchange = true) {
const { networkId } = useWeb3Context()
const [state] = useTokensContext()
const tokenDetails = safeAccess(state, [networkId]) || {}
return requireExchange
? Object.keys(tokenDetails)
.filter(
tokenAddress =>
tokenAddress === 'ETH' ||
(safeAccess(tokenDetails, [tokenAddress, EXCHANGE_ADDRESS]) &&
safeAccess(tokenDetails, [tokenAddress, EXCHANGE_ADDRESS]) !== ethers.constants.AddressZero)
)
.reduce((accumulator, tokenAddress) => {
accumulator[tokenAddress] = tokenDetails[tokenAddress]
return accumulator
}, {})
: tokenDetails
}
import React, { Component, createContext, useContext, useCallback, useEffect } from 'react'
import { useWeb3Context } from 'web3-react'
import { ethers } from 'ethers'
import merge from 'lodash.merge'
import { useBlockEffect } from '../hooks'
const TRANSACTION = 'transaction'
const RESPONSE = 'response'
const COMPLETED = 'completed'
const RECEIPT = 'receipt'
const TransactionContext = createContext()
function removeUndefinedValues(o) {
return Object.keys(o)
.filter(k => o[k] !== undefined)
.reduce((innerO, k) => {
innerO[k] = o[k]
return innerO
}, {})
}
function createTransactionNode(response, completed, receipt, noUndefinedValues) {
const node = { [RESPONSE]: response, [COMPLETED]: completed, [RECEIPT]: receipt }
return noUndefinedValues ? removeUndefinedValues(node) : node
}
// tree creation
function createTokenDetailTree(hash, response, completed, receipt, noUndefinedValues = false) {
return { [hash]: createTransactionNode(response, completed, receipt, noUndefinedValues) }
}
export default class Provider extends Component {
constructor(props) {
super(props)
this.getTransactions = () => {
return this.state[TRANSACTION]
}
this.addTransaction = (hash, response) => {
this.setState(state => ({
[TRANSACTION]: merge(state[TRANSACTION], createTokenDetailTree(hash, response, false))
}))
}
this.updateTransaction = (hash, receipt) => {
this.setState(state => ({
[TRANSACTION]: merge(state[TRANSACTION], createTokenDetailTree(hash, undefined, true, receipt, true))
}))
}
this.clearTransactions = () => {
this.setState({ [TRANSACTION]: {} })
}
this.state = {
[TRANSACTION]: {},
getTransactions: this.getTransactions,
addTransaction: this.addTransaction,
updateTransaction: this.updateTransaction,
clearTransactions: this.clearTransactions
}
}
render() {
return <TransactionContext.Provider value={this.state}>{this.props.children}</TransactionContext.Provider>
}
}
export function useTransactionContext() {
return useContext(TransactionContext)
}
export function Updater() {
const { library, networkId } = useWeb3Context()
const { getTransactions, updateTransaction, clearTransactions } = useTransactionContext()
useEffect(() => {
return () => {
clearTransactions()
}
}, [clearTransactions, networkId])
const updateTransactionHashes = useCallback(() => {
if (library) {
const transactions = getTransactions()
Object.keys(transactions)
.filter(k => !transactions[k][COMPLETED])
.forEach(hash => {
library.getTransactionReceipt(hash).then(receipt => {
if (receipt) {
updateTransaction(hash, receipt)
}
})
})
}
}, [library, getTransactions, updateTransaction])
useBlockEffect(updateTransactionHashes)
return null
}
export function useAllTransactions() {
const { getTransactions } = useTransactionContext()
return getTransactions()
}
export function usePendingApproval(tokenAddress) {
const allTransactions = useAllTransactions()
return (
Object.keys(allTransactions).filter(hash => {
const transaction = allTransactions[hash]
if (
transaction.completed ||
transaction.response.to !== tokenAddress ||
transaction.response.data.substring(0, 10) !== ethers.utils.id('approve(address,uint256)').substring(0, 10)
) {
return false
} else {
return true
}
}).length >= 1
)
}
import React, { createContext, useContext, useReducer, useCallback, useMemo, useEffect } from 'react'
import { useWeb3Context } from 'web3-react'
import { ethers } from 'ethers'
import { safeAccess } from '../utils'
import { useBlockNumber } from './Application'
const RESPONSE = 'response'
const BLOCK_NUMBER_CHECKED = 'BLOCK_NUMBER_CHECKED'
const RECEIPT = 'receipt'
const ADD = 'ADD'
const CHECK = 'CHECK'
const FINALIZE = 'FINALIZE'
const TransactionsContext = createContext()
export function useTransactionsContext() {
return useContext(TransactionsContext)
}
function reducer(state, { type, payload }) {
switch (type) {
case ADD: {
const { networkId, hash, response } = payload
if (safeAccess(state, [networkId, hash]) !== null) {
throw Error('Attempted to add existing transaction.')
}
return {
...state,
[networkId]: {
...(safeAccess(state, [networkId]) || {}),
[hash]: {
[RESPONSE]: response
}
}
}
}
case CHECK: {
const { networkId, hash, blockNumber } = payload
if (safeAccess(state, [networkId, hash]) === null) {
throw Error('Attempted to check non-existent transaction.')
}
return {
...state,
[networkId]: {
...(safeAccess(state, [networkId]) || {}),
[hash]: {
...(safeAccess(state, [networkId, hash]) || {}),
[BLOCK_NUMBER_CHECKED]: blockNumber
}
}
}
}
case FINALIZE: {
const { networkId, hash, receipt } = payload
if (safeAccess(state, [networkId, hash]) === null) {
throw Error('Attempted to finalize non-existent transaction.')
}
return {
...state,
[networkId]: {
...(safeAccess(state, [networkId]) || {}),
[hash]: {
...(safeAccess(state, [networkId, hash]) || {}),
[RECEIPT]: receipt
}
}
}
}
default: {
throw Error(`Unexpected action type in TransactionsContext reducer: '${type}'.`)
}
}
}
export default function Provider({ children }) {
const [state, dispatch] = useReducer(reducer, {})
const add = useCallback((networkId, hash, response) => {
dispatch({ type: ADD, payload: { networkId, hash, response } })
}, [])
const check = useCallback((networkId, hash, blockNumber) => {
dispatch({ type: ADD, payload: { networkId, hash, blockNumber } })
}, [])
const finalize = useCallback((networkId, hash, receipt) => {
dispatch({ type: FINALIZE, payload: { networkId, hash, receipt } })
}, [])
const contextValue = useMemo(() => [state, { add, check, finalize }], [state, add, check, finalize])
return <TransactionsContext.Provider value={contextValue}>{children}</TransactionsContext.Provider>
}
export function Updater() {
const { networkId, library } = useWeb3Context()
const globalBlockNumber = useBlockNumber()
const [state, { check, finalize }] = useTransactionsContext()
useEffect(() => {
if ((networkId || networkId === 0) && library) {
const allTransactions = safeAccess(state, [networkId]) || {}
const allUncheckedTransactions = Object.keys(allTransactions).filter(
hash => !allTransactions[hash][RECEIPT] && allTransactions[hash][BLOCK_NUMBER_CHECKED] !== globalBlockNumber
)
let stale = false
Object.keys(allUncheckedTransactions).forEach(hash => {
library
.getTransactionReceipt(hash)
.then(receipt => {
if (!stale) {
if (!receipt) {
check(networkId, hash, globalBlockNumber)
} else {
finalize(networkId, hash, receipt)
}
}
})
.catch(() => {
check(networkId, hash, globalBlockNumber)
})
})
return () => {
stale = true
}
}
}, [networkId, library, state, globalBlockNumber, check, finalize])
return null
}
export function useTransactionAdder() {
const { networkId } = useWeb3Context()
const [, { add }] = useTransactionsContext()
return useCallback(
response => {
if (!(networkId || networkId === 0)) {
throw Error(`Invalid networkId '${networkId}`)
}
const hash = safeAccess(response, ['hash'])
if (!hash) {
throw Error('No transaction hash found.')
}
add(networkId, hash, response)
},
[networkId, add]
)
}
export function useAllTransactions() {
const { networkId } = useWeb3Context()
const [state] = useTransactionsContext()
return safeAccess(state, [networkId]) || {}
}
export function usePendingApproval(tokenAddress) {
const allTransactions = useAllTransactions()
return (
Object.keys(allTransactions).filter(hash => {
if (
allTransactions[hash][RECEIPT] ||
allTransactions[hash][RESPONSE].to !== tokenAddress ||
allTransactions[hash][RESPONSE].data.substring(0, 10) !==
ethers.utils.id('approve(address,uint256)').substring(0, 10)
) {
return false
} else {
return true
}
}).length >= 1
)
}
...@@ -23,22 +23,6 @@ export function useBodyKeyDown(targetKey, onKeyDown, suppressOnKeyDown = false) ...@@ -23,22 +23,6 @@ export function useBodyKeyDown(targetKey, onKeyDown, suppressOnKeyDown = false)
}, [downHandler]) }, [downHandler])
} }
export function useBlockEffect(functionToRun) {
const { library } = useWeb3Context()
useEffect(() => {
if (library) {
function wrappedEffect(blockNumber) {
functionToRun(blockNumber)
}
library.on('block', wrappedEffect)
return () => {
library.removeListener('block', wrappedEffect)
}
}
}, [library, functionToRun])
}
// returns null on errors // returns null on errors
export function useContract(address, ABI, withSignerIfPossible = true) { export function useContract(address, ABI, withSignerIfPossible = true) {
const { library, account } = useWeb3Context() const { library, account } = useWeb3Context()
......
...@@ -2,14 +2,16 @@ import React from 'react' ...@@ -2,14 +2,16 @@ import React from 'react'
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom'
import ReactGA from 'react-ga' import ReactGA from 'react-ga'
import Web3Provider, { Connectors } from 'web3-react' import Web3Provider, { Connectors } from 'web3-react'
import ThemeProvider, { GlobalStyle } from './theme'
import ApplicationContextProvider, { Updater as ApplicationContextUpdater } from './contexts/Application' import ApplicationContextProvider, { Updater as ApplicationContextUpdater } from './contexts/Application'
import TransactionContextProvider, { Updater as TransactionUpdater } from './contexts/Transaction' import TransactionContextProvider, { Updater as TransactionContextUpdater } from './contexts/Transactions'
import StaticContextProvider, { Updater as StaticContextUpdater } from './contexts/Static' import TokensContextProvider from './contexts/Tokens'
import BlockContextProvider, { Updater as BlockContextUpdater } from './contexts/Block' import BalancesContextProvider from './contexts/Balances'
import AllowancesContextProvider from './contexts/Allowances'
import App from './pages/App' import App from './pages/App'
import './index.scss'
import './i18n' import './i18n'
if (process.env.NODE_ENV === 'production') { if (process.env.NODE_ENV === 'production') {
...@@ -30,9 +32,11 @@ function ContextProviders({ children }) { ...@@ -30,9 +32,11 @@ function ContextProviders({ children }) {
return ( return (
<ApplicationContextProvider> <ApplicationContextProvider>
<TransactionContextProvider> <TransactionContextProvider>
<StaticContextProvider> <TokensContextProvider>
<BlockContextProvider>{children}</BlockContextProvider> <BalancesContextProvider>
</StaticContextProvider> <AllowancesContextProvider>{children}</AllowancesContextProvider>
</BalancesContextProvider>
</TokensContextProvider>
</TransactionContextProvider> </TransactionContextProvider>
</ApplicationContextProvider> </ApplicationContextProvider>
) )
...@@ -42,19 +46,22 @@ function Updaters() { ...@@ -42,19 +46,22 @@ function Updaters() {
return ( return (
<> <>
<ApplicationContextUpdater /> <ApplicationContextUpdater />
<TransactionUpdater /> <TransactionContextUpdater />
<StaticContextUpdater />
<BlockContextUpdater />
</> </>
) )
} }
ReactDOM.render( ReactDOM.render(
<Web3Provider connectors={connectors} libraryName="ethers.js"> <ThemeProvider>
<ContextProviders> <>
<Updaters /> <GlobalStyle />
<App /> <Web3Provider connectors={connectors} libraryName="ethers.js">
</ContextProviders> <ContextProviders>
</Web3Provider>, <Updaters />
<App />
</ContextProviders>
</Web3Provider>
</>
</ThemeProvider>,
document.getElementById('root') document.getElementById('root')
) )
@import url('https://rsms.me/inter/inter.css');
@import './variables.scss';
html,
body {
margin: 0;
padding: 0;
font-family: 'Inter UI', sans-serif;
font-size: 16px;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
overflow-x: hidden;
}
#root {
position: relative;
display: flex;
flex-flow: column nowrap;
height: 100vh;
width: 100vw;
overflow-x: hidden;
overflow-y: auto;
background-color: $white;
z-index: 100;
-webkit-tap-highlight-color: rgba(255, 255, 255, 0);
@media only screen and (min-width: 768px) {
justify-content: center;
align-items: center;
}
}
#modal-root {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 200;
}
.loader {
border: 1px solid transparent; /* Light grey */
border-top: 1px solid $royal-blue; /* Blue */
border-radius: 50%;
width: 0.75rem;
height: 0.75rem;
margin-right: 0.25rem;
animation: spin 1s cubic-bezier(0.25, 0.46, 0.45, 0.94) infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
...@@ -10,13 +10,14 @@ import OversizedPanel from '../../components/OversizedPanel' ...@@ -10,13 +10,14 @@ import OversizedPanel from '../../components/OversizedPanel'
import ContextualInfo from '../../components/ContextualInfo' import ContextualInfo from '../../components/ContextualInfo'
import PlusBlue from '../../assets/images/plus-blue.svg' import PlusBlue from '../../assets/images/plus-blue.svg'
import PlusGrey from '../../assets/images/plus-grey.svg' import PlusGrey from '../../assets/images/plus-grey.svg'
import { useBlockEffect, useExchangeContract } from '../../hooks' import { useExchangeContract } from '../../hooks'
import { amountFormatter, calculateGasMargin } from '../../utils' import { amountFormatter, calculateGasMargin } from '../../utils'
import { useTokenDetails } from '../../contexts/Static' import { useTransactionAdder } from '../../contexts/Transactions'
import { useAddressBalance, useExchangeReserves, useAddressAllowance } from '../../contexts/Block' import { useTokenDetails } from '../../contexts/Tokens'
import { useAddressBalance, useExchangeReserves } from '../../contexts/Balances'
import { useAddressAllowance } from '../../contexts/Allowances'
import './pool.scss' import './pool.scss'
import { useTransactionContext } from '../../contexts/Transaction'
const INPUT = 0 const INPUT = 0
const OUTPUT = 1 const OUTPUT = 1
...@@ -117,7 +118,7 @@ function getMarketRate(reserveETH, reserveToken, decimals, invert = false) { ...@@ -117,7 +118,7 @@ function getMarketRate(reserveETH, reserveToken, decimals, invert = false) {
export default function AddLiquidity() { export default function AddLiquidity() {
const { t } = useTranslation() const { t } = useTranslation()
const { active, account } = useWeb3Context() const { library, active, account } = useWeb3Context()
const [addLiquidityState, dispatchAddLiquidityState] = useReducer(addLiquidityStateReducer, initialAddLiquidityState) const [addLiquidityState, dispatchAddLiquidityState] = useReducer(addLiquidityStateReducer, initialAddLiquidityState)
const { inputValue, outputValue, lastEditedField, outputCurrency } = addLiquidityState const { inputValue, outputValue, lastEditedField, outputCurrency } = addLiquidityState
...@@ -141,8 +142,12 @@ export default function AddLiquidity() { ...@@ -141,8 +142,12 @@ export default function AddLiquidity() {
}, [exchangeContract]) }, [exchangeContract])
useEffect(() => { useEffect(() => {
fetchPoolTokens() fetchPoolTokens()
}, [fetchPoolTokens]) library.on('block', fetchPoolTokens)
useBlockEffect(fetchPoolTokens)
return () => {
library.removeListener('block', fetchPoolTokens)
}
}, [fetchPoolTokens, library])
const poolTokenBalance = useAddressBalance(account, exchangeAddress) const poolTokenBalance = useAddressBalance(account, exchangeAddress)
const exchangeETHBalance = useAddressBalance(exchangeAddress, 'ETH') const exchangeETHBalance = useAddressBalance(exchangeAddress, 'ETH')
...@@ -279,7 +284,7 @@ export default function AddLiquidity() { ...@@ -279,7 +284,7 @@ export default function AddLiquidity() {
) )
} }
const { addTransaction } = useTransactionContext() const addTransaction = useTransactionAdder()
const isActive = active && account const isActive = active && account
const isValid = inputError === null || outputError === null const isValid = inputError === null || outputError === null
...@@ -311,7 +316,7 @@ export default function AddLiquidity() { ...@@ -311,7 +316,7 @@ export default function AddLiquidity() {
} }
) )
.then(response => { .then(response => {
addTransaction(response.hash, response) addTransaction(response)
}) })
} }
...@@ -333,7 +338,6 @@ export default function AddLiquidity() { ...@@ -333,7 +338,6 @@ export default function AddLiquidity() {
} }
}, [decimals, inputValue, isNewExchange, outputValue]) }, [decimals, inputValue, isNewExchange, outputValue])
console.log('rendering')
// parse input value // parse input value
useEffect(() => { useEffect(() => {
if (isNewExchange === false && inputValue && marketRate && lastEditedField === INPUT) { if (isNewExchange === false && inputValue && marketRate && lastEditedField === INPUT) {
......
...@@ -8,9 +8,9 @@ import ReactGA from 'react-ga' ...@@ -8,9 +8,9 @@ import ReactGA from 'react-ga'
import AddressInputPanel from '../../components/AddressInputPanel' import AddressInputPanel from '../../components/AddressInputPanel'
import OversizedPanel from '../../components/OversizedPanel' import OversizedPanel from '../../components/OversizedPanel'
import { useTokenDetails } from '../../contexts/Static'
import { useTransactionContext } from '../../contexts/Transaction'
import { useFactoryContract } from '../../hooks' import { useFactoryContract } from '../../hooks'
import { useTokenDetails } from '../../contexts/Tokens'
import { useTransactionAdder } from '../../contexts/Transactions'
function CreateExchange({ history, location }) { function CreateExchange({ history, location }) {
const { t } = useTranslation() const { t } = useTranslation()
...@@ -24,7 +24,7 @@ function CreateExchange({ history, location }) { ...@@ -24,7 +24,7 @@ function CreateExchange({ history, location }) {
const [tokenAddressError, setTokenAddressError] = useState() const [tokenAddressError, setTokenAddressError] = useState()
const { name, symbol, decimals, exchangeAddress } = useTokenDetails(tokenAddress.address) const { name, symbol, decimals, exchangeAddress } = useTokenDetails(tokenAddress.address)
const { addTransaction } = useTransactionContext() const addTransaction = useTransactionAdder()
// clear location state, if it exists // clear location state, if it exists
useEffect(() => { useEffect(() => {
...@@ -61,11 +61,12 @@ function CreateExchange({ history, location }) { ...@@ -61,11 +61,12 @@ function CreateExchange({ history, location }) {
const estimatedGasLimit = await factory.estimate.createExchange(tokenAddress.address) const estimatedGasLimit = await factory.estimate.createExchange(tokenAddress.address)
factory.createExchange(tokenAddress.address, { gasLimit: estimatedGasLimit }).then(response => { factory.createExchange(tokenAddress.address, { gasLimit: estimatedGasLimit }).then(response => {
addTransaction(response.hash, response)
ReactGA.event({ ReactGA.event({
category: 'Pool', category: 'Pool',
action: 'CreateExchange' action: 'CreateExchange'
}) })
addTransaction(response)
}) })
} }
......
...@@ -10,11 +10,11 @@ import ContextualInfo from '../../components/ContextualInfo' ...@@ -10,11 +10,11 @@ import ContextualInfo from '../../components/ContextualInfo'
import OversizedPanel from '../../components/OversizedPanel' import OversizedPanel from '../../components/OversizedPanel'
import ArrowDownBlue from '../../assets/images/arrow-down-blue.svg' import ArrowDownBlue from '../../assets/images/arrow-down-blue.svg'
import ArrowDownGrey from '../../assets/images/arrow-down-grey.svg' import ArrowDownGrey from '../../assets/images/arrow-down-grey.svg'
import { useExchangeContract, useBlockEffect } from '../../hooks' import { useExchangeContract } from '../../hooks'
import { useAddressBalance } from '../../contexts/Block' import { useTransactionAdder } from '../../contexts/Transactions'
import { useTokenDetails } from '../../contexts/Static' import { useTokenDetails } from '../../contexts/Tokens'
import { useAddressBalance } from '../../contexts/Balances'
import { calculateGasMargin, amountFormatter } from '../../utils' import { calculateGasMargin, amountFormatter } from '../../utils'
import { useTransactionContext } from '../../contexts/Transaction'
// denominated in bips // denominated in bips
const ALLOWED_SLIPPAGE = ethers.utils.bigNumberify(200) const ALLOWED_SLIPPAGE = ethers.utils.bigNumberify(200)
...@@ -71,10 +71,10 @@ function calculateSlippageBounds(value) { ...@@ -71,10 +71,10 @@ function calculateSlippageBounds(value) {
} }
export default function RemoveLiquidity() { export default function RemoveLiquidity() {
const { account, active } = useWeb3Context() const { library, account, active } = useWeb3Context()
const { t } = useTranslation() const { t } = useTranslation()
const { addTransaction } = useTransactionContext() const addTransaction = useTransactionAdder()
const [outputCurrency, setOutputCurrency] = useState('') const [outputCurrency, setOutputCurrency] = useState('')
const [value, setValue] = useState('') const [value, setValue] = useState('')
...@@ -162,8 +162,12 @@ export default function RemoveLiquidity() { ...@@ -162,8 +162,12 @@ export default function RemoveLiquidity() {
}, [exchange]) }, [exchange])
useEffect(() => { useEffect(() => {
fetchPoolTokens() fetchPoolTokens()
}, [fetchPoolTokens]) library.on('block', fetchPoolTokens)
useBlockEffect(fetchPoolTokens)
return () => {
library.removeListener('block', fetchPoolTokens)
}
}, [fetchPoolTokens, library])
async function onRemoveLiquidity() { async function onRemoveLiquidity() {
ReactGA.event({ ReactGA.event({
...@@ -185,7 +189,7 @@ export default function RemoveLiquidity() { ...@@ -185,7 +189,7 @@ export default function RemoveLiquidity() {
gasLimit: calculateGasMargin(estimatedGasLimit, GAS_MARGIN) gasLimit: calculateGasMargin(estimatedGasLimit, GAS_MARGIN)
}) })
.then(response => { .then(response => {
addTransaction(response.hash, response) addTransaction(response)
}) })
} }
......
...@@ -10,14 +10,14 @@ import OversizedPanel from '../../components/OversizedPanel' ...@@ -10,14 +10,14 @@ import OversizedPanel from '../../components/OversizedPanel'
import AddressInputPanel from '../../components/AddressInputPanel' import AddressInputPanel from '../../components/AddressInputPanel'
import ArrowDownBlue from '../../assets/images/arrow-down-blue.svg' import ArrowDownBlue from '../../assets/images/arrow-down-blue.svg'
import ArrowDownGrey from '../../assets/images/arrow-down-grey.svg' import ArrowDownGrey from '../../assets/images/arrow-down-grey.svg'
import { useAddressBalance, useAddressAllowance, useExchangeReserves } from '../../contexts/Block' import { isAddress, amountFormatter, calculateGasMargin } from '../../utils'
import { useTokenDetails } from '../../contexts/Static'
import { useTransactionContext } from '../../contexts/Transaction'
import { amountFormatter, calculateGasMargin } from '../../utils'
import { useExchangeContract } from '../../hooks' import { useExchangeContract } from '../../hooks'
import { useTokenDetails } from '../../contexts/Tokens'
import { useTransactionAdder } from '../../contexts/Transactions'
import { useAddressBalance, useExchangeReserves } from '../../contexts/Balances'
import { useAddressAllowance } from '../../contexts/Allowances'
import './send.scss' import './send.scss'
import { isAddress } from 'web3-utils'
const INPUT = 0 const INPUT = 0
const OUTPUT = 1 const OUTPUT = 1
...@@ -194,7 +194,7 @@ export default function Swap() { ...@@ -194,7 +194,7 @@ export default function Swap() {
const { t } = useTranslation() const { t } = useTranslation()
const { account } = useWeb3Context() const { account } = useWeb3Context()
const { addTransaction } = useTransactionContext() const addTransaction = useTransactionAdder()
// analytics // analytics
useEffect(() => { useEffect(() => {
...@@ -619,7 +619,7 @@ export default function Swap() { ...@@ -619,7 +619,7 @@ export default function Swap() {
const estimatedGasLimit = await estimate(...args, { value }) const estimatedGasLimit = await estimate(...args, { value })
method(...args, { value, gasLimit: calculateGasMargin(estimatedGasLimit, GAS_MARGIN) }).then(response => { method(...args, { value, gasLimit: calculateGasMargin(estimatedGasLimit, GAS_MARGIN) }).then(response => {
addTransaction(response.hash, response) addTransaction(response)
}) })
} }
......
...@@ -9,11 +9,12 @@ import ContextualInfo from '../../components/ContextualInfo' ...@@ -9,11 +9,12 @@ import ContextualInfo from '../../components/ContextualInfo'
import OversizedPanel from '../../components/OversizedPanel' import OversizedPanel from '../../components/OversizedPanel'
import ArrowDownBlue from '../../assets/images/arrow-down-blue.svg' import ArrowDownBlue from '../../assets/images/arrow-down-blue.svg'
import ArrowDownGrey from '../../assets/images/arrow-down-grey.svg' import ArrowDownGrey from '../../assets/images/arrow-down-grey.svg'
import { useAddressBalance, useAddressAllowance, useExchangeReserves } from '../../contexts/Block'
import { useTokenDetails } from '../../contexts/Static'
import { useTransactionContext } from '../../contexts/Transaction'
import { amountFormatter, calculateGasMargin } from '../../utils' import { amountFormatter, calculateGasMargin } from '../../utils'
import { useExchangeContract } from '../../hooks' import { useExchangeContract } from '../../hooks'
import { useTokenDetails } from '../../contexts/Tokens'
import { useTransactionAdder } from '../../contexts/Transactions'
import { useAddressBalance, useExchangeReserves } from '../../contexts/Balances'
import { useAddressAllowance } from '../../contexts/Allowances'
import './swap.scss' import './swap.scss'
...@@ -192,7 +193,7 @@ export default function Swap() { ...@@ -192,7 +193,7 @@ export default function Swap() {
const { t } = useTranslation() const { t } = useTranslation()
const { account } = useWeb3Context() const { account } = useWeb3Context()
const { addTransaction } = useTransactionContext() const addTransaction = useTransactionAdder()
// analytics // analytics
useEffect(() => { useEffect(() => {
...@@ -284,7 +285,6 @@ export default function Swap() { ...@@ -284,7 +285,6 @@ export default function Swap() {
const [showUnlock, setShowUnlock] = useState(false) const [showUnlock, setShowUnlock] = useState(false)
useEffect(() => { useEffect(() => {
const inputValueCalculation = independentField === INPUT ? independentValueParsed : dependentValueMaximum const inputValueCalculation = independentField === INPUT ? independentValueParsed : dependentValueMaximum
if (inputBalance && (inputAllowance || inputCurrency === 'ETH') && inputValueCalculation) { if (inputBalance && (inputAllowance || inputCurrency === 'ETH') && inputValueCalculation) {
if (inputBalance.lt(inputValueCalculation)) { if (inputBalance.lt(inputValueCalculation)) {
setInputError(t('insufficientBalance')) setInputError(t('insufficientBalance'))
...@@ -381,7 +381,6 @@ export default function Swap() { ...@@ -381,7 +381,6 @@ export default function Swap() {
if (intermediateValue.lte(ethers.constants.Zero)) { if (intermediateValue.lte(ethers.constants.Zero)) {
throw Error() throw Error()
} }
// console.log('hi!', amountFormatter(intermediateValue, ))
const calculatedDependentValue = calculateEtherTokenInputFromOutput( const calculatedDependentValue = calculateEtherTokenInputFromOutput(
intermediateValue, intermediateValue,
reserveTokenFirst, reserveTokenFirst,
...@@ -596,7 +595,7 @@ export default function Swap() { ...@@ -596,7 +595,7 @@ export default function Swap() {
const estimatedGasLimit = await estimate(...args, { value }) const estimatedGasLimit = await estimate(...args, { value })
method(...args, { value, gasLimit: calculateGasMargin(estimatedGasLimit, GAS_MARGIN) }).then(response => { method(...args, { value, gasLimit: calculateGasMargin(estimatedGasLimit, GAS_MARGIN) }).then(response => {
addTransaction(response.hash, response) addTransaction(response)
}) })
} }
......
import React from 'react'
import { ThemeProvider as StyledComponentsThemeProvider, createGlobalStyle } from 'styled-components'
const theme = {
uniswapPink: '#DC6BE5',
royalBlue: '#2f80ed',
white: '#FFF',
black: '#000'
}
export default function ThemeProvider({ children }) {
return <StyledComponentsThemeProvider theme={theme}>{children}</StyledComponentsThemeProvider>
}
export const GlobalStyle = createGlobalStyle`
@import url('https://rsms.me/inter/inter.css');
html,
body {
padding: 0;
margin: 0;
font-family: Inter, sans-serif;
font-variant: none;
font-size: 16px;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
overflow-x: hidden;
}
#root {
position: relative;
display: flex;
flex-flow: column nowrap;
height: 100vh;
width: 100vw;
overflow-x: hidden;
overflow-y: auto;
background-color: ${props => props.theme.white};
z-index: 100;
-webkit-tap-highlight-color: rgba(255, 255, 255, 0);
@media only screen and (min-width: 768px) {
justify-content: center;
align-items: center;
}
}
#modal-root {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 200;
}
.loader {
border: 1px solid transparent;
border-top: 1px solid ${props => props.theme.royalBlue};
border-radius: 50%;
width: 0.75rem;
height: 0.75rem;
margin-right: 0.25rem;
animation: spin 1s cubic-bezier(0.25, 0.46, 0.45, 0.94) infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
`
...@@ -14,6 +14,13 @@ export const ERROR_CODES = ['TOKEN_NAME', 'TOKEN_SYMBOL', 'TOKEN_DECIMALS'].redu ...@@ -14,6 +14,13 @@ export const ERROR_CODES = ['TOKEN_NAME', 'TOKEN_SYMBOL', 'TOKEN_DECIMALS'].redu
{} {}
) )
export function safeAccess(object, path) {
return path.reduce(
(accumulator, currentValue) => (accumulator && accumulator[currentValue] ? accumulator[currentValue] : null),
object
)
}
export function isAddress(value) { export function isAddress(value) {
try { try {
ethers.utils.getAddress(value) ethers.utils.getAddress(value)
......
...@@ -1006,6 +1006,23 @@ ...@@ -1006,6 +1006,23 @@
resolved "https://registry.yarnpkg.com/@csstools/normalize.css/-/normalize.css-9.0.1.tgz#c27b391d8457d1e893f1eddeaf5e5412d12ffbb5" resolved "https://registry.yarnpkg.com/@csstools/normalize.css/-/normalize.css-9.0.1.tgz#c27b391d8457d1e893f1eddeaf5e5412d12ffbb5"
integrity sha512-6It2EVfGskxZCQhuykrfnALg7oVeiI6KclWSmGDqB0AiInVrTGB9Jp9i4/Ad21u9Jde/voVQz6eFX/eSg/UsPA== integrity sha512-6It2EVfGskxZCQhuykrfnALg7oVeiI6KclWSmGDqB0AiInVrTGB9Jp9i4/Ad21u9Jde/voVQz6eFX/eSg/UsPA==
"@emotion/is-prop-valid@^0.7.3":
version "0.7.3"
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.7.3.tgz#a6bf4fa5387cbba59d44e698a4680f481a8da6cc"
integrity sha512-uxJqm/sqwXw3YPA5GXX365OBcJGFtxUVkB6WyezqFHlNe9jqUWH5ur2O2M8dGBz61kn1g3ZBlzUunFQXQIClhA==
dependencies:
"@emotion/memoize" "0.7.1"
"@emotion/memoize@0.7.1":
version "0.7.1"
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.1.tgz#e93c13942592cf5ef01aa8297444dc192beee52f"
integrity sha512-Qv4LTqO11jepd5Qmlp3M1YEjBumoTHcHFdgPTQ+sFlIL5myi/7xu/POwP7IRu6odBdmLXdtIs1D6TuW6kbwbbg==
"@emotion/unitless@^0.7.0":
version "0.7.3"
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.3.tgz#6310a047f12d21a1036fb031317219892440416f"
integrity sha512-4zAPlpDEh2VwXswwr/t8xGNDGg8RQiPxtxZ3qQEXyQsBV39ptTdESCjuBvGze1nLMVrxmTIKmnO/nAV8Tqjjzg==
"@jest/console@^24.7.1": "@jest/console@^24.7.1":
version "24.7.1" version "24.7.1"
resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.7.1.tgz#32a9e42535a97aedfe037e725bd67e954b459545" resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.7.1.tgz#32a9e42535a97aedfe037e725bd67e954b459545"
...@@ -1067,6 +1084,15 @@ ...@@ -1067,6 +1084,15 @@
jest-message-util "^24.7.1" jest-message-util "^24.7.1"
jest-mock "^24.7.0" jest-mock "^24.7.0"
"@jest/fake-timers@^24.8.0":
version "24.8.0"
resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-24.8.0.tgz#2e5b80a4f78f284bcb4bd5714b8e10dd36a8d3d1"
integrity sha512-2M4d5MufVXwi6VzZhJ9f5S/wU4ud2ck0kxPof1Iz3zWx6Y+V2eJrES9jEktB6O3o/oEyk+il/uNu9PvASjWXQw==
dependencies:
"@jest/types" "^24.8.0"
jest-message-util "^24.8.0"
jest-mock "^24.8.0"
"@jest/reporters@^24.7.1": "@jest/reporters@^24.7.1":
version "24.7.1" version "24.7.1"
resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-24.7.1.tgz#38ac0b096cd691bbbe3051ddc25988d42e37773a" resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-24.7.1.tgz#38ac0b096cd691bbbe3051ddc25988d42e37773a"
...@@ -1111,6 +1137,15 @@ ...@@ -1111,6 +1137,15 @@
"@jest/types" "^24.7.0" "@jest/types" "^24.7.0"
"@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-lib-coverage" "^2.0.0"
"@jest/test-result@^24.8.0":
version "24.8.0"
resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.8.0.tgz#7675d0aaf9d2484caa65e048d9b467d160f8e9d3"
integrity sha512-+YdLlxwizlfqkFDh7Mc7ONPQAhA4YylU1s529vVM1rsf67vGZH/2GGm5uO8QzPeVyaVMobCQ7FTxl38QrKRlng==
dependencies:
"@jest/console" "^24.7.1"
"@jest/types" "^24.8.0"
"@types/istanbul-lib-coverage" "^2.0.0"
"@jest/test-sequencer@^24.7.1": "@jest/test-sequencer@^24.7.1":
version "24.7.1" version "24.7.1"
resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-24.7.1.tgz#9c18e428e1ad945fa74f6233a9d35745ca0e63e0" resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-24.7.1.tgz#9c18e428e1ad945fa74f6233a9d35745ca0e63e0"
...@@ -1142,6 +1177,27 @@ ...@@ -1142,6 +1177,27 @@
source-map "^0.6.1" source-map "^0.6.1"
write-file-atomic "2.4.1" write-file-atomic "2.4.1"
"@jest/transform@^24.8.0":
version "24.8.0"
resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-24.8.0.tgz#628fb99dce4f9d254c6fd9341e3eea262e06fef5"
integrity sha512-xBMfFUP7TortCs0O+Xtez2W7Zu1PLH9bvJgtraN1CDST6LBM/eTOZ9SfwS/lvV8yOfcDpFmwf9bq5cYbXvqsvA==
dependencies:
"@babel/core" "^7.1.0"
"@jest/types" "^24.8.0"
babel-plugin-istanbul "^5.1.0"
chalk "^2.0.1"
convert-source-map "^1.4.0"
fast-json-stable-stringify "^2.0.0"
graceful-fs "^4.1.15"
jest-haste-map "^24.8.0"
jest-regex-util "^24.3.0"
jest-util "^24.8.0"
micromatch "^3.1.10"
realpath-native "^1.1.0"
slash "^2.0.0"
source-map "^0.6.1"
write-file-atomic "2.4.1"
"@jest/types@^24.7.0": "@jest/types@^24.7.0":
version "24.7.0" version "24.7.0"
resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.7.0.tgz#c4ec8d1828cdf23234d9b4ee31f5482a3f04f48b" resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.7.0.tgz#c4ec8d1828cdf23234d9b4ee31f5482a3f04f48b"
...@@ -1150,6 +1206,15 @@ ...@@ -1150,6 +1206,15 @@
"@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-lib-coverage" "^2.0.0"
"@types/yargs" "^12.0.9" "@types/yargs" "^12.0.9"
"@jest/types@^24.8.0":
version "24.8.0"
resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.8.0.tgz#f31e25948c58f0abd8c845ae26fcea1491dea7ad"
integrity sha512-g17UxVr2YfBtaMUxn9u/4+siG1ptg9IGYAYwvpwn61nBg779RXnjE/m7CxYcIzEt0AbHZZAHSEZNhkE2WxURVg==
dependencies:
"@types/istanbul-lib-coverage" "^2.0.0"
"@types/istanbul-reports" "^1.1.1"
"@types/yargs" "^12.0.9"
"@ledgerhq/devices@^4.50.0": "@ledgerhq/devices@^4.50.0":
version "4.50.0" version "4.50.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-4.50.0.tgz#3a1b762948fd3720e73eafad4767d18a903a4b05" resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-4.50.0.tgz#3a1b762948fd3720e73eafad4767d18a903a4b05"
...@@ -1211,6 +1276,58 @@ ...@@ -1211,6 +1276,58 @@
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
"@reach/auto-id@0.2.0":
version "0.2.0"
resolved "https://registry.yarnpkg.com/@reach/auto-id/-/auto-id-0.2.0.tgz#97f9e48fe736aa5c6f4f32cf73c1f19d005f8550"
integrity sha512-lVK/svL2HuQdp7jgvlrLkFsUx50Az9chAhxpiPwBqcS83I2pVWvXp98FOcSCCJCV++l115QmzHhFd+ycw1zLBg==
"@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/observe-rect@^1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@reach/observe-rect/-/observe-rect-1.0.3.tgz#2ea3dcc369ab22bd9f050a92ea319321356a61e8"
integrity sha1-LqPcw2mrIr2fBQqS6jGTITVqYeg=
"@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==
dependencies:
"@reach/component-component" "^0.1.3"
"@reach/rect@^0.2.1":
version "0.2.1"
resolved "https://registry.yarnpkg.com/@reach/rect/-/rect-0.2.1.tgz#7343020174c90e2290b844d17c03fd9c78e6b601"
integrity sha512-aZ9RsNHDMQ3zETonikqu9/85iXxj+LPqZ9Gr9UAncj3AufYmGeWG3XG6b37B+7ORH+mkhVpLU2ZlIWxmOe9Cqg==
dependencies:
"@reach/component-component" "^0.1.3"
"@reach/observe-rect" "^1.0.3"
"@reach/tooltip@^0.2.0":
version "0.2.0"
resolved "https://registry.yarnpkg.com/@reach/tooltip/-/tooltip-0.2.0.tgz#705da2c5487d3f611f3d40482b387b6f42825b8e"
integrity sha512-RKJkGR+w3vS+flGjcVL82SK016E6rzjG8wC4ZtFu03VCAxJyhveG0uaB3juv7Rx+u8CEwv2gxfWgfMWgrJ2cRA==
dependencies:
"@reach/auto-id" "0.2.0"
"@reach/portal" "^0.2.1"
"@reach/rect" "^0.2.1"
"@reach/utils" "^0.2.2"
"@reach/visually-hidden" "^0.1.4"
prop-types "^15.7.2"
"@reach/utils@^0.2.2":
version "0.2.2"
resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.2.2.tgz#c3a05ae9fd1f921988ae8a89b5a0d28d1a2b92df"
integrity sha512-jYeIi46AA5jh2gfdXD/nInUYfeLp3girRafiajP7AVHF6B4hpYAzUSx/ZH4xmPyf5alut5rml2DHxrv+X+Xu+A==
"@reach/visually-hidden@^0.1.4":
version "0.1.4"
resolved "https://registry.yarnpkg.com/@reach/visually-hidden/-/visually-hidden-0.1.4.tgz#0dc4ecedf523004337214187db70a46183bd945b"
integrity sha512-QHbzXjflSlCvDd6vJwdwx16mSB+vUCCQMiU/wK/CgVNPibtpEiIbisyxkpZc55DyDFNUIqP91rSUsNae+ogGDQ==
"@svgr/babel-plugin-add-jsx-attribute@^4.2.0": "@svgr/babel-plugin-add-jsx-attribute@^4.2.0":
version "4.2.0" version "4.2.0"
resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.2.0.tgz#dadcb6218503532d6884b210e7f3c502caaa44b1" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.2.0.tgz#dadcb6218503532d6884b210e7f3c502caaa44b1"
...@@ -1377,11 +1494,26 @@ ...@@ -1377,11 +1494,26 @@
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@types/istanbul-lib-coverage@^2.0.0": "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff"
integrity sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg== integrity sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==
"@types/istanbul-lib-report@*":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#e5471e7fa33c61358dd38426189c037a58433b8c"
integrity sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==
dependencies:
"@types/istanbul-lib-coverage" "*"
"@types/istanbul-reports@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz#7a8cbf6a406f36c8add871625b278eaf0b0d255a"
integrity sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==
dependencies:
"@types/istanbul-lib-coverage" "*"
"@types/istanbul-lib-report" "*"
"@types/node@*": "@types/node@*":
version "11.13.4" version "11.13.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-11.13.4.tgz#f83ec3c3e05b174b7241fadeb6688267fe5b22ca" resolved "https://registry.yarnpkg.com/@types/node/-/node-11.13.4.tgz#f83ec3c3e05b174b7241fadeb6688267fe5b22ca"
...@@ -2247,7 +2379,7 @@ babel-helpers@^6.24.1: ...@@ -2247,7 +2379,7 @@ babel-helpers@^6.24.1:
babel-runtime "^6.22.0" babel-runtime "^6.22.0"
babel-template "^6.24.1" babel-template "^6.24.1"
babel-jest@24.7.1, babel-jest@^24.7.1: babel-jest@^24.7.1:
version "24.7.1" version "24.7.1"
resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.7.1.tgz#73902c9ff15a7dfbdc9994b0b17fcefd96042178" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.7.1.tgz#73902c9ff15a7dfbdc9994b0b17fcefd96042178"
integrity sha512-GPnLqfk8Mtt0i4OemjWkChi73A3ALs4w2/QbG64uAj8b5mmwzxc7jbJVRZt8NJkxi6FopVHog9S3xX6UJKb2qg== integrity sha512-GPnLqfk8Mtt0i4OemjWkChi73A3ALs4w2/QbG64uAj8b5mmwzxc7jbJVRZt8NJkxi6FopVHog9S3xX6UJKb2qg==
...@@ -2260,6 +2392,19 @@ babel-jest@24.7.1, babel-jest@^24.7.1: ...@@ -2260,6 +2392,19 @@ babel-jest@24.7.1, babel-jest@^24.7.1:
chalk "^2.4.2" chalk "^2.4.2"
slash "^2.0.0" slash "^2.0.0"
babel-jest@^24.8.0:
version "24.8.0"
resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.8.0.tgz#5c15ff2b28e20b0f45df43fe6b7f2aae93dba589"
integrity sha512-+5/kaZt4I9efoXzPlZASyK/lN9qdRKmmUav9smVc0ruPQD7IsfucQ87gpOE8mn2jbDuS6M/YOW6n3v9ZoIfgnw==
dependencies:
"@jest/transform" "^24.8.0"
"@jest/types" "^24.8.0"
"@types/babel__core" "^7.1.0"
babel-plugin-istanbul "^5.1.0"
babel-preset-jest "^24.6.0"
chalk "^2.4.2"
slash "^2.0.0"
babel-loader@8.0.5: babel-loader@8.0.5:
version "8.0.5" version "8.0.5"
resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.5.tgz#225322d7509c2157655840bba52e46b6c2f2fe33" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.5.tgz#225322d7509c2157655840bba52e46b6c2f2fe33"
...@@ -2321,6 +2466,16 @@ babel-plugin-named-asset-import@^0.3.2: ...@@ -2321,6 +2466,16 @@ babel-plugin-named-asset-import@^0.3.2:
resolved "https://registry.yarnpkg.com/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.2.tgz#20978ed446b8e1bf4a2f42d0a94c0ece85f75f4f" resolved "https://registry.yarnpkg.com/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.2.tgz#20978ed446b8e1bf4a2f42d0a94c0ece85f75f4f"
integrity sha512-CxwvxrZ9OirpXQ201Ec57OmGhmI8/ui/GwTDy0hSp6CmRvgRC0pSair6Z04Ck+JStA0sMPZzSJ3uE4n17EXpPQ== integrity sha512-CxwvxrZ9OirpXQ201Ec57OmGhmI8/ui/GwTDy0hSp6CmRvgRC0pSair6Z04Ck+JStA0sMPZzSJ3uE4n17EXpPQ==
"babel-plugin-styled-components@>= 1":
version "1.10.0"
resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-1.10.0.tgz#ff1f42ad2cc78c21f26b62266b8f564dbc862939"
integrity sha512-sQVKG8irFXx14ZfaK1bBePirfkacl3j8nZwSZK+ZjsbnadRHKQTbhXbe/RB1vT6Vgkz45E+V95LBq4KqdhZUNw==
dependencies:
"@babel/helper-annotate-as-pure" "^7.0.0"
"@babel/helper-module-imports" "^7.0.0"
babel-plugin-syntax-jsx "^6.18.0"
lodash "^4.17.10"
babel-plugin-syntax-async-functions@^6.8.0: babel-plugin-syntax-async-functions@^6.8.0:
version "6.13.0" version "6.13.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
...@@ -2331,6 +2486,11 @@ babel-plugin-syntax-exponentiation-operator@^6.8.0: ...@@ -2331,6 +2486,11 @@ babel-plugin-syntax-exponentiation-operator@^6.8.0:
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de"
integrity sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4= integrity sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=
babel-plugin-syntax-jsx@^6.18.0:
version "6.18.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=
babel-plugin-syntax-object-rest-spread@^6.8.0: babel-plugin-syntax-object-rest-spread@^6.8.0:
version "6.13.0" version "6.13.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
...@@ -2621,10 +2781,10 @@ babel-preset-jest@^24.6.0: ...@@ -2621,10 +2781,10 @@ babel-preset-jest@^24.6.0:
"@babel/plugin-syntax-object-rest-spread" "^7.0.0" "@babel/plugin-syntax-object-rest-spread" "^7.0.0"
babel-plugin-jest-hoist "^24.6.0" babel-plugin-jest-hoist "^24.6.0"
babel-preset-react-app@^8.0.0: babel-preset-react-app@^9.0.0:
version "8.0.0" version "9.0.0"
resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-8.0.0.tgz#930b6e28cdcfdff97ddb8bef9226d504f244d326" resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-9.0.0.tgz#703108142bc9dd7173bde6a1a0138a762abc76f9"
integrity sha512-6Dmj7e8l7eWE+R6sKKLRrGEQXMfcBqBYlphaAgT1ml8qT1NEP+CyTZyfjmgKGqHZfwH3RQCUOuP6y4mpGc7tgg== integrity sha512-YVsDA8HpAKklhFLJtl9+AgaxrDaor8gGvDFlsg1ByOS0IPGUovumdv4/gJiAnLcDmZmKlH6+9sVOz4NVW7emAg==
dependencies: dependencies:
"@babel/core" "7.4.3" "@babel/core" "7.4.3"
"@babel/plugin-proposal-class-properties" "7.4.0" "@babel/plugin-proposal-class-properties" "7.4.0"
...@@ -3294,6 +3454,11 @@ camelcase@^5.0.0, camelcase@^5.2.0, camelcase@^5.3.1: ...@@ -3294,6 +3454,11 @@ camelcase@^5.0.0, camelcase@^5.2.0, camelcase@^5.3.1:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
camelize@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b"
integrity sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=
caniuse-api@^3.0.0: caniuse-api@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0"
...@@ -3914,6 +4079,11 @@ css-blank-pseudo@^0.1.4: ...@@ -3914,6 +4079,11 @@ css-blank-pseudo@^0.1.4:
dependencies: dependencies:
postcss "^7.0.5" postcss "^7.0.5"
css-color-keywords@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05"
integrity sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=
css-color-names@0.0.4, css-color-names@^0.0.4: css-color-names@0.0.4, css-color-names@^0.0.4:
version "0.0.4" version "0.0.4"
resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
...@@ -3984,6 +4154,15 @@ css-select@^2.0.0: ...@@ -3984,6 +4154,15 @@ css-select@^2.0.0:
domutils "^1.7.0" domutils "^1.7.0"
nth-check "^1.0.2" nth-check "^1.0.2"
css-to-react-native@^2.2.2:
version "2.3.1"
resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-2.3.1.tgz#cf0f61e0514846e2d4dc188b0886e29d8bef64a2"
integrity sha512-yO+oEx1Lf+hDKasqQRVrAvzMCz825Huh1VMlEEDlRWyAhFb/FWb6I0KpEF1PkyKQ7NEdcx9d5M2ZEWgJAsgPvQ==
dependencies:
camelize "^1.0.0"
css-color-keywords "^1.0.0"
postcss-value-parser "^3.3.0"
css-tree@1.0.0-alpha.28: css-tree@1.0.0-alpha.28:
version "1.0.0-alpha.28" version "1.0.0-alpha.28"
resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.28.tgz#8e8968190d886c9477bc8d61e96f61af3f7ffa7f" resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.28.tgz#8e8968190d886c9477bc8d61e96f61af3f7ffa7f"
...@@ -4781,10 +4960,10 @@ escodegen@^1.11.0, escodegen@^1.9.1: ...@@ -4781,10 +4960,10 @@ escodegen@^1.11.0, escodegen@^1.9.1:
optionalDependencies: optionalDependencies:
source-map "~0.6.1" source-map "~0.6.1"
eslint-config-react-app@^4.0.0: eslint-config-react-app@^4.0.1:
version "4.0.0" version "4.0.1"
resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-4.0.0.tgz#1651f44b3830d863817af6ebed0916193aa870c3" resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-4.0.1.tgz#23fd0fd7ea89442ef1e733f66a7207674b23c8db"
integrity sha512-SeFxaI+0NAzWPFAI9AT+Vp9Xe2u5RCnn0JVEXkE338HgoPujc38Bc0upCJw4BWmavvIN/ODmE6EuzHoAEn3ozw== integrity sha512-ZsaoXUIGsK8FCi/x4lT2bZR5mMkL/Kgj+Lnw690rbvvUr/uiwgFiD8FcfAhkCycm7Xte6O5lYz4EqMx2vX7jgw==
dependencies: dependencies:
confusing-browser-globals "^1.0.7" confusing-browser-globals "^1.0.7"
...@@ -5710,6 +5889,21 @@ flush-write-stream@^1.0.0: ...@@ -5710,6 +5889,21 @@ flush-write-stream@^1.0.0:
inherits "^2.0.3" inherits "^2.0.3"
readable-stream "^2.3.6" readable-stream "^2.3.6"
focus-trap-react@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/focus-trap-react/-/focus-trap-react-6.0.0.tgz#3f5a9f68447dd374d22388fb4c50018be83e74a5"
integrity sha512-mvEYxmP75PMx0vOqoIAmJHO/qUEvdTAdz6gLlEZyxxODnuKQdnKea2RWTYxghAPrV+ibiIq2o/GTSgQycnAjcw==
dependencies:
focus-trap "^4.0.2"
focus-trap@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-4.0.2.tgz#4ee2b96547c9ea0e4252a2d4b2cca68944194663"
integrity sha512-HtLjfAK7Hp2qbBtLS6wEznID1mPT+48ZnP2nkHzgjpL4kroYHg0CdqJ5cTXk+UO5znAxF5fRUkhdyfgrhh8Lzw==
dependencies:
tabbable "^3.1.2"
xtend "^4.0.1"
follow-redirects@^1.0.0: follow-redirects@^1.0.0:
version "1.7.0" version "1.7.0"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.7.0.tgz#489ebc198dc0e7f64167bd23b03c4c19b5784c76" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.7.0.tgz#489ebc198dc0e7f64167bd23b03c4c19b5784c76"
...@@ -5753,10 +5947,10 @@ forever-agent@~0.6.1: ...@@ -5753,10 +5947,10 @@ forever-agent@~0.6.1:
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
fork-ts-checker-webpack-plugin@1.0.1: fork-ts-checker-webpack-plugin@1.1.1:
version "1.0.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-1.0.1.tgz#140453c4dc3dc35937034b7416b66a3bacfbc3a8" resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-1.1.1.tgz#caf2a210778fb1e171b6993ca0a40f9b6589e3b7"
integrity sha512-RrVxSiNtngsFDLQpP2QlrVaJK1zqRdwhtwslmDUWQTg3t3GW8QN7D3EpW/EAI+oqTqL0dGvLyluyYQ/eIrIHvQ== integrity sha512-gqWAEMLlae/oeVnN6RWCAhesOJMswAN1MaKNqhhjXHV5O0/rTUjWI4UbgQHdlrVbCnb+xLotXmJbBlC66QmpFw==
dependencies: dependencies:
babel-code-frame "^6.22.0" babel-code-frame "^6.22.0"
chalk "^2.4.1" chalk "^2.4.1"
...@@ -5765,6 +5959,7 @@ fork-ts-checker-webpack-plugin@1.0.1: ...@@ -5765,6 +5959,7 @@ fork-ts-checker-webpack-plugin@1.0.1:
minimatch "^3.0.4" minimatch "^3.0.4"
semver "^5.6.0" semver "^5.6.0"
tapable "^1.0.0" tapable "^1.0.0"
worker-rpc "^0.1.0"
form-data@~2.3.2: form-data@~2.3.2:
version "2.3.3" version "2.3.3"
...@@ -7351,6 +7546,25 @@ jest-haste-map@^24.7.1: ...@@ -7351,6 +7546,25 @@ jest-haste-map@^24.7.1:
optionalDependencies: optionalDependencies:
fsevents "^1.2.7" fsevents "^1.2.7"
jest-haste-map@^24.8.0:
version "24.8.0"
resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.8.0.tgz#51794182d877b3ddfd6e6d23920e3fe72f305800"
integrity sha512-ZBPRGHdPt1rHajWelXdqygIDpJx8u3xOoLyUBWRW28r3tagrgoepPrzAozW7kW9HrQfhvmiv1tncsxqHJO1onQ==
dependencies:
"@jest/types" "^24.8.0"
anymatch "^2.0.0"
fb-watchman "^2.0.0"
graceful-fs "^4.1.15"
invariant "^2.2.4"
jest-serializer "^24.4.0"
jest-util "^24.8.0"
jest-worker "^24.6.0"
micromatch "^3.1.10"
sane "^4.0.3"
walker "^1.0.7"
optionalDependencies:
fsevents "^1.2.7"
jest-jasmine2@^24.7.1: jest-jasmine2@^24.7.1:
version "24.7.1" version "24.7.1"
resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.7.1.tgz#01398686dabe46553716303993f3be62e5d9d818" resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.7.1.tgz#01398686dabe46553716303993f3be62e5d9d818"
...@@ -7404,6 +7618,20 @@ jest-message-util@^24.7.1: ...@@ -7404,6 +7618,20 @@ jest-message-util@^24.7.1:
slash "^2.0.0" slash "^2.0.0"
stack-utils "^1.0.1" stack-utils "^1.0.1"
jest-message-util@^24.8.0:
version "24.8.0"
resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.8.0.tgz#0d6891e72a4beacc0292b638685df42e28d6218b"
integrity sha512-p2k71rf/b6ns8btdB0uVdljWo9h0ovpnEe05ZKWceQGfXYr4KkzgKo3PBi8wdnd9OtNh46VpNIJynUn/3MKm1g==
dependencies:
"@babel/code-frame" "^7.0.0"
"@jest/test-result" "^24.8.0"
"@jest/types" "^24.8.0"
"@types/stack-utils" "^1.0.1"
chalk "^2.0.1"
micromatch "^3.1.10"
slash "^2.0.0"
stack-utils "^1.0.1"
jest-mock@^24.5.0, jest-mock@^24.7.0: jest-mock@^24.5.0, jest-mock@^24.7.0:
version "24.7.0" version "24.7.0"
resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.7.0.tgz#e49ce7262c12d7f5897b0d8af77f6db8e538023b" resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.7.0.tgz#e49ce7262c12d7f5897b0d8af77f6db8e538023b"
...@@ -7411,6 +7639,13 @@ jest-mock@^24.5.0, jest-mock@^24.7.0: ...@@ -7411,6 +7639,13 @@ jest-mock@^24.5.0, jest-mock@^24.7.0:
dependencies: dependencies:
"@jest/types" "^24.7.0" "@jest/types" "^24.7.0"
jest-mock@^24.8.0:
version "24.8.0"
resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.8.0.tgz#2f9d14d37699e863f1febf4e4d5a33b7fdbbde56"
integrity sha512-6kWugwjGjJw+ZkK4mDa0Df3sDlUTsV47MSrT0nGQ0RBWJbpODDQ8MHDVtGtUYBne3IwZUhtB7elxHspU79WH3A==
dependencies:
"@jest/types" "^24.8.0"
jest-pnp-resolver@^1.2.1: jest-pnp-resolver@^1.2.1:
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a" resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a"
...@@ -7536,6 +7771,24 @@ jest-util@^24.5.0, jest-util@^24.7.1: ...@@ -7536,6 +7771,24 @@ jest-util@^24.5.0, jest-util@^24.7.1:
slash "^2.0.0" slash "^2.0.0"
source-map "^0.6.0" source-map "^0.6.0"
jest-util@^24.8.0:
version "24.8.0"
resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.8.0.tgz#41f0e945da11df44cc76d64ffb915d0716f46cd1"
integrity sha512-DYZeE+XyAnbNt0BG1OQqKy/4GVLPtzwGx5tsnDrFcax36rVE3lTA5fbvgmbVPUZf9w77AJ8otqR4VBbfFJkUZA==
dependencies:
"@jest/console" "^24.7.1"
"@jest/fake-timers" "^24.8.0"
"@jest/source-map" "^24.3.0"
"@jest/test-result" "^24.8.0"
"@jest/types" "^24.8.0"
callsites "^3.0.0"
chalk "^2.0.1"
graceful-fs "^4.1.15"
is-ci "^2.0.0"
mkdirp "^0.5.1"
slash "^2.0.0"
source-map "^0.6.0"
jest-validate@^24.7.0: jest-validate@^24.7.0:
version "24.7.0" version "24.7.0"
resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.7.0.tgz#70007076f338528ee1b1c8a8258b1b0bb982508d" resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.7.0.tgz#70007076f338528ee1b1c8a8258b1b0bb982508d"
...@@ -8157,11 +8410,6 @@ lodash.memoize@^4.1.2: ...@@ -8157,11 +8410,6 @@ lodash.memoize@^4.1.2:
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=
lodash.merge@^4.6.1:
version "4.6.1"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.1.tgz#adc25d9cb99b9391c59624f379fbba60d7111d54"
integrity sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==
lodash.mergewith@^4.6.0: lodash.mergewith@^4.6.0:
version "4.6.1" version "4.6.1"
resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927" resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927"
...@@ -8380,6 +8628,11 @@ memdown@^1.0.0: ...@@ -8380,6 +8628,11 @@ memdown@^1.0.0:
ltgt "~2.2.0" ltgt "~2.2.0"
safe-buffer "~5.1.1" safe-buffer "~5.1.1"
memoize-one@^5.0.0:
version "5.0.4"
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.0.4.tgz#005928aced5c43d890a4dfab18ca908b0ec92cbc"
integrity sha512-P0z5IeAH6qHHGkJIXWw0xC2HNEgkx/9uWWBQw64FJj3/ol14VYdfVGWWr0fXfjhhv3TKVIqUq65os6O4GUNksA==
memory-fs@^0.4.0, memory-fs@^0.4.1, memory-fs@~0.4.1: memory-fs@^0.4.0, memory-fs@^0.4.1, memory-fs@~0.4.1:
version "0.4.1" version "0.4.1"
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"
...@@ -8468,6 +8721,11 @@ methods@~1.1.2: ...@@ -8468,6 +8721,11 @@ methods@~1.1.2:
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
microevent.ts@~0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/microevent.ts/-/microevent.ts-0.1.0.tgz#390748b8a515083e6b63cd5112a3f18c2fe0eba8"
integrity sha1-OQdIuKUVCD5rY81REqPxjC/g66g=
micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8: micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8:
version "3.1.10" version "3.1.10"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
...@@ -8778,6 +9036,11 @@ no-case@^2.2.0: ...@@ -8778,6 +9036,11 @@ no-case@^2.2.0:
dependencies: dependencies:
lower-case "^1.1.1" lower-case "^1.1.1"
no-scroll@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/no-scroll/-/no-scroll-2.1.1.tgz#f37e08cb159b75a5bdbfc0a87cd9223e120e6e27"
integrity sha512-YTzGAJOo/B6hkodeT5SKKHpOhAzjMfkUCCXjLJwjWk2F4/InIg+HbdH9kmT7bKpleDuqLZDTRy2OdNtAj0IVyQ==
node-abi@^2.7.0: node-abi@^2.7.0:
version "2.7.1" version "2.7.1"
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.7.1.tgz#a8997ae91176a5fbaa455b194976e32683cda643" resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.7.1.tgz#a8997ae91176a5fbaa455b194976e32683cda643"
...@@ -10412,7 +10675,7 @@ prompts@^2.0.1: ...@@ -10412,7 +10675,7 @@ prompts@^2.0.1:
kleur "^3.0.2" kleur "^3.0.2"
sisteransi "^1.0.0" sisteransi "^1.0.0"
prop-types@^15.5.6, prop-types@^15.6.2: prop-types@^15.5.4, prop-types@^15.5.6, prop-types@^15.6.2, prop-types@^15.7.2:
version "15.7.2" version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
...@@ -10652,10 +10915,10 @@ rc@^1.2.7: ...@@ -10652,10 +10915,10 @@ rc@^1.2.7:
minimist "^1.2.0" minimist "^1.2.0"
strip-json-comments "~2.0.1" strip-json-comments "~2.0.1"
react-app-polyfill@^1.0.0: react-app-polyfill@^1.0.1:
version "1.0.0" version "1.0.1"
resolved "https://registry.yarnpkg.com/react-app-polyfill/-/react-app-polyfill-1.0.0.tgz#735c725c1d4261b710cb200c498789c8b80e0f74" resolved "https://registry.yarnpkg.com/react-app-polyfill/-/react-app-polyfill-1.0.1.tgz#809a858e44f9564c7f4205e173076f90048274f1"
integrity sha512-fbZxEZdfx+rVENMvGTFjUcDDOZGKHaiavA8Y+FwM2I/o8gJT6pCYZk19XfeOntVzGZH2F1qqH7SLjXMhUM+YJw== integrity sha512-LbVpT1NdzTdDDs7xEZdebjDrqsvKi5UyVKUQqtTYYNyC1JJYVAwNQWe4ybWvoT2V2WW9PGVO2u5Y6aVj4ER/Ow==
dependencies: dependencies:
core-js "3.0.1" core-js "3.0.1"
object-assign "4.1.1" object-assign "4.1.1"
...@@ -10664,10 +10927,19 @@ react-app-polyfill@^1.0.0: ...@@ -10664,10 +10927,19 @@ react-app-polyfill@^1.0.0:
regenerator-runtime "0.13.2" regenerator-runtime "0.13.2"
whatwg-fetch "3.0.0" whatwg-fetch "3.0.0"
react-dev-utils@^9.0.0: react-aria-modal@^4.0.0:
version "9.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-9.0.0.tgz#356d95db442441c5d4748e0e49f4fd1e71aecbbd" resolved "https://registry.yarnpkg.com/react-aria-modal/-/react-aria-modal-4.0.0.tgz#b195e9ad6bd360b628c1853381ab4e7466d2328c"
integrity sha512-HXvxOnABzIQH804ros5dBFryw4x0FU7Tl5KU2xg71jKx0EDsJYK0LuVVdj9qoLIgD1pmjzpjl7q7pjwXKIe37A== integrity sha512-crdEAIHc5xXi6YqZeUgRDJN1uromSehU1XSEegVPU8/okmf1tEDwnzb6ULl+PJy4aS6sb6fUiWEdMNTLAX2HBA==
dependencies:
focus-trap-react "^6.0.0"
no-scroll "^2.1.1"
react-displace "^2.3.0"
react-dev-utils@^9.0.1:
version "9.0.1"
resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-9.0.1.tgz#5c03d85a0b2537d0c46af7165c24a7dfb274bef2"
integrity sha512-pnaeMo/Pxel8aZpxk1WwxT3uXxM3tEwYvsjCYn5R7gNxjhN1auowdcLDzFB8kr7rafAj2rxmvfic/fbac5CzwQ==
dependencies: dependencies:
"@babel/code-frame" "7.0.0" "@babel/code-frame" "7.0.0"
address "1.0.3" address "1.0.3"
...@@ -10678,7 +10950,7 @@ react-dev-utils@^9.0.0: ...@@ -10678,7 +10950,7 @@ react-dev-utils@^9.0.0:
escape-string-regexp "1.0.5" escape-string-regexp "1.0.5"
filesize "3.6.1" filesize "3.6.1"
find-up "3.0.0" find-up "3.0.0"
fork-ts-checker-webpack-plugin "1.0.1" fork-ts-checker-webpack-plugin "1.1.1"
global-modules "2.0.0" global-modules "2.0.0"
globby "8.0.2" globby "8.0.2"
gzip-size "5.0.0" gzip-size "5.0.0"
...@@ -10688,13 +10960,18 @@ react-dev-utils@^9.0.0: ...@@ -10688,13 +10960,18 @@ react-dev-utils@^9.0.0:
loader-utils "1.2.3" loader-utils "1.2.3"
opn "5.4.0" opn "5.4.0"
pkg-up "2.0.0" pkg-up "2.0.0"
react-error-overlay "^5.1.5" react-error-overlay "^5.1.6"
recursive-readdir "2.2.2" recursive-readdir "2.2.2"
shell-quote "1.6.1" shell-quote "1.6.1"
sockjs-client "1.3.0" sockjs-client "1.3.0"
strip-ansi "5.2.0" strip-ansi "5.2.0"
text-table "0.2.0" text-table "0.2.0"
react-displace@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/react-displace/-/react-displace-2.3.0.tgz#6915f8f2f279a29a7b58442405c26edc3d441429"
integrity sha512-T8g/lyn3IX8kxLO4k4vJ/oIO9G72pRTc9GYslqKsfPcN4gY5+FYR5OHxeTH1skPjVylJrveGE3OC2qCt3BuHeA==
react-dom@^16.8.6: react-dom@^16.8.6:
version "16.8.6" version "16.8.6"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.6.tgz#71d6303f631e8b0097f56165ef608f051ff6e10f" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.6.tgz#71d6303f631e8b0097f56165ef608f051ff6e10f"
...@@ -10705,10 +10982,10 @@ react-dom@^16.8.6: ...@@ -10705,10 +10982,10 @@ react-dom@^16.8.6:
prop-types "^15.6.2" prop-types "^15.6.2"
scheduler "^0.13.6" scheduler "^0.13.6"
react-error-overlay@^5.1.5: react-error-overlay@^5.1.6:
version "5.1.5" version "5.1.6"
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-5.1.5.tgz#884530fd055476c764eaa8ab13b8ecf1f57bbf2c" resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-5.1.6.tgz#0cd73407c5d141f9638ae1e0c63e7b2bf7e9929d"
integrity sha512-O9JRum1Zq/qCPFH5qVEvDDrVun8Jv9vbHtZXCR1EuRj9sKg1xJTlHxBzU6AkCzpvxRLuiY4OKImy3cDLQ+UTdg== integrity sha512-X1Y+0jR47ImDVr54Ab6V9eGk0Hnu7fVWGeHQSOXHf/C2pF9c6uy3gef8QUeuUiWlNb0i08InPSE5a/KJzNzw1Q==
react-ga@^2.5.7: react-ga@^2.5.7:
version "2.5.7" version "2.5.7"
...@@ -10757,26 +11034,27 @@ react-router@5.0.0: ...@@ -10757,26 +11034,27 @@ react-router@5.0.0:
tiny-invariant "^1.0.2" tiny-invariant "^1.0.2"
tiny-warning "^1.0.0" tiny-warning "^1.0.0"
react-scripts@^3.0.0: react-scripts@^3.0.1:
version "3.0.0" version "3.0.1"
resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-3.0.0.tgz#a715613ef3eace025907b409cec8505096e0233e" resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-3.0.1.tgz#e5565350d8069cc9966b5998d3fe3befe3d243ac"
integrity sha512-F4HegoBuUKZvEzXYksQu05Y6vJqallhHkQUEL6M7OQ5rYLBQC/4MTK6km9ZZvEK9TqMy1XA8SSEJGJgTEr6bSQ== integrity sha512-LKEjBhVpEB+c312NeJhzF+NATxF7JkHNr5GhtwMeRS1cMeLElMeIu8Ye7WGHtDP7iz7ra4ryy48Zpo6G/cwWUw==
dependencies: dependencies:
"@babel/core" "7.4.3" "@babel/core" "7.4.3"
"@svgr/webpack" "4.1.0" "@svgr/webpack" "4.1.0"
"@typescript-eslint/eslint-plugin" "1.6.0" "@typescript-eslint/eslint-plugin" "1.6.0"
"@typescript-eslint/parser" "1.6.0" "@typescript-eslint/parser" "1.6.0"
babel-eslint "10.0.1" babel-eslint "10.0.1"
babel-jest "24.7.1" babel-jest "^24.8.0"
babel-loader "8.0.5" babel-loader "8.0.5"
babel-plugin-named-asset-import "^0.3.2" babel-plugin-named-asset-import "^0.3.2"
babel-preset-react-app "^8.0.0" babel-preset-react-app "^9.0.0"
camelcase "^5.2.0"
case-sensitive-paths-webpack-plugin "2.2.0" case-sensitive-paths-webpack-plugin "2.2.0"
css-loader "2.1.1" css-loader "2.1.1"
dotenv "6.2.0" dotenv "6.2.0"
dotenv-expand "4.2.0" dotenv-expand "4.2.0"
eslint "^5.16.0" eslint "^5.16.0"
eslint-config-react-app "^4.0.0" eslint-config-react-app "^4.0.1"
eslint-loader "2.1.2" eslint-loader "2.1.2"
eslint-plugin-flowtype "2.50.1" eslint-plugin-flowtype "2.50.1"
eslint-plugin-import "2.16.0" eslint-plugin-import "2.16.0"
...@@ -10800,13 +11078,14 @@ react-scripts@^3.0.0: ...@@ -10800,13 +11078,14 @@ react-scripts@^3.0.0:
postcss-normalize "7.0.1" postcss-normalize "7.0.1"
postcss-preset-env "6.6.0" postcss-preset-env "6.6.0"
postcss-safe-parser "4.0.1" postcss-safe-parser "4.0.1"
react-app-polyfill "^1.0.0" react-app-polyfill "^1.0.1"
react-dev-utils "^9.0.0" react-dev-utils "^9.0.1"
resolve "1.10.0" resolve "1.10.0"
sass-loader "7.1.0" sass-loader "7.1.0"
semver "6.0.0" semver "6.0.0"
style-loader "0.23.1" style-loader "0.23.1"
terser-webpack-plugin "1.2.3" terser-webpack-plugin "1.2.3"
ts-pnp "1.1.2"
url-loader "1.1.2" url-loader "1.1.2"
webpack "4.29.6" webpack "4.29.6"
webpack-dev-server "3.2.1" webpack-dev-server "3.2.1"
...@@ -12177,6 +12456,23 @@ style-loader@0.23.1: ...@@ -12177,6 +12456,23 @@ style-loader@0.23.1:
loader-utils "^1.1.0" loader-utils "^1.1.0"
schema-utils "^1.0.0" schema-utils "^1.0.0"
styled-components@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-4.2.0.tgz#811fbbec4d64c7189f6c7482b9eb6fefa7fefef7"
integrity sha512-L/LzkL3ZbBhqIVHdR7DbYujy4tqvTNRfc+4JWDCYyhTatI+8CRRQUmdaR0+ARl03DWsfKLhjewll5uNLrqrl4A==
dependencies:
"@babel/helper-module-imports" "^7.0.0"
"@emotion/is-prop-valid" "^0.7.3"
"@emotion/unitless" "^0.7.0"
babel-plugin-styled-components ">= 1"
css-to-react-native "^2.2.2"
memoize-one "^5.0.0"
prop-types "^15.5.4"
react-is "^16.6.0"
stylis "^3.5.0"
stylis-rule-sheet "^0.0.10"
supports-color "^5.5.0"
stylehacks@^4.0.0: stylehacks@^4.0.0:
version "4.0.3" version "4.0.3"
resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5"
...@@ -12186,12 +12482,22 @@ stylehacks@^4.0.0: ...@@ -12186,12 +12482,22 @@ stylehacks@^4.0.0:
postcss "^7.0.0" postcss "^7.0.0"
postcss-selector-parser "^3.0.0" postcss-selector-parser "^3.0.0"
stylis-rule-sheet@^0.0.10:
version "0.0.10"
resolved "https://registry.yarnpkg.com/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz#44e64a2b076643f4b52e5ff71efc04d8c3c4a430"
integrity sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==
stylis@^3.5.0:
version "3.5.4"
resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.4.tgz#f665f25f5e299cf3d64654ab949a57c768b73fbe"
integrity sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==
supports-color@^2.0.0: supports-color@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
supports-color@^5.3.0: supports-color@^5.3.0, supports-color@^5.5.0:
version "5.5.0" version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
...@@ -12249,6 +12555,11 @@ symbol-tree@^3.2.2: ...@@ -12249,6 +12555,11 @@ symbol-tree@^3.2.2:
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6"
integrity sha1-rifbOPZgp64uHDt9G8KQgZuFGeY= integrity sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=
tabbable@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-3.1.2.tgz#f2d16cccd01f400e38635c7181adfe0ad965a4a2"
integrity sha512-wjB6puVXTYO0BSFtCmWQubA/KIn7Xvajw0x0l6eJUudMG/EAiJvIUnyNX6xO4NpGrJ16lbD0eUseB9WxW0vlpQ==
table@^5.2.3: table@^5.2.3:
version "5.2.3" version "5.2.3"
resolved "https://registry.yarnpkg.com/table/-/table-5.2.3.tgz#cde0cc6eb06751c009efab27e8c820ca5b67b7f2" resolved "https://registry.yarnpkg.com/table/-/table-5.2.3.tgz#cde0cc6eb06751c009efab27e8c820ca5b67b7f2"
...@@ -12555,6 +12866,11 @@ trough@^1.0.0: ...@@ -12555,6 +12866,11 @@ trough@^1.0.0:
dependencies: dependencies:
glob "^7.1.2" glob "^7.1.2"
ts-pnp@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.1.2.tgz#be8e4bfce5d00f0f58e0666a82260c34a57af552"
integrity sha512-f5Knjh7XCyRIzoC/z1Su1yLLRrPrFCgtUAh/9fCSP6NKbATwpOL1+idQVXQokK9GRFURn/jYPGPfegIctwunoA==
ts-pnp@^1.0.0: ts-pnp@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.0.1.tgz#fde74a6371676a167abaeda1ffc0fdb423520098" resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.0.1.tgz#fde74a6371676a167abaeda1ffc0fdb423520098"
...@@ -13713,6 +14029,13 @@ worker-farm@^1.5.2: ...@@ -13713,6 +14029,13 @@ worker-farm@^1.5.2:
dependencies: dependencies:
errno "~0.1.7" errno "~0.1.7"
worker-rpc@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/worker-rpc/-/worker-rpc-0.1.0.tgz#5f1258dca3d617cd18ca86587f8a05ac0eebd834"
integrity sha1-XxJY3KPWF80YyoZYf4oFrA7r2DQ=
dependencies:
microevent.ts "~0.1.0"
wrap-ansi@^2.0.0: wrap-ansi@^2.0.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
......
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