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
a6ca7d54
Commit
a6ca7d54
authored
Nov 26, 2024
by
Uniswap Labs Service Account
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ci(release): publish latest release
parent
463d6270
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
54 additions
and
74 deletions
+54
-74
VERSION
VERSION
+1
-1
datadog.ts
apps/extension/src/app/datadog.ts
+3
-0
FallbackEthSend.tsx
...equestContent/EthSend/FallbackEthSend/FallbackEthSend.tsx
+3
-4
utils.ts
...eatures/dappRequests/requestContent/EthSend/Swap/utils.ts
+34
-15
SortButton.test.tsx
apps/mobile/src/components/explore/SortButton.test.tsx
+1
-16
useOpenBackupReminderModal.ts
apps/mobile/src/utils/useOpenBackupReminderModal.ts
+2
-11
ActionSheetDropdown.tsx
.../uniswap/src/components/dropdowns/ActionSheetDropdown.tsx
+9
-15
NetworkFilter.test.tsx
...ges/uniswap/src/components/network/NetworkFilter.test.tsx
+1
-12
No files found.
VERSION
View file @
a6ca7d54
mobile/1.39
extension/1.9.0
\ No newline at end of file
\ No newline at end of file
apps/extension/src/app/datadog.ts
View file @
a6ca7d54
...
@@ -31,6 +31,9 @@ export async function initializeDatadog(appName: string): Promise<void> {
...
@@ -31,6 +31,9 @@ export async function initializeDatadog(appName: string): Promise<void> {
// otherwise DataDog will ignore error events
// otherwise DataDog will ignore error events
event
.
view
.
url
=
event
.
view
.
url
.
replace
(
/^chrome-extension:
\/\/[
a-z
]{32}\/
/i
,
''
)
event
.
view
.
url
=
event
.
view
.
url
.
replace
(
/^chrome-extension:
\/\/[
a-z
]{32}\/
/i
,
''
)
if
(
event
.
error
&&
event
.
type
===
'
error
'
)
{
if
(
event
.
error
&&
event
.
type
===
'
error
'
)
{
if
(
event
.
error
.
source
===
'
console
'
)
{
return
false
}
Object
.
defineProperty
(
event
.
error
,
'
stack
'
,
{
Object
.
defineProperty
(
event
.
error
,
'
stack
'
,
{
value
:
event
.
error
.
stack
?.
replace
(
/chrome-extension:
\/\/[
a-z
]{32}
/gi
,
''
),
value
:
event
.
error
.
stack
?.
replace
(
/chrome-extension:
\/\/[
a-z
]{32}
/gi
,
''
),
writable
:
false
,
writable
:
false
,
...
...
apps/extension/src/app/features/dappRequests/requestContent/EthSend/FallbackEthSend/FallbackEthSend.tsx
View file @
a6ca7d54
import
{
BigNumber
}
from
'
ethers
'
import
{
useCallback
}
from
'
react
'
import
{
useCallback
}
from
'
react
'
import
{
useTranslation
}
from
'
react-i18next
'
import
{
useTranslation
}
from
'
react-i18next
'
import
{
useDappLastChainId
}
from
'
src/app/features/dapp/hooks
'
import
{
useDappLastChainId
}
from
'
src/app/features/dapp/hooks
'
import
{
DappRequestContent
}
from
'
src/app/features/dappRequests/DappRequestContent
'
import
{
DappRequestContent
}
from
'
src/app/features/dappRequests/DappRequestContent
'
import
{
useDappRequestQueueContext
}
from
'
src/app/features/dappRequests/DappRequestQueueContext
'
import
{
useDappRequestQueueContext
}
from
'
src/app/features/dappRequests/DappRequestQueueContext
'
import
{
isNonZeroBigNumber
}
from
'
src/app/features/dappRequests/requestContent/EthSend/Swap/utils
'
import
{
SendTransactionRequest
}
from
'
src/app/features/dappRequests/types/DappRequestTypes
'
import
{
SendTransactionRequest
}
from
'
src/app/features/dappRequests/types/DappRequestTypes
'
import
{
useCopyToClipboard
}
from
'
src/app/hooks/useOnCopyToClipboard
'
import
{
useCopyToClipboard
}
from
'
src/app/hooks/useOnCopyToClipboard
'
import
{
Anchor
,
Flex
,
Text
,
TouchableArea
}
from
'
ui/src
'
import
{
Anchor
,
Flex
,
Text
,
TouchableArea
}
from
'
ui/src
'
...
@@ -55,6 +55,7 @@ export function FallbackEthSendRequestContent({
...
@@ -55,6 +55,7 @@ export function FallbackEthSendRequestContent({
)
)
const
{
parsedTransactionData
}
=
useNoYoloParser
(
dappRequest
.
transaction
,
chainId
)
const
{
parsedTransactionData
}
=
useNoYoloParser
(
dappRequest
.
transaction
,
chainId
)
const
transactionCurrencies
=
useTransactionCurrencies
({
chainId
,
to
:
toAddress
,
parsedTransactionData
})
const
transactionCurrencies
=
useTransactionCurrencies
({
chainId
,
to
:
toAddress
,
parsedTransactionData
})
const
showSpendingEthDetails
=
isNonZeroBigNumber
(
sending
)
&&
chainId
return
(
return
(
<
DappRequestContent
<
DappRequestContent
...
@@ -74,9 +75,7 @@ export function FallbackEthSendRequestContent({
...
@@ -74,9 +75,7 @@ export function FallbackEthSendRequestContent({
p=
"$spacing16"
p=
"$spacing16"
width=
"100%"
width=
"100%"
>
>
{
sending
&&
!
BigNumber
.
from
(
sending
).
eq
(
0
)
&&
chainId
&&
(
{
showSpendingEthDetails
&&
<
SpendingEthDetails
chainId=
{
chainId
}
value=
{
sending
}
/>
}
<
SpendingEthDetails
chainId=
{
chainId
}
value=
{
sending
}
/>
)
}
{
transactionCurrencies
?.
map
((
currencyInfo
,
i
)
=>
(
{
transactionCurrencies
?.
map
((
currencyInfo
,
i
)
=>
(
<
SpendingDetails
<
SpendingDetails
key=
{
currencyInfo
.
currencyId
}
key=
{
currencyInfo
.
currencyId
}
...
...
apps/extension/src/app/features/dappRequests/requestContent/EthSend/Swap/utils.ts
View file @
a6ca7d54
...
@@ -162,20 +162,6 @@ function extractTokenAddresses(commands: UniversalRouterCommand[]): {
...
@@ -162,20 +162,6 @@ function extractTokenAddresses(commands: UniversalRouterCommand[]): {
return
{
inputAddress
,
outputAddress
}
return
{
inputAddress
,
outputAddress
}
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function
isZeroBigNumber
(
bigNumberObj
:
any
):
boolean
{
// The true type of bigNumberObj is { type: string; hex: string } but param.value is any type
try
{
if
(
!
bigNumberObj
)
{
return
true
}
const
bigNumber
=
BigNumber
.
from
(
bigNumberObj
.
hex
)
return
bigNumber
.
isZero
()
}
catch
(
error
)
{
return
true
// Treat as zero if there's any error
}
}
function
getTokenAmounts
(
commands
:
UniversalRouterCommand
[]):
{
function
getTokenAmounts
(
commands
:
UniversalRouterCommand
[]):
{
inputValue
:
string
inputValue
:
string
outputValue
:
string
outputValue
:
string
...
@@ -205,7 +191,9 @@ function getTokenAmounts(commands: UniversalRouterCommand[]): {
...
@@ -205,7 +191,9 @@ function getTokenAmounts(commands: UniversalRouterCommand[]): {
const
inputValue
=
firstAmountInParam
?.
value
const
inputValue
=
firstAmountInParam
?.
value
const
fallbackOutputValue
=
sweepAmountOutParam
?.
value
||
unwrapWethAmountOutParam
?.
value
const
fallbackOutputValue
=
sweepAmountOutParam
?.
value
||
unwrapWethAmountOutParam
?.
value
const
outputValue
=
const
outputValue
=
fallbackOutputValue
&&
isZeroBigNumber
(
lastAmountOutParam
?.
value
)
?
fallbackOutputValue
:
lastAmountOutParam
?.
value
fallbackOutputValue
&&
isZeroBigNumberParam
(
lastAmountOutParam
?.
value
)
?
fallbackOutputValue
:
lastAmountOutParam
?.
value
return
{
return
{
inputValue
:
inputValue
||
'
0
'
,
// Safe due to assert
inputValue
:
inputValue
||
'
0
'
,
// Safe due to assert
...
@@ -384,3 +372,34 @@ export function getTokenDetailsFromV4SwapCommands(command: UniversalRouterComman
...
@@ -384,3 +372,34 @@ export function getTokenDetailsFromV4SwapCommands(command: UniversalRouterComman
return
{
inputAddress
,
outputAddress
,
inputValue
,
outputValue
}
return
{
inputAddress
,
outputAddress
,
inputValue
,
outputValue
}
}
}
export
function
isNonZeroBigNumber
(
value
:
string
|
undefined
):
boolean
{
if
(
!
value
)
{
return
false
}
try
{
const
valueBN
=
BigNumber
.
from
(
value
)
return
!
valueBN
.
isZero
()
}
catch
{
return
false
}
}
interface
BigNumberParam
{
type
:
string
hex
:
string
}
const
isBigNumberParam
=
(
obj
:
unknown
):
obj
is
BigNumberParam
=>
typeof
obj
===
'
object
'
&&
!!
obj
&&
'
hex
'
in
obj
&&
typeof
(
obj
as
BigNumberParam
).
hex
===
'
string
'
// We have to type this as unknown because BigNumberSchema is any (as defined in apps/extension/src/app/features/dappRequests/types/EthersTypes.ts)
function
isZeroBigNumberParam
(
bigNumberObj
:
unknown
):
boolean
{
// We treat an undefined or badly formatted param as zero
if
(
!
bigNumberObj
||
!
isBigNumberParam
(
bigNumberObj
))
{
return
true
}
return
!
isNonZeroBigNumber
(
bigNumberObj
.
hex
)
}
apps/mobile/src/components/explore/SortButton.test.tsx
View file @
a6ca7d54
import
{
SortButton
}
from
'
src/components/explore/SortButton
'
import
{
SortButton
}
from
'
src/components/explore/SortButton
'
import
{
act
,
render
}
from
'
src/test/test-utils
'
import
{
render
}
from
'
src/test/test-utils
'
import
{
CustomRankingType
,
ExploreOrderBy
,
RankingType
}
from
'
wallet/src/features/wallet/types
'
import
{
CustomRankingType
,
ExploreOrderBy
,
RankingType
}
from
'
wallet/src/features/wallet/types
'
jest
.
mock
(
'
react-native-context-menu-view
'
,
()
=>
{
jest
.
mock
(
'
react-native-context-menu-view
'
,
()
=>
{
...
@@ -9,21 +9,9 @@ jest.mock('react-native-context-menu-view', () => {
...
@@ -9,21 +9,9 @@ jest.mock('react-native-context-menu-view', () => {
})
})
describe
(
'
SortButton
'
,
()
=>
{
describe
(
'
SortButton
'
,
()
=>
{
beforeEach
(()
=>
{
jest
.
useFakeTimers
()
})
afterEach
(()
=>
{
jest
.
useRealTimers
()
})
it
(
'
renders without error
'
,
()
=>
{
it
(
'
renders without error
'
,
()
=>
{
const
tree
=
render
(<
SortButton
orderBy=
{
RankingType
.
Volume
}
/>)
const
tree
=
render
(<
SortButton
orderBy=
{
RankingType
.
Volume
}
/>)
act
(
async
()
=>
{
jest
.
runAllTimers
()
})
expect
(
tree
).
toMatchSnapshot
()
expect
(
tree
).
toMatchSnapshot
()
})
})
...
@@ -46,9 +34,6 @@ describe('SortButton', () => {
...
@@ -46,9 +34,6 @@ describe('SortButton', () => {
describe
.
each
(
cases
)(
'
when ordering by $test
'
,
({
orderBy
,
label
})
=>
{
describe
.
each
(
cases
)(
'
when ordering by $test
'
,
({
orderBy
,
label
})
=>
{
it
(
`renders
${
label
}
as the selected option`
,
()
=>
{
it
(
`renders
${
label
}
as the selected option`
,
()
=>
{
const
{
queryByText
}
=
render
(<
SortButton
orderBy=
{
orderBy
}
/>)
const
{
queryByText
}
=
render
(<
SortButton
orderBy=
{
orderBy
}
/>)
act
(
async
()
=>
{
jest
.
runAllTimers
()
})
const
selectedOption
=
queryByText
(
label
)
const
selectedOption
=
queryByText
(
label
)
expect
(
selectedOption
).
toBeTruthy
()
expect
(
selectedOption
).
toBeTruthy
()
...
...
apps/mobile/src/utils/useOpenBackupReminderModal.ts
View file @
a6ca7d54
...
@@ -10,31 +10,22 @@ import { selectBackupReminderLastSeenTs } from 'wallet/src/features/behaviorHist
...
@@ -10,31 +10,22 @@ import { selectBackupReminderLastSeenTs } from 'wallet/src/features/behaviorHist
import
{
Account
}
from
'
wallet/src/features/wallet/accounts/types
'
import
{
Account
}
from
'
wallet/src/features/wallet/accounts/types
'
const
BACKUP_REMINDER_DELAY_MS
=
20
*
ONE_SECOND_MS
const
BACKUP_REMINDER_DELAY_MS
=
20
*
ONE_SECOND_MS
const
BACKUP_REMINDER_MIN_TIMEOUT_MS
=
2
*
ONE_SECOND_MS
export
function
useOpenBackupReminderModal
(
activeAccount
:
Account
):
void
{
export
function
useOpenBackupReminderModal
(
activeAccount
:
Account
):
void
{
const
dispatch
=
useDispatch
()
const
dispatch
=
useDispatch
()
const
txns
=
useSelectAddressTransactions
(
activeAccount
.
address
)
const
txns
=
useSelectAddressTransactions
(
activeAccount
.
address
)
const
{
isOpen
:
isBackupReminderModalOpen
}
=
useSelector
(
selectModalState
(
ModalName
.
BackupReminder
))
const
{
isOpen
:
isBackupReminderModalOpen
}
=
useSelector
(
selectModalState
(
ModalName
.
BackupReminder
))
const
{
isOpen
:
isBackupReminderWarningModalOpen
}
=
useSelector
(
selectModalState
(
ModalName
.
BackupReminderWarning
))
const
backupReminderLastSeenTs
=
useSelector
(
selectBackupReminderLastSeenTs
)
const
backupReminderLastSeenTs
=
useSelector
(
selectBackupReminderLastSeenTs
)
const
isSignerAccount
=
activeAccount
.
type
===
AccountType
.
SignerMnemonic
const
isSignerAccount
=
activeAccount
.
type
===
AccountType
.
SignerMnemonic
const
shouldOpenBackupReminderModal
=
const
shouldOpenBackupReminderModal
=
!
isBackupReminderModalOpen
&&
!
isBackupReminderModalOpen
&&
isSignerAccount
&&
!!
txns
&&
!
activeAccount
.
backups
!
isBackupReminderWarningModalOpen
&&
isSignerAccount
&&
!!
txns
&&
!
activeAccount
.
backups
useEffect
(()
=>
{
useEffect
(()
=>
{
if
(
shouldOpenBackupReminderModal
&&
backupReminderLastSeenTs
===
undefined
)
{
if
(
shouldOpenBackupReminderModal
&&
backupReminderLastSeenTs
===
undefined
)
{
// Get the min addedTime from the transactions (i.e. the user's first transaction)
// Get the min addedTime from the transactions (i.e. the user's first transaction)
const
minAddedTime
=
Math
.
min
(...
txns
.
map
((
txn
)
=>
txn
.
addedTime
))
const
minAddedTime
=
Math
.
min
(...
txns
.
map
((
txn
)
=>
txn
.
addedTime
))
const
remainingTimeMs
=
Math
.
max
(
const
remainingTimeMs
=
Math
.
max
(
minAddedTime
+
BACKUP_REMINDER_DELAY_MS
-
Date
.
now
(),
0
)
minAddedTime
+
BACKUP_REMINDER_DELAY_MS
-
Date
.
now
(),
BACKUP_REMINDER_MIN_TIMEOUT_MS
,
)
const
timeoutId
=
setTimeout
(()
=>
{
const
timeoutId
=
setTimeout
(()
=>
{
dispatch
(
openModal
({
name
:
ModalName
.
BackupReminder
}))
dispatch
(
openModal
({
name
:
ModalName
.
BackupReminder
}))
},
remainingTimeMs
)
},
remainingTimeMs
)
...
...
packages/uniswap/src/components/dropdowns/ActionSheetDropdown.tsx
View file @
a6ca7d54
...
@@ -20,8 +20,7 @@ import { BaseCard } from 'uniswap/src/components/BaseCard/BaseCard'
...
@@ -20,8 +20,7 @@ import { BaseCard } from 'uniswap/src/components/BaseCard/BaseCard'
import
{
Scrollbar
}
from
'
uniswap/src/components/misc/Scrollbar
'
import
{
Scrollbar
}
from
'
uniswap/src/components/misc/Scrollbar
'
import
{
MenuItemProp
}
from
'
uniswap/src/components/modals/ActionSheetModal
'
import
{
MenuItemProp
}
from
'
uniswap/src/components/modals/ActionSheetModal
'
import
{
useAppInsets
}
from
'
uniswap/src/hooks/useAppInsets
'
import
{
useAppInsets
}
from
'
uniswap/src/hooks/useAppInsets
'
import
{
isAndroid
,
isInterface
,
isTouchable
}
from
'
utilities/src/platform
'
import
{
isAndroid
,
isInterface
,
isMobileApp
,
isTouchable
}
from
'
utilities/src/platform
'
import
{
useTimeout
}
from
'
utilities/src/time/timing
'
const
DEFAULT_MIN_WIDTH
=
225
const
DEFAULT_MIN_WIDTH
=
225
...
@@ -177,22 +176,17 @@ const ActionSheetBackdropWithContent = memo(function ActionSheetBackdropWithCont
...
@@ -177,22 +176,17 @@ const ActionSheetBackdropWithContent = memo(function ActionSheetBackdropWithCont
toggleMeasurements
:
DropdownState
[
'
toggleMeasurements
'
]
toggleMeasurements
:
DropdownState
[
'
toggleMeasurements
'
]
contentProps
:
ActionSheetDropdownProps
contentProps
:
ActionSheetDropdownProps
closeOnSelect
:
boolean
closeOnSelect
:
boolean
}):
JSX
.
Element
|
null
{
}):
JSX
.
Element
{
/*
/*
There is a race condition when we switch from a view with one Portal to another view with a Portal.
We need to add key to Portal on mobile, becuase of a bug in tamagui.
It seems that if we mount a second Portal while the first is still mounted, the second would not work properly.
Remove when https://linear.app/uniswap/issue/WALL-4817/tamaguis-portal-stops-reacting-to-re-renders is done
setTimeout with 0ms is a workaround to avoid this issue for now
Remove when https://linear.app/uniswap/issue/WALL-4817 is resolved
*/
*/
const
[
shouldRender
,
setShouldRender
]
=
useState
(
false
)
const
key
=
useMemo
(
useTimeout
(()
=>
setShouldRender
(
true
),
0
)
()
=>
(
isMobileApp
?
Math
.
random
()
:
undefined
),
// eslint-disable-next-line react-hooks/exhaustive-deps
[
closeDropdown
,
styles
,
isOpen
,
toggleMeasurements
,
contentProps
,
closeOnSelect
],
if
(
!
shouldRender
)
{
)
return
null
}
return
(
return
(
<
Portal
zIndex=
{
styles
?.
dropdownZIndex
||
zIndices
.
popover
}
>
<
Portal
key=
{
key
}
zIndex=
{
styles
?.
dropdownZIndex
||
zIndices
.
popover
}
>
<
AnimatePresence
custom=
{
{
isOpen
}
}
>
<
AnimatePresence
custom=
{
{
isOpen
}
}
>
{
isOpen
&&
toggleMeasurements
&&
(
{
isOpen
&&
toggleMeasurements
&&
(
<>
<>
...
...
packages/uniswap/src/components/network/NetworkFilter.test.tsx
View file @
a6ca7d54
import
{
NetworkFilter
}
from
'
uniswap/src/components/network/NetworkFilter
'
import
{
NetworkFilter
}
from
'
uniswap/src/components/network/NetworkFilter
'
import
{
act
,
render
}
from
'
uniswap/src/test/test-utils
'
import
{
render
}
from
'
uniswap/src/test/test-utils
'
import
ReactDOM
from
'
react-dom
'
import
ReactDOM
from
'
react-dom
'
import
{
SUPPORTED_CHAIN_IDS
}
from
'
uniswap/src/features/chains/types
'
import
{
SUPPORTED_CHAIN_IDS
}
from
'
uniswap/src/features/chains/types
'
...
@@ -9,19 +9,8 @@ ReactDOM.createPortal = jest.fn((element) => {
...
@@ -9,19 +9,8 @@ ReactDOM.createPortal = jest.fn((element) => {
})
})
describe
(
NetworkFilter
,
()
=>
{
describe
(
NetworkFilter
,
()
=>
{
beforeEach
(()
=>
{
jest
.
useFakeTimers
()
})
afterEach
(()
=>
{
jest
.
useRealTimers
()
})
it
(
'
renders a NetworkFilter
'
,
()
=>
{
it
(
'
renders a NetworkFilter
'
,
()
=>
{
const
tree
=
render
(<
NetworkFilter
chainIds=
{
SUPPORTED_CHAIN_IDS
}
selectedChain=
{
null
}
onPressChain=
{
()
=>
null
}
/>)
const
tree
=
render
(<
NetworkFilter
chainIds=
{
SUPPORTED_CHAIN_IDS
}
selectedChain=
{
null
}
onPressChain=
{
()
=>
null
}
/>)
act
(
async
()
=>
{
jest
.
runAllTimers
()
})
expect
(
tree
).
toMatchSnapshot
()
expect
(
tree
).
toMatchSnapshot
()
})
})
})
})
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