Commit d58dc14b authored by Jack Short's avatar Jack Short Committed by GitHub

feat: initial token selector for pay with any token (#5848)

* feat: initial token selector for pay with any token

* addressing some comments

* addressing comments

* linting
parent 909e18cb
...@@ -15,13 +15,15 @@ import { useBag } from 'nft/hooks/useBag' ...@@ -15,13 +15,15 @@ import { useBag } from 'nft/hooks/useBag'
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 } from 'react' import { PropsWithChildren, useMemo, useReducer } 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 styled, { useTheme } from 'styled-components/macro' 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;
` `
...@@ -142,6 +144,7 @@ export const BagFooter = ({ ...@@ -142,6 +144,7 @@ export const BagFooter = ({
const inputCurrency = useCurrency('ETH') const inputCurrency = useCurrency('ETH')
const setBagExpanded = useBag((state) => state.setBagExpanded) const setBagExpanded = useBag((state) => state.setBagExpanded)
const [showTokenSelector, toggleTokenSelector] = useReducer((state) => !state, false)
const { balance: balanceInEth } = useWalletBalance() const { balance: balanceInEth } = useWalletBalance()
const sufficientBalance = useMemo(() => { const sufficientBalance = useMemo(() => {
...@@ -200,7 +203,7 @@ export const BagFooter = ({ ...@@ -200,7 +203,7 @@ export const BagFooter = ({
<ThemedText.SubHeaderSmall> <ThemedText.SubHeaderSmall>
<Trans>Pay with</Trans> <Trans>Pay with</Trans>
</ThemedText.SubHeaderSmall> </ThemedText.SubHeaderSmall>
<CurrencyInput> <CurrencyInput onClick={toggleTokenSelector}>
<CurrencyLogo currency={inputCurrency} size="24px" /> <CurrencyLogo currency={inputCurrency} size="24px" />
<ThemedText.HeadlineSmall fontWeight={500} lineHeight="24px"> <ThemedText.HeadlineSmall fontWeight={500} lineHeight="24px">
{inputCurrency?.symbol} {inputCurrency?.symbol}
...@@ -256,6 +259,7 @@ export const BagFooter = ({ ...@@ -256,6 +259,7 @@ export const BagFooter = ({
</ActionButton> </ActionButton>
</TraceEvent> </TraceEvent>
</Footer> </Footer>
{showTokenSelector && <BagTokenSelectorModal 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;
}
`
export const BagTokenSelectorModal = ({ overlayClick }: { overlayClick: () => void }) => {
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} />
})}
</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 styled from 'styled-components/macro'
import { ThemedText } from 'theme'
const TokenRow = styled(Row)`
padding: 8px 0px;
justify-content: space-between;
`
const TokenInfoRow = styled(Row)`
gap: 8px;
`
const StyledBalanceText = styled(ThemedText.SubHeader)`
white-space: nowrap;
overflow: hidden;
width: 100%;
text-overflow: ellipsis;
text-align: right;
`
export const CurrencyRow = ({ currency }: { currency: Currency }) => {
const { account } = useWeb3React()
const balance = useCurrencyBalance(account ?? undefined, currency)
return (
<TokenRow>
<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} />}
</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