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 { ...@@ -45,6 +45,7 @@ interface CurrencySearchProps {
showCommonBases?: boolean showCommonBases?: boolean
showCurrencyAmount?: boolean showCurrencyAmount?: boolean
disableNonToken?: boolean disableNonToken?: boolean
onlyShowCurrenciesWithBalance?: boolean
} }
export function CurrencySearch({ export function CurrencySearch({
...@@ -56,6 +57,7 @@ export function CurrencySearch({ ...@@ -56,6 +57,7 @@ export function CurrencySearch({
disableNonToken, disableNonToken,
onDismiss, onDismiss,
isOpen, isOpen,
onlyShowCurrenciesWithBalance,
}: CurrencySearchProps) { }: CurrencySearchProps) {
const { chainId } = useWeb3React() const { chainId } = useWeb3React()
const theme = useTheme() const theme = useTheme()
...@@ -92,6 +94,10 @@ export function CurrencySearch({ ...@@ -92,6 +94,10 @@ export function CurrencySearch({
!balancesAreLoading !balancesAreLoading
? filteredTokens ? filteredTokens
.filter((token) => { .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 there is no query, filter out unselected user-added tokens with no balance.
if (!debouncedQuery && token instanceof UserAddedToken) { if (!debouncedQuery && token instanceof UserAddedToken) {
if (selectedCurrency?.equals(token) || otherSelectedCurrency?.equals(token)) return true if (selectedCurrency?.equals(token) || otherSelectedCurrency?.equals(token)) return true
...@@ -101,7 +107,15 @@ export function CurrencySearch({ ...@@ -101,7 +107,15 @@ export function CurrencySearch({
}) })
.sort(tokenComparator.bind(null, balances)) .sort(tokenComparator.bind(null, balances))
: [], : [],
[balances, balancesAreLoading, debouncedQuery, filteredTokens, otherSelectedCurrency, selectedCurrency] [
balances,
balancesAreLoading,
debouncedQuery,
filteredTokens,
otherSelectedCurrency,
selectedCurrency,
onlyShowCurrenciesWithBalance,
]
) )
const isLoading = Boolean(balancesAreLoading && !tokenLoaderTimerElapsed) const isLoading = Boolean(balancesAreLoading && !tokenLoaderTimerElapsed)
...@@ -114,11 +128,23 @@ export function CurrencySearch({ ...@@ -114,11 +128,23 @@ export function CurrencySearch({
const s = debouncedQuery.toLowerCase().trim() const s = debouncedQuery.toLowerCase().trim()
const tokens = filteredSortedTokens.filter((t) => !(t.equals(wrapped) || (disableNonToken && t.isNative))) const tokens = filteredSortedTokens.filter((t) => !(t.equals(wrapped) || (disableNonToken && t.isNative)))
const natives = (disableNonToken || native.equals(wrapped) ? [wrapped] : [native, wrapped]).filter( const shouldShowWrapped =
(n) => n.symbol?.toLowerCase()?.indexOf(s) !== -1 || n.name?.toLowerCase()?.indexOf(s) !== -1 !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] return [...natives, ...tokens]
}, [debouncedQuery, filteredSortedTokens, wrapped, disableNonToken, native]) }, [
debouncedQuery,
filteredSortedTokens,
onlyShowCurrenciesWithBalance,
balancesAreLoading,
balances,
wrapped,
disableNonToken,
native,
])
const handleCurrencySelect = useCallback( const handleCurrencySelect = useCallback(
(currency: Currency, hasWarning?: boolean) => { (currency: Currency, hasWarning?: boolean) => {
...@@ -168,7 +194,9 @@ export function CurrencySearch({ ...@@ -168,7 +194,9 @@ export function CurrencySearch({
// if no results on main list, show option to expand into inactive // if no results on main list, show option to expand into inactive
const filteredInactiveTokens = useSearchInactiveTokenLists( 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. // Timeout token loader after 3 seconds to avoid hanging in a loading state.
......
...@@ -17,6 +17,7 @@ interface CurrencySearchModalProps { ...@@ -17,6 +17,7 @@ interface CurrencySearchModalProps {
showCommonBases?: boolean showCommonBases?: boolean
showCurrencyAmount?: boolean showCurrencyAmount?: boolean
disableNonToken?: boolean disableNonToken?: boolean
onlyShowCurrenciesWithBalance?: boolean
} }
enum CurrencyModalView { enum CurrencyModalView {
...@@ -34,6 +35,7 @@ export default memo(function CurrencySearchModal({ ...@@ -34,6 +35,7 @@ export default memo(function CurrencySearchModal({
showCommonBases = false, showCommonBases = false,
showCurrencyAmount = true, showCurrencyAmount = true,
disableNonToken = false, disableNonToken = false,
onlyShowCurrenciesWithBalance = false,
}: CurrencySearchModalProps) { }: CurrencySearchModalProps) {
const [modalView, setModalView] = useState<CurrencyModalView>(CurrencyModalView.search) const [modalView, setModalView] = useState<CurrencyModalView>(CurrencyModalView.search)
const lastOpen = useLast(isOpen) const lastOpen = useLast(isOpen)
...@@ -84,6 +86,7 @@ export default memo(function CurrencySearchModal({ ...@@ -84,6 +86,7 @@ export default memo(function CurrencySearchModal({
showCommonBases={showCommonBases} showCommonBases={showCommonBases}
showCurrencyAmount={showCurrencyAmount} showCurrencyAmount={showCurrencyAmount}
disableNonToken={disableNonToken} disableNonToken={disableNonToken}
onlyShowCurrenciesWithBalance={onlyShowCurrenciesWithBalance}
/> />
) )
break break
......
...@@ -10,6 +10,7 @@ import Column from 'components/Column' ...@@ -10,6 +10,7 @@ import Column from 'components/Column'
import Loader from 'components/Loader' import Loader from 'components/Loader'
import CurrencyLogo from 'components/Logo/CurrencyLogo' import CurrencyLogo from 'components/Logo/CurrencyLogo'
import Row from 'components/Row' import Row from 'components/Row'
import CurrencySearchModal from 'components/SearchModal/CurrencySearchModal'
import { SupportedChainId } from 'constants/chains' import { SupportedChainId } from 'constants/chains'
import { PayWithAnyTokenVariant, usePayWithAnyTokenFlag } from 'featureFlags/flags/payWithAnyToken' import { PayWithAnyTokenVariant, usePayWithAnyTokenFlag } from 'featureFlags/flags/payWithAnyToken'
import { useCurrency } from 'hooks/Tokens' import { useCurrency } from 'hooks/Tokens'
...@@ -21,7 +22,7 @@ import { useTokenInput } from 'nft/hooks/useTokenInput' ...@@ -21,7 +22,7 @@ import { useTokenInput } from 'nft/hooks/useTokenInput'
import { useWalletBalance } from 'nft/hooks/useWalletBalance' import { useWalletBalance } from 'nft/hooks/useWalletBalance'
import { BagStatus } from 'nft/types' import { BagStatus } from 'nft/types'
import { ethNumberStandardFormatter, formatWeiToDecimal } from 'nft/utils' 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 { AlertTriangle, ChevronDown } from 'react-feather'
import { useToggleWalletModal } from 'state/application/hooks' import { useToggleWalletModal } from 'state/application/hooks'
import { TradeState } from 'state/routing/types' import { TradeState } from 'state/routing/types'
...@@ -29,8 +30,6 @@ import styled, { useTheme } from 'styled-components/macro' ...@@ -29,8 +30,6 @@ import styled, { useTheme } from 'styled-components/macro'
import { ThemedText } from 'theme' import { ThemedText } from 'theme'
import { switchChain } from 'utils/switchChain' import { switchChain } from 'utils/switchChain'
import { BagTokenSelectorModal } from './tokenSelector/BagTokenSelectorModal'
const FooterContainer = styled.div` const FooterContainer = styled.div`
padding: 0px 12px; padding: 0px 12px;
` `
...@@ -146,7 +145,7 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti ...@@ -146,7 +145,7 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti
const defaultCurrency = useCurrency('ETH') const defaultCurrency = useCurrency('ETH')
const setBagExpanded = useBag((state) => state.setBagExpanded) const setBagExpanded = useBag((state) => state.setBagExpanded)
const [showTokenSelector, toggleTokenSelector] = useReducer((state) => !state, false) const [tokenSelectorOpen, setTokenSelectorOpen] = useState(false)
const { balance: balanceInEth } = useWalletBalance() const { balance: balanceInEth } = useWalletBalance()
const sufficientBalance = useMemo(() => { const sufficientBalance = useMemo(() => {
...@@ -218,7 +217,7 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti ...@@ -218,7 +217,7 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti
<ThemedText.SubHeaderSmall> <ThemedText.SubHeaderSmall>
<Trans>Pay with</Trans> <Trans>Pay with</Trans>
</ThemedText.SubHeaderSmall> </ThemedText.SubHeaderSmall>
<CurrencyInput onClick={toggleTokenSelector}> <CurrencyInput onClick={() => setTokenSelectorOpen(true)}>
<CurrencyLogo currency={activeCurrency} size="24px" /> <CurrencyLogo currency={activeCurrency} size="24px" />
<ThemedText.HeadlineSmall fontWeight={500} lineHeight="24px"> <ThemedText.HeadlineSmall fontWeight={500} lineHeight="24px">
{activeCurrency?.symbol} {activeCurrency?.symbol}
...@@ -278,16 +277,13 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti ...@@ -278,16 +277,13 @@ export const BagFooter = ({ totalEthPrice, bagStatus, fetchAssets, eventProperti
</ActionButton> </ActionButton>
</TraceEvent> </TraceEvent>
</Footer> </Footer>
{showTokenSelector && ( <CurrencySearchModal
<BagTokenSelectorModal isOpen={tokenSelectorOpen}
selectedCurrency={activeCurrency ?? undefined} onDismiss={() => setTokenSelectorOpen(false)}
handleCurrencySelect={(currency: Currency | undefined) => { onCurrencySelect={(currency: Currency) => setInputCurrency(currency.isNative ? undefined : currency)}
setInputCurrency(currency) selectedCurrency={activeCurrency ?? undefined}
toggleTokenSelector() onlyShowCurrenciesWithBalance={true}
}} />
overlayClick={toggleTokenSelector}
/>
)}
</FooterContainer> </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