Commit 35a03e26 authored by Jack Short's avatar Jack Short Committed by GitHub

fix: using the swap token selector for pay with any token (#5902)

* feat: adds input token quote for nfts

* remove eslint

* correct usdc pricing

* fix: uses swap token selector for pay with any token selector

* check when balances are loaded

* removing token selector

* only showing active tokens in pay with any token
parent ac0badfb
......@@ -45,6 +45,7 @@ interface CurrencySearchProps {
showCommonBases?: boolean
showCurrencyAmount?: boolean
disableNonToken?: boolean
onlyShowCurrenciesWithBalance?: boolean
}
export function CurrencySearch({
......@@ -56,6 +57,7 @@ export function CurrencySearch({
disableNonToken,
onDismiss,
isOpen,
onlyShowCurrenciesWithBalance,
}: CurrencySearchProps) {
const { chainId } = useWeb3React()
const theme = useTheme()
......@@ -92,6 +94,10 @@ export function CurrencySearch({
!balancesAreLoading
? filteredTokens
.filter((token) => {
if (onlyShowCurrenciesWithBalance) {
return balances[token.address]?.greaterThan(0)
}
// If there is no query, filter out unselected user-added tokens with no balance.
if (!debouncedQuery && token instanceof UserAddedToken) {
if (selectedCurrency?.equals(token) || otherSelectedCurrency?.equals(token)) return true
......@@ -101,7 +107,15 @@ export function CurrencySearch({
})
.sort(tokenComparator.bind(null, balances))
: [],
[balances, balancesAreLoading, debouncedQuery, filteredTokens, otherSelectedCurrency, selectedCurrency]
[
balances,
balancesAreLoading,
debouncedQuery,
filteredTokens,
otherSelectedCurrency,
selectedCurrency,
onlyShowCurrenciesWithBalance,
]
)
const isLoading = Boolean(balancesAreLoading && !tokenLoaderTimerElapsed)
......@@ -114,11 +128,23 @@ export function CurrencySearch({
const s = debouncedQuery.toLowerCase().trim()
const tokens = filteredSortedTokens.filter((t) => !(t.equals(wrapped) || (disableNonToken && t.isNative)))
const natives = (disableNonToken || native.equals(wrapped) ? [wrapped] : [native, wrapped]).filter(
(n) => n.symbol?.toLowerCase()?.indexOf(s) !== -1 || n.name?.toLowerCase()?.indexOf(s) !== -1
)
const shouldShowWrapped =
!onlyShowCurrenciesWithBalance || (!balancesAreLoading && balances[wrapped.address]?.greaterThan(0))
const natives = (
disableNonToken || native.equals(wrapped) ? [wrapped] : shouldShowWrapped ? [native, wrapped] : [native]
).filter((n) => n.symbol?.toLowerCase()?.indexOf(s) !== -1 || n.name?.toLowerCase()?.indexOf(s) !== -1)
return [...natives, ...tokens]
}, [debouncedQuery, filteredSortedTokens, wrapped, disableNonToken, native])
}, [
debouncedQuery,
filteredSortedTokens,
onlyShowCurrenciesWithBalance,
balancesAreLoading,
balances,
wrapped,
disableNonToken,
native,
])
const handleCurrencySelect = useCallback(
(currency: Currency, hasWarning?: boolean) => {
......@@ -168,7 +194,9 @@ export function CurrencySearch({
// if no results on main list, show option to expand into inactive
const filteredInactiveTokens = useSearchInactiveTokenLists(
filteredTokens.length === 0 || (debouncedQuery.length > 2 && !isAddressSearch) ? debouncedQuery : undefined
!onlyShowCurrenciesWithBalance && (filteredTokens.length === 0 || (debouncedQuery.length > 2 && !isAddressSearch))
? debouncedQuery
: undefined
)
// Timeout token loader after 3 seconds to avoid hanging in a loading state.
......
......@@ -17,6 +17,7 @@ interface CurrencySearchModalProps {
showCommonBases?: boolean
showCurrencyAmount?: boolean
disableNonToken?: boolean
onlyShowCurrenciesWithBalance?: boolean
}
enum CurrencyModalView {
......@@ -34,6 +35,7 @@ export default memo(function CurrencySearchModal({
showCommonBases = false,
showCurrencyAmount = true,
disableNonToken = false,
onlyShowCurrenciesWithBalance = false,
}: CurrencySearchModalProps) {
const [modalView, setModalView] = useState<CurrencyModalView>(CurrencyModalView.search)
const lastOpen = useLast(isOpen)
......@@ -84,6 +86,7 @@ export default memo(function CurrencySearchModal({
showCommonBases={showCommonBases}
showCurrencyAmount={showCurrencyAmount}
disableNonToken={disableNonToken}
onlyShowCurrenciesWithBalance={onlyShowCurrenciesWithBalance}
/>
)
break
......
......@@ -10,6 +10,7 @@ import Column from 'components/Column'
import Loader from 'components/Loader'
import CurrencyLogo from 'components/Logo/CurrencyLogo'
import Row from 'components/Row'
import CurrencySearchModal from 'components/SearchModal/CurrencySearchModal'
import { SupportedChainId } from 'constants/chains'
import { PayWithAnyTokenVariant, usePayWithAnyTokenFlag } from 'featureFlags/flags/payWithAnyToken'
import { useCurrency } from 'hooks/Tokens'
......@@ -21,7 +22,7 @@ import { useTokenInput } from 'nft/hooks/useTokenInput'
import { useWalletBalance } from 'nft/hooks/useWalletBalance'
import { BagStatus } from 'nft/types'
import { ethNumberStandardFormatter, formatWeiToDecimal } from 'nft/utils'
import { PropsWithChildren, useMemo, useReducer } from 'react'
import { PropsWithChildren, useMemo, useState } from 'react'
import { AlertTriangle, ChevronDown } from 'react-feather'
import { useToggleWalletModal } from 'state/application/hooks'
import { TradeState } from 'state/routing/types'
......@@ -29,8 +30,6 @@ import styled, { useTheme } from 'styled-components/macro'
import { ThemedText } from 'theme'
import { switchChain } from 'utils/switchChain'
import { BagTokenSelectorModal } from './tokenSelector/BagTokenSelectorModal'
const FooterContainer = styled.div`
padding: 0px 12px;
`
......@@ -146,7 +145,7 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti
const defaultCurrency = useCurrency('ETH')
const setBagExpanded = useBag((state) => state.setBagExpanded)
const [showTokenSelector, toggleTokenSelector] = useReducer((state) => !state, false)
const [tokenSelectorOpen, setTokenSelectorOpen] = useState(false)
const { balance: balanceInEth } = useWalletBalance()
const sufficientBalance = useMemo(() => {
......@@ -218,7 +217,7 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti
<ThemedText.SubHeaderSmall>
<Trans>Pay with</Trans>
</ThemedText.SubHeaderSmall>
<CurrencyInput onClick={toggleTokenSelector}>
<CurrencyInput onClick={() => setTokenSelectorOpen(true)}>
<CurrencyLogo currency={activeCurrency} size="24px" />
<ThemedText.HeadlineSmall fontWeight={500} lineHeight="24px">
{activeCurrency?.symbol}
......@@ -278,16 +277,13 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti
</ActionButton>
</TraceEvent>
</Footer>
{showTokenSelector && (
<BagTokenSelectorModal
selectedCurrency={activeCurrency ?? undefined}
handleCurrencySelect={(currency: Currency | undefined) => {
setInputCurrency(currency)
toggleTokenSelector()
}}
overlayClick={toggleTokenSelector}
/>
)}
<CurrencySearchModal
isOpen={tokenSelectorOpen}
onDismiss={() => setTokenSelectorOpen(false)}
onCurrencySelect={(currency: Currency) => setInputCurrency(currency.isNative ? undefined : currency)}
selectedCurrency={activeCurrency ?? undefined}
onlyShowCurrenciesWithBalance={true}
/>
</FooterContainer>
)
}
import { Trans } from '@lingui/macro'
import { Currency, Token } from '@uniswap/sdk-core'
import Column from 'components/Column'
import Row from 'components/Row'
import { useAllTokens } from 'hooks/Tokens'
import useNativeCurrency from 'lib/hooks/useNativeCurrency'
import { tokenComparator } from 'lib/hooks/useTokenList/sorting'
import { Portal } from 'nft/components/common/Portal'
import { Overlay } from 'nft/components/modals/Overlay'
import { useMemo } from 'react'
import { X } from 'react-feather'
import { useAllTokenBalances } from 'state/connection/hooks'
import styled from 'styled-components/macro'
import { ThemedText } from 'theme'
import { Z_INDEX } from 'theme/zIndex'
import { CurrencyRow } from './CurrencyRow'
const ModalWrapper = styled(Column)`
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 420px;
height: 368px;
z-index: ${Z_INDEX.modalOverTooltip};
background: ${({ theme }) => theme.backgroundSurface};
border-radius: 20px;
border: ${({ theme }) => `1px solid ${theme.backgroundOutline}`};
box-shadow: ${({ theme }) => theme.deepShadow};
`
const TitleRow = styled(Row)`
padding: 20px;
justify-content: space-between;
`
const TokenSelectorContainer = styled(Column)`
border-top: 1px solid ${({ theme }) => theme.backgroundOutline};
padding: 20px;
height: 100%;
overflow-y: scroll;
gap: 8px;
::-webkit-scrollbar {
width: 0px;
height: 0px;
}
`
interface BagTokenSelectorModalProps {
selectedCurrency: Currency | undefined
handleCurrencySelect: (currency: Currency | undefined) => void
overlayClick: () => void
}
export const BagTokenSelectorModal = ({
selectedCurrency,
handleCurrencySelect,
overlayClick,
}: BagTokenSelectorModalProps) => {
const defaultTokens = useAllTokens()
const [balances, balancesAreLoading] = useAllTokenBalances()
const sortedTokens: Token[] = useMemo(
() =>
!balancesAreLoading
? Object.values(defaultTokens)
.filter((token) => {
return balances[token.address]?.greaterThan(0)
})
.sort(tokenComparator.bind(null, balances))
: [],
[balances, balancesAreLoading, defaultTokens]
)
const native = useNativeCurrency()
const wrapped = native.wrapped
const currencies: Currency[] = useMemo(() => {
const tokens = sortedTokens.filter((t) => !t.equals(wrapped))
const natives: Currency[] = []
if (native.equals(wrapped)) {
natives.push(wrapped)
} else {
natives.push(native)
if (balances[wrapped.address]?.greaterThan(0)) {
natives.push(wrapped)
}
}
return [...natives, ...tokens]
}, [sortedTokens, native, wrapped, balances])
return (
<Portal>
<ModalWrapper>
<TitleRow>
<ThemedText.SubHeader fontWeight={500} lineHeight="24px">
<Trans>Select a token</Trans>
</ThemedText.SubHeader>
<X size={24} cursor="pointer" onClick={overlayClick} />
</TitleRow>
<TokenSelectorContainer>
{currencies.map((currency) => {
return (
<CurrencyRow
key={currency.isToken ? currency.wrapped.address : currency.name}
currency={currency}
selected={
(!selectedCurrency && currency.isNative) || (!!selectedCurrency && selectedCurrency.equals(currency))
}
selectCurrency={handleCurrencySelect}
/>
)
})}
</TokenSelectorContainer>
</ModalWrapper>
<Overlay onClick={overlayClick} />
</Portal>
)
}
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import Column from 'components/Column'
import CurrencyLogo from 'components/Logo/CurrencyLogo'
import Row from 'components/Row'
import useCurrencyBalance from 'lib/hooks/useCurrencyBalance'
import { Check } from 'react-feather'
import styled from 'styled-components/macro'
import { ThemedText } from 'theme'
const TokenRow = styled(Row)`
padding: 8px 0px;
gap: 12px;
justify-content: space-between;
cursor: pointer;
`
const TokenInfoRow = styled(Row)`
gap: 8px;
`
const StyledBalanceText = styled(ThemedText.SubHeader)`
white-space: nowrap;
overflow: hidden;
width: 100%;
text-overflow: ellipsis;
text-align: right;
`
const StyledCheck = styled(Check)`
color: ${({ theme }) => theme.accentAction};
flex-shrink: 0;
`
interface CurrencyRowProps {
currency: Currency
selected: boolean
selectCurrency: (currency: Currency | undefined) => void
}
export const CurrencyRow = ({ currency, selected, selectCurrency }: CurrencyRowProps) => {
const { account } = useWeb3React()
const balance = useCurrencyBalance(account ?? undefined, currency)
return (
<TokenRow onClick={() => selectCurrency(currency.isNative ? undefined : currency)}>
<TokenInfoRow>
<CurrencyLogo currency={currency} size="36px" />
<Column>
<ThemedText.SubHeader fontWeight={500} lineHeight="24px">
{currency.name}
</ThemedText.SubHeader>
<ThemedText.BodySmall lineHeight="20px" color="textSecondary">
{currency.symbol}
</ThemedText.BodySmall>
</Column>
</TokenInfoRow>
{balance && <Balance balance={balance} />}
{selected && <StyledCheck size={20} />}
</TokenRow>
)
}
const Balance = ({ balance }: { balance: CurrencyAmount<Currency> }) => {
return (
<StyledBalanceText fontWeight={500} lineHeight="24px">
{balance.toSignificant(4)}
</StyledBalanceText>
)
}
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