ci(release): publish latest release

parent 8c6c0e90
IPFS hash of the deployment:
- CIDv0: `QmVUZGU9EBHPpn3BZRhKTQB5VZuDtv2PUetyHxxpfmzcp9`
- CIDv1: `bafybeidkbbgtppk3euej56wgoxllerdoggnsz3fgkirnhrgvlbmff4reii`
- CIDv0: `QmNxB7dgMsLA6wASBs8xCSjKa4XAkeZNiiaf7uAG7KxPme`
- CIDv1: `bafybeiajdg2uit3dy2c5dbxclr7w6subg6t4fxnegfifpiskay2qlyys5u`
The latest release is always mirrored at [app.uniswap.org](https://app.uniswap.org).
......@@ -10,21 +10,15 @@ You can also access the Uniswap Interface from an IPFS gateway.
Your Uniswap settings are never remembered across different URLs.
IPFS gateways:
- https://bafybeidkbbgtppk3euej56wgoxllerdoggnsz3fgkirnhrgvlbmff4reii.ipfs.dweb.link/
- https://bafybeidkbbgtppk3euej56wgoxllerdoggnsz3fgkirnhrgvlbmff4reii.ipfs.cf-ipfs.com/
- [ipfs://QmVUZGU9EBHPpn3BZRhKTQB5VZuDtv2PUetyHxxpfmzcp9/](ipfs://QmVUZGU9EBHPpn3BZRhKTQB5VZuDtv2PUetyHxxpfmzcp9/)
- https://bafybeiajdg2uit3dy2c5dbxclr7w6subg6t4fxnegfifpiskay2qlyys5u.ipfs.dweb.link/
- https://bafybeiajdg2uit3dy2c5dbxclr7w6subg6t4fxnegfifpiskay2qlyys5u.ipfs.cf-ipfs.com/
- [ipfs://QmNxB7dgMsLA6wASBs8xCSjKa4XAkeZNiiaf7uAG7KxPme/](ipfs://QmNxB7dgMsLA6wASBs8xCSjKa4XAkeZNiiaf7uAG7KxPme/)
## 5.11.0 (2024-02-20)
## 5.12.0 (2024-02-22)
### Features
* **web:** [uni-tags] show username in header (#6353) 28fbb53
* **web:** move PDP in-chart fees display to tooltip (#6288) eaad394
### Bug Fixes
* **web:** swap e2e tests (#6412) d5a637e
* **web:** hotfix to prod for unitags launch (#6465) e22ab94
web/5.11.0
\ No newline at end of file
web/5.12.0
\ No newline at end of file
......@@ -3,21 +3,25 @@ import { getTestSelector } from '../../utils'
describe('Uni tags support', () => {
beforeEach(() => {
const unitagSpy = cy.spy().as('unitagSpy')
cy.intercept(/gateway.uniswap.org\/v2\/address/, (req) => {
unitagSpy(req)
})
cy.visit('/swap', {
featureFlags: [{ name: FeatureFlag.uniTags, value: true }],
})
})
it('displays claim banner in account drawer', () => {
it('displays banner in account drawer', () => {
cy.get(getTestSelector('web3-status-connected')).click()
cy.contains('Claim your Uniswap username')
cy.contains('Introducing uni.eth usernames')
})
it('displays large claim banner on page', () => {
it('displays large banner on page', () => {
cy.get(getTestSelector('large-unitag-banner')).should('be.visible')
})
it('does not display claim banner on landing page', () => {
it('does not display banner on landing page', () => {
cy.visit('/?intro=true', {
featureFlags: [{ name: FeatureFlag.uniTags, value: true }],
})
......@@ -32,7 +36,7 @@ describe('Uni tags support', () => {
cy.get(getTestSelector('get-the-app-close-button')).click()
cy.get(getTestSelector('large-unitag-banner')).should('not.be.visible')
cy.get(getTestSelector('web3-status-connected')).click()
cy.get('Claim your Uniswap username').should('not.exist')
cy.get('Introducing uni.eth usernames').should('not.exist')
})
it('hides itself when reject button is clicked', () => {
......@@ -41,6 +45,65 @@ describe('Uni tags support', () => {
})
cy.get(getTestSelector('large-unitag-banner')).should('not.be.visible')
cy.get(getTestSelector('web3-status-connected')).click()
cy.get('Claim your Uniswap username').should('not.exist')
cy.get('Introducing uni.eth usernames').should('not.exist')
})
it('shows address if no Unitag or ENS exists', () => {
cy.hardhat().then(() => {
const unusedAccount = '0xF030EaA01aFf57A23483dC8A1c3550d153be69Fb'
cy.get(getTestSelector('web3-status-connected')).click()
cy.window().then((win) => win.ethereum.emit('accountsChanged', [unusedAccount]))
cy.get(getTestSelector('account-drawer-status')).within(() => {
cy.contains('0xF030...69Fb').should('be.visible')
})
})
})
it('shows Unitag, followed by address, if Unitag exists but not ENS', () => {
cy.intercept(/address/, { fixture: 'mini-portfolio/unitag.json' })
cy.hardhat().then(() => {
const accountWithUnitag = '0xF030EaA01aFf57A23483dC8A1c3550d153be69Fb'
cy.get(getTestSelector('web3-status-connected')).click()
cy.window().then((win) => win.ethereum.emit('accountsChanged', [accountWithUnitag]))
cy.get(getTestSelector('account-drawer-status')).within(() => {
cy.contains('hayden').should('be.visible')
cy.contains('0xF030...69Fb').should('be.visible')
})
})
})
it('shows ENS, followed by address, if ENS exists but not Unitag', () => {
cy.hardhat().then(() => {
const haydenAccount = '0x50EC05ADe8280758E2077fcBC08D878D4aef79C3'
const haydenENS = 'hayden.eth'
cy.get(getTestSelector('web3-status-connected')).click()
cy.window().then((win) => win.ethereum.emit('accountsChanged', [haydenAccount]))
cy.get(getTestSelector('account-drawer-status')).within(() => {
cy.contains(haydenENS).should('be.visible')
cy.contains('0x50EC...79C3').should('be.visible')
})
})
})
it('shows Unitag and more option if user has both Unitag and ENS', () => {
cy.intercept(/address/, { fixture: 'mini-portfolio/unitag.json' })
cy.hardhat().then(() => {
const haydenAccount = '0x50EC05ADe8280758E2077fcBC08D878D4aef79C3'
const haydenUnitag = 'hayden'
const haydenENS = 'hayden.eth'
cy.get(getTestSelector('web3-status-connected')).click()
cy.window().then((win) => win.ethereum.emit('accountsChanged', [haydenAccount]))
cy.get(getTestSelector('account-drawer-status')).within(() => {
cy.contains(haydenUnitag).should('be.visible')
cy.contains('0x50EC...79C3').should('be.visible')
})
cy.get(getTestSelector('secondary-identifiers'))
.trigger('mouseover')
.click()
.within(() => {
cy.contains(haydenENS).should('be.visible')
cy.contains('0x50EC...79C3').should('be.visible')
})
})
})
})
{
"username": "hayden"
}
\ No newline at end of file
......@@ -26,22 +26,20 @@ import { useNavigate } from 'react-router-dom'
import { useAppDispatch } from 'state/hooks'
import { setRecentConnectionDisconnected } from 'state/user/reducer'
import styled from 'styled-components'
import { CopyHelper, ThemedText } from 'theme/components'
import { Icons } from 'ui/src'
import { shortenAddress } from 'utilities/src/addresses'
import { ThemedText } from 'theme/components'
import { isPathBlocked } from 'utils/blockedPaths'
import { NumberType, useFormatter } from 'utils/formatNumbers'
import { useUnitagByAddress } from 'wallet/src/features/unitags/hooks'
import { useCloseModal, useFiatOnrampAvailability, useOpenModal, useToggleModal } from '../../state/application/hooks'
import { ApplicationModal } from '../../state/application/reducer'
import { useUserHasAvailableClaim, useUserUnclaimedAmount } from '../../state/claim/hooks'
import StatusIcon from '../Identicon/StatusIcon'
import { useCachedPortfolioBalancesQuery } from '../PrefetchBalancesWrapper/PrefetchBalancesWrapper'
import { ActionTile } from './ActionTile'
import IconButton, { IconHoverText, IconWithConfirmTextButton } from './IconButton'
import MiniPortfolio from './MiniPortfolio'
import { useToggleAccountDrawer } from './MiniPortfolio/hooks'
import { portfolioFadeInAnimation } from './MiniPortfolio/PortfolioRow'
import { Status } from './Status'
const AuthenticatedHeaderWrapper = styled.div`
padding: 20px 16px;
......@@ -85,24 +83,6 @@ const IconContainer = styled.div`
}
`
const StatusWrapper = styled.div`
display: inline-block;
width: 70%;
max-width: 70%;
padding-right: 8px;
display: inline-flex;
`
const AccountNamesWrapper = styled.div`
overflow: hidden;
white-space: nowrap;
display: flex;
width: 100%;
flex-direction: column;
justify-content: center;
margin-left: 8px;
`
const HeaderWrapper = styled.div`
margin-bottom: 20px;
display: flex;
......@@ -110,11 +90,6 @@ const HeaderWrapper = styled.div`
align-items: flex-start;
`
const CopyText = styled(CopyHelper).attrs({
iconSize: 14,
iconPosition: 'right',
})``
const FadeInColumn = styled(Column)`
${portfolioFadeInAnimation}
`
......@@ -207,26 +182,7 @@ export default function AuthenticatedHeader({
return (
<AuthenticatedHeaderWrapper>
<HeaderWrapper>
<StatusWrapper>
<StatusIcon account={account} connection={connection} size={40} />
{account && (
<AccountNamesWrapper>
<ThemedText.SubHeader>
<CopyText toCopy={unitag?.username ?? ENSName ?? account}>
<Row gap="xs">
{unitag?.username ?? ENSName ?? shortenAddress(account)}
{unitag?.username && <Icons.Unitag size={24} />}
</Row>
</CopyText>
</ThemedText.SubHeader>
{(unitag || ENSName) && (
<ThemedText.BodySmall color="neutral2">
<CopyText toCopy={account}>{shortenAddress(account)}</CopyText>
</ThemedText.BodySmall>
)}
</AccountNamesWrapper>
)}
</StatusWrapper>
<Status account={account} ensUsername={ENSName} uniswapUsername={unitag?.username} connection={connection} />
<IconContainer>
<IconButton
hideHorizontal={showDisconnectConfirm}
......
import Column from 'components/Column'
import { ENS } from 'components/Icons/ENS'
import { EthMini } from 'components/Icons/EthMini'
import StatusIcon from 'components/Identicon/StatusIcon'
import Row from 'components/Row'
import { Connection } from 'connection/types'
import { useOnClickOutside } from 'hooks/useOnClickOutside'
import { useRef, useState } from 'react'
import { MoreHorizontal } from 'react-feather'
import styled from 'styled-components'
import { ClickableStyle, CopyHelper, ThemedText } from 'theme/components'
import { Icons } from 'ui/src'
import { shortenAddress } from 'utilities/src/addresses'
const Container = styled.div`
display: inline-block;
width: 70%;
max-width: 70%;
padding-right: 8px;
display: inline-flex;
`
const Identifiers = styled.div`
white-space: nowrap;
display: flex;
width: 100%;
flex-direction: column;
justify-content: center;
margin-left: 8px;
user-select: none;
`
const SecondaryIdentifiersContainer = styled(Row)`
position: relative;
user-select: none;
:hover > div > #more-identifiers-icon {
display: inline-block;
}
`
const MoreIcon = styled(MoreHorizontal)<{ $isActive: boolean }>`
height: 16px;
width: 16px;
color: ${({ theme }) => theme.neutral2};
cursor: pointer;
display: ${({ $isActive }) => !$isActive && 'none'};
${ClickableStyle}
`
const Dropdown = styled(Column)`
width: 240px;
position: absolute;
top: 20px;
gap: 2px;
padding: 8px;
border-radius: 20px;
border: 1px solid ${({ theme }) => theme.surface3};
background: ${({ theme }) => theme.surface1};
`
const EnsIcon = styled(ENS)`
height: 20px;
width: 20px;
padding: 2px 3px;
`
function SecondaryIdentifier({
Icon,
displayValue,
copyValue,
}: {
Icon: React.ComponentType
displayValue: string
copyValue: string
}) {
return (
<CopyHelper iconSize={20} iconPosition="right" toCopy={copyValue}>
<Row width="240px" padding="8px 4px">
<Icon />
<Row margin="0px 8px">{displayValue}</Row>
</Row>
</CopyHelper>
)
}
function SecondaryIdentifiers({
account,
uniswapUsername,
ensUsername,
}: {
account: string
ensUsername: string | null
uniswapUsername?: string
}) {
const [isDropdownOpen, setIsDropdownOpen] = useState(false)
const ref = useRef<HTMLDivElement>(null)
useOnClickOutside(ref, () => setIsDropdownOpen(false))
// Dropdown is present if more than one secondary identifier is available
if (uniswapUsername && ensUsername) {
return (
<SecondaryIdentifiersContainer data-testid="secondary-identifiers" ref={ref}>
<Row onClick={() => setIsDropdownOpen(!isDropdownOpen)} gap="8px">
<ThemedText.BodySmall color="neutral2">{shortenAddress(account)}</ThemedText.BodySmall>
<MoreIcon id="more-identifiers-icon" $isActive={isDropdownOpen} />
</Row>
{isDropdownOpen && (
<Dropdown>
<SecondaryIdentifier Icon={EnsIcon} displayValue={ensUsername} copyValue={ensUsername} />
<SecondaryIdentifier Icon={EthMini} displayValue={shortenAddress(account)} copyValue={account} />
</Dropdown>
)}
</SecondaryIdentifiersContainer>
)
}
// Dropdown is not present if only one secondary identifier is available
return (
<ThemedText.BodySmall color="neutral2">
<CopyHelper iconSize={14} iconPosition="right" toCopy={account}>
{shortenAddress(account)}
</CopyHelper>
</ThemedText.BodySmall>
)
}
export function Status({
account,
ensUsername,
uniswapUsername,
connection,
}: {
account: string
ensUsername: string | null
uniswapUsername?: string
connection: Connection
}) {
return (
<Container data-testid="account-drawer-status">
<StatusIcon account={account} connection={connection} size={40} />
<Identifiers>
<ThemedText.SubHeader>
<CopyHelper
iconSize={14}
iconPosition="right"
toCopy={uniswapUsername ? uniswapUsername + '.uni.eth' : ensUsername ? ensUsername : account}
>
<Row gap="2px">
{uniswapUsername ?? ensUsername ?? shortenAddress(account)}
{uniswapUsername && <Icons.Unitag size={24} />}
</Row>
</CopyHelper>
</ThemedText.SubHeader>
{(uniswapUsername || ensUsername) && (
<SecondaryIdentifiers account={account} ensUsername={ensUsername} uniswapUsername={uniswapUsername} />
)}
</Identifiers>
</Container>
)
}
......@@ -10,22 +10,29 @@ import pfp4 from './assets/pfp4.png'
import { useUniTagBanner } from './useUniTagBanner'
const StyledPopupContainer = styled(PopupContainer)`
height: 160px;
height: 176px;
width: 390px;
right: 28px;
bottom: 46px;
@media screen and (max-width: ${BREAKPOINTS.md}px) {
height: 136px;
height: 150px;
width: 369px;
right: unset;
left: unset;
bottom: 73px;
}
@media screen and (max-width: ${BREAKPOINTS.xs}px) {
height: 150px;
width: 90%;
}
@media screen and (max-width: 305px) {
display: none;
}
border: none;
background: none;
overflow: hidden;
`
const Container = styled.div`
const ContentContainer = styled.div`
height: 100%;
width: 100%;
position: relative;
......@@ -42,47 +49,50 @@ const CopyContainer = styled.div`
height: 68px;
width: 280px;
gap: 4px;
@media screen and (max-width: ${BREAKPOINTS.xs}px) {
width: 90%;
}
`
const ButtonsContainer = styled.div`
position: absolute;
top: 104px;
left: 16px;
bottom: 16px;
gap: 12px;
z-index: 1;
width: calc(100% - 32px);
@media screen and (max-width: ${BREAKPOINTS.md}px) {
top: 88px;
left: 16px;
}
`
const GraphicsContainer = styled(Column)`
position: absolute;
top: 0px;
left: 318px;
opacity: 0.8;
gap: 7px;
top: 12px;
right: 19px;
@media screen and (max-width: ${BREAKPOINTS.md}px) {
left: 275px;
top: 12px;
right: 38px;
}
@media screen and (max-width: ${BREAKPOINTS.xs}px) {
display: none;
}
gap: 6px;
opacity: 0.8;
`
export function LargeUniTagBanner() {
const { shouldHideUniTagBanner, handleAccept, handleReject } = useUniTagBanner()
return (
<StyledPopupContainer show={!shouldHideUniTagBanner} data-testid="large-unitag-banner">
<Container>
<ContentContainer>
<CopyContainer>
<Copy large />
</CopyContainer>
<ButtonsContainer>
<Buttons large onAccept={handleAccept} onReject={handleReject} />
</ButtonsContainer>
</Container>
</ContentContainer>
<GraphicsContainer>
<Profile pfp={pfp1} name="maggie" color="#67bcff" rotation={-2} offset={5} large />
<Profile pfp={pfp2} name="hayden" color="#8CD698" rotation={3} offset={-88} large />
<Profile pfp={pfp2} name="hayden" color="#8CD698" rotation={3} offset={-94} large />
<Profile pfp={pfp3} name="unicorn" color="#E89DE5" rotation={-2} offset={5} large />
<Profile pfp={pfp4} name="bryan" color="#FE7C00" rotation={-2} offset={-80} large />
<Profile pfp={pfp4} name="bryan" color="#FE7C00" rotation={-2} offset={-78} large />
</GraphicsContainer>
</StyledPopupContainer>
)
......
......@@ -12,23 +12,42 @@ import { useUniTagBanner } from './useUniTagBanner'
const Container = styled(Row)`
width: 100%;
max-height: 140px;
height: 100%;
position: relative;
overflow: hidden;
padding: 16px;
gap: 16px;
background: ${({ theme }) => theme.surface1};
border: 1px solid ${({ theme }) => theme.surface3};
border-radius: 20px;
margin-top: 12px;
box-shadow: 0px 0px 10px 0px rgba(34, 34, 34, 0.04);
@media screen and (max-width: 1440px) {
padding-right: 2px;
gap: 6px;
}
@media screen and (max-width: 310px) {
display: none;
}
`
const ContentContainer = styled(Column)`
padding: 16px;
padding-right: 0px;
gap: 16px;
max-width: 290px;
@media screen and (min-width: ${BREAKPOINTS.sm}px) and (max-width: 1440px) {
max-width: 205px;
}
`
const GraphicsContainer = styled.div`
position: absolute;
right: 0px;
bottom: 0px;
height: 100%;
overflow: hidden;
padding: 0px 8px;
`
const GraphicsInner = styled(Column)`
gap: 8px;
margin-top: -14px;
@media screen and (min-width: ${BREAKPOINTS.sm}px) and (max-width: 1440px) {
margin-top: -6px;
}
`
const Title = styled.div<{ large?: boolean }>`
font-weight: 500;
font-size: ${({ large }) => (large ? '18px' : '14px')};
......@@ -124,18 +143,22 @@ const UserName = styled.div<{ $color: string; $rotation: number }>`
font-weight: 535;
line-height: 14px;
margin-top: -8px;
box-shadow: 0px 0px 10.178px 0px rgba(0, 0, 0, 0.09);
`
export function Copy({ large }: { large?: boolean }) {
return (
<Column gap="4px">
<Row gap="4px">
<Title large={large}>
<Trans>Claim your Uniswap username</Trans>
<Trans>Introducing uni.eth usernames</Trans>
</Title>
{large && <Icons.Unitag size={24} />}
</Row>
<Subtitle large={large}>
<Trans>Sharing your address has never been easier. Claim now in the mobile app!</Trans>
<Trans>
Build a personalized web3 profile and easily share your address with friends. Get yours now in the Uniswap
mobile app.
</Trans>
</Subtitle>
</Column>
)
......@@ -151,7 +174,7 @@ export function Buttons({
onReject?: () => void
}) {
return (
<Row gap={large ? '12px' : '4px'}>
<Row gap={large ? '12px' : '8px'}>
<AcceptButton
data-testid="unitag-banner-accept-button"
size={ButtonSize.medium}
......@@ -208,15 +231,17 @@ export function UniTagBanner() {
return (
<Container justify="space-between">
<Column gap="16px">
<ContentContainer gap="16px">
<Copy />
<Buttons onAccept={handleAccept} onReject={handleReject} />
</Column>
<Column gap="8px">
<Profile pfp={pfp1} name="maggie" color="#67bcff" rotation={-2} />
<Profile pfp={pfp2} name="hayden" color="#8CD698" rotation={3} />
<Profile pfp={pfp3} name="unicorn" color="#E89DE5" rotation={-2} />
</Column>
</ContentContainer>
<GraphicsContainer>
<GraphicsInner>
<Profile pfp={pfp1} name="maggie" color="#67bcff" rotation={-2} />
<Profile pfp={pfp2} name="hayden" color="#8CD698" rotation={3} />
<Profile pfp={pfp3} name="unicorn" color="#E89DE5" rotation={-2} />
</GraphicsInner>
</GraphicsContainer>
</Container>
)
}
import { ComponentProps } from 'react'
export function ENS(props: ComponentProps<'svg'>) {
return (
<svg width="14" height="17" viewBox="0 0 14 17" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
<mask id="mask0_3571_13594" maskUnits="userSpaceOnUse" x="0" y="0" width="14" height="17">
<path d="M13.884 0.25H0.115845V16.0833H13.884V0.25Z" fill="white" />
</mask>
<g mask="url(#mask0_3571_13594)">
<path
d="M1.90911 3.97531C2.05233 3.70031 2.25902 3.46587 2.51096 3.29266L6.73911 0.25L2.40686 7.63234C2.40686 7.63234 2.02834 6.97314 1.88071 6.63958C1.69675 6.22018 1.60397 5.76444 1.60887 5.30422C1.61377 4.84399 1.71625 4.39044 1.90911 3.97531ZM0.164095 9.06787C0.211834 9.77385 0.405387 10.4612 0.731793 11.0838C1.0582 11.7064 1.50993 12.25 2.05673 12.6781L6.73341 16.0387C6.73341 16.0387 3.80741 11.6932 1.33942 7.36907C1.08956 6.91222 0.921588 6.41274 0.843548 5.89454C0.809002 5.65989 0.809002 5.42118 0.843548 5.18653C0.779198 5.30943 0.654286 5.56103 0.654286 5.56103C0.404041 6.08695 0.233613 6.64937 0.148954 7.22864C0.100226 7.84093 0.105293 8.4565 0.164095 9.06787ZM12.0877 9.65298C11.9362 9.31946 11.5615 8.66021 11.5615 8.66021L7.23686 16.0387L11.465 12.998C11.7169 12.8248 11.9236 12.5904 12.0669 12.3153C12.2597 11.9002 12.3621 11.4466 12.3671 10.9865C12.372 10.5262 12.2792 10.0704 12.0952 9.65105L12.0877 9.65298ZM13.8043 7.22275C13.7565 6.51682 13.563 5.82947 13.2366 5.20685C12.9102 4.58423 12.4584 4.04065 11.9116 3.61253L7.24251 0.25C7.24251 0.25 10.1666 4.59554 12.6365 8.91963C12.8857 9.37662 13.053 9.87609 13.1305 10.3942C13.165 10.6288 13.165 10.8675 13.1305 11.1022C13.1949 10.9793 13.3198 10.7277 13.3198 10.7277C13.57 10.2017 13.7405 9.63932 13.8251 9.06005C13.8744 8.44781 13.87 7.83224 13.8119 7.22082L13.8043 7.22275Z"
fill="#9B9B9B"
/>
</g>
</svg>
)
}
export function EthMini() {
return (
<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M13.9227 10.306L9.99918 11.6873L6.07687 10.306C5.86579 10.231 5.77039 9.97478 5.87772 9.76976L9.42794 3.01292C9.67838 2.55038 10.3224 2.55038 10.5728 3.01292L14.123 9.76976C14.2292 9.97353 14.1337 10.231 13.9227 10.306Z"
fill="#9B9B9B"
/>
<path
d="M13.5005 12.9175L10.5358 17.3754C10.2735 17.7629 9.72488 17.7629 9.46252 17.3754L6.49788 12.9175C6.36669 12.7199 6.55153 12.4612 6.76857 12.5375L9.71298 13.5625C9.80838 13.6 9.90378 13.6125 9.99918 13.6125C10.0946 13.6125 10.19 13.6 10.2854 13.5625L13.2298 12.5375C13.4468 12.4612 13.6317 12.7199 13.5005 12.9175Z"
fill="#9B9B9B"
/>
</svg>
)
}
import { useUniTagsEnabled } from 'featureFlags/flags/uniTags'
import styled from 'styled-components'
import { useUnitagByAddress } from 'wallet/src/features/unitags/hooks'
const Container = styled.div<{ $iconSize: number }>`
height: ${({ $iconSize: iconSize }) => `${iconSize}px`};
width: ${({ $iconSize: iconSize }) => `${iconSize}px`};
border-radius: 50%;
background-color: ${({ theme }) => theme.surface3};
font-size: initial;
`
const Profile = styled.img`
height: inherit;
width: inherit;
border-radius: inherit;
object-fit: cover;
`
export function UniTagProfilePicture({ account, size }: { account: string; size: number }) {
const { unitag } = useUnitagByAddress(account, useUniTagsEnabled() && Boolean(account))
return (
<Container $iconSize={size}>
{unitag && unitag.metadata && <Profile alt={unitag.username} src={unitag.metadata.avatar} />}
</Container>
)
}
......@@ -116,12 +116,12 @@ const AddressAndChevronContainer = styled.div<{ $loading?: boolean }>`
}
`
const Text = styled.p`
const Text = styled.span`
flex: 1 1 auto;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin: 0 0.25rem 0 0.25rem;
margin: 0 2px;
font-size: 1rem;
width: fit-content;
font-weight: 485;
......
......@@ -62,6 +62,28 @@ const mockedSendContextWithVerifiedRecipientInput: SendContextType = {
setSendState: jest.fn(),
}
const mockedSendContextWithUnitag: SendContextType = {
sendState: {
exactAmountToken: '1',
exactAmountFiat: undefined,
recipient: 'hayden.eth',
inputCurrency: DAI,
inputInFiat: false,
validatedRecipientData: {
address: '0x9984b4b4E408e8D618A879e5315BD30952c89103',
ensName: 'hayden.eth',
},
},
derivedSendInfo: {
recipientData: {
address: '0x9984b4b4E408e8D618A879e5315BD30952c89103',
ensName: 'hayden.eth',
unitag: 'hayden',
},
},
setSendState: jest.fn(),
}
describe('SendCurrencyInputform', () => {
it('should render placeholder values', () => {
const { container } = render(
......@@ -99,4 +121,17 @@ describe('SendCurrencyInputform', () => {
expect(screen.getByText(shortenAddress('0x9984b4b4E408e8D618A879e5315BD30952c89103'))).toBeVisible()
expect(container.firstChild).toMatchSnapshot()
})
it('should render correctly with unitag', () => {
const { container } = render(
<SwapAndLimitContext.Provider value={mockSwapAndLimitContextValue}>
<SendContext.Provider value={mockedSendContextWithUnitag}>
<SendRecipientForm />
</SendContext.Provider>
</SwapAndLimitContext.Provider>
)
expect(screen.getByText('hayden')).toBeVisible()
expect(screen.getByText(shortenAddress('0x9984b4b4E408e8D618A879e5315BD30952c89103'))).toBeVisible()
expect(container.firstChild).toMatchSnapshot()
})
})
......@@ -4,6 +4,8 @@ import Column, { AutoColumn } from 'components/Column'
import Identicon from 'components/Identicon'
import Row from 'components/Row'
import { Unicon } from 'components/Unicon'
import { UniTagProfilePicture } from 'components/UniTag/UniTagProfilePicture'
import { useUniTagsEnabled } from 'featureFlags/flags/uniTags'
import useENSName from 'hooks/useENSName'
import { useGroupedRecentTransfers } from 'hooks/useGroupedRecentTransfers'
import { useOnClickOutside } from 'hooks/useOnClickOutside'
......@@ -15,7 +17,9 @@ import { useSendContext } from 'state/send/SendContext'
import styled, { css, keyframes } from 'styled-components'
import { ClickableStyle, ThemedText } from 'theme/components'
import { AnimationType } from 'theme/components/FadePresence'
import { Icons } from 'ui/src'
import { shortenAddress } from 'utilities/src/addresses'
import { useUnitagByAddress, useUnitagByName } from 'wallet/src/features/unitags/hooks'
const StyledConfirmedRecipientRow = styled(Row)`
padding: 6px 0px;
......@@ -115,6 +119,7 @@ const AutocompleteRow = ({
selectRecipient: (recipient: RecipientData) => void
}) => {
const { account } = useWeb3React()
const { unitag } = useUnitagByAddress(address, useUniTagsEnabled() && Boolean(address))
const { ENSName } = useENSName(address)
const cachedEnsName = ENSName || validatedEnsName
const formattedAddress = shortenAddress(address)
......@@ -123,17 +128,31 @@ const AutocompleteRow = ({
selectRecipient({
address,
ensName: cachedEnsName,
unitag: unitag?.username,
}),
[address, cachedEnsName, selectRecipient]
[address, cachedEnsName, selectRecipient, unitag?.username]
)
return (
<StyledAutocompleteRow justify="space-between" padding="8px 0px" onClick={boundSelectRecipient}>
<Row gap="sm">
{cachedEnsName ? <Identicon account={address} size={36} /> : <Unicon address={address} size={36} />}
{unitag?.metadata?.avatar ? (
<UniTagProfilePicture account={address} size={36} />
) : cachedEnsName ? (
<Identicon account={address} size={36} />
) : (
<Unicon address={address} size={36} />
)}
<Column>
<ThemedText.BodyPrimary lineHeight="24px">{cachedEnsName ?? formattedAddress}</ThemedText.BodyPrimary>
{cachedEnsName && <ThemedText.LabelSmall lineHeight="20px">{formattedAddress}</ThemedText.LabelSmall>}
<Row gap="xs">
<ThemedText.BodyPrimary lineHeight="24px">
{unitag?.username ?? cachedEnsName ?? formattedAddress}
</ThemedText.BodyPrimary>
{unitag?.username && <Icons.Unitag size={24} />}
</Row>
{(unitag || cachedEnsName) && (
<ThemedText.LabelSmall lineHeight="20px">{formattedAddress}</ThemedText.LabelSmall>
)}
</Column>
</Row>
{account && (
......@@ -198,6 +217,8 @@ export function SendRecipientForm({ disabled }: { disabled?: boolean }) {
const { recipient } = sendState
const { recipientData } = derivedSendInfo
const unitagMetadata = useUnitagByName(recipientData?.unitag, useUniTagsEnabled() && Boolean(recipientData?.unitag))
.unitag?.metadata
const { transfers: recentTransfers } = useGroupedRecentTransfers(account)
const [[isFocusing, isForcingFocus], setFocus] = useState([false, false])
......@@ -313,15 +334,20 @@ export function SendRecipientForm({ disabled }: { disabled?: boolean }) {
) : (
<StyledConfirmedRecipientRow>
<StyledConfirmedRecipientDisplayRow gap="md" onClick={editValidatedRecipient}>
{recipientData.ensName ? (
{unitagMetadata?.avatar ? (
<UniTagProfilePicture account={recipientData.address} size={36} />
) : recipientData.ensName ? (
<Identicon account={recipientData.address} size={36} />
) : (
<Unicon address={recipientData.address} size={36} />
)}
<Column>
<ThemedText.BodyPrimary lineHeight="24px">
{recipientData.ensName ?? shortenAddress(recipientData.address)}
</ThemedText.BodyPrimary>
<Row gap="xs">
<ThemedText.BodyPrimary lineHeight="24px">
{recipientData.unitag ?? recipientData.ensName ?? shortenAddress(recipientData.address)}
</ThemedText.BodyPrimary>
{recipientData.unitag && <Icons.Unitag size={24} />}
</Row>
{Boolean(recipientData.ensName) && (
<ThemedText.LabelMicro lineHeight="16px">{shortenAddress(recipientData.address)}</ThemedText.LabelMicro>
)}
......
......@@ -9,12 +9,14 @@ import Identicon from 'components/Identicon'
import { ChainLogo } from 'components/Logo/ChainLogo'
import Modal from 'components/Modal'
import Row from 'components/Row'
import { UniTagProfilePicture } from 'components/UniTag/UniTagProfilePicture'
import { Unicon } from 'components/Unicon'
import { useStablecoinValue } from 'hooks/useStablecoinPrice'
import { ReactNode } from 'react'
import { useSendContext } from 'state/send/SendContext'
import styled from 'styled-components'
import { ClickableStyle, CloseIcon, Separator, ThemedText } from 'theme/components'
import { Icons } from 'ui/src'
import { shortenAddress } from 'utilities/src/addresses'
import { NumberType, useFormatter } from 'utils/formatNumbers'
......@@ -117,15 +119,20 @@ export function SendReviewModal({ onConfirm, onDismiss }: { onConfirm: () => voi
<SendModalHeader
label={<Trans>To</Trans>}
header={
recipientData?.ensName ? (
<ThemedText.HeadlineLarge>{recipientData.ensName}</ThemedText.HeadlineLarge>
recipientData?.unitag || recipientData?.ensName ? (
<Row gap="sm">
<ThemedText.HeadlineLarge>{recipientData.unitag ?? recipientData.ensName}</ThemedText.HeadlineLarge>
{recipientData?.unitag && <Icons.Unitag size={36} />}
</Row>
) : (
shortenAddress(recipientData?.address)
)
}
subheader={recipientData?.ensName && shortenAddress(recipientData.address)}
subheader={(recipientData?.unitag || recipientData?.ensName) && shortenAddress(recipientData.address)}
image={
recipientData?.ensName ? (
recipientData?.unitag ? (
<UniTagProfilePicture account={recipientData.address} size={36} />
) : recipientData?.ensName ? (
<Identicon account={recipientData.address} size={36} />
) : (
<Unicon address={recipientData?.address ?? ''} size={36} />
......
......@@ -142,7 +142,7 @@ exports[`SendCurrencyInputform should render correctly with no verified recipien
</span>
`;
exports[`SendCurrencyInputform should render correctly with verified recipient 1`] = `
exports[`SendCurrencyInputform should render correctly with unitag 1`] = `
.c2 {
box-sizing: border-box;
margin: 0;
......@@ -185,6 +185,24 @@ exports[`SendCurrencyInputform should render correctly with verified recipient 1
}
.c8 {
width: 100%;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
padding: 0;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: start;
-webkit-justify-content: flex-start;
-ms-flex-pack: start;
justify-content: flex-start;
gap: 4px;
}
.c9 {
color: #222222;
-webkit-letter-spacing: -0.01em;
-moz-letter-spacing: -0.01em;
......@@ -192,7 +210,7 @@ exports[`SendCurrencyInputform should render correctly with verified recipient 1
letter-spacing: -0.01em;
}
.c9 {
.c10 {
color: #7D7D7D;
-webkit-letter-spacing: -0.01em;
-moz-letter-spacing: -0.01em;
......@@ -246,7 +264,280 @@ exports[`SendCurrencyInputform should render correctly with verified recipient 1
opacity: 0.4;
}
.c11 {
color: #CECECE;
-webkit-text-decoration: none;
text-decoration: none;
cursor: pointer;
-webkit-transition-duration: 125ms;
transition-duration: 125ms;
}
.c11:hover {
opacity: 0.6;
}
.c11:active {
opacity: 0.4;
}
.c1 {
position: relative;
background-color: #F9F9F9;
border-radius: 16px;
padding: 12px 16px;
gap: 4px;
opacity: 1;
pointer-events: initial;
}
<span
class=" _dsp_contents"
>
<span
class=" t_light _dsp_contents is_Theme"
>
<div
class="c0 c1"
>
<div
class="c2 c3 c4"
>
<div
class="c2 c5 c6"
>
<div
class="c7"
>
<span>
<div
style="border-radius: 50px; overflow: hidden; padding: 0px; margin: 0px; width: 36px; height: 36px; display: inline-block; background: rgb(200, 20, 83);"
>
<svg
height="36"
width="36"
x="0"
y="0"
>
<rect
fill="#F29602"
height="36"
transform="translate(-1.3639893162257823 0.27350588462642744) rotate(171.3 18 18)"
width="36"
x="0"
y="0"
/>
<rect
fill="#FA6C00"
height="36"
transform="translate(7.665150362825969 -12.44820359430869) rotate(394.5 18 18)"
width="36"
x="0"
y="0"
/>
<rect
fill="#FB1868"
height="36"
transform="translate(23.55150004628138 -6.949396678861342) rotate(445.6 18 18)"
width="36"
x="0"
y="0"
/>
</svg>
</div>
</span>
</div>
<div
class="c0"
>
<div
class="c2 c8"
>
<div
class="c9 css-n8z49y"
>
hayden
</div>
<span
class="_dsp_contents"
>
<div
class="css-view-175oi2r r-flexBasis-1mlwlqe r-overflow-1udh08x r-zIndex-417010 is_Image _height-24px _width-24px"
>
<div
class="css-view-175oi2r r-backgroundColor-1niwhzg r-backgroundPosition-vvn4in r-backgroundRepeat-u6sd8q r-bottom-1p0dtai r-height-1pi2tsx r-left-1d2f490 r-position-u8s1d r-right-zchlnj r-top-ipm5af r-width-13qz1uu r-zIndex-1wyyakw r-backgroundSize-4gszlv"
style="background-image: url(unitag-light.png);"
/>
<img
alt=""
class="css-accessibilityImage-9pa8cd"
draggable="false"
src="unitag-light.png"
/>
</div>
</span>
</div>
<div
class="c10 css-obwv3p"
>
0x9984...9103
</div>
</div>
</div>
<svg
class="c11"
fill="none"
height="20"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="20"
xmlns="http://www.w3.org/2000/svg"
>
<line
x1="18"
x2="6"
y1="6"
y2="18"
/>
<line
x1="6"
x2="18"
y1="6"
y2="18"
/>
</svg>
</div>
</div>
</span>
</span>
`;
exports[`SendCurrencyInputform should render correctly with verified recipient 1`] = `
.c2 {
box-sizing: border-box;
margin: 0;
min-width: 0;
}
.c3 {
width: 100%;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
padding: 0;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: start;
-webkit-justify-content: flex-start;
-ms-flex-pack: start;
justify-content: flex-start;
}
.c5 {
width: 100%;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
padding: 0;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: start;
-webkit-justify-content: flex-start;
-ms-flex-pack: start;
justify-content: flex-start;
gap: 12px;
}
.c8 {
width: 100%;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
padding: 0;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: start;
-webkit-justify-content: flex-start;
-ms-flex-pack: start;
justify-content: flex-start;
gap: 4px;
}
.c9 {
color: #222222;
-webkit-letter-spacing: -0.01em;
-moz-letter-spacing: -0.01em;
-ms-letter-spacing: -0.01em;
letter-spacing: -0.01em;
}
.c10 {
color: #7D7D7D;
-webkit-letter-spacing: -0.01em;
-moz-letter-spacing: -0.01em;
-ms-letter-spacing: -0.01em;
letter-spacing: -0.01em;
}
.c0 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-pack: start;
-webkit-justify-content: flex-start;
-ms-flex-pack: start;
justify-content: flex-start;
}
.c7 {
height: 36px;
width: 36px;
border-radius: 50%;
background-color: #22222212;
font-size: initial;
}
.c4 {
padding: 6px 0px;
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
}
.c6 {
-webkit-text-decoration: none;
text-decoration: none;
cursor: pointer;
-webkit-transition-duration: 125ms;
transition-duration: 125ms;
}
.c6:hover {
opacity: 0.6;
}
.c6:active {
opacity: 0.4;
}
.c11 {
color: #CECECE;
-webkit-text-decoration: none;
text-decoration: none;
......@@ -255,11 +546,11 @@ exports[`SendCurrencyInputform should render correctly with verified recipient 1
transition-duration: 125ms;
}
.c10:hover {
.c11:hover {
opacity: 0.6;
}
.c10:active {
.c11:active {
opacity: 0.4;
}
......@@ -333,19 +624,23 @@ exports[`SendCurrencyInputform should render correctly with verified recipient 1
class="c0"
>
<div
class="c8 css-n8z49y"
class="c2 c8"
>
hayden.eth
<div
class="c9 css-n8z49y"
>
hayden.eth
</div>
</div>
<div
class="c9 css-obwv3p"
class="c10 css-obwv3p"
>
0x9984...9103
</div>
</div>
</div>
<svg
class="c10"
class="c11"
fill="none"
height="20"
stroke="currentColor"
......
......@@ -15,14 +15,14 @@ exports[`SendCurrencyInputform should render input in fiat correctly 1`] = `
min-width: 0;
}
.c24 {
.c25 {
box-sizing: border-box;
margin: 0;
min-width: 0;
width: 100%;
}
.c25 {
.c26 {
box-sizing: border-box;
margin: 0;
min-width: 0;
......@@ -31,7 +31,7 @@ exports[`SendCurrencyInputform should render input in fiat correctly 1`] = `
width: min-content;
}
.c27 {
.c28 {
box-sizing: border-box;
margin: 0;
min-width: 0;
......@@ -142,7 +142,25 @@ exports[`SendCurrencyInputform should render input in fiat correctly 1`] = `
justify-content: space-between;
}
.c26 {
.c22 {
width: 100%;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
padding: 0;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: start;
-webkit-justify-content: flex-start;
-ms-flex-pack: start;
justify-content: flex-start;
gap: 8px;
}
.c27 {
width: -webkit-min-content;
width: -moz-min-content;
width: min-content;
......@@ -202,7 +220,7 @@ exports[`SendCurrencyInputform should render input in fiat correctly 1`] = `
opacity: 0.4;
}
.c23 {
.c24 {
width: 100%;
height: 1px;
background-color: #22222212;
......@@ -228,7 +246,7 @@ exports[`SendCurrencyInputform should render input in fiat correctly 1`] = `
border-radius: 50%;
}
.c28 {
.c29 {
padding: 16px;
width: 100%;
line-height: 24px;
......@@ -267,25 +285,25 @@ exports[`SendCurrencyInputform should render input in fiat correctly 1`] = `
transform: perspective(1px) translateZ(0);
}
.c28:disabled {
.c29:disabled {
opacity: 50%;
cursor: auto;
pointer-events: none;
}
.c28 > * {
.c29 > * {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.c28 > a {
.c29 > a {
-webkit-text-decoration: none;
text-decoration: none;
}
.c29 {
.c30 {
background-color: #FC72FF;
font-size: 20px;
font-weight: 535;
......@@ -293,21 +311,21 @@ exports[`SendCurrencyInputform should render input in fiat correctly 1`] = `
color: #FFFFFF;
}
.c29:focus {
.c30:focus {
box-shadow: 0 0 0 1pt #fb58ff;
background-color: #fb58ff;
}
.c29:hover {
.c30:hover {
background-color: #fb58ff;
}
.c29:active {
.c30:active {
box-shadow: 0 0 0 1pt #fb3fff;
background-color: #fb3fff;
}
.c29:disabled {
.c30:disabled {
background-color: #22222212;
color: #7D7D7D;
cursor: auto;
......@@ -407,7 +425,7 @@ exports[`SendCurrencyInputform should render input in fiat correctly 1`] = `
align-items: center;
}
.c22 {
.c23 {
height: 36px;
width: 36px;
border-radius: 50%;
......@@ -584,9 +602,13 @@ exports[`SendCurrencyInputform should render input in fiat correctly 1`] = `
class="c7 css-15popx1"
>
<div
class="c7 css-15popx1"
class="c5 c22"
>
hayden.eth
<div
class="c7 css-15popx1"
>
hayden.eth
</div>
</div>
</div>
<div
......@@ -599,7 +621,7 @@ exports[`SendCurrencyInputform should render input in fiat correctly 1`] = `
style="height: 36px;"
>
<div
class="c22"
class="c23"
>
<span>
<div
......@@ -643,10 +665,10 @@ exports[`SendCurrencyInputform should render input in fiat correctly 1`] = `
</div>
</div>
<div
class="c23"
class="c24"
/>
<div
class="c24 c17"
class="c25 c17"
width="100%"
>
<div
......@@ -655,7 +677,7 @@ exports[`SendCurrencyInputform should render input in fiat correctly 1`] = `
Network cost
</div>
<div
class="c25 c26"
class="c26 c27"
width="min-content"
>
<svg
......@@ -697,7 +719,7 @@ exports[`SendCurrencyInputform should render input in fiat correctly 1`] = `
</div>
</div>
<button
class="c27 c28 c29"
class="c28 c29 c30"
>
Confirm send
</button>
......@@ -719,14 +741,14 @@ exports[`SendCurrencyInputform should render input in token amount correctly 1`]
min-width: 0;
}
.c24 {
.c25 {
box-sizing: border-box;
margin: 0;
min-width: 0;
width: 100%;
}
.c25 {
.c26 {
box-sizing: border-box;
margin: 0;
min-width: 0;
......@@ -735,7 +757,7 @@ exports[`SendCurrencyInputform should render input in token amount correctly 1`]
width: min-content;
}
.c27 {
.c28 {
box-sizing: border-box;
margin: 0;
min-width: 0;
......@@ -846,7 +868,25 @@ exports[`SendCurrencyInputform should render input in token amount correctly 1`]
justify-content: space-between;
}
.c26 {
.c22 {
width: 100%;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
padding: 0;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: start;
-webkit-justify-content: flex-start;
-ms-flex-pack: start;
justify-content: flex-start;
gap: 8px;
}
.c27 {
width: -webkit-min-content;
width: -moz-min-content;
width: min-content;
......@@ -906,7 +946,7 @@ exports[`SendCurrencyInputform should render input in token amount correctly 1`]
opacity: 0.4;
}
.c23 {
.c24 {
width: 100%;
height: 1px;
background-color: #22222212;
......@@ -932,7 +972,7 @@ exports[`SendCurrencyInputform should render input in token amount correctly 1`]
border-radius: 50%;
}
.c28 {
.c29 {
padding: 16px;
width: 100%;
line-height: 24px;
......@@ -971,25 +1011,25 @@ exports[`SendCurrencyInputform should render input in token amount correctly 1`]
transform: perspective(1px) translateZ(0);
}
.c28:disabled {
.c29:disabled {
opacity: 50%;
cursor: auto;
pointer-events: none;
}
.c28 > * {
.c29 > * {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.c28 > a {
.c29 > a {
-webkit-text-decoration: none;
text-decoration: none;
}
.c29 {
.c30 {
background-color: #FC72FF;
font-size: 20px;
font-weight: 535;
......@@ -997,21 +1037,21 @@ exports[`SendCurrencyInputform should render input in token amount correctly 1`]
color: #FFFFFF;
}
.c29:focus {
.c30:focus {
box-shadow: 0 0 0 1pt #fb58ff;
background-color: #fb58ff;
}
.c29:hover {
.c30:hover {
background-color: #fb58ff;
}
.c29:active {
.c30:active {
box-shadow: 0 0 0 1pt #fb3fff;
background-color: #fb3fff;
}
.c29:disabled {
.c30:disabled {
background-color: #22222212;
color: #7D7D7D;
cursor: auto;
......@@ -1111,7 +1151,7 @@ exports[`SendCurrencyInputform should render input in token amount correctly 1`]
align-items: center;
}
.c22 {
.c23 {
height: 36px;
width: 36px;
border-radius: 50%;
......@@ -1288,9 +1328,13 @@ exports[`SendCurrencyInputform should render input in token amount correctly 1`]
class="c7 css-15popx1"
>
<div
class="c7 css-15popx1"
class="c5 c22"
>
hayden.eth
<div
class="c7 css-15popx1"
>
hayden.eth
</div>
</div>
</div>
<div
......@@ -1303,7 +1347,7 @@ exports[`SendCurrencyInputform should render input in token amount correctly 1`]
style="height: 36px;"
>
<div
class="c22"
class="c23"
>
<span>
<div
......@@ -1347,10 +1391,10 @@ exports[`SendCurrencyInputform should render input in token amount correctly 1`]
</div>
</div>
<div
class="c23"
class="c24"
/>
<div
class="c24 c17"
class="c25 c17"
width="100%"
>
<div
......@@ -1359,7 +1403,7 @@ exports[`SendCurrencyInputform should render input in token amount correctly 1`]
Network cost
</div>
<div
class="c25 c26"
class="c26 c27"
width="min-content"
>
<svg
......@@ -1401,7 +1445,7 @@ exports[`SendCurrencyInputform should render input in token amount correctly 1`]
</div>
</div>
<button
class="c27 c28 c29"
class="c28 c29 c30"
>
Confirm send
</button>
......
......@@ -2,6 +2,7 @@ import { TransactionRequest } from '@ethersproject/abstract-provider'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { nativeOnChain } from 'constants/tokens'
import { useUniTagsEnabled } from 'featureFlags/flags/uniTags'
import { useCurrency } from 'hooks/Tokens'
import useENSAddress from 'hooks/useENSAddress'
import useENSName from 'hooks/useENSName'
......@@ -13,10 +14,12 @@ import { useMemo } from 'react'
import { SendState } from 'state/send/SendContext'
import { isAddress } from 'utilities/src/addresses'
import { useCreateTransferTransaction } from 'utils/transfer'
import { useUnitagByAddress, useUnitagByName } from 'wallet/src/features/unitags/hooks'
export interface RecipientData {
address: string
ensName?: string
unitag?: string
}
export enum SendInputError {
......@@ -38,24 +41,47 @@ export function useDerivedSendInfo(state: SendState): SendInfo {
const { account, chainId, provider } = useWeb3React()
const { exactAmountToken, exactAmountFiat, inputInFiat, inputCurrency, recipient, validatedRecipientData } = state
const isUniTagsEnabled = useUniTagsEnabled()
const { unitag: recipientInputUnitag } = useUnitagByName(
validatedRecipientData ? undefined : recipient,
isUniTagsEnabled && Boolean(recipient)
)
const recipientInputUnitagUsername = validatedRecipientData?.unitag ?? recipientInputUnitag?.username
const recipientInputUnitagAddress = recipientInputUnitag?.address?.address
const { address: recipientInputEnsAddress } = useENSAddress(validatedRecipientData ? undefined : recipient)
const validatedRecipientAddress = useMemo(() => {
if (validatedRecipientData) {
return validatedRecipientData.address
}
return isAddress(recipient) || isAddress(recipientInputEnsAddress) || undefined
}, [recipient, recipientInputEnsAddress, validatedRecipientData])
return (
isAddress(recipient) || isAddress(recipientInputEnsAddress) || isAddress(recipientInputUnitagAddress) || undefined
)
}, [recipient, recipientInputEnsAddress, recipientInputUnitagAddress, validatedRecipientData])
const { unitag } = useUnitagByAddress(
recipientInputUnitagUsername ? undefined : validatedRecipientAddress,
isUniTagsEnabled && Boolean(validatedRecipientAddress)
)
const { ENSName } = useENSName(validatedRecipientData?.ensName ? undefined : validatedRecipientAddress)
const recipientData = useMemo(() => {
if (validatedRecipientAddress) {
return {
address: validatedRecipientAddress,
ensName: recipientInputEnsAddress ? recipient : validatedRecipientData?.ensName ?? ENSName ?? undefined,
unitag: recipientInputUnitagUsername ?? unitag?.username,
}
}
return undefined
}, [ENSName, recipient, recipientInputEnsAddress, validatedRecipientData?.ensName, validatedRecipientAddress])
}, [
validatedRecipientAddress,
recipientInputEnsAddress,
recipient,
validatedRecipientData?.ensName,
ENSName,
recipientInputUnitagUsername,
unitag?.username,
])
const nativeCurrency = useCurrency('ETH')
const [inputCurrencyBalance, nativeCurencyBalance] = useCurrencyBalances(
......
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