Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e480f0ebe5 | ||
|
|
f6ceecbc5e | ||
|
|
a0348b45be | ||
|
|
e4b37cffcc | ||
|
|
dd69cccf91 | ||
|
|
8b228de88f | ||
|
|
f91fc3c6a6 | ||
|
|
e0e2b40f9f | ||
|
|
bc1c61b63a | ||
|
|
446ad3e0d4 | ||
|
|
65e58a08cf | ||
|
|
71b20b432c | ||
|
|
ecfa179b3f | ||
|
|
6c94a0f585 |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@uniswap/widgets",
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.6",
|
||||
"description": "Uniswap Interface",
|
||||
"homepage": ".",
|
||||
"files": [
|
||||
|
||||
@@ -13,6 +13,7 @@ import useUSDCPrice, { useUSDCValue } from './useUSDCPrice'
|
||||
|
||||
const V3_SWAP_DEFAULT_SLIPPAGE = new Percent(50, 10_000) // .50%
|
||||
const ONE_TENTHS_PERCENT = new Percent(10, 10_000) // .10%
|
||||
export const DEFAULT_AUTO_SLIPPAGE = ONE_TENTHS_PERCENT
|
||||
|
||||
/**
|
||||
* Return a guess of the gas cost used in computing slippage tolerance for a given trade
|
||||
@@ -44,7 +45,7 @@ export default function useAutoSlippageTolerance(
|
||||
const nativeCurrencyPrice = useUSDCPrice((trade && nativeCurrency) ?? undefined)
|
||||
|
||||
return useMemo(() => {
|
||||
if (!trade || onL2) return ONE_TENTHS_PERCENT
|
||||
if (!trade || onL2) return DEFAULT_AUTO_SLIPPAGE
|
||||
|
||||
const nativeGasCost =
|
||||
nativeGasPrice && typeof gasEstimate === 'number'
|
||||
|
||||
@@ -3,7 +3,7 @@ import { SupportedChainId } from 'constants/chains'
|
||||
import uriToHttp from 'lib/utils/uriToHttp'
|
||||
import Vibrant from 'node-vibrant/lib/bundle.js'
|
||||
import { shade } from 'polished'
|
||||
import { useLayoutEffect, useState } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { WrappedTokenInfo } from 'state/lists/wrappedTokenInfo'
|
||||
import { hex } from 'wcag-contrast'
|
||||
|
||||
@@ -64,7 +64,7 @@ async function getColorFromUriPath(uri: string): Promise<string | null> {
|
||||
export function useColor(token?: Token) {
|
||||
const [color, setColor] = useState('#2172E5')
|
||||
|
||||
useLayoutEffect(() => {
|
||||
useEffect(() => {
|
||||
let stale = false
|
||||
|
||||
if (token) {
|
||||
@@ -87,7 +87,7 @@ export function useColor(token?: Token) {
|
||||
export function useListColor(listImageUri?: string) {
|
||||
const [color, setColor] = useState('#2172E5')
|
||||
|
||||
useLayoutEffect(() => {
|
||||
useEffect(() => {
|
||||
let stale = false
|
||||
|
||||
if (listImageUri) {
|
||||
|
||||
@@ -12,13 +12,14 @@ function isWindowVisible() {
|
||||
* Returns whether the window is currently visible to the user.
|
||||
*/
|
||||
export default function useIsWindowVisible(): boolean {
|
||||
const [focused, setFocused] = useState<boolean>(isWindowVisible())
|
||||
const [focused, setFocused] = useState<boolean>(false)
|
||||
const listener = useCallback(() => {
|
||||
setFocused(isWindowVisible())
|
||||
}, [setFocused])
|
||||
|
||||
useEffect(() => {
|
||||
if (!isVisibilityStateSupported()) return undefined
|
||||
setFocused((focused) => isWindowVisible())
|
||||
|
||||
document.addEventListener('visibilitychange', listener)
|
||||
return () => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Currency, CurrencyAmount, Price, Token, TradeType } from '@uniswap/sdk-core'
|
||||
import useActiveWeb3React from 'hooks/useActiveWeb3React'
|
||||
import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount'
|
||||
import { useMemo } from 'react'
|
||||
import { useMemo, useRef } from 'react'
|
||||
|
||||
import { SupportedChainId } from '../constants/chains'
|
||||
import { DAI_OPTIMISM, USDC_ARBITRUM, USDC_MAINNET, USDC_POLYGON } from '../constants/tokens'
|
||||
@@ -32,8 +32,7 @@ export default function useUSDCPrice(currency?: Currency): Price<Currency, Token
|
||||
maxHops: 2,
|
||||
})
|
||||
const v3USDCTrade = useClientSideV3Trade(TradeType.EXACT_OUTPUT, amountOut, currency)
|
||||
|
||||
return useMemo(() => {
|
||||
const price = useMemo(() => {
|
||||
if (!currency || !stablecoin) {
|
||||
return undefined
|
||||
}
|
||||
@@ -54,6 +53,12 @@ export default function useUSDCPrice(currency?: Currency): Price<Currency, Token
|
||||
|
||||
return undefined
|
||||
}, [currency, stablecoin, v2USDCTrade, v3USDCTrade.trade])
|
||||
|
||||
const lastPrice = useRef(price)
|
||||
if (!price || !lastPrice.current || !price.equalTo(lastPrice.current)) {
|
||||
lastPrice.current = price
|
||||
}
|
||||
return lastPrice.current
|
||||
}
|
||||
|
||||
export function useUSDCValue(currencyAmount: CurrencyAmount<Currency> | undefined | null) {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { SupportedChainId } from 'constants/chains'
|
||||
import { nativeOnChain } from 'constants/tokens'
|
||||
import { useUpdateAtom } from 'jotai/utils'
|
||||
import { useSwapInfo } from 'lib/hooks/swap'
|
||||
import { SwapInfoUpdater } from 'lib/hooks/swap/useSwapInfo'
|
||||
import { SwapInfoProvider } from 'lib/hooks/swap/useSwapInfo'
|
||||
import { Field, swapAtom } from 'lib/state/swap'
|
||||
import { useEffect } from 'react'
|
||||
import { WrappedTokenInfo } from 'state/lists/wrappedTokenInfo'
|
||||
@@ -54,7 +54,8 @@ function Fixture() {
|
||||
|
||||
export default (
|
||||
<>
|
||||
<SwapInfoUpdater />
|
||||
<Fixture />
|
||||
<SwapInfoProvider>
|
||||
<Fixture />
|
||||
</SwapInfoProvider>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { TokenInfo } from '@uniswap/token-lists'
|
||||
import { useAtom } from 'jotai'
|
||||
import { SwapInfoUpdater } from 'lib/hooks/swap/useSwapInfo'
|
||||
import { SwapInfoProvider } from 'lib/hooks/swap/useSwapInfo'
|
||||
import useSyncConvenienceFee, { FeeOptions } from 'lib/hooks/swap/useSyncConvenienceFee'
|
||||
import useSyncTokenDefaults, { TokenDefaults } from 'lib/hooks/swap/useSyncTokenDefaults'
|
||||
import { usePendingTransactions } from 'lib/hooks/transactions'
|
||||
import useActiveWeb3React from 'lib/hooks/useActiveWeb3React'
|
||||
import useHasFocus from 'lib/hooks/useHasFocus'
|
||||
import useOnSupportedNetwork from 'lib/hooks/useOnSupportedNetwork'
|
||||
import { useSyncTokenList } from 'lib/hooks/useTokenList'
|
||||
import { useIsTokenListLoaded, useSyncTokenList } from 'lib/hooks/useTokenList'
|
||||
import { displayTxHashAtom } from 'lib/state/swap'
|
||||
import { SwapTransactionInfo, Transaction, TransactionType, WrapTransactionInfo } from 'lib/state/transactions'
|
||||
import { useState } from 'react'
|
||||
@@ -47,12 +47,10 @@ export interface SwapProps extends TokenDefaults, FeeOptions {
|
||||
onConnectWallet?: () => void
|
||||
}
|
||||
|
||||
function Updaters(props: SwapProps & { disabled: boolean }) {
|
||||
useSyncTokenList(props.tokenList)
|
||||
function Updaters(props: SwapProps) {
|
||||
useSyncTokenDefaults(props)
|
||||
useSyncConvenienceFee(props)
|
||||
|
||||
return props.disabled ? null : <SwapInfoUpdater />
|
||||
return null
|
||||
}
|
||||
|
||||
export default function Swap(props: SwapProps) {
|
||||
@@ -68,23 +66,28 @@ export default function Swap(props: SwapProps) {
|
||||
const onSupportedNetwork = useOnSupportedNetwork()
|
||||
const isDisabled = !(active && onSupportedNetwork)
|
||||
|
||||
useSyncTokenList(props.tokenList)
|
||||
const isTokenListLoaded = useIsTokenListLoaded()
|
||||
|
||||
const focused = useHasFocus(wrapper)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Updaters {...props} disabled={isDisabled} />
|
||||
{isTokenListLoaded && <Updaters {...props} />}
|
||||
<Header title={<Trans>Swap</Trans>}>
|
||||
{active && <Wallet disabled={!account} onClick={props.onConnectWallet} />}
|
||||
<Settings disabled={isDisabled} />
|
||||
</Header>
|
||||
<div ref={setWrapper}>
|
||||
<BoundaryProvider value={wrapper}>
|
||||
<Input disabled={isDisabled} focused={focused} />
|
||||
<ReverseButton disabled={isDisabled} />
|
||||
<Output disabled={isDisabled} focused={focused}>
|
||||
<Toolbar disabled={!active} />
|
||||
<SwapButton disabled={isDisabled} />
|
||||
</Output>
|
||||
<SwapInfoProvider disabled={isDisabled}>
|
||||
<Input disabled={isDisabled} focused={focused} />
|
||||
<ReverseButton disabled={isDisabled} />
|
||||
<Output disabled={isDisabled} focused={focused}>
|
||||
<Toolbar disabled={!active} />
|
||||
<SwapButton disabled={isDisabled} />
|
||||
</Output>
|
||||
</SwapInfoProvider>
|
||||
</BoundaryProvider>
|
||||
</div>
|
||||
{displayTx && (
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { IntegrationError } from 'lib/errors'
|
||||
import { FeeOptions } from 'lib/hooks/swap/useSyncConvenienceFee'
|
||||
import { DefaultAddress, TokenDefaults } from 'lib/hooks/swap/useSyncTokenDefaults'
|
||||
@@ -48,19 +47,23 @@ export default function useValidate(props: ValidatorProps) {
|
||||
}
|
||||
}, [convenienceFee, convenienceFeeRecipient])
|
||||
|
||||
const { defaultInputTokenAddress, defaultInputAmount, defaultOutputTokenAddress, defaultOutputAmount } = props
|
||||
const { defaultInputAmount, defaultOutputAmount } = props
|
||||
useEffect(() => {
|
||||
if (defaultOutputAmount && defaultInputAmount) {
|
||||
throw new IntegrationError('defaultInputAmount and defaultOutputAmount may not both be defined.')
|
||||
}
|
||||
if (defaultInputAmount && BigNumber.from(defaultInputAmount).lt(0)) {
|
||||
if (defaultInputAmount && (isNaN(+defaultInputAmount) || defaultInputAmount < 0)) {
|
||||
throw new IntegrationError(`defaultInputAmount must be a positive number (you set it to ${defaultInputAmount})`)
|
||||
}
|
||||
if (defaultOutputAmount && BigNumber.from(defaultOutputAmount).lt(0)) {
|
||||
if (defaultOutputAmount && (isNaN(+defaultOutputAmount) || defaultOutputAmount < 0)) {
|
||||
throw new IntegrationError(
|
||||
`defaultOutputAmount must be a positive number (you set it to ${defaultOutputAmount}).`
|
||||
)
|
||||
}
|
||||
}, [defaultInputAmount, defaultOutputAmount])
|
||||
|
||||
const { defaultInputTokenAddress, defaultOutputTokenAddress } = props
|
||||
useEffect(() => {
|
||||
if (
|
||||
defaultInputTokenAddress &&
|
||||
!isAddressOrAddressMap(defaultInputTokenAddress) &&
|
||||
@@ -79,5 +82,5 @@ export default function useValidate(props: ValidatorProps) {
|
||||
`defaultOutputTokenAddress must be a valid address or "NATIVE" (you set it to ${defaultOutputTokenAddress}).`
|
||||
)
|
||||
}
|
||||
}, [defaultInputTokenAddress, defaultInputAmount, defaultOutputTokenAddress, defaultOutputAmount])
|
||||
}, [defaultInputTokenAddress, defaultOutputTokenAddress])
|
||||
}
|
||||
|
||||
@@ -26,16 +26,17 @@ function TokenImg({ token, ...rest }: TokenImgProps) {
|
||||
setAttempt((attempt) => ++attempt)
|
||||
}, [])
|
||||
|
||||
return useMemo(() => {
|
||||
const src = useMemo(() => {
|
||||
// Trigger a re-render when an error occurs.
|
||||
void attempt
|
||||
|
||||
const src = srcs.find((src) => !badSrcs.has(src))
|
||||
if (!src) return <MissingToken color="secondary" {...rest} />
|
||||
return srcs.find((src) => !badSrcs.has(src))
|
||||
}, [attempt, srcs])
|
||||
|
||||
const alt = tokenInfo.name || tokenInfo.symbol
|
||||
return <img src={src} alt={alt} key={alt} onError={onError} {...rest} />
|
||||
}, [attempt, onError, rest, srcs, tokenInfo.name, tokenInfo.symbol])
|
||||
if (!src) return <MissingToken color="secondary" {...rest} />
|
||||
|
||||
const alt = tokenInfo.name || tokenInfo.symbol
|
||||
return <img src={src} alt={alt} key={alt} onError={onError} {...rest} />
|
||||
}
|
||||
|
||||
export default styled(TokenImg)<{ size?: number }>`
|
||||
|
||||
@@ -6,6 +6,8 @@ import { InterfaceTrade, TradeState } from 'state/routing/types'
|
||||
|
||||
import useClientSideSmartOrderRouterTrade from '../routing/useClientSideSmartOrderRouterTrade'
|
||||
|
||||
export const INVALID_TRADE = { state: TradeState.INVALID, trade: undefined }
|
||||
|
||||
/**
|
||||
* Returns the best v2+v3 trade for a desired swap.
|
||||
* @param tradeType whether the swap is an exact in/out
|
||||
@@ -39,6 +41,7 @@ export function useBestTrade(
|
||||
return useMemo(() => {
|
||||
const { state, trade } = tradeObject
|
||||
// If the trade is in a settled state, return it.
|
||||
if (state === TradeState.INVALID) return INVALID_TRADE
|
||||
if ((state !== TradeState.LOADING && state !== TradeState.SYNCING) || trade) return tradeObject
|
||||
|
||||
const [currencyIn, currencyOut] =
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
import { Currency, CurrencyAmount, Percent, TradeType } from '@uniswap/sdk-core'
|
||||
import { atom } from 'jotai'
|
||||
import { useAtomValue, useUpdateAtom } from 'jotai/utils'
|
||||
import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core'
|
||||
import { useAtomValue } from 'jotai/utils'
|
||||
import useActiveWeb3React from 'lib/hooks/useActiveWeb3React'
|
||||
import { useCurrencyBalances } from 'lib/hooks/useCurrencyBalance'
|
||||
import useSlippage, { DEFAULT_SLIPPAGE, Slippage } from 'lib/hooks/useSlippage'
|
||||
import useUSDCPriceImpact, { PriceImpact } from 'lib/hooks/useUSDCPriceImpact'
|
||||
import { Field, swapAtom } from 'lib/state/swap'
|
||||
import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount'
|
||||
import { useEffect, useMemo } from 'react'
|
||||
import { createContext, PropsWithChildren, useContext, useMemo } from 'react'
|
||||
import { InterfaceTrade, TradeState } from 'state/routing/types'
|
||||
|
||||
import useActiveWeb3React from '../useActiveWeb3React'
|
||||
import useSlippage, { Slippage } from '../useSlippage'
|
||||
import useUSDCPriceImpact, { PriceImpact } from '../useUSDCPriceImpact'
|
||||
import { useBestTrade } from './useBestTrade'
|
||||
import { INVALID_TRADE, useBestTrade } from './useBestTrade'
|
||||
import useWrapCallback, { WrapType } from './useWrapCallback'
|
||||
|
||||
interface SwapField {
|
||||
@@ -33,7 +32,6 @@ interface SwapInfo {
|
||||
|
||||
// from the current swap inputs, compute the best trade and return it.
|
||||
function useComputeSwapInfo(): SwapInfo {
|
||||
const { account } = useActiveWeb3React()
|
||||
const { type: wrapType } = useWrapCallback()
|
||||
const isWrapping = wrapType === WrapType.WRAP || wrapType === WrapType.UNWRAP
|
||||
const { independentField, amount, [Field.INPUT]: currencyIn, [Field.OUTPUT]: currencyOut } = useAtomValue(swapAtom)
|
||||
@@ -58,6 +56,8 @@ function useComputeSwapInfo(): SwapInfo {
|
||||
() => (isWrapping || !isExactIn ? parsedAmount : trade.trade?.outputAmount),
|
||||
[isExactIn, isWrapping, parsedAmount, trade.trade?.outputAmount]
|
||||
)
|
||||
|
||||
const { account } = useActiveWeb3React()
|
||||
const [balanceIn, balanceOut] = useCurrencyBalances(
|
||||
account,
|
||||
useMemo(() => [currencyIn, currencyOut], [currencyIn, currencyOut])
|
||||
@@ -102,21 +102,24 @@ function useComputeSwapInfo(): SwapInfo {
|
||||
)
|
||||
}
|
||||
|
||||
const swapInfoAtom = atom<SwapInfo>({
|
||||
const DEFAULT_SWAP_INFO: SwapInfo = {
|
||||
[Field.INPUT]: {},
|
||||
[Field.OUTPUT]: {},
|
||||
trade: { state: TradeState.INVALID },
|
||||
slippage: { auto: true, allowed: new Percent(0) },
|
||||
})
|
||||
trade: INVALID_TRADE,
|
||||
slippage: DEFAULT_SLIPPAGE,
|
||||
}
|
||||
|
||||
export function SwapInfoUpdater() {
|
||||
const setSwapInfo = useUpdateAtom(swapInfoAtom)
|
||||
const SwapInfoContext = createContext(DEFAULT_SWAP_INFO)
|
||||
|
||||
export function SwapInfoProvider({ children, disabled }: PropsWithChildren<{ disabled?: boolean }>) {
|
||||
const swapInfo = useComputeSwapInfo()
|
||||
useEffect(() => setSwapInfo(swapInfo), [setSwapInfo, swapInfo])
|
||||
return null
|
||||
if (disabled) {
|
||||
return <SwapInfoContext.Provider value={DEFAULT_SWAP_INFO}>{children}</SwapInfoContext.Provider>
|
||||
}
|
||||
return <SwapInfoContext.Provider value={swapInfo}>{children}</SwapInfoContext.Provider>
|
||||
}
|
||||
|
||||
/** Requires that SwapInfoUpdater be installed in the DOM tree. **/
|
||||
export default function useSwapInfo(): SwapInfo {
|
||||
return useAtomValue(swapInfoAtom)
|
||||
return useContext(SwapInfoContext)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import useActiveWeb3React from 'lib/hooks/useActiveWeb3React'
|
||||
import { useToken } from 'lib/hooks/useCurrency'
|
||||
import useNativeCurrency from 'lib/hooks/useNativeCurrency'
|
||||
import { Field, Swap, swapAtom } from 'lib/state/swap'
|
||||
import { useCallback, useLayoutEffect, useState } from 'react'
|
||||
import { useCallback, useLayoutEffect, useRef } from 'react'
|
||||
|
||||
import useOnSupportedNetwork from '../useOnSupportedNetwork'
|
||||
|
||||
@@ -71,13 +71,11 @@ export default function useSyncTokenDefaults({
|
||||
updateSwap((swap) => ({ ...swap, ...defaultSwapState }))
|
||||
}, [defaultInputAmount, defaultInputToken, defaultOutputAmount, defaultOutputToken, updateSwap])
|
||||
|
||||
const [previousChainId, setPreviousChainId] = useState(chainId)
|
||||
const lastChainId = useRef<number | undefined>(undefined)
|
||||
useLayoutEffect(() => {
|
||||
setPreviousChainId(chainId)
|
||||
}, [chainId])
|
||||
useLayoutEffect(() => {
|
||||
if (chainId && chainId !== previousChainId) {
|
||||
if (chainId && chainId !== lastChainId.current) {
|
||||
setToDefaults()
|
||||
}
|
||||
}, [chainId, previousChainId, setToDefaults])
|
||||
lastChainId.current = chainId
|
||||
}, [chainId, setToDefaults])
|
||||
}
|
||||
|
||||
@@ -19,9 +19,9 @@ function useUpdateChainBlock() {
|
||||
(block: number) => {
|
||||
setChainBlock((chainBlock) => {
|
||||
if (chainBlock.chainId === chainId) {
|
||||
if (chainBlock.block === block) return chainBlock
|
||||
if (typeof chainBlock.block !== 'number') return { chainId, block }
|
||||
return { chainId, block: Math.max(block, chainBlock.block) }
|
||||
if (!chainBlock.block || chainBlock.block < block) {
|
||||
return { chainId, block }
|
||||
}
|
||||
}
|
||||
return chainBlock
|
||||
})
|
||||
|
||||
@@ -47,7 +47,7 @@ export function useNativeCurrencyBalances(uncheckedAddresses?: (string | undefin
|
||||
}
|
||||
|
||||
const ERC20Interface = new Interface(ERC20ABI) as Erc20Interface
|
||||
const tokenBalancesGasRequirement = { gasRequired: 125_000 }
|
||||
const tokenBalancesGasRequirement = { gasRequired: 185_000 }
|
||||
|
||||
/**
|
||||
* Returns a map of token addresses to their eventually consistent token balances for a single account.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Currency } from '@uniswap/sdk-core'
|
||||
import { useTheme } from 'lib/theme'
|
||||
import Vibrant from 'node-vibrant/lib/bundle.js'
|
||||
import { useEffect, useLayoutEffect, useState } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
import useCurrencyLogoURIs from './useCurrencyLogoURIs'
|
||||
|
||||
@@ -57,7 +57,7 @@ export default function useCurrencyColor(token?: Currency) {
|
||||
const theme = useTheme()
|
||||
const logoURIs = useCurrencyLogoURIs(token)
|
||||
|
||||
useLayoutEffect(() => {
|
||||
useEffect(() => {
|
||||
let stale = false
|
||||
|
||||
if (theme.tokenColorExtraction && token) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
|
||||
import useAutoSlippageTolerance from 'hooks/useAutoSlippageTolerance'
|
||||
import useAutoSlippageTolerance, { DEFAULT_AUTO_SLIPPAGE } from 'hooks/useAutoSlippageTolerance'
|
||||
import { useAtomValue } from 'jotai/utils'
|
||||
import { autoSlippageAtom, maxSlippageAtom } from 'lib/state/settings'
|
||||
import { useMemo } from 'react'
|
||||
@@ -17,6 +17,8 @@ export interface Slippage {
|
||||
warning?: 'warning' | 'error'
|
||||
}
|
||||
|
||||
export const DEFAULT_SLIPPAGE = { auto: true, allowed: DEFAULT_AUTO_SLIPPAGE }
|
||||
|
||||
/** Returns the allowed slippage, and whether it is auto-slippage. */
|
||||
export default function useSlippage(trade: InterfaceTrade<Currency, Currency, TradeType> | undefined): Slippage {
|
||||
const shouldUseAutoSlippage = useAtomValue(autoSlippageAtom)
|
||||
@@ -27,6 +29,9 @@ export default function useSlippage(trade: InterfaceTrade<Currency, Currency, Tr
|
||||
const auto = shouldUseAutoSlippage || !maxSlippage
|
||||
const allowed = shouldUseAutoSlippage ? autoSlippage : maxSlippage ?? autoSlippage
|
||||
const warning = auto ? undefined : getSlippageWarning(allowed)
|
||||
if (auto && allowed === DEFAULT_AUTO_SLIPPAGE) {
|
||||
return DEFAULT_SLIPPAGE
|
||||
}
|
||||
return { auto, allowed, warning }
|
||||
}, [autoSlippage, maxSlippage, shouldUseAutoSlippage])
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { i18n } from '@lingui/core'
|
||||
import { I18nProvider } from '@lingui/react'
|
||||
import { SupportedLocale } from 'constants/locales'
|
||||
import { DEFAULT_LOCALE, SupportedLocale } from 'constants/locales'
|
||||
import {
|
||||
af,
|
||||
ar,
|
||||
@@ -79,8 +79,6 @@ const plurals: LocalePlural = {
|
||||
export async function dynamicActivate(locale: SupportedLocale) {
|
||||
i18n.loadLocaleData(locale, { plurals: () => plurals[locale] })
|
||||
try {
|
||||
// There are no default messages in production,
|
||||
// see https://github.com/lingui/js-lingui/issues/388#issuecomment-497779030
|
||||
const catalog = await import(`${process.env.REACT_APP_LOCALES}/${locale}.js`)
|
||||
// Bundlers will either export it as default or as a named export named default.
|
||||
i18n.load(locale, catalog.messages || catalog.default.messages)
|
||||
@@ -104,6 +102,16 @@ export function Provider({ locale, forceRenderAfterLocaleChange = true, onActiva
|
||||
})
|
||||
}, [locale, onActivate])
|
||||
|
||||
// Initialize the locale immediately if it is DEFAULT_LOCALE, so that keys are shown while the translation messages load.
|
||||
// This renders the translation _keys_, not the translation _messages_, which is only acceptable while loading the DEFAULT_LOCALE,
|
||||
// as [there are no "default" messages](https://github.com/lingui/js-lingui/issues/388#issuecomment-497779030).
|
||||
// See https://github.com/lingui/js-lingui/issues/1194#issuecomment-1068488619.
|
||||
if (i18n.locale === undefined && locale === DEFAULT_LOCALE) {
|
||||
i18n.loadLocaleData(DEFAULT_LOCALE, { plurals: () => plurals[DEFAULT_LOCALE] })
|
||||
i18n.load(DEFAULT_LOCALE, {})
|
||||
i18n.activate(DEFAULT_LOCALE)
|
||||
}
|
||||
|
||||
return (
|
||||
<I18nProvider forceRenderOnLocaleChange={forceRenderAfterLocaleChange} i18n={i18n}>
|
||||
{children}
|
||||
|
||||
Reference in New Issue
Block a user