Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
I
interface
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
LuckySwap
interface
Commits
ad632eb4
Commit
ad632eb4
authored
Feb 22, 2024
by
Uniswap Labs Service Account
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ci(release): publish latest release
parent
8c6c0e90
Changes
18
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
868 additions
and
170 deletions
+868
-170
RELEASE
RELEASE
+7
-13
VERSION
VERSION
+1
-1
uniTags.test.ts
apps/web/cypress/e2e/mini-portfolio/uniTags.test.ts
+69
-6
unitag.json
apps/web/cypress/fixtures/mini-portfolio/unitag.json
+3
-0
AuthenticatedHeader.tsx
.../web/src/components/AccountDrawer/AuthenticatedHeader.tsx
+3
-47
Status.tsx
apps/web/src/components/AccountDrawer/Status.tsx
+155
-0
LargeUniTagBanner.tsx
apps/web/src/components/Banner/UniTag/LargeUniTagBanner.tsx
+27
-17
index.tsx
apps/web/src/components/Banner/UniTag/index.tsx
+42
-17
ENS.tsx
apps/web/src/components/Icons/ENS.tsx
+17
-0
EthMini.tsx
apps/web/src/components/Icons/EthMini.tsx
+14
-0
UniTagProfilePicture.tsx
apps/web/src/components/UniTag/UniTagProfilePicture.tsx
+28
-0
index.tsx
apps/web/src/components/Web3Status/index.tsx
+2
-2
SendRecipientForm.test.tsx
apps/web/src/pages/Swap/Send/SendRecipientForm.test.tsx
+35
-0
SendRecipientForm.tsx
apps/web/src/pages/Swap/Send/SendRecipientForm.tsx
+34
-8
SendReviewModal.tsx
apps/web/src/pages/Swap/Send/SendReviewModal.tsx
+11
-4
SendRecipientForm.test.tsx.snap
...s/Swap/Send/__snapshots__/SendRecipientForm.test.tsx.snap
+303
-8
SendReviewModal.test.tsx.snap
...ges/Swap/Send/__snapshots__/SendReviewModal.test.tsx.snap
+88
-44
hooks.tsx
apps/web/src/state/send/hooks.tsx
+29
-3
No files found.
RELEASE
View file @
ad632eb4
IPFS hash of the deployment:
- CIDv0: `Qm
VUZGU9EBHPpn3BZRhKTQB5VZuDtv2PUetyHxxpfmzcp9
`
- CIDv1: `bafybei
dkbbgtppk3euej56wgoxllerdoggnsz3fgkirnhrgvlbmff4reii
`
- CIDv0: `Qm
NxB7dgMsLA6wASBs8xCSjKa4XAkeZNiiaf7uAG7KxPme
`
- CIDv1: `bafybei
ajdg2uit3dy2c5dbxclr7w6subg6t4fxnegfifpiskay2qlyys5u
`
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://bafybei
dkbbgtppk3euej56wgoxllerdoggnsz3fgkirnhrgvlbmff4reii
.ipfs.dweb.link/
- https://bafybei
dkbbgtppk3euej56wgoxllerdoggnsz3fgkirnhrgvlbmff4reii
.ipfs.cf-ipfs.com/
- [ipfs://Qm
VUZGU9EBHPpn3BZRhKTQB5VZuDtv2PUetyHxxpfmzcp9/](ipfs://QmVUZGU9EBHPpn3BZRhKTQB5VZuDtv2PUetyHxxpfmzcp9
/)
- https://bafybei
ajdg2uit3dy2c5dbxclr7w6subg6t4fxnegfifpiskay2qlyys5u
.ipfs.dweb.link/
- https://bafybei
ajdg2uit3dy2c5dbxclr7w6subg6t4fxnegfifpiskay2qlyys5u
.ipfs.cf-ipfs.com/
- [ipfs://Qm
NxB7dgMsLA6wASBs8xCSjKa4XAkeZNiiaf7uAG7KxPme/](ipfs://QmNxB7dgMsLA6wASBs8xCSjKa4XAkeZNiiaf7uAG7KxPme
/)
## 5.1
1.0 (2024-02-20
)
## 5.1
2.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
VERSION
View file @
ad632eb4
web/5.11.0
\ No newline at end of file
web/5.12.0
\ No newline at end of file
apps/web/cypress/e2e/mini-portfolio/uniTags.test.ts
View file @
ad632eb4
...
...
@@ -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
'
)
})
})
})
})
apps/web/cypress/fixtures/mini-portfolio/unitag.json
0 → 100644
View file @
ad632eb4
{
"username"
:
"hayden"
}
\ No newline at end of file
apps/web/src/components/AccountDrawer/AuthenticatedHeader.tsx
View file @
ad632eb4
...
...
@@ -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
}
...
...
apps/web/src/components/AccountDrawer/Status.tsx
0 → 100644
View file @
ad632eb4
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
>
)
}
apps/web/src/components/Banner/UniTag/LargeUniTagBanner.tsx
View file @
ad632eb4
...
...
@@ -10,22 +10,29 @@ import pfp4 from './assets/pfp4.png'
import
{
useUniTagBanner
}
from
'
./useUniTagBanner
'
const
StyledPopupContainer
=
styled
(
PopupContainer
)
`
height: 1
60
px;
height: 1
76
px;
width: 390px;
right: 28px;
bottom: 46px;
@media screen and (max-width:
${
BREAKPOINTS
.
md
}
px) {
height: 1
36
px;
height: 1
50
px;
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
Cont
entCont
ainer
=
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
>
<
Cont
entCont
ainer
>
<
CopyContainer
>
<
Copy
large
/>
</
CopyContainer
>
<
ButtonsContainer
>
<
Buttons
large
onAccept=
{
handleAccept
}
onReject=
{
handleReject
}
/>
</
ButtonsContainer
>
</
Container
>
</
Cont
entCont
ainer
>
<
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
>
)
...
...
apps/web/src/components/Banner/UniTag/index.tsx
View file @
ad632eb4
...
...
@@ -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
'
:
'
4
px
'
}
>
<
Row
gap=
{
large
?
'
12px
'
:
'
8
px
'
}
>
<
AcceptButton
data
-
testid=
"unitag-banner-accept-button"
size=
{
ButtonSize
.
medium
}
...
...
@@ -208,15 +231,17 @@ export function UniTagBanner() {
return (
<Container justify="space-between">
<Co
lumn
gap="16px">
<Co
ntentContainer
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>
)
}
apps/web/src/components/Icons/ENS.tsx
0 → 100644
View file @
ad632eb4
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
>
)
}
apps/web/src/components/Icons/EthMini.tsx
0 → 100644
View file @
ad632eb4
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
>
)
}
apps/web/src/components/UniTag/UniTagProfilePicture.tsx
0 → 100644
View file @
ad632eb4
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
>
)
}
apps/web/src/components/Web3Status/index.tsx
View file @
ad632eb4
...
...
@@ -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;
...
...
apps/web/src/pages/Swap/Send/SendRecipientForm.test.tsx
View file @
ad632eb4
...
...
@@ -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
()
})
})
apps/web/src/pages/Swap/Send/SendRecipientForm.tsx
View file @
ad632eb4
...
...
@@ -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
>
)
}
...
...
apps/web/src/pages/Swap/Send/SendReviewModal.tsx
View file @
ad632eb4
...
...
@@ -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} />
...
...
apps/web/src/pages/Swap/Send/__snapshots__/SendRecipientForm.test.tsx.snap
View file @
ad632eb4
...
...
@@ -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;
}
.c
9
{
.c
10
{
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;
}
.c1
0
:hover {
.c1
1
:hover {
opacity: 0.6;
}
.c1
0
:active {
.c1
1
:active {
opacity: 0.4;
}
...
...
@@ -333,19 +624,23 @@ exports[`SendCurrencyInputform should render correctly with verified recipient 1
class="c0"
>
<div
class="c
8 css-n8z49y
"
class="c
2 c8
"
>
hayden.eth
<div
class="c9 css-n8z49y"
>
hayden.eth
</div>
</div>
<div
class="c
9
css-obwv3p"
class="c
10
css-obwv3p"
>
0x9984...9103
</div>
</div>
</div>
<svg
class="c1
0
"
class="c1
1
"
fill="none"
height="20"
stroke="currentColor"
...
...
apps/web/src/pages/Swap/Send/__snapshots__/SendReviewModal.test.tsx.snap
View file @
ad632eb4
...
...
@@ -15,14 +15,14 @@ exports[`SendCurrencyInputform should render input in fiat correctly 1`] = `
min-width: 0;
}
.c2
4
{
.c2
5
{
box-sizing: border-box;
margin: 0;
min-width: 0;
width: 100%;
}
.c2
5
{
.c2
6
{
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;
}
.c2
7
{
.c2
8
{
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;
}
.c2
3
{
.c2
4
{
width: 100%;
height: 1px;
background-color: #22222212;
...
...
@@ -228,7 +246,7 @@ exports[`SendCurrencyInputform should render input in fiat correctly 1`] = `
border-radius: 50%;
}
.c2
8
{
.c2
9
{
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);
}
.c2
8
:disabled {
.c2
9
:disabled {
opacity: 50%;
cursor: auto;
pointer-events: none;
}
.c2
8
> * {
.c2
9
> * {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.c2
8
> a {
.c2
9
> a {
-webkit-text-decoration: none;
text-decoration: none;
}
.c
29
{
.c
30
{
background-color: #FC72FF;
font-size: 20px;
font-weight: 535;
...
...
@@ -293,21 +311,21 @@ exports[`SendCurrencyInputform should render input in fiat correctly 1`] = `
color: #FFFFFF;
}
.c
29
:focus {
.c
30
:focus {
box-shadow: 0 0 0 1pt #fb58ff;
background-color: #fb58ff;
}
.c
29
:hover {
.c
30
:hover {
background-color: #fb58ff;
}
.c
29
:active {
.c
30
:active {
box-shadow: 0 0 0 1pt #fb3fff;
background-color: #fb3fff;
}
.c
29
:disabled {
.c
30
:disabled {
background-color: #22222212;
color: #7D7D7D;
cursor: auto;
...
...
@@ -407,7 +425,7 @@ exports[`SendCurrencyInputform should render input in fiat correctly 1`] = `
align-items: center;
}
.c2
2
{
.c2
3
{
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="c
7 css-15popx1
"
class="c
5 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="c2
2
"
class="c2
3
"
>
<span>
<div
...
...
@@ -643,10 +665,10 @@ exports[`SendCurrencyInputform should render input in fiat correctly 1`] = `
</div>
</div>
<div
class="c2
3
"
class="c2
4
"
/>
<div
class="c2
4
c17"
class="c2
5
c17"
width="100%"
>
<div
...
...
@@ -655,7 +677,7 @@ exports[`SendCurrencyInputform should render input in fiat correctly 1`] = `
Network cost
</div>
<div
class="c2
5 c26
"
class="c2
6 c27
"
width="min-content"
>
<svg
...
...
@@ -697,7 +719,7 @@ exports[`SendCurrencyInputform should render input in fiat correctly 1`] = `
</div>
</div>
<button
class="c2
7 c28 c29
"
class="c2
8 c29 c30
"
>
Confirm send
</button>
...
...
@@ -719,14 +741,14 @@ exports[`SendCurrencyInputform should render input in token amount correctly 1`]
min-width: 0;
}
.c2
4
{
.c2
5
{
box-sizing: border-box;
margin: 0;
min-width: 0;
width: 100%;
}
.c2
5
{
.c2
6
{
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;
}
.c2
7
{
.c2
8
{
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;
}
.c2
3
{
.c2
4
{
width: 100%;
height: 1px;
background-color: #22222212;
...
...
@@ -932,7 +972,7 @@ exports[`SendCurrencyInputform should render input in token amount correctly 1`]
border-radius: 50%;
}
.c2
8
{
.c2
9
{
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);
}
.c2
8
:disabled {
.c2
9
:disabled {
opacity: 50%;
cursor: auto;
pointer-events: none;
}
.c2
8
> * {
.c2
9
> * {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.c2
8
> a {
.c2
9
> a {
-webkit-text-decoration: none;
text-decoration: none;
}
.c
29
{
.c
30
{
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;
}
.c
29
:focus {
.c
30
:focus {
box-shadow: 0 0 0 1pt #fb58ff;
background-color: #fb58ff;
}
.c
29
:hover {
.c
30
:hover {
background-color: #fb58ff;
}
.c
29
:active {
.c
30
:active {
box-shadow: 0 0 0 1pt #fb3fff;
background-color: #fb3fff;
}
.c
29
:disabled {
.c
30
: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;
}
.c2
2
{
.c2
3
{
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="c
7 css-15popx1
"
class="c
5 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="c2
2
"
class="c2
3
"
>
<span>
<div
...
...
@@ -1347,10 +1391,10 @@ exports[`SendCurrencyInputform should render input in token amount correctly 1`]
</div>
</div>
<div
class="c2
3
"
class="c2
4
"
/>
<div
class="c2
4
c17"
class="c2
5
c17"
width="100%"
>
<div
...
...
@@ -1359,7 +1403,7 @@ exports[`SendCurrencyInputform should render input in token amount correctly 1`]
Network cost
</div>
<div
class="c2
5 c26
"
class="c2
6 c27
"
width="min-content"
>
<svg
...
...
@@ -1401,7 +1445,7 @@ exports[`SendCurrencyInputform should render input in token amount correctly 1`]
</div>
</div>
<button
class="c2
7 c28 c29
"
class="c2
8 c29 c30
"
>
Confirm send
</button>
...
...
apps/web/src/state/send/hooks.tsx
View file @
ad632eb4
...
...
@@ -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
(
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment