Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4dd4f9283 | ||
|
|
7798443919 | ||
|
|
392d78b9da | ||
|
|
231289732c | ||
|
|
140ff7a674 | ||
|
|
3fbc4e34f4 | ||
|
|
b964953daf | ||
|
|
649fd9c845 | ||
|
|
6347e63a15 | ||
|
|
bdcb9a8a0a | ||
|
|
8d90bb7a39 | ||
|
|
d70b456855 | ||
|
|
fbb797fa54 | ||
|
|
8ace518311 | ||
|
|
67c776c995 | ||
|
|
719754c46c |
3
.env
3
.env
@@ -1,2 +1,3 @@
|
|||||||
REACT_APP_CHAIN_ID="1"
|
REACT_APP_CHAIN_ID="1"
|
||||||
REACT_APP_NETWORK_URL="https://mainnet.infura.io/v3/4bf032f2d38a4ed6bb975b80d6340847"
|
REACT_APP_NETWORK_URL="https://mainnet.infura.io/v3/4bf032f2d38a4ed6bb975b80d6340847"
|
||||||
|
REACT_APP_WALLETCONNECT_BRIDGE_URL="https://uniswap.bridge.walletconnect.org"
|
||||||
8
.github/workflows/release.yaml
vendored
8
.github/workflows/release.yaml
vendored
@@ -54,6 +54,14 @@ jobs:
|
|||||||
pinata-api-key: ${{ secrets.PINATA_API_KEY }}
|
pinata-api-key: ${{ secrets.PINATA_API_KEY }}
|
||||||
pinata-secret-api-key: ${{ secrets.PINATA_API_SECRET_KEY }}
|
pinata-secret-api-key: ${{ secrets.PINATA_API_SECRET_KEY }}
|
||||||
|
|
||||||
|
- name: Pin to Crust
|
||||||
|
uses: crustio/ipfs-crust-action@v1.0.8
|
||||||
|
continue-on-error: true
|
||||||
|
timeout-minutes: 2
|
||||||
|
with:
|
||||||
|
cid: ${{ steps.upload.outputs.hash }}
|
||||||
|
seeds: ${{ secrets.CRUST_SEEDS }}
|
||||||
|
|
||||||
- name: Convert CIDv0 to CIDv1
|
- name: Convert CIDv0 to CIDv1
|
||||||
id: convert_cidv0
|
id: convert_cidv0
|
||||||
uses: uniswap/convert-cidv0-cidv1@v1.0.0
|
uses: uniswap/convert-cidv0-cidv1@v1.0.0
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ The interface will not work on other networks.
|
|||||||
|
|
||||||
## Contributions
|
## Contributions
|
||||||
|
|
||||||
**Please open all pull requests against the `master` branch.**
|
**Please open all pull requests against the `main` branch.**
|
||||||
CI checks will run against all PRs.
|
CI checks will run against all PRs.
|
||||||
|
|
||||||
## Accessing Uniswap Interface V1
|
## Accessing Uniswap Interface V1
|
||||||
|
|||||||
@@ -94,9 +94,6 @@
|
|||||||
"workbox-routing": "^6.1.0",
|
"workbox-routing": "^6.1.0",
|
||||||
"workbox-strategies": "^6.1.0"
|
"workbox-strategies": "^6.1.0"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
|
||||||
"@walletconnect/web3-provider": "1.1.1-alpha.0"
|
|
||||||
},
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"start": "react-scripts start",
|
||||||
"start:service-worker": "yarn build && yarn serve -s build",
|
"start:service-worker": "yarn build && yarn serve -s build",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React, { useContext, useRef, useState } from 'react'
|
import React, { useContext, useRef, useState } from 'react'
|
||||||
import { Settings, X } from 'react-feather'
|
import { Settings, X } from 'react-feather'
|
||||||
|
import ReactGA from 'react-ga'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import styled, { ThemeContext } from 'styled-components'
|
import styled, { ThemeContext } from 'styled-components'
|
||||||
import { useOnClickOutside } from '../../hooks/useOnClickOutside'
|
import { useOnClickOutside } from '../../hooks/useOnClickOutside'
|
||||||
@@ -236,7 +237,13 @@ export default function SettingsTab() {
|
|||||||
<Toggle
|
<Toggle
|
||||||
id="toggle-disable-multihop-button"
|
id="toggle-disable-multihop-button"
|
||||||
isActive={singleHopOnly}
|
isActive={singleHopOnly}
|
||||||
toggle={() => (singleHopOnly ? setSingleHopOnly(false) : setSingleHopOnly(true))}
|
toggle={() => {
|
||||||
|
ReactGA.event({
|
||||||
|
category: 'Routing',
|
||||||
|
action: singleHopOnly ? 'disable single hop' : 'enable single hop'
|
||||||
|
})
|
||||||
|
setSingleHopOnly(!singleHopOnly)
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ export function AdvancedSwapDetails({ trade }: AdvancedSwapDetailsProps) {
|
|||||||
{!showRoute && (
|
{!showRoute && (
|
||||||
<AutoColumn style={{ padding: '12px 16px 0 16px' }}>
|
<AutoColumn style={{ padding: '12px 16px 0 16px' }}>
|
||||||
<InfoLink
|
<InfoLink
|
||||||
href={'https://uniswap.info/pair/' + trade.route.pairs[0].liquidityToken.address}
|
href={'https://info.uniswap.org/pair/' + trade.route.pairs[0].liquidityToken.address}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
View pair analytics ↗
|
View pair analytics ↗
|
||||||
|
|||||||
@@ -6,10 +6,12 @@ import { PortisConnector } from '@web3-react/portis-connector'
|
|||||||
|
|
||||||
import { FortmaticConnector } from './Fortmatic'
|
import { FortmaticConnector } from './Fortmatic'
|
||||||
import { NetworkConnector } from './NetworkConnector'
|
import { NetworkConnector } from './NetworkConnector'
|
||||||
|
import UNISWAP_LOGO_URL from '../assets/svg/logo.svg'
|
||||||
|
|
||||||
const NETWORK_URL = process.env.REACT_APP_NETWORK_URL
|
const NETWORK_URL = process.env.REACT_APP_NETWORK_URL
|
||||||
const FORMATIC_KEY = process.env.REACT_APP_FORTMATIC_KEY
|
const FORMATIC_KEY = process.env.REACT_APP_FORTMATIC_KEY
|
||||||
const PORTIS_ID = process.env.REACT_APP_PORTIS_ID
|
const PORTIS_ID = process.env.REACT_APP_PORTIS_ID
|
||||||
|
const WALLETCONNECT_BRIDGE_URL = process.env.REACT_APP_WALLETCONNECT_BRIDGE_URL
|
||||||
|
|
||||||
export const NETWORK_CHAIN_ID: number = parseInt(process.env.REACT_APP_CHAIN_ID ?? '1')
|
export const NETWORK_CHAIN_ID: number = parseInt(process.env.REACT_APP_CHAIN_ID ?? '1')
|
||||||
|
|
||||||
@@ -33,7 +35,7 @@ export const injected = new InjectedConnector({
|
|||||||
// mainnet only
|
// mainnet only
|
||||||
export const walletconnect = new WalletConnectConnector({
|
export const walletconnect = new WalletConnectConnector({
|
||||||
rpc: { 1: NETWORK_URL },
|
rpc: { 1: NETWORK_URL },
|
||||||
bridge: 'https://bridge.walletconnect.org',
|
bridge: WALLETCONNECT_BRIDGE_URL,
|
||||||
qrcode: true,
|
qrcode: true,
|
||||||
pollingInterval: 15000
|
pollingInterval: 15000
|
||||||
})
|
})
|
||||||
@@ -54,6 +56,5 @@ export const portis = new PortisConnector({
|
|||||||
export const walletlink = new WalletLinkConnector({
|
export const walletlink = new WalletLinkConnector({
|
||||||
url: NETWORK_URL,
|
url: NETWORK_URL,
|
||||||
appName: 'Uniswap',
|
appName: 'Uniswap',
|
||||||
appLogoUrl:
|
appLogoUrl: UNISWAP_LOGO_URL
|
||||||
'https://mpng.pngfly.com/20181202/bex/kisspng-emoji-domain-unicorn-pin-badges-sticker-unicorn-tumblr-emoji-unicorn-iphoneemoji-5c046729264a77.5671679315437924251569.jpg'
|
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -14,13 +14,16 @@ type ChainTokenList = {
|
|||||||
readonly [chainId in ChainId]: Token[]
|
readonly [chainId in ChainId]: Token[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const AMPL = new Token(ChainId.MAINNET, '0xD46bA6D942050d489DBd938a2C909A5d5039A161', 9, 'AMPL', 'Ampleforth')
|
||||||
export const DAI = new Token(ChainId.MAINNET, '0x6B175474E89094C44Da98b954EedeAC495271d0F', 18, 'DAI', 'Dai Stablecoin')
|
export const DAI = new Token(ChainId.MAINNET, '0x6B175474E89094C44Da98b954EedeAC495271d0F', 18, 'DAI', 'Dai Stablecoin')
|
||||||
export const USDC = new Token(ChainId.MAINNET, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 6, 'USDC', 'USD//C')
|
export const USDC = new Token(ChainId.MAINNET, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 6, 'USDC', 'USD//C')
|
||||||
export const USDT = new Token(ChainId.MAINNET, '0xdAC17F958D2ee523a2206206994597C13D831ec7', 6, 'USDT', 'Tether USD')
|
export const USDT = new Token(ChainId.MAINNET, '0xdAC17F958D2ee523a2206206994597C13D831ec7', 6, 'USDT', 'Tether USD')
|
||||||
export const COMP = new Token(ChainId.MAINNET, '0xc00e94Cb662C3520282E6f5717214004A7f26888', 18, 'COMP', 'Compound')
|
|
||||||
export const MKR = new Token(ChainId.MAINNET, '0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2', 18, 'MKR', 'Maker')
|
|
||||||
export const AMPL = new Token(ChainId.MAINNET, '0xD46bA6D942050d489DBd938a2C909A5d5039A161', 9, 'AMPL', 'Ampleforth')
|
|
||||||
export const WBTC = new Token(ChainId.MAINNET, '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', 8, 'WBTC', 'Wrapped BTC')
|
export const WBTC = new Token(ChainId.MAINNET, '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', 8, 'WBTC', 'Wrapped BTC')
|
||||||
|
export const FEI = new Token(ChainId.MAINNET, '0x956F47F50A910163D8BF957Cf5846D573E7f87CA', 18, 'FEI', 'Fei USD')
|
||||||
|
export const TRIBE = new Token(ChainId.MAINNET, '0xc7283b66Eb1EB5FB86327f08e1B5816b0720212B', 18, 'TRIBE', 'Tribe')
|
||||||
|
export const FRAX = new Token(ChainId.MAINNET, '0x853d955aCEf822Db058eb8505911ED77F175b99e', 18, 'FRAX', 'Frax')
|
||||||
|
export const FXS = new Token(ChainId.MAINNET, '0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0', 18, 'FXS', 'Frax Share')
|
||||||
|
export const renBTC = new Token(ChainId.MAINNET, '0xEB4C2781e4ebA804CE9a9803C67d0893436bB27D', 8, 'renBTC', 'renBTC')
|
||||||
|
|
||||||
// Block time here is slightly higher (~1s) than average in order to avoid ongoing proposals past the displayed time
|
// Block time here is slightly higher (~1s) than average in order to avoid ongoing proposals past the displayed time
|
||||||
export const AVERAGE_BLOCK_TIME_IN_SECS = 13
|
export const AVERAGE_BLOCK_TIME_IN_SECS = 13
|
||||||
@@ -62,7 +65,20 @@ const WETH_ONLY: ChainTokenList = {
|
|||||||
// used to construct intermediary pairs for trading
|
// used to construct intermediary pairs for trading
|
||||||
export const BASES_TO_CHECK_TRADES_AGAINST: ChainTokenList = {
|
export const BASES_TO_CHECK_TRADES_AGAINST: ChainTokenList = {
|
||||||
...WETH_ONLY,
|
...WETH_ONLY,
|
||||||
[ChainId.MAINNET]: [...WETH_ONLY[ChainId.MAINNET], DAI, USDC, USDT, COMP, MKR, WBTC]
|
[ChainId.MAINNET]: [...WETH_ONLY[ChainId.MAINNET], DAI, USDC, USDT, WBTC]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ADDITIONAL_BASES: { [chainId in ChainId]?: { [tokenAddress: string]: Token[] } } = {
|
||||||
|
[ChainId.MAINNET]: {
|
||||||
|
'0xA948E86885e12Fb09AfEF8C52142EBDbDf73cD18': [new Token(ChainId.MAINNET, UNI_ADDRESS, 18, 'UNI', 'Uniswap')],
|
||||||
|
'0x561a4717537ff4AF5c687328c0f7E90a319705C0': [new Token(ChainId.MAINNET, UNI_ADDRESS, 18, 'UNI', 'Uniswap')],
|
||||||
|
[FEI.address]: [TRIBE],
|
||||||
|
[TRIBE.address]: [FEI],
|
||||||
|
[FRAX.address]: [FXS],
|
||||||
|
[FXS.address]: [FRAX],
|
||||||
|
[WBTC.address]: [renBTC],
|
||||||
|
[renBTC.address]: [WBTC]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -17,6 +17,14 @@
|
|||||||
"decimals": 6,
|
"decimals": 6,
|
||||||
"chainId": 1,
|
"chainId": 1,
|
||||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x4922a015c4407F87432B179bb209e125432E4a2A/logo.png"
|
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x4922a015c4407F87432B179bb209e125432E4a2A/logo.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Grump Cat",
|
||||||
|
"address": "0x93B2FfF814FCaEFFB01406e80B4Ecd89Ca6A021b",
|
||||||
|
"symbol": "GRUMPY",
|
||||||
|
"decimals": 9,
|
||||||
|
"chainId": 1,
|
||||||
|
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x4922a015c4407F87432B179bb209e125432E4a2A/logo.png"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,12 @@ import { Currency, CurrencyAmount, Pair, Token, Trade } from '@uniswap/sdk'
|
|||||||
import flatMap from 'lodash.flatmap'
|
import flatMap from 'lodash.flatmap'
|
||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
|
|
||||||
import { BASES_TO_CHECK_TRADES_AGAINST, CUSTOM_BASES, BETTER_TRADE_LESS_HOPS_THRESHOLD } from '../constants'
|
import {
|
||||||
|
BASES_TO_CHECK_TRADES_AGAINST,
|
||||||
|
CUSTOM_BASES,
|
||||||
|
BETTER_TRADE_LESS_HOPS_THRESHOLD,
|
||||||
|
ADDITIONAL_BASES
|
||||||
|
} from '../constants'
|
||||||
import { PairState, usePairs } from '../data/Reserves'
|
import { PairState, usePairs } from '../data/Reserves'
|
||||||
import { wrappedCurrency } from '../utils/wrappedCurrency'
|
import { wrappedCurrency } from '../utils/wrappedCurrency'
|
||||||
|
|
||||||
@@ -14,17 +19,22 @@ import { useUserSingleHopOnly } from 'state/user/hooks'
|
|||||||
function useAllCommonPairs(currencyA?: Currency, currencyB?: Currency): Pair[] {
|
function useAllCommonPairs(currencyA?: Currency, currencyB?: Currency): Pair[] {
|
||||||
const { chainId } = useActiveWeb3React()
|
const { chainId } = useActiveWeb3React()
|
||||||
|
|
||||||
const bases: Token[] = chainId ? BASES_TO_CHECK_TRADES_AGAINST[chainId] : []
|
|
||||||
|
|
||||||
const [tokenA, tokenB] = chainId
|
const [tokenA, tokenB] = chainId
|
||||||
? [wrappedCurrency(currencyA, chainId), wrappedCurrency(currencyB, chainId)]
|
? [wrappedCurrency(currencyA, chainId), wrappedCurrency(currencyB, chainId)]
|
||||||
: [undefined, undefined]
|
: [undefined, undefined]
|
||||||
|
|
||||||
|
const bases: Token[] = useMemo(() => {
|
||||||
|
if (!chainId) return []
|
||||||
|
|
||||||
|
const common = BASES_TO_CHECK_TRADES_AGAINST[chainId] ?? []
|
||||||
|
const additionalA = tokenA ? ADDITIONAL_BASES[chainId]?.[tokenA.address] ?? [] : []
|
||||||
|
const additionalB = tokenB ? ADDITIONAL_BASES[chainId]?.[tokenB.address] ?? [] : []
|
||||||
|
|
||||||
|
return [...common, ...additionalA, ...additionalB]
|
||||||
|
}, [chainId, tokenA, tokenB])
|
||||||
|
|
||||||
const basePairs: [Token, Token][] = useMemo(
|
const basePairs: [Token, Token][] = useMemo(
|
||||||
() =>
|
() => flatMap(bases, (base): [Token, Token][] => bases.map(otherBase => [base, otherBase])),
|
||||||
flatMap(bases, (base): [Token, Token][] => bases.map(otherBase => [base, otherBase])).filter(
|
|
||||||
([t0, t1]) => t0.address !== t1.address
|
|
||||||
),
|
|
||||||
[bases]
|
[bases]
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -46,10 +56,9 @@ function useAllCommonPairs(currencyA?: Currency, currencyB?: Currency): Pair[] {
|
|||||||
.filter(([tokenA, tokenB]) => {
|
.filter(([tokenA, tokenB]) => {
|
||||||
if (!chainId) return true
|
if (!chainId) return true
|
||||||
const customBases = CUSTOM_BASES[chainId]
|
const customBases = CUSTOM_BASES[chainId]
|
||||||
if (!customBases) return true
|
|
||||||
|
|
||||||
const customBasesA: Token[] | undefined = customBases[tokenA.address]
|
const customBasesA: Token[] | undefined = customBases?.[tokenA.address]
|
||||||
const customBasesB: Token[] | undefined = customBases[tokenB.address]
|
const customBasesB: Token[] | undefined = customBases?.[tokenB.address]
|
||||||
|
|
||||||
if (!customBasesA && !customBasesB) return true
|
if (!customBasesA && !customBasesB) return true
|
||||||
|
|
||||||
|
|||||||
@@ -28,8 +28,14 @@ if (!!window.ethereum) {
|
|||||||
|
|
||||||
const GOOGLE_ANALYTICS_ID: string | undefined = process.env.REACT_APP_GOOGLE_ANALYTICS_ID
|
const GOOGLE_ANALYTICS_ID: string | undefined = process.env.REACT_APP_GOOGLE_ANALYTICS_ID
|
||||||
if (typeof GOOGLE_ANALYTICS_ID === 'string') {
|
if (typeof GOOGLE_ANALYTICS_ID === 'string') {
|
||||||
ReactGA.initialize(GOOGLE_ANALYTICS_ID)
|
ReactGA.initialize(GOOGLE_ANALYTICS_ID, {
|
||||||
|
gaOptions: {
|
||||||
|
storage: 'none',
|
||||||
|
storeGac: false
|
||||||
|
}
|
||||||
|
})
|
||||||
ReactGA.set({
|
ReactGA.set({
|
||||||
|
anonymizeIp: true,
|
||||||
customBrowserType: !isMobile ? 'desktop' : 'web3' in window || 'ethereum' in window ? 'mobileWeb3' : 'mobileRegular'
|
customBrowserType: !isMobile ? 'desktop' : 'web3' in window || 'ethereum' in window ? 'mobileWeb3' : 'mobileRegular'
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -29,18 +29,16 @@ function fetchClaim(account: string, chainId: ChainId): Promise<UserClaimData |
|
|||||||
|
|
||||||
return (CLAIM_PROMISES[key] =
|
return (CLAIM_PROMISES[key] =
|
||||||
CLAIM_PROMISES[key] ??
|
CLAIM_PROMISES[key] ??
|
||||||
fetch(`https://gentle-frost-9e74.uniswap.workers.dev/${chainId}/${formatted}`)
|
fetch('https://merkle-drop-1.uniswap.workers.dev/', {
|
||||||
.then(res => {
|
body: JSON.stringify({ chainId, address: formatted }),
|
||||||
if (res.status === 200) {
|
headers: {
|
||||||
return res.json()
|
'Content-Type': 'application/json',
|
||||||
} else {
|
'Referrer-Policy': 'no-referrer'
|
||||||
console.debug(`No claim for account ${formatted} on chain ID ${chainId}`)
|
},
|
||||||
return null
|
method: 'POST'
|
||||||
}
|
})
|
||||||
})
|
.then(res => (res.ok ? res.json() : console.log(`No claim for account ${formatted} on chain ID ${chainId}`)))
|
||||||
.catch(error => {
|
.catch(error => console.error('Failed to get claim data', error)))
|
||||||
console.error('Failed to get claim data', error)
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse distributorContract blob and detect if user has claim data
|
// parse distributorContract blob and detect if user has claim data
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { ChainId, Pair, Token } from '@uniswap/sdk'
|
import { ChainId, Pair, Token } from '@uniswap/sdk'
|
||||||
import flatMap from 'lodash.flatmap'
|
import flatMap from 'lodash.flatmap'
|
||||||
import ReactGA from 'react-ga'
|
|
||||||
import { useCallback, useMemo } from 'react'
|
import { useCallback, useMemo } from 'react'
|
||||||
import { shallowEqual, useDispatch, useSelector } from 'react-redux'
|
import { shallowEqual, useDispatch, useSelector } from 'react-redux'
|
||||||
import { BASES_TO_TRACK_LIQUIDITY_FOR, PINNED_PAIRS } from '../../constants'
|
import { BASES_TO_TRACK_LIQUIDITY_FOR, PINNED_PAIRS } from '../../constants'
|
||||||
@@ -92,10 +91,6 @@ export function useUserSingleHopOnly(): [boolean, (newSingleHopOnly: boolean) =>
|
|||||||
|
|
||||||
const setSingleHopOnly = useCallback(
|
const setSingleHopOnly = useCallback(
|
||||||
(newSingleHopOnly: boolean) => {
|
(newSingleHopOnly: boolean) => {
|
||||||
ReactGA.event({
|
|
||||||
category: 'Routing',
|
|
||||||
action: newSingleHopOnly ? 'enable single hop' : 'disable single hop'
|
|
||||||
})
|
|
||||||
dispatch(updateUserSingleHopOnly({ userSingleHopOnly: newSingleHopOnly }))
|
dispatch(updateUserSingleHopOnly({ userSingleHopOnly: newSingleHopOnly }))
|
||||||
},
|
},
|
||||||
[dispatch]
|
[dispatch]
|
||||||
|
|||||||
Reference in New Issue
Block a user