ci(release): publish latest release

parent fbe0233c
* @uniswap/web-admins
IPFS hash of the deployment: We are back with some new new updates! Here’s the latest:
- CIDv0: `Qmb16dcqcbFFjG7vkpfKEeZp4fNHBcbzXwuPLW92MQNRAx`
- CIDv1: `bafybeif4ewp6t3m3h2yfzmgwe6o3lcccxeec5asf5xkezonc6vwcpxw5de`
The latest release is always mirrored at [app.uniswap.org](https://app.uniswap.org). UniswapX is live: We’ve integrated the UniswapX protocol, which aggregates liquidity across onchain and offchain sources for better quotes.
You can also access the Uniswap Interface from an IPFS gateway. Easy import to Uniswap Extension: Onboard onto our new Chrome extension wallet easily by scanning a QR code with your Uniswap Mobile App.
**BEWARE**: The Uniswap interface uses [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) to remember your settings, such as which tokens you have imported.
**You should always use an IPFS gateway that enforces origin separation**, or our hosted deployment of the latest release at [app.uniswap.org](https://app.uniswap.org).
Your Uniswap settings are never remembered across different URLs.
IPFS gateways: Transaction Details: Press anything on the Activity Screen and see more robust details about any of your transactions (swaps, sends, NFTs, etc).
- https://bafybeif4ewp6t3m3h2yfzmgwe6o3lcccxeec5asf5xkezonc6vwcpxw5de.ipfs.dweb.link/
- https://bafybeif4ewp6t3m3h2yfzmgwe6o3lcccxeec5asf5xkezonc6vwcpxw5de.ipfs.cf-ipfs.com/
- [ipfs://Qmb16dcqcbFFjG7vkpfKEeZp4fNHBcbzXwuPLW92MQNRAx/](ipfs://Qmb16dcqcbFFjG7vkpfKEeZp4fNHBcbzXwuPLW92MQNRAx/)
### 5.40.3 (2024-07-25)
Other changes:
- Onboarding improvements
- Various bug fixes and performance improvements
web/5.40.3 mobile/1.31.1
\ No newline at end of file \ No newline at end of file
...@@ -131,17 +131,17 @@ android { ...@@ -131,17 +131,17 @@ android {
dev { dev {
isDefault(true) isDefault(true)
applicationIdSuffix ".dev" applicationIdSuffix ".dev"
versionName "1.31" versionName "1.31.1"
dimension "variant" dimension "variant"
} }
beta { beta {
applicationIdSuffix ".beta" applicationIdSuffix ".beta"
versionName "1.31" versionName "1.31.1"
dimension "variant" dimension "variant"
} }
prod { prod {
dimension "variant" dimension "variant"
versionName "1.31" versionName "1.31.1"
} }
} }
......
...@@ -2534,7 +2534,7 @@ ...@@ -2534,7 +2534,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.31; MARKETING_VERSION = 1.31.1;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
...@@ -2580,7 +2580,7 @@ ...@@ -2580,7 +2580,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.31; MARKETING_VERSION = 1.31.1;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.widgets; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.widgets;
...@@ -2626,7 +2626,7 @@ ...@@ -2626,7 +2626,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.31; MARKETING_VERSION = 1.31.1;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.dev.widgets; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.dev.widgets;
...@@ -2672,7 +2672,7 @@ ...@@ -2672,7 +2672,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.31; MARKETING_VERSION = 1.31.1;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.beta.widgets; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.beta.widgets;
...@@ -2714,7 +2714,7 @@ ...@@ -2714,7 +2714,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.31; MARKETING_VERSION = 1.31.1;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
...@@ -2757,7 +2757,7 @@ ...@@ -2757,7 +2757,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.31; MARKETING_VERSION = 1.31.1;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.WidgetIntentExtension; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.WidgetIntentExtension;
...@@ -2800,7 +2800,7 @@ ...@@ -2800,7 +2800,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.31; MARKETING_VERSION = 1.31.1;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.dev.WidgetIntentExtension; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.dev.WidgetIntentExtension;
...@@ -2843,7 +2843,7 @@ ...@@ -2843,7 +2843,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.31; MARKETING_VERSION = 1.31.1;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.beta.WidgetIntentExtension; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.beta.WidgetIntentExtension;
...@@ -2879,7 +2879,7 @@ ...@@ -2879,7 +2879,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.31; MARKETING_VERSION = 1.31.1;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"$(inherited)", "$(inherited)",
"-ObjC", "-ObjC",
...@@ -2917,7 +2917,7 @@ ...@@ -2917,7 +2917,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.31; MARKETING_VERSION = 1.31.1;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"$(inherited)", "$(inherited)",
"-ObjC", "-ObjC",
...@@ -3103,7 +3103,7 @@ ...@@ -3103,7 +3103,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.31; MARKETING_VERSION = 1.31.1;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
...@@ -3147,7 +3147,7 @@ ...@@ -3147,7 +3147,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.31; MARKETING_VERSION = 1.31.1;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.OneSignalNotificationServiceExtension; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.OneSignalNotificationServiceExtension;
...@@ -3251,7 +3251,7 @@ ...@@ -3251,7 +3251,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.31; MARKETING_VERSION = 1.31.1;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"$(inherited)", "$(inherited)",
"-ObjC", "-ObjC",
...@@ -3322,7 +3322,7 @@ ...@@ -3322,7 +3322,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.31; MARKETING_VERSION = 1.31.1;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.beta.OneSignalNotificationServiceExtension; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.beta.OneSignalNotificationServiceExtension;
...@@ -3426,7 +3426,7 @@ ...@@ -3426,7 +3426,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.31; MARKETING_VERSION = 1.31.1;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"$(inherited)", "$(inherited)",
"-ObjC", "-ObjC",
...@@ -3497,7 +3497,7 @@ ...@@ -3497,7 +3497,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.31; MARKETING_VERSION = 1.31.1;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.dev.OneSignalNotificationServiceExtension; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.dev.OneSignalNotificationServiceExtension;
......
...@@ -66,6 +66,7 @@ import { ...@@ -66,6 +66,7 @@ import {
v63Schema, v63Schema,
v64Schema, v64Schema,
v65Schema, v65Schema,
v66Schema,
v6Schema, v6Schema,
v7Schema, v7Schema,
v8Schema, v8Schema,
...@@ -1407,4 +1408,11 @@ describe('Redux state migrations', () => { ...@@ -1407,4 +1408,11 @@ describe('Redux state migrations', () => {
const v66 = migrations[66] const v66 = migrations[66]
testActivatePendingAccounts(v66, v65Schema) testActivatePendingAccounts(v66, v65Schema)
}) })
it('migrates from v66 to v67', () => {
const v66Stub = { ...v66Schema }
const v67 = migrations[67](v66Stub)
expect(v67.behaviorHistory.extensionOnboardingState).toBe(ExtensionOnboardingState.Undefined)
})
}) })
...@@ -877,6 +877,18 @@ export const migrations = { ...@@ -877,6 +877,18 @@ export const migrations = {
65: addRoutingFieldToTransactions, 65: addRoutingFieldToTransactions,
66: activatePendingAccounts, 66: activatePendingAccounts,
67: function resetOnboardingStateForGA(state: any) {
const newState = { ...state }
// Reset state so that everyone gets the new promo banner even if theyve dismissed the beta version.
newState.behaviorHistory = {
...state.behaviorHistory,
extensionOnboardingState: ExtensionOnboardingState.Undefined,
}
return newState
},
} }
export const MOBILE_STATE_VERSION = 66 export const MOBILE_STATE_VERSION = 67
...@@ -505,6 +505,8 @@ export const v65Schema = { ...v64Schema } ...@@ -505,6 +505,8 @@ export const v65Schema = { ...v64Schema }
export const v66Schema = { ...v65Schema } export const v66Schema = { ...v65Schema }
export const v67Schema = { ...v66Schema }
// TODO: [MOB-201] use function with typed output when API reducers are removed from rootReducer // TODO: [MOB-201] use function with typed output when API reducers are removed from rootReducer
// export const getSchema = (): RootState => v0Schema // export const getSchema = (): RootState => v0Schema
export const getSchema = (): typeof v65Schema => v65Schema export const getSchema = (): typeof v67Schema => v67Schema
...@@ -102,7 +102,7 @@ export function WalletConnectRequestModalContent({ ...@@ -102,7 +102,7 @@ export function WalletConnectRequestModalContent({
<Flex gap="$spacing8" mb="$spacing12" pt="$spacing20" px="$spacing4"> <Flex gap="$spacing8" mb="$spacing12" pt="$spacing20" px="$spacing4">
<NetworkFeeFooter chainId={chainId} gasFeeUSD={hasGasFee ? gasFeeUSD : '0'} showNetworkLogo={hasGasFee} /> <NetworkFeeFooter chainId={chainId} gasFeeUSD={hasGasFee ? gasFeeUSD : '0'} showNetworkLogo={hasGasFee} />
<AddressFooter activeAccountAddress={request.account} /> <AddressFooter activeAccountAddress={request.account} px="$spacing8" />
</Flex> </Flex>
{!hasSufficientFunds && ( {!hasSufficientFunds && (
......
...@@ -141,7 +141,7 @@ const SwitchAccountRow = ({ activeAddress, setModalState }: SwitchAccountProps): ...@@ -141,7 +141,7 @@ const SwitchAccountRow = ({ activeAddress, setModalState }: SwitchAccountProps):
return ( return (
<TouchableArea disabled={!accountIsSwitchable} m="$none" testID={TestID.WCDappSwitchAccount} onPress={onPress}> <TouchableArea disabled={!accountIsSwitchable} m="$none" testID={TestID.WCDappSwitchAccount} onPress={onPress}>
<Flex row justifyContent="space-between"> <Flex row justifyContent="space-between">
<AddressFooter activeAccountAddress={activeAddress} /> <AddressFooter activeAccountAddress={activeAddress} px="$spacing8" />
{accountIsSwitchable && <RotatableChevron color="$neutral2" direction="down" height={16} width={16} />} {accountIsSwitchable && <RotatableChevron color="$neutral2" direction="down" height={16} width={16} />}
</Flex> </Flex>
</TouchableArea> </TouchableArea>
......
...@@ -48,14 +48,13 @@ export const ActivityTab = memo( ...@@ -48,14 +48,13 @@ export const ActivityTab = memo(
dispatch(openModal({ name: ModalName.WalletConnectScan, initialState: ScannerModalState.WalletQr })) dispatch(openModal({ name: ModalName.WalletConnectScan, initialState: ScannerModalState.WalletQr }))
} }
const { maybeLoaderComponent, maybeEmptyComponent, renderActivityItem, sectionData, keyExtractor } = const { maybeEmptyComponent, renderActivityItem, sectionData, keyExtractor } = useActivityData({
useActivityData({ owner,
owner, authTrigger: requiresBiometrics ? biometricsTrigger : undefined,
authTrigger: requiresBiometrics ? biometricsTrigger : undefined, isExternalProfile,
isExternalProfile, emptyComponentStyle: containerProps?.emptyComponentStyle,
emptyComponentStyle: containerProps?.emptyComponentStyle, onPressEmptyState: onPressReceive,
onPressEmptyState: onPressReceive, })
})
const refreshControl = useMemo(() => { const refreshControl = useMemo(() => {
return ( return (
...@@ -77,12 +76,8 @@ export const ActivityTab = memo( ...@@ -77,12 +76,8 @@ export const ActivityTab = memo(
ref={ref as ForwardedRef<Animated.FlatList<any>>} ref={ref as ForwardedRef<Animated.FlatList<any>>}
ListEmptyComponent={maybeEmptyComponent} ListEmptyComponent={maybeEmptyComponent}
// we add a footer to cover any possible space, so user can scroll the top menu all the way to the top // we add a footer to cover any possible space, so user can scroll the top menu all the way to the top
ListFooterComponent={ ListFooterComponent={isExternalProfile ? null : adaptiveFooter}
<> // `sectionData` will be either an array of transactions or an array of loading skeletons
{maybeLoaderComponent}
{isExternalProfile ? null : adaptiveFooter}
</>
}
data={sectionData} data={sectionData}
estimatedItemSize={ESTIMATED_ITEM_SIZE} estimatedItemSize={ESTIMATED_ITEM_SIZE}
initialNumToRender={20} initialNumToRender={20}
......
...@@ -16,7 +16,7 @@ function key(item: FORServiceProvider): string { ...@@ -16,7 +16,7 @@ function key(item: FORServiceProvider): string {
} }
const CEX_ICON_SIZE = iconSizes.icon36 const CEX_ICON_SIZE = iconSizes.icon36
const CEX_ICON_BORDER_RADIUS = 12 const CEX_ICON_BORDER_RADIUS = 8
function CEXItemWrapper({ function CEXItemWrapper({
serviceProvider, serviceProvider,
......
...@@ -16,6 +16,7 @@ import { RecoveryWalletInfo, useOnDeviceRecoveryData } from 'src/screens/Import/ ...@@ -16,6 +16,7 @@ import { RecoveryWalletInfo, useOnDeviceRecoveryData } from 'src/screens/Import/
import { hideSplashScreen } from 'src/utils/splashScreen' import { hideSplashScreen } from 'src/utils/splashScreen'
import { DynamicConfigs, OnDeviceRecoveryConfigKey } from 'uniswap/src/features/gating/configs' import { DynamicConfigs, OnDeviceRecoveryConfigKey } from 'uniswap/src/features/gating/configs'
import { useDynamicConfigValue } from 'uniswap/src/features/gating/hooks' import { useDynamicConfigValue } from 'uniswap/src/features/gating/hooks'
import Trace from 'uniswap/src/features/telemetry/Trace'
import { MobileEventName } from 'uniswap/src/features/telemetry/constants' import { MobileEventName } from 'uniswap/src/features/telemetry/constants'
import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send'
import { ImportType, OnboardingEntryPoint } from 'uniswap/src/types/onboarding' import { ImportType, OnboardingEntryPoint } from 'uniswap/src/types/onboarding'
...@@ -133,6 +134,7 @@ export function AppLoadingScreen({ navigation }: Props): JSX.Element | null { ...@@ -133,6 +134,7 @@ export function AppLoadingScreen({ navigation }: Props): JSX.Element | null {
20, 20,
) )
// Used to stop this running multiple times during navigation
const [finished, setFinished] = useState(false) const [finished, setFinished] = useState(false)
const [mnemonicIds, setMnemonicIds] = useState<string[]>() const [mnemonicIds, setMnemonicIds] = useState<string[]>()
...@@ -148,7 +150,12 @@ export function AppLoadingScreen({ navigation }: Props): JSX.Element | null { ...@@ -148,7 +150,12 @@ export function AppLoadingScreen({ navigation }: Props): JSX.Element | null {
useEffect(() => { useEffect(() => {
Keyring.getMnemonicIds() Keyring.getMnemonicIds()
.then((storedMnemonicIds) => setMnemonicIds(storedMnemonicIds)) .then((storedMnemonicIds) => {
setMnemonicIds(storedMnemonicIds)
sendAnalyticsEvent(MobileEventName.AutomatedOnDeviceRecoveryMnemonicsFound, {
mnemonicCount: storedMnemonicIds.length,
})
})
.catch(() => { .catch(() => {
logger.error('Failed to load mnemonic ids', { logger.error('Failed to load mnemonic ids', {
tags: { file: 'AppLoadingScreen', function: 'getMnemonicIds' }, tags: { file: 'AppLoadingScreen', function: 'getMnemonicIds' },
...@@ -170,36 +177,41 @@ export function AppLoadingScreen({ navigation }: Props): JSX.Element | null { ...@@ -170,36 +177,41 @@ export function AppLoadingScreen({ navigation }: Props): JSX.Element | null {
// Logic to determine what screen to show on app load // Logic to determine what screen to show on app load
useEffect(() => { useEffect(() => {
async function checkOnDeviceRecovery(): Promise<void> { if (!mnemonicIds || finished) {
if (!mnemonicIds || loading || finished) { return
}
const mnemonicIdsCount = mnemonicIds.length
const firstMnemonicId = mnemonicIds[0]
if (mnemonicIdsCount === 1 && firstMnemonicId) {
if (loading) {
return return
} }
const mnemonicIdsCount = mnemonicIds.length
const firstMnemonicId = mnemonicIds[0]
// Used to stop this running multiple times as the following logic is async
setFinished(true) setFinished(true)
if (mnemonicIdsCount === 1 && firstMnemonicId) { sendAnalyticsEvent(MobileEventName.AutomatedOnDeviceRecoverySingleMnemonicFetched, {
if (significantRecoveryWalletInfos.length) { balance: significantRecoveryWalletInfos[0]?.balance ?? 0,
finishRecovery(firstMnemonicId, significantRecoveryWalletInfos) hasUnitag: Boolean(significantRecoveryWalletInfos[0]?.unitag),
} else { hasENS: Boolean(significantRecoveryWalletInfos[0]?.ensName),
navigateToLanding() })
} if (significantRecoveryWalletInfos.length) {
} else if (mnemonicIdsCount > 1) { finishRecovery(firstMnemonicId, significantRecoveryWalletInfos)
navigation.replace(OnboardingScreens.OnDeviceRecovery, {
importType: ImportType.OnDeviceRecovery,
entryPoint: OnboardingEntryPoint.FreshInstallOrReplace,
mnemonicIds: mnemonicIds.slice(0, maxMnemonicsToLoad),
})
} else { } else {
navigateToLanding() navigateToLanding()
} }
} else if (mnemonicIdsCount > 1) {
setFinished(true)
navigation.replace(OnboardingScreens.OnDeviceRecovery, {
importType: ImportType.OnDeviceRecovery,
entryPoint: OnboardingEntryPoint.FreshInstallOrReplace,
mnemonicIds: mnemonicIds.slice(0, maxMnemonicsToLoad),
})
} else {
setFinished(true)
navigateToLanding()
} }
checkOnDeviceRecovery().catch(() => {
logger.warn('AppLoadingScreen', 'checkOnDeviceRecovery', 'Failed to check on device recovery')
})
}, [ }, [
dispatch, dispatch,
finishRecovery, finishRecovery,
...@@ -212,5 +224,9 @@ export function AppLoadingScreen({ navigation }: Props): JSX.Element | null { ...@@ -212,5 +224,9 @@ export function AppLoadingScreen({ navigation }: Props): JSX.Element | null {
significantRecoveryWalletInfos, significantRecoveryWalletInfos,
]) ])
return <SplashScreen /> return (
<Trace logImpression screen={OnboardingScreens.AppLoading}>
<SplashScreen />
</Trace>
)
} }
import { NativeStackScreenProps } from '@react-navigation/native-stack' import { NativeStackScreenProps } from '@react-navigation/native-stack'
import { SharedEventName } from '@uniswap/analytics-events'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import React, { useCallback, useEffect, useState } from 'react' import React, { useCallback, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
...@@ -18,7 +19,8 @@ import { iconSizes } from 'ui/src/theme' ...@@ -18,7 +19,8 @@ import { iconSizes } from 'ui/src/theme'
import { DynamicConfigs, OnDeviceRecoveryConfigKey } from 'uniswap/src/features/gating/configs' import { DynamicConfigs, OnDeviceRecoveryConfigKey } from 'uniswap/src/features/gating/configs'
import { useDynamicConfigValue } from 'uniswap/src/features/gating/hooks' import { useDynamicConfigValue } from 'uniswap/src/features/gating/hooks'
import Trace from 'uniswap/src/features/telemetry/Trace' import Trace from 'uniswap/src/features/telemetry/Trace'
import { ModalName } from 'uniswap/src/features/telemetry/constants' import { ElementName, ModalName } from 'uniswap/src/features/telemetry/constants'
import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send'
import { TestID } from 'uniswap/src/test/fixtures/testIDs' import { TestID } from 'uniswap/src/test/fixtures/testIDs'
import { ImportType, OnboardingEntryPoint } from 'uniswap/src/types/onboarding' import { ImportType, OnboardingEntryPoint } from 'uniswap/src/types/onboarding'
import { OnboardingScreens } from 'uniswap/src/types/screens/mobile' import { OnboardingScreens } from 'uniswap/src/types/screens/mobile'
...@@ -105,6 +107,10 @@ export function OnDeviceRecoveryScreen({ ...@@ -105,6 +107,10 @@ export function OnDeviceRecoveryScreen({
setSelectedMnemonicId(undefined) setSelectedMnemonicId(undefined)
setSelectedRecoveryWalletInfos([]) setSelectedRecoveryWalletInfos([])
setShowConfirmationModal(false) setShowConfirmationModal(false)
sendAnalyticsEvent(SharedEventName.ELEMENT_CLICKED, {
element: ElementName.OnDeviceRecoveryModalCancel,
})
} }
const onPressConfirm = async (): Promise<void> => { const onPressConfirm = async (): Promise<void> => {
...@@ -112,6 +118,10 @@ export function OnDeviceRecoveryScreen({ ...@@ -112,6 +118,10 @@ export function OnDeviceRecoveryScreen({
await clearNonSelectedStoredAddresses() await clearNonSelectedStoredAddresses()
setShowConfirmationModal(false) setShowConfirmationModal(false)
sendAnalyticsEvent(SharedEventName.ELEMENT_CLICKED, {
element: ElementName.OnDeviceRecoveryModalConfirm,
})
if (selectedMnemonicId && selectedRecoveryWalletInfos.length) { if (selectedMnemonicId && selectedRecoveryWalletInfos.length) {
setRecoveredImportedAccounts( setRecoveredImportedAccounts(
selectedRecoveryWalletInfos.map((walletInfo, index): SignerMnemonicAccount => { selectedRecoveryWalletInfos.map((walletInfo, index): SignerMnemonicAccount => {
...@@ -187,6 +197,10 @@ export function OnDeviceRecoveryScreen({ ...@@ -187,6 +197,10 @@ export function OnDeviceRecoveryScreen({
setSelectedMnemonicId(mnemonicId) setSelectedMnemonicId(mnemonicId)
setSelectedRecoveryWalletInfos(recoveryAddressesInfos) setSelectedRecoveryWalletInfos(recoveryAddressesInfos)
setShowConfirmationModal(true) setShowConfirmationModal(true)
sendAnalyticsEvent(SharedEventName.ELEMENT_CLICKED, {
element: ElementName.OnDeviceRecoveryWallet,
})
}} }}
onPressViewRecoveryPhrase={() => { onPressViewRecoveryPhrase={() => {
navigation.navigate(OnboardingScreens.OnDeviceRecoveryViewSeedPhrase, { navigation.navigate(OnboardingScreens.OnDeviceRecoveryViewSeedPhrase, {
...@@ -214,11 +228,13 @@ export function OnDeviceRecoveryScreen({ ...@@ -214,11 +228,13 @@ export function OnDeviceRecoveryScreen({
<Text color="$neutral3" variant="body3" onPress={onPressOtherWallet}> <Text color="$neutral3" variant="body3" onPress={onPressOtherWallet}>
{t('onboarding.import.onDeviceRecovery.other_options.label')} {t('onboarding.import.onDeviceRecovery.other_options.label')}
</Text> </Text>
<TouchableArea alignItems="center" hitSlop={16} mb="$spacing12" testID={TestID.WatchWallet}> <Trace logPress element={ElementName.OnDeviceRecoveryImportOther}>
<Text color="$accent1" variant="buttonLabel3" onPress={onPressOtherWallet}> <TouchableArea alignItems="center" hitSlop={16} mb="$spacing12" testID={TestID.WatchWallet}>
{t('onboarding.import.onDeviceRecovery.other_options')} <Text color="$accent1" variant="buttonLabel3" onPress={onPressOtherWallet}>
</Text> {t('onboarding.import.onDeviceRecovery.other_options')}
</TouchableArea> </Text>
</TouchableArea>
</Trace>
</Flex> </Flex>
</Flex> </Flex>
</Flex> </Flex>
......
...@@ -31,21 +31,21 @@ type Props = NativeStackScreenProps<OnboardingStackParamList, OnboardingScreens. ...@@ -31,21 +31,21 @@ type Props = NativeStackScreenProps<OnboardingStackParamList, OnboardingScreens.
const LIVE_CHECK_DELAY = 1000 const LIVE_CHECK_DELAY = 1000
const validateForm = ({ const validateForm = ({
isAddress, validAddress,
name, name,
walletExists, walletExists,
loading, loading,
isSmartContractAddress, isSmartContractAddress,
isValidSmartContract, isValidSmartContract,
}: { }: {
isAddress: string | null validAddress: string | null
name: string | null name: string | null
walletExists: boolean walletExists: boolean
loading: boolean loading: boolean
isSmartContractAddress: boolean isSmartContractAddress: boolean
isValidSmartContract: boolean isValidSmartContract: boolean
}): boolean => { }): boolean => {
return (!!isAddress || !!name) && !walletExists && !loading && (!isSmartContractAddress || isValidSmartContract) return (!!validAddress || !!name) && !walletExists && !loading && (!isSmartContractAddress || isValidSmartContract)
} }
const getErrorText = ({ const getErrorText = ({
...@@ -85,28 +85,28 @@ export function WatchWalletScreen({ navigation, route: { params } }: Props): JSX ...@@ -85,28 +85,28 @@ export function WatchWalletScreen({ navigation, route: { params } }: Props): JSX
const normalizedValue = normalizeTextInput(value ?? '') const normalizedValue = normalizeTextInput(value ?? '')
const hasSuffixIncluded = normalizedValue.includes('.') const hasSuffixIncluded = normalizedValue.includes('.')
const { address: resolvedAddress, name } = useENS(UniverseChainId.Mainnet, normalizedValue, !hasSuffixIncluded) const { address: resolvedAddress, name } = useENS(UniverseChainId.Mainnet, normalizedValue, !hasSuffixIncluded)
const isAddress = getValidAddress(normalizedValue, true, false) const validAddress = getValidAddress(normalizedValue, true, false)
const { isSmartContractAddress, loading } = useIsSmartContractAddress( const { isSmartContractAddress, loading } = useIsSmartContractAddress(
(isAddress || resolvedAddress) ?? undefined, (validAddress || resolvedAddress) ?? undefined,
UniverseChainId.Mainnet, UniverseChainId.Mainnet,
) )
// Allow smart contracts with non-null balances // Allow smart contracts with non-null balances
const { data: balancesById } = usePortfolioBalances({ const { data: balancesById } = usePortfolioBalances({
address: isSmartContractAddress ? (isAddress || resolvedAddress) ?? undefined : undefined, address: isSmartContractAddress ? (validAddress || resolvedAddress) ?? undefined : undefined,
fetchPolicy: 'cache-and-network', fetchPolicy: 'cache-and-network',
}) })
const isValidSmartContract = isSmartContractAddress && !!balancesById const isValidSmartContract = isSmartContractAddress && !!balancesById
const onCompleteOnboarding = useCompleteOnboardingCallback(params) const onCompleteOnboarding = useCompleteOnboardingCallback(params)
const walletExists = Object.keys(initialAccounts).some( const walletExists = Object.keys(initialAccounts.current).some(
(accountAddress) => (accountAddress) =>
areAddressesEqual(accountAddress, resolvedAddress) || areAddressesEqual(accountAddress, normalizedValue), areAddressesEqual(accountAddress, resolvedAddress) || areAddressesEqual(accountAddress, validAddress),
) )
// Form validation. // Form validation.
const isValid = validateForm({ const isValid = validateForm({
isAddress, validAddress,
name, name,
walletExists, walletExists,
loading, loading,
...@@ -159,7 +159,7 @@ export function WatchWalletScreen({ navigation, route: { params } }: Props): JSX ...@@ -159,7 +159,7 @@ export function WatchWalletScreen({ navigation, route: { params } }: Props): JSX
blurOnSubmit blurOnSubmit
errorMessage={errorText} errorMessage={errorText}
inputAlignment="flex-start" inputAlignment="flex-start"
inputSuffix={isAddress || hasSuffixIncluded ? undefined : '.eth'} inputSuffix={validAddress || hasSuffixIncluded ? undefined : '.eth'}
liveCheck={showLiveCheck} liveCheck={showLiveCheck}
placeholderLabel={t('account.wallet.watch.placeholder')} placeholderLabel={t('account.wallet.watch.placeholder')}
shouldUseMinHeight={false} shouldUseMinHeight={false}
...@@ -185,7 +185,7 @@ export function WatchWalletScreen({ navigation, route: { params } }: Props): JSX ...@@ -185,7 +185,7 @@ export function WatchWalletScreen({ navigation, route: { params } }: Props): JSX
</Text> </Text>
</Flex> </Flex>
</Flex> </Flex>
<Button disabled={!isValid} testID={TestID.Next} onPress={onSubmit}> <Button disabled={!isValid} mt="$spacing24" testID={TestID.Next} onPress={onSubmit}>
{t('common.button.continue')} {t('common.button.continue')}
</Button> </Button>
</SafeKeyboardOnboardingScreen> </SafeKeyboardOnboardingScreen>
......
...@@ -2,682 +2,647 @@ ...@@ -2,682 +2,647 @@
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d</loc> <loc>https://app.uniswap.org/nfts/collection/0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x60e4d786628fea6478f785a6d7e704777c86a7c6</loc> <loc>https://app.uniswap.org/nfts/collection/0x60e4d786628fea6478f785a6d7e704777c86a7c6</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xed5af388653567af2f388e6224dc7c4b3241c544</loc> <loc>https://app.uniswap.org/nfts/collection/0xed5af388653567af2f388e6224dc7c4b3241c544</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x34d85c9cdeb23fa97cb08333b511ac86e1c4e258</loc> <loc>https://app.uniswap.org/nfts/collection/0x34d85c9cdeb23fa97cb08333b511ac86e1c4e258</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x99a9b7c1116f9ceeb1652de04d5969cce509b069</loc> <loc>https://app.uniswap.org/nfts/collection/0x99a9b7c1116f9ceeb1652de04d5969cce509b069</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x49cf6f5d44e70224e2e23fdcdd2c053f30ada28b</loc> <loc>https://app.uniswap.org/nfts/collection/0x49cf6f5d44e70224e2e23fdcdd2c053f30ada28b</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xb7f7f6c52f2e2fdb1963eab30438024864c313f6</loc> <loc>https://app.uniswap.org/nfts/collection/0xb7f7f6c52f2e2fdb1963eab30438024864c313f6</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x23581767a106ae21c074b2276d25e5c3e136a68b</loc> <loc>https://app.uniswap.org/nfts/collection/0x23581767a106ae21c074b2276d25e5c3e136a68b</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x8a90cab2b38dba80c64b7734e58ee1db38b8992e</loc> <loc>https://app.uniswap.org/nfts/collection/0x8a90cab2b38dba80c64b7734e58ee1db38b8992e</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xba30e5f9bb24caa003e9f2f0497ad287fdf95623</loc> <loc>https://app.uniswap.org/nfts/collection/0xba30e5f9bb24caa003e9f2f0497ad287fdf95623</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xbd3531da5cf5857e7cfaa92426877b022e612cf8</loc> <loc>https://app.uniswap.org/nfts/collection/0xbd3531da5cf5857e7cfaa92426877b022e612cf8</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x7bd29408f11d2bfc23c34f18275bbf23bb716bc7</loc> <loc>https://app.uniswap.org/nfts/collection/0x7bd29408f11d2bfc23c34f18275bbf23bb716bc7</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x306b1ea3ecdf94ab739f1910bbda052ed4a9f949</loc> <loc>https://app.uniswap.org/nfts/collection/0x306b1ea3ecdf94ab739f1910bbda052ed4a9f949</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x1a92f7381b9f03921564a437210bb9396471050c</loc> <loc>https://app.uniswap.org/nfts/collection/0x1a92f7381b9f03921564a437210bb9396471050c</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x5cc5b05a8a13e3fbdb0bb9fccd98d38e50f90c38</loc> <loc>https://app.uniswap.org/nfts/collection/0x5cc5b05a8a13e3fbdb0bb9fccd98d38e50f90c38</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x5af0d9827e0c53e4799bb226655a1de152a425a5</loc> <loc>https://app.uniswap.org/nfts/collection/0x5af0d9827e0c53e4799bb226655a1de152a425a5</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x3bf2922f4520a8ba0c2efc3d2a1539678dad5e9d</loc> <loc>https://app.uniswap.org/nfts/collection/0x3bf2922f4520a8ba0c2efc3d2a1539678dad5e9d</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xe785e82358879f061bc3dcac6f0444462d4b5330</loc> <loc>https://app.uniswap.org/nfts/collection/0xe785e82358879f061bc3dcac6f0444462d4b5330</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x76be3b62873462d2142405439777e971754e8e77</loc> <loc>https://app.uniswap.org/nfts/collection/0x76be3b62873462d2142405439777e971754e8e77</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xfd43af6d3fe1b916c026f6ac35b3ede068d1ca01</loc> <loc>https://app.uniswap.org/nfts/collection/0xfd43af6d3fe1b916c026f6ac35b3ede068d1ca01</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x1cb1a5e65610aeff2551a50f76a87a7d3fb649c6</loc> <loc>https://app.uniswap.org/nfts/collection/0x1cb1a5e65610aeff2551a50f76a87a7d3fb649c6</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xff9c1b15b16263c61d017ee9f65c50e4ae0113d7</loc> <loc>https://app.uniswap.org/nfts/collection/0xff9c1b15b16263c61d017ee9f65c50e4ae0113d7</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x6339e5e072086621540d0362c4e3cea0d643e114</loc> <loc>https://app.uniswap.org/nfts/collection/0x6339e5e072086621540d0362c4e3cea0d643e114</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xb932a70a57673d89f4acffbe830e8ed7f75fb9e0</loc> <loc>https://app.uniswap.org/nfts/collection/0xb932a70a57673d89f4acffbe830e8ed7f75fb9e0</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x79fcdef22feed20eddacbb2587640e45491b757f</loc> <loc>https://app.uniswap.org/nfts/collection/0x79fcdef22feed20eddacbb2587640e45491b757f</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xa3aee8bce55beea1951ef834b99f3ac60d1abeeb</loc> <loc>https://app.uniswap.org/nfts/collection/0xa3aee8bce55beea1951ef834b99f3ac60d1abeeb</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x769272677fab02575e84945f03eca517acc544cc</loc> <loc>https://app.uniswap.org/nfts/collection/0x769272677fab02575e84945f03eca517acc544cc</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x4db1f25d3d98600140dfc18deb7515be5bd293af</loc> <loc>https://app.uniswap.org/nfts/collection/0x4db1f25d3d98600140dfc18deb7515be5bd293af</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x34eebee6942d8def3c125458d1a86e0a897fd6f9</loc> <loc>https://app.uniswap.org/nfts/collection/0x34eebee6942d8def3c125458d1a86e0a897fd6f9</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x59468516a8259058bad1ca5f8f4bff190d30e066</loc> <loc>https://app.uniswap.org/nfts/collection/0x59468516a8259058bad1ca5f8f4bff190d30e066</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x394e3d3044fc89fcdd966d3cb35ac0b32b0cda91</loc> <loc>https://app.uniswap.org/nfts/collection/0x394e3d3044fc89fcdd966d3cb35ac0b32b0cda91</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x60bb1e2aa1c9acafb4d34f71585d7e959f387769</loc> <loc>https://app.uniswap.org/nfts/collection/0x60bb1e2aa1c9acafb4d34f71585d7e959f387769</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x28472a58a490c5e09a238847f66a68a47cc76f0f</loc> <loc>https://app.uniswap.org/nfts/collection/0x28472a58a490c5e09a238847f66a68a47cc76f0f</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x341a1c534248966c4b6afad165b98daed4b964ef</loc> <loc>https://app.uniswap.org/nfts/collection/0x341a1c534248966c4b6afad165b98daed4b964ef</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x82c7a8f707110f5fbb16184a5933e9f78a34c6ab</loc> <loc>https://app.uniswap.org/nfts/collection/0x82c7a8f707110f5fbb16184a5933e9f78a34c6ab</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xccc441ac31f02cd96c153db6fd5fe0a2f4e6a68d</loc> <loc>https://app.uniswap.org/nfts/collection/0xccc441ac31f02cd96c153db6fd5fe0a2f4e6a68d</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x764aeebcf425d56800ef2c84f2578689415a2daa</loc> <loc>https://app.uniswap.org/nfts/collection/0x764aeebcf425d56800ef2c84f2578689415a2daa</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x160c404b2b49cbc3240055ceaee026df1e8497a0</loc> <loc>https://app.uniswap.org/nfts/collection/0x160c404b2b49cbc3240055ceaee026df1e8497a0</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xd2f668a8461d6761115daf8aeb3cdf5f40c532c6</loc> <loc>https://app.uniswap.org/nfts/collection/0xd2f668a8461d6761115daf8aeb3cdf5f40c532c6</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x39ee2c7b3cb80254225884ca001f57118c8f21b6</loc> <loc>https://app.uniswap.org/nfts/collection/0x39ee2c7b3cb80254225884ca001f57118c8f21b6</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xd774557b647330c91bf44cfeab205095f7e6c367</loc> <loc>https://app.uniswap.org/nfts/collection/0xd774557b647330c91bf44cfeab205095f7e6c367</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x1792a96e5668ad7c167ab804a100ce42395ce54d</loc> <loc>https://app.uniswap.org/nfts/collection/0x1792a96e5668ad7c167ab804a100ce42395ce54d</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xf87e31492faf9a91b02ee0deaad50d51d56d5d4d</loc> <loc>https://app.uniswap.org/nfts/collection/0xf87e31492faf9a91b02ee0deaad50d51d56d5d4d</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x04afa589e2b933f9463c5639f412b183ec062505</loc> <loc>https://app.uniswap.org/nfts/collection/0x04afa589e2b933f9463c5639f412b183ec062505</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xe75512aa3bec8f00434bbd6ad8b0a3fbff100ad6</loc> <loc>https://app.uniswap.org/nfts/collection/0xe75512aa3bec8f00434bbd6ad8b0a3fbff100ad6</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x348fc118bcc65a92dc033a951af153d14d945312</loc> <loc>https://app.uniswap.org/nfts/collection/0x348fc118bcc65a92dc033a951af153d14d945312</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x892848074ddea461a15f337250da3ce55580ca85</loc> <loc>https://app.uniswap.org/nfts/collection/0x892848074ddea461a15f337250da3ce55580ca85</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x5946aeaab44e65eb370ffaa6a7ef2218cff9b47d</loc> <loc>https://app.uniswap.org/nfts/collection/0x5946aeaab44e65eb370ffaa6a7ef2218cff9b47d</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x282bdd42f4eb70e7a9d9f40c8fea0825b7f68c5d</loc> <loc>https://app.uniswap.org/nfts/collection/0x282bdd42f4eb70e7a9d9f40c8fea0825b7f68c5d</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x4b15a9c28034dc83db40cd810001427d3bd7163d</loc> <loc>https://app.uniswap.org/nfts/collection/0x4b15a9c28034dc83db40cd810001427d3bd7163d</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x7ea3cca10668b8346aec0bf1844a49e995527c8b</loc> <loc>https://app.uniswap.org/nfts/collection/0x7ea3cca10668b8346aec0bf1844a49e995527c8b</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xb852c6b5892256c264cc2c888ea462189154d8d7</loc> <loc>https://app.uniswap.org/nfts/collection/0xb852c6b5892256c264cc2c888ea462189154d8d7</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x9378368ba6b85c1fba5b131b530f5f5bedf21a18</loc> <loc>https://app.uniswap.org/nfts/collection/0x9378368ba6b85c1fba5b131b530f5f5bedf21a18</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x2acab3dea77832c09420663b0e1cb386031ba17b</loc> <loc>https://app.uniswap.org/nfts/collection/0x2acab3dea77832c09420663b0e1cb386031ba17b</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x0c2e57efddba8c768147d1fdf9176a0a6ebd5d83</loc> <loc>https://app.uniswap.org/nfts/collection/0x0c2e57efddba8c768147d1fdf9176a0a6ebd5d83</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x08d7c0242953446436f34b4c78fe9da38c73668d</loc> <loc>https://app.uniswap.org/nfts/collection/0x08d7c0242953446436f34b4c78fe9da38c73668d</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x8943c7bac1914c9a7aba750bf2b6b09fd21037e0</loc> <loc>https://app.uniswap.org/nfts/collection/0x8943c7bac1914c9a7aba750bf2b6b09fd21037e0</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x364c828ee171616a39897688a831c2499ad972ec</loc> <loc>https://app.uniswap.org/nfts/collection/0x364c828ee171616a39897688a831c2499ad972ec</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x7f36182dee28c45de6072a34d29855bae76dbe2f</loc> <loc>https://app.uniswap.org/nfts/collection/0x7f36182dee28c45de6072a34d29855bae76dbe2f</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xf61f24c2d93bf2de187546b14425bf631f28d6dc</loc> <loc>https://app.uniswap.org/nfts/collection/0xf61f24c2d93bf2de187546b14425bf631f28d6dc</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x797a48c46be32aafcedcfd3d8992493d8a1f256b</loc> <loc>https://app.uniswap.org/nfts/collection/0x797a48c46be32aafcedcfd3d8992493d8a1f256b</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x123b30e25973fecd8354dd5f41cc45a3065ef88c</loc> <loc>https://app.uniswap.org/nfts/collection/0x123b30e25973fecd8354dd5f41cc45a3065ef88c</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x6632a9d63e142f17a668064d41a21193b49b41a0</loc> <loc>https://app.uniswap.org/nfts/collection/0x6632a9d63e142f17a668064d41a21193b49b41a0</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xf4ee95274741437636e748ddac70818b4ed7d043</loc> <loc>https://app.uniswap.org/nfts/collection/0xf4ee95274741437636e748ddac70818b4ed7d043</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x57a204aa1042f6e66dd7730813f4024114d74f37</loc> <loc>https://app.uniswap.org/nfts/collection/0x57a204aa1042f6e66dd7730813f4024114d74f37</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xd1258db6ac08eb0e625b75b371c023da478e94a9</loc> <loc>https://app.uniswap.org/nfts/collection/0xd1258db6ac08eb0e625b75b371c023da478e94a9</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x75e95ba5997eb235f40ecf8347cdb11f18ff640b</loc> <loc>https://app.uniswap.org/nfts/collection/0x75e95ba5997eb235f40ecf8347cdb11f18ff640b</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xd532b88607b1877fe20c181cba2550e3bbd6b31c</loc> <loc>https://app.uniswap.org/nfts/collection/0xd532b88607b1877fe20c181cba2550e3bbd6b31c</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xa1d4657e0e6507d5a94d06da93e94dc7c8c44b51</loc> <loc>https://app.uniswap.org/nfts/collection/0xa1d4657e0e6507d5a94d06da93e94dc7c8c44b51</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xedb61f74b0d09b2558f1eeb79b247c1f363ae452</loc> <loc>https://app.uniswap.org/nfts/collection/0xedb61f74b0d09b2558f1eeb79b247c1f363ae452</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x7d8820fa92eb1584636f4f5b8515b5476b75171a</loc> <loc>https://app.uniswap.org/nfts/collection/0x7d8820fa92eb1584636f4f5b8515b5476b75171a</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x231d3559aa848bf10366fb9868590f01d34bf240</loc> <loc>https://app.uniswap.org/nfts/collection/0x231d3559aa848bf10366fb9868590f01d34bf240</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xad9fd7cb4fc7a0fbce08d64068f60cbde22ed34c</loc> <loc>https://app.uniswap.org/nfts/collection/0xad9fd7cb4fc7a0fbce08d64068f60cbde22ed34c</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x0e9d6552b85be180d941f1ca73ae3e318d2d4f1f</loc> <loc>https://app.uniswap.org/nfts/collection/0x0e9d6552b85be180d941f1ca73ae3e318d2d4f1f</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xb716600ed99b4710152582a124c697a7fe78adbf</loc> <loc>https://app.uniswap.org/nfts/collection/0xb716600ed99b4710152582a124c697a7fe78adbf</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xaadc2d4261199ce24a4b0a57370c4fcf43bb60aa</loc> <loc>https://app.uniswap.org/nfts/collection/0xaadc2d4261199ce24a4b0a57370c4fcf43bb60aa</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x4e1f41613c9084fdb9e34e11fae9412427480e56</loc> <loc>https://app.uniswap.org/nfts/collection/0x4e1f41613c9084fdb9e34e11fae9412427480e56</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x79986af15539de2db9a5086382daeda917a9cf0c</loc> <loc>https://app.uniswap.org/nfts/collection/0x79986af15539de2db9a5086382daeda917a9cf0c</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xc99c679c50033bbc5321eb88752e89a93e9e83c5</loc> <loc>https://app.uniswap.org/nfts/collection/0xc99c679c50033bbc5321eb88752e89a93e9e83c5</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xc36cf0cfcb5d905b8b513860db0cfe63f6cf9f5c</loc> <loc>https://app.uniswap.org/nfts/collection/0xc36cf0cfcb5d905b8b513860db0cfe63f6cf9f5c</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x9c8ff314c9bc7f6e59a9d9225fb22946427edc03</loc> <loc>https://app.uniswap.org/nfts/collection/0x9c8ff314c9bc7f6e59a9d9225fb22946427edc03</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x3110ef5f612208724ca51f5761a69081809f03b7</loc> <loc>https://app.uniswap.org/nfts/collection/0x3110ef5f612208724ca51f5761a69081809f03b7</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x036721e5a769cc48b3189efbb9cce4471e8a48b1</loc> <loc>https://app.uniswap.org/nfts/collection/0x036721e5a769cc48b3189efbb9cce4471e8a48b1</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x524cab2ec69124574082676e6f654a18df49a048</loc> <loc>https://app.uniswap.org/nfts/collection/0x524cab2ec69124574082676e6f654a18df49a048</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x7ab2352b1d2e185560494d5e577f9d3c238b78c5</loc> <loc>https://app.uniswap.org/nfts/collection/0x7ab2352b1d2e185560494d5e577f9d3c238b78c5</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x32973908faee0bf825a343000fe412ebe56f802a</loc> <loc>https://app.uniswap.org/nfts/collection/0x32973908faee0bf825a343000fe412ebe56f802a</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x7daec605e9e2a1717326eedfd660601e2753a057</loc> <loc>https://app.uniswap.org/nfts/collection/0x7daec605e9e2a1717326eedfd660601e2753a057</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xc1caf0c19a8ac28c41fe59ba6c754e4b9bd54de9</loc> <loc>https://app.uniswap.org/nfts/collection/0xc1caf0c19a8ac28c41fe59ba6c754e4b9bd54de9</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x33fd426905f149f8376e227d0c9d3340aad17af1</loc> <loc>https://app.uniswap.org/nfts/collection/0x33fd426905f149f8376e227d0c9d3340aad17af1</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x466cfcd0525189b573e794f554b8a751279213ac</loc> <loc>https://app.uniswap.org/nfts/collection/0x466cfcd0525189b573e794f554b8a751279213ac</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x6be69b2a9b153737887cfcdca7781ed1511c7e36</loc> <loc>https://app.uniswap.org/nfts/collection/0x6be69b2a9b153737887cfcdca7781ed1511c7e36</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x80336ad7a747236ef41f47ed2c7641828a480baa</loc> <loc>https://app.uniswap.org/nfts/collection/0x80336ad7a747236ef41f47ed2c7641828a480baa</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x9401518f4ebba857baa879d9f76e1cc8b31ed197</loc> <loc>https://app.uniswap.org/nfts/collection/0x9401518f4ebba857baa879d9f76e1cc8b31ed197</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x4b61413d4392c806e6d0ff5ee91e6073c21d6430</loc> <loc>https://app.uniswap.org/nfts/collection/0x4b61413d4392c806e6d0ff5ee91e6073c21d6430</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xc3f733ca98e0dad0386979eb96fb1722a1a05e69</loc> <loc>https://app.uniswap.org/nfts/collection/0xc3f733ca98e0dad0386979eb96fb1722a1a05e69</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x09233d553058c2f42ba751c87816a8e9fae7ef10</loc> <loc>https://app.uniswap.org/nfts/collection/0x09233d553058c2f42ba751c87816a8e9fae7ef10</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x960b7a6bcd451c9968473f7bbfd9be826efd549a</loc> <loc>https://app.uniswap.org/nfts/collection/0x960b7a6bcd451c9968473f7bbfd9be826efd549a</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x36d30b3b85255473d27dd0f7fd8f35e36a9d6f06</loc> <loc>https://app.uniswap.org/nfts/collection/0x36d30b3b85255473d27dd0f7fd8f35e36a9d6f06</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x698fbaaca64944376e2cdc4cad86eaa91362cf54</loc> <loc>https://app.uniswap.org/nfts/collection/0x698fbaaca64944376e2cdc4cad86eaa91362cf54</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x497a9a79e82e6fc0ff10a16f6f75e6fcd5ae65a8</loc> <loc>https://app.uniswap.org/nfts/collection/0x497a9a79e82e6fc0ff10a16f6f75e6fcd5ae65a8</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x41a322b28d0ff354040e2cbc676f0320d8c8850d</loc> <loc>https://app.uniswap.org/nfts/collection/0x41a322b28d0ff354040e2cbc676f0320d8c8850d</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xa9c0a07a7cb84ad1f2ffab06de3e55aab7d523e8</loc> <loc>https://app.uniswap.org/nfts/collection/0xa9c0a07a7cb84ad1f2ffab06de3e55aab7d523e8</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x942bc2d3e7a589fe5bd4a5c6ef9727dfd82f5c8a</loc> <loc>https://app.uniswap.org/nfts/collection/0x942bc2d3e7a589fe5bd4a5c6ef9727dfd82f5c8a</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb</loc> <loc>https://app.uniswap.org/nfts/collection/0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x8821bee2ba0df28761afff119d66390d594cd280</loc> <loc>https://app.uniswap.org/nfts/collection/0x8821bee2ba0df28761afff119d66390d594cd280</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x8c6def540b83471664edc6d5cf75883986932674</loc> <loc>https://app.uniswap.org/nfts/collection/0x8c6def540b83471664edc6d5cf75883986932674</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x8d9710f0e193d3f95c0723eaaf1a81030dc9116d</loc> <loc>https://app.uniswap.org/nfts/collection/0x8d9710f0e193d3f95c0723eaaf1a81030dc9116d</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x86825dfca7a6224cfbd2da48e85df2fc3aa7c4b1</loc> <loc>https://app.uniswap.org/nfts/collection/0x86825dfca7a6224cfbd2da48e85df2fc3aa7c4b1</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x629a673a8242c2ac4b7b8c5d8735fbeac21a6205</loc> <loc>https://app.uniswap.org/nfts/collection/0x629a673a8242c2ac4b7b8c5d8735fbeac21a6205</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x9a534628b4062e123ce7ee2222ec20b86e16ca8f</loc> <loc>https://app.uniswap.org/nfts/collection/0x9a534628b4062e123ce7ee2222ec20b86e16ca8f</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xc2c747e0f7004f9e8817db2ca4997657a7746928</loc> <loc>https://app.uniswap.org/nfts/collection/0xc2c747e0f7004f9e8817db2ca4997657a7746928</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x73da73ef3a6982109c4d5bdb0db9dd3e3783f313</loc> <loc>https://app.uniswap.org/nfts/collection/0x73da73ef3a6982109c4d5bdb0db9dd3e3783f313</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xc92ceddfb8dd984a89fb494c376f9a48b999aafc</loc> <loc>https://app.uniswap.org/nfts/collection/0xc92ceddfb8dd984a89fb494c376f9a48b999aafc</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x3248e8ba90facc4fdd3814518c14f8cc4d980e4b</loc> <loc>https://app.uniswap.org/nfts/collection/0x3248e8ba90facc4fdd3814518c14f8cc4d980e4b</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x67d9417c9c3c250f61a83c7e8658dac487b56b09</loc> <loc>https://app.uniswap.org/nfts/collection/0x67d9417c9c3c250f61a83c7e8658dac487b56b09</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xb6a37b5d14d502c3ab0ae6f3a0e058bc9517786e</loc> <loc>https://app.uniswap.org/nfts/collection/0xb6a37b5d14d502c3ab0ae6f3a0e058bc9517786e</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x86c10d10eca1fca9daf87a279abccabe0063f247</loc> <loc>https://app.uniswap.org/nfts/collection/0x86c10d10eca1fca9daf87a279abccabe0063f247</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x4b3406a41399c7fd2ba65cbc93697ad9e7ea61e5</loc> <loc>https://app.uniswap.org/nfts/collection/0x4b3406a41399c7fd2ba65cbc93697ad9e7ea61e5</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xb0640e8b5f24bedc63c33d371923d68fde020303</loc> <loc>https://app.uniswap.org/nfts/collection/0xb0640e8b5f24bedc63c33d371923d68fde020303</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xd3d9ddd0cf0a5f0bfb8f7fceae075df687eaebab</loc> <loc>https://app.uniswap.org/nfts/collection/0xd3d9ddd0cf0a5f0bfb8f7fceae075df687eaebab</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xa5c0bd78d1667c13bfb403e2a3336871396713c5</loc> <loc>https://app.uniswap.org/nfts/collection/0xa5c0bd78d1667c13bfb403e2a3336871396713c5</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x4d7d2e237d64d1484660b55c0a4cc092fa5e6716</loc> <loc>https://app.uniswap.org/nfts/collection/0x4d7d2e237d64d1484660b55c0a4cc092fa5e6716</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xfcb1315c4273954f74cb16d5b663dbf479eec62e</loc> <loc>https://app.uniswap.org/nfts/collection/0xfcb1315c4273954f74cb16d5b663dbf479eec62e</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x66d1db16101502ed0ca428842c619ca7b62c8fef</loc> <loc>https://app.uniswap.org/nfts/collection/0x66d1db16101502ed0ca428842c619ca7b62c8fef</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x128675d4fddbc4a0d3f8aa777d8ee0fb8b427c2f</loc> <loc>https://app.uniswap.org/nfts/collection/0x128675d4fddbc4a0d3f8aa777d8ee0fb8b427c2f</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x19b86299c21505cdf59ce63740b240a9c822b5e4</loc> <loc>https://app.uniswap.org/nfts/collection/0x19b86299c21505cdf59ce63740b240a9c822b5e4</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xacf63e56fd08970b43401492a02f6f38b6635c91</loc> <loc>https://app.uniswap.org/nfts/collection/0xacf63e56fd08970b43401492a02f6f38b6635c91</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0x0bebad1ff25c623dff9605dad4a8f782d5da37df</loc> <loc>https://app.uniswap.org/nfts/collection/0x0bebad1ff25c623dff9605dad4a8f782d5da37df</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
<url> <url>
<loc>https://app.uniswap.org/nfts/collection/0xdceaf1652a131f32a821468dc03a92df0edd86ea</loc> <loc>https://app.uniswap.org/nfts/collection/0xdceaf1652a131f32a821468dc03a92df0edd86ea</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod> <lastmod>2024-05-20T17:20:52.753Z</lastmod>
<priority>0.7</priority>
</url>
<url>
<loc>https://app.uniswap.org/nfts/collection/0x273f7f8e6489682df756151f5525576e322d51a3</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod>
<priority>0.7</priority>
</url>
<url>
<loc>https://app.uniswap.org/nfts/collection/0x77372a4cc66063575b05b44481f059be356964a4</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod>
<priority>0.7</priority>
</url>
<url>
<loc>https://app.uniswap.org/nfts/collection/0xf5b0a3efb8e8e4c201e2a935f110eaaf3ffecb8d</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod>
<priority>0.7</priority>
</url>
<url>
<loc>https://app.uniswap.org/nfts/collection/0x22c36bfdcef207f9c0cc941936eff94d4246d14a</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod>
<priority>0.7</priority>
</url>
<url>
<loc>https://app.uniswap.org/nfts/collection/0x59325733eb952a92e069c87f0a6168b29e80627f</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod>
<priority>0.7</priority>
</url>
<url>
<loc>https://app.uniswap.org/nfts/collection/0x0e3a2a1f2146d86a604adc220b4967a898d7fe07</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod>
<priority>0.7</priority>
</url>
<url>
<loc>https://app.uniswap.org/nfts/collection/0x3af2a97414d1101e2107a70e7f33955da1346305</loc>
<lastmod>2024-07-05T19:43:14.783Z</lastmod>
<priority>0.7</priority> <priority>0.7</priority>
</url> </url>
</urlset> </urlset>
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -20,7 +20,7 @@ export function AddressDisplay({ address, enableCopyAddress }: { address: Addres ...@@ -20,7 +20,7 @@ export function AddressDisplay({ address, enableCopyAddress }: { address: Addres
const uniswapUsername = unitag?.username const uniswapUsername = unitag?.username
const AddressDisplay = ( const AddressDisplay = (
<Flex row gap="2px" alignItems="center"> <Flex row gap="2px">
<IdentifierText>{uniswapUsername ?? ENSName ?? shortenAddress(address)}</IdentifierText> <IdentifierText>{uniswapUsername ?? ENSName ?? shortenAddress(address)}</IdentifierText>
{uniswapUsername && <Unitag size={18} />} {uniswapUsername && <Unitag size={18} />}
</Flex> </Flex>
......
...@@ -2,7 +2,6 @@ import { MenuState, miniPortfolioMenuStateAtom } from 'components/AccountDrawer/ ...@@ -2,7 +2,6 @@ import { MenuState, miniPortfolioMenuStateAtom } from 'components/AccountDrawer/
import { useOpenLimitOrders, usePendingActivity } from 'components/AccountDrawer/MiniPortfolio/Activity/hooks' import { useOpenLimitOrders, usePendingActivity } from 'components/AccountDrawer/MiniPortfolio/Activity/hooks'
import { useFilterPossiblyMaliciousPositionInfo } from 'components/AccountDrawer/MiniPortfolio/Pools' import { useFilterPossiblyMaliciousPositionInfo } from 'components/AccountDrawer/MiniPortfolio/Pools'
import useMultiChainPositions from 'components/AccountDrawer/MiniPortfolio/Pools/useMultiChainPositions' import useMultiChainPositions from 'components/AccountDrawer/MiniPortfolio/Pools/useMultiChainPositions'
import { useAccountDrawer } from 'components/AccountDrawer/MiniPortfolio/hooks'
import { Pool } from 'components/Icons/Pool' import { Pool } from 'components/Icons/Pool'
import { ExtensionRequestMethods, useUniswapExtensionConnector } from 'components/WalletModal/useOrderedConnections' import { ExtensionRequestMethods, useUniswapExtensionConnector } from 'components/WalletModal/useOrderedConnections'
import { t } from 'i18n' import { t } from 'i18n'
...@@ -37,13 +36,12 @@ const DeepLinkButton = ({ Icon, Label, onPress }: { Icon: JSX.Element; Label: st ...@@ -37,13 +36,12 @@ const DeepLinkButton = ({ Icon, Label, onPress }: { Icon: JSX.Element; Label: st
py="$spacing12" py="$spacing12"
fontSize="$large" fontSize="$large"
onPress={onPress} onPress={onPress}
hoverStyle={{ opacity: 0.9 }}
> >
{Icon} {Icon}
<Text display="flex" flex={1} variant="buttonLabel3"> <Text display="flex" flex={1} variant="buttonLabel3">
{Label} {Label}
</Text> </Text>
<RotatableChevron width={iconSizes.icon20} height={iconSizes.icon20} color="$neutral3" direction="right" /> <RotatableChevron width={iconSizes.icon20} height={iconSizes.icon20} color="$neutral1" direction="right" />
</Button> </Button>
) )
} }
...@@ -51,7 +49,6 @@ const DeepLinkButton = ({ Icon, Label, onPress }: { Icon: JSX.Element; Label: st ...@@ -51,7 +49,6 @@ const DeepLinkButton = ({ Icon, Label, onPress }: { Icon: JSX.Element; Label: st
export function ExtensionDeeplinks({ account }: { account: string }) { export function ExtensionDeeplinks({ account }: { account: string }) {
const theme = useTheme() const theme = useTheme()
const uniswapExtensionConnector = useUniswapExtensionConnector() const uniswapExtensionConnector = useUniswapExtensionConnector()
const accountDrawer = useAccountDrawer()
const setMenu = useUpdateAtom(miniPortfolioMenuStateAtom) const setMenu = useUpdateAtom(miniPortfolioMenuStateAtom)
const { openLimitOrders } = useOpenLimitOrders(account) const { openLimitOrders } = useOpenLimitOrders(account)
...@@ -77,7 +74,6 @@ export function ExtensionDeeplinks({ account }: { account: string }) { ...@@ -77,7 +74,6 @@ export function ExtensionDeeplinks({ account }: { account: string }) {
Label={t('extension.open')} Label={t('extension.open')}
onPress={() => { onPress={() => {
uniswapExtensionConnector.extensionRequest(ExtensionRequestMethods.OPEN_SIDEBAR, 'Tokens') uniswapExtensionConnector.extensionRequest(ExtensionRequestMethods.OPEN_SIDEBAR, 'Tokens')
accountDrawer.close()
}} }}
/> />
<DeepLinkButton <DeepLinkButton
...@@ -90,7 +86,6 @@ export function ExtensionDeeplinks({ account }: { account: string }) { ...@@ -90,7 +86,6 @@ export function ExtensionDeeplinks({ account }: { account: string }) {
Label={t('common.activity')} Label={t('common.activity')}
onPress={() => { onPress={() => {
uniswapExtensionConnector.extensionRequest(ExtensionRequestMethods.OPEN_SIDEBAR, 'Activity') uniswapExtensionConnector.extensionRequest(ExtensionRequestMethods.OPEN_SIDEBAR, 'Activity')
accountDrawer.close()
setActivityUnread(false) setActivityUnread(false)
}} }}
/> />
......
...@@ -665,7 +665,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -665,7 +665,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
<div <div
class="c24 css-142zc9n" class="c24 css-142zc9n"
> >
By connecting a wallet, you agree to Uniswap Labs’ By connecting a wallet, you agree to Uniswap Labs’
<a <a
class="c25 c26" class="c25 c26"
href="https://uniswap.org/terms-of-service/" href="https://uniswap.org/terms-of-service/"
...@@ -712,14 +712,14 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -712,14 +712,14 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
min-width: 0; min-width: 0;
} }
.c19 { .c20 {
box-sizing: border-box; box-sizing: border-box;
margin: 0; margin: 0;
min-width: 0; min-width: 0;
padding: 8px 0px; padding: 8px 0px;
} }
.c23 { .c24 {
box-sizing: border-box; box-sizing: border-box;
margin: 0; margin: 0;
min-width: 0; min-width: 0;
...@@ -727,7 +727,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -727,7 +727,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
margin-right: 18px; margin-right: 18px;
} }
.c27 { .c28 {
box-sizing: border-box; box-sizing: border-box;
margin: 0; margin: 0;
min-width: 0; min-width: 0;
...@@ -789,7 +789,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -789,7 +789,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
gap: 4px; gap: 4px;
} }
.c20 { .c21 {
width: 100%; width: 100%;
display: -webkit-box; display: -webkit-box;
display: -webkit-flex; display: -webkit-flex;
...@@ -807,7 +807,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -807,7 +807,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
padding: 8px 0px; padding: 8px 0px;
} }
.c24 { .c25 {
width: 100%; width: 100%;
display: -webkit-box; display: -webkit-box;
display: -webkit-flex; display: -webkit-flex;
...@@ -824,7 +824,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -824,7 +824,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
justify-content: flex-start; justify-content: flex-start;
} }
.c28 { .c29 {
width: 100%; width: 100%;
display: -webkit-box; display: -webkit-box;
display: -webkit-flex; display: -webkit-flex;
...@@ -863,7 +863,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -863,7 +863,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
letter-spacing: -0.01em; letter-spacing: -0.01em;
} }
.c36 { .c37 {
color: #7D7D7D; color: #7D7D7D;
-webkit-letter-spacing: -0.01em; -webkit-letter-spacing: -0.01em;
-moz-letter-spacing: -0.01em; -moz-letter-spacing: -0.01em;
...@@ -871,7 +871,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -871,7 +871,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
letter-spacing: -0.01em; letter-spacing: -0.01em;
} }
.c37 { .c38 {
-webkit-text-decoration: none; -webkit-text-decoration: none;
text-decoration: none; text-decoration: none;
cursor: pointer; cursor: pointer;
...@@ -882,11 +882,11 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -882,11 +882,11 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
font-weight: 500; font-weight: 500;
} }
.c37:hover { .c38:hover {
opacity: 0.6; opacity: 0.6;
} }
.c37:active { .c38:active {
opacity: 0.4; opacity: 0.4;
} }
...@@ -934,7 +934,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -934,7 +934,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
gap: 12px; gap: 12px;
} }
.c26 { .c27 {
display: -webkit-box; display: -webkit-box;
display: -webkit-flex; display: -webkit-flex;
display: -ms-flexbox; display: -ms-flexbox;
...@@ -1002,7 +1002,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -1002,7 +1002,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
justify-content: center; justify-content: center;
} }
.c32 { .c33 {
display: -webkit-box; display: -webkit-box;
display: -webkit-flex; display: -webkit-flex;
display: -ms-flexbox; display: -ms-flexbox;
...@@ -1019,7 +1019,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -1019,7 +1019,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
align-items: center; align-items: center;
} }
.c31 { .c32 {
-webkit-align-items: center; -webkit-align-items: center;
-webkit-box-align: center; -webkit-box-align: center;
-ms-flex-align: center; -ms-flex-align: center;
...@@ -1047,7 +1047,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -1047,7 +1047,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
transition: 125ms; transition: 125ms;
} }
.c34 { .c35 {
display: -webkit-box; display: -webkit-box;
display: -webkit-flex; display: -webkit-flex;
display: -ms-flexbox; display: -ms-flexbox;
...@@ -1069,7 +1069,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -1069,7 +1069,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
padding: 0 8px; padding: 0 8px;
} }
.c33 { .c34 {
display: -webkit-box; display: -webkit-box;
display: -webkit-flex; display: -webkit-flex;
display: -ms-flexbox; display: -ms-flexbox;
...@@ -1087,18 +1087,18 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -1087,18 +1087,18 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
justify-content: center; justify-content: center;
} }
.c33 img { .c34 img {
border: 1px solid #22222212; border: 1px solid #22222212;
border-radius: 12px; border-radius: 12px;
} }
.c33 > img, .c34 > img,
.c33 span { .c34 span {
height: 40px; height: 40px;
width: 40px; width: 40px;
} }
.c30 { .c31 {
-webkit-align-items: stretch; -webkit-align-items: stretch;
-webkit-box-align: stretch; -webkit-box-align: stretch;
-ms-flex-align: stretch; -ms-flex-align: stretch;
...@@ -1119,16 +1119,16 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -1119,16 +1119,16 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
background-color: #F9F9F9; background-color: #F9F9F9;
} }
.c30:hover { .c31:hover {
cursor: pointer; cursor: pointer;
background-color: #22222212; background-color: #22222212;
} }
.c30:focus { .c31:focus {
background-color: #22222212; background-color: #22222212;
} }
.c38 { .c39 {
font-weight: 535; font-weight: 535;
color: #7D7D7D; color: #7D7D7D;
} }
...@@ -1170,7 +1170,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -1170,7 +1170,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
gap: 16px; gap: 16px;
} }
.c29 { .c30 {
display: grid; display: grid;
-webkit-flex: 1; -webkit-flex: 1;
-ms-flex: 1; -ms-flex: 1;
...@@ -1178,17 +1178,17 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -1178,17 +1178,17 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
grid-gap: 2px; grid-gap: 2px;
border-radius: 12px; border-radius: 12px;
overflow: hidden; overflow: hidden;
opacity: 1; opacity: 0;
max-height: 100vh; max-height: 0;
-webkit-transition: max-height 125ms ease-in-out,opacity 125ms ease-in-out; -webkit-transition: max-height 125ms ease-in-out,opacity 125ms ease-in-out;
transition: max-height 125ms ease-in-out,opacity 125ms ease-in-out; transition: max-height 125ms ease-in-out,opacity 125ms ease-in-out;
} }
.c35 { .c36 {
padding: 0 4px; padding: 0 4px;
} }
.c21 { .c22 {
-webkit-text-decoration: none; -webkit-text-decoration: none;
text-decoration: none; text-decoration: none;
cursor: pointer; cursor: pointer;
...@@ -1200,21 +1200,21 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -1200,21 +1200,21 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
user-select: none; user-select: none;
} }
.c21:hover { .c22:hover {
opacity: 0.6; opacity: 0.6;
} }
.c21:active { .c22:active {
opacity: 0.4; opacity: 0.4;
} }
.c22 { .c23 {
height: 1px; height: 1px;
width: 100%; width: 100%;
background: #22222212; background: #22222212;
} }
.c25 { .c26 {
height: 20px; height: 20px;
width: 20px; width: 20px;
fill: #7D7D7D; fill: #7D7D7D;
...@@ -1347,7 +1347,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -1347,7 +1347,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
} }
@media (max-width:960px) { @media (max-width:960px) {
.c33 { .c34 {
-webkit-align-items: flex-end; -webkit-align-items: flex-end;
-webkit-box-align: flex-end; -webkit-box-align: flex-end;
-ms-flex-align: flex-end; -ms-flex-align: flex-end;
...@@ -1355,8 +1355,14 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -1355,8 +1355,14 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
} }
} }
@media screen and (max-width:396px) {
.c19 {
display: none;
}
}
@media (max-width:960px) { @media (max-width:960px) {
.c29 { .c30 {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
} }
...@@ -1481,14 +1487,11 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -1481,14 +1487,11 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
fill="none" fill="none"
stroke-width="8" stroke-width="8"
style="color: rgb(252, 114, 255); width: 40px; height: 40px; min-width: 40px; background-color: rgb(255, 239, 255); border-top-left-radius: 8px; border-top-right-radius: 8px; border-bottom-right-radius: 8px; border-bottom-left-radius: 8px; padding: 7px 7px 7px 7px;" style="color: rgb(252, 114, 255); width: 40px; height: 40px; min-width: 40px; background-color: rgb(255, 239, 255); border-top-left-radius: 8px; border-top-right-radius: 8px; border-bottom-right-radius: 8px; border-bottom-left-radius: 8px; padding: 7px 7px 7px 7px;"
viewBox="0 0 22 22" viewBox="0 0 43 43"
> >
<path <path
d="M6.92609 1.83331H3.87053C3.33028 1.83331 2.81215 2.04793 2.43013 2.42995C2.04811 2.81197 1.8335 3.33009 1.8335 3.87035V6.92591M20.1668 6.92591V3.87035C20.1668 3.33009 19.9522 2.81197 19.5702 2.42995C19.1882 2.04793 18.67 1.83331 18.1298 1.83331H15.0742M15.0742 20.1666H18.1298C18.67 20.1666 19.1882 19.952 19.5702 19.57C19.9522 19.188 20.1668 18.6699 20.1668 18.1296V15.0741M1.8335 15.0741V18.1296C1.8335 18.6699 2.04811 19.188 2.43013 19.57C2.81215 19.952 3.33028 20.1666 3.87053 20.1666H6.92609M12.1829 12.1827V14.5483M12.1829 16.9139H14.5484V12.1827M14.5482 13.3654H16.9138M16.914 15.7311V16.9139M5.67739 5.08581H9.22578C9.5524 5.08581 9.81717 5.35059 9.81717 5.67721V9.22559C9.81717 9.55221 9.5524 9.81699 9.22578 9.81699H5.67739C5.35077 9.81699 5.08599 9.55221 5.08599 9.22559V5.67721C5.08599 5.35059 5.35077 5.08581 5.67739 5.08581ZM5.67739 12.1827H9.22578C9.5524 12.1827 9.81717 12.4475 9.81717 12.7741V16.3225C9.81717 16.6491 9.5524 16.9139 9.22578 16.9139H5.67739C5.35077 16.9139 5.08599 16.6491 5.08599 16.3225V12.7741C5.08599 12.4475 5.35077 12.1827 5.67739 12.1827ZM12.7743 5.08581H16.3226C16.6493 5.08581 16.914 5.35059 16.914 5.67721V9.22559C16.914 9.55221 16.6493 9.81699 16.3226 9.81699H12.7743C12.4476 9.81699 12.1829 9.55221 12.1829 9.22559V5.67721C12.1829 5.35059 12.4476 5.08581 12.7743 5.08581Z" d="M28.3632 6.11328H14.3633C10.8633 6.11328 9.11328 7.86327 9.11328 11.3633V32.3632C9.11328 35.8632 10.8633 37.6132 14.3633 37.6132H28.3632C31.8632 37.6132 33.6132 35.8632 33.6132 32.3632V11.3633C33.6132 7.86327 31.8632 6.11328 28.3632 6.11328ZM21.3632 34.1132C20.3972 34.1132 19.6132 33.3292 19.6132 32.3632C19.6132 31.3972 20.3972 30.6132 21.3632 30.6132C22.3292 30.6132 23.1132 31.3972 23.1132 32.3632C23.1132 33.3292 22.3292 34.1132 21.3632 34.1132ZM23.9882 12.6758H18.7382C18.0137 12.6758 17.4257 12.0878 17.4257 11.3633C17.4257 10.6388 18.0137 10.0508 18.7382 10.0508H23.9882C24.7127 10.0508 25.3007 10.6388 25.3007 11.3633C25.3007 12.0878 24.7127 12.6758 23.9882 12.6758Z"
stroke="currentColor" fill="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1.75"
/> />
</svg> </svg>
<div <div
...@@ -1501,7 +1504,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -1501,7 +1504,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
class="font_button _fontFamily-299667014 _display-inline _boxSizing-border-box _wordWrap-break-word _mt-0px _mr-0px _mb-0px _ml-0px _color-843134974 _fontSize-16px _lineHeight-24px _fontWeight-500 _whiteSpace-nowrap" class="font_button _fontFamily-299667014 _display-inline _boxSizing-border-box _wordWrap-break-word _mt-0px _mr-0px _mb-0px _ml-0px _color-843134974 _fontSize-16px _lineHeight-24px _fontWeight-500 _whiteSpace-nowrap"
data-disable-theme="true" data-disable-theme="true"
> >
Uniswap Mobile Mobile Wallet
</span> </span>
<span <span
class="font_body _fontFamily-299667014 _display-inline _boxSizing-border-box _wordWrap-break-word _mt-0px _mr-0px _mb-0px _ml-0px _color-843135005 _fontSize-12px _lineHeight-16px _fontWeight-400 _whiteSpace-nowrap" class="font_body _fontFamily-299667014 _display-inline _boxSizing-border-box _wordWrap-break-word _mt-0px _mr-0px _mb-0px _ml-0px _color-843135005 _fontSize-12px _lineHeight-16px _fontWeight-400 _whiteSpace-nowrap"
...@@ -1511,17 +1514,77 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -1511,17 +1514,77 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
</span> </span>
</div> </div>
</div> </div>
<div
class="c19"
>
<svg
fill="none"
stroke-width="8"
style="color: rgb(125, 125, 125); width: 20px; height: 20px;"
viewBox="0 0 24 24"
>
<path
d="M9 2H3C2.44772 2 2 2.44772 2 3V9C2 9.55228 2.44772 10 3 10H9C9.55228 10 10 9.55228 10 9V3C10 2.44772 9.55228 2 9 2Z"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M9 13.9999H3C2.44772 13.9999 2 14.4476 2 14.9999V20.9999C2 21.5522 2.44772 21.9999 3 21.9999H9C9.55228 21.9999 10 21.5522 10 20.9999V14.9999C10 14.4476 9.55228 13.9999 9 13.9999Z"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M21 2H15C14.4477 2 14 2.44772 14 3V9C14 9.55228 14.4477 10 15 10H21C21.5523 10 22 9.55228 22 9V3C22 2.44772 21.5523 2 21 2Z"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M14 13.9999V17.9999"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M14 21.9999H18V13.9999"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M18 16H22"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M22 20.0001V22.0001"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
</svg>
</div>
</div> </div>
</div> </div>
</div> </div>
<div <div
class="c19 c20 c21" class="c20 c21 c22"
> >
<div <div
class="c22" class="c23"
/> />
<div <div
class="c23 c24" class="c24 c25"
> >
<span <span
class="font_body _fontFamily-299667014 _display-inline _boxSizing-border-box _wordWrap-break-word _mt-0px _mr-0px _mb-0px _ml-0px _color-843135005 _fontSize-14px _lineHeight-20px _fontWeight-400 _whiteSpace-nowrap" class="font_body _fontFamily-299667014 _display-inline _boxSizing-border-box _wordWrap-break-word _mt-0px _mr-0px _mb-0px _ml-0px _color-843135005 _fontSize-14px _lineHeight-20px _fontWeight-400 _whiteSpace-nowrap"
...@@ -1530,7 +1593,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -1530,7 +1593,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
Other wallets Other wallets
</span> </span>
<svg <svg
class="c25" class="c26"
fill="none" fill="none"
height="28" height="28"
viewBox="0 0 28 28" viewBox="0 0 28 28"
...@@ -1538,41 +1601,37 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -1538,41 +1601,37 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
> >
<path <path
d="M13.9912 11.9609C14.2812 11.9609 14.5273 11.8379 14.8086 11.6094L20.75 6.81055C20.9609 6.62598 21.0928 6.3623 21.0928 6.0459C21.0928 5.43945 20.6094 5 20.0557 5C19.8008 5 19.5371 5.10547 19.291 5.30762L14 9.5791L8.7002 5.30762C8.44531 5.10547 8.19043 5 7.93555 5C7.38184 5 6.89844 5.43945 6.89844 6.0459C6.89844 6.3623 7.03027 6.62598 7.24121 6.81055L13.1738 11.6006C13.4639 11.8379 13.71 11.9609 13.9912 11.9609Z" d="M13.9912 5.42773C13.71 5.42773 13.4639 5.55957 13.1738 5.78809L7.24121 10.5869C7.03027 10.7627 6.89844 11.0264 6.89844 11.3516C6.89844 11.9492 7.38184 12.3887 7.93555 12.3887C8.19043 12.3887 8.44531 12.292 8.7002 12.0898L14 7.81836L19.291 12.0898C19.5371 12.292 19.8008 12.3887 20.0557 12.3887C20.6094 12.3887 21.0928 11.9492 21.0928 11.3516C21.0928 11.0264 20.9609 10.7627 20.75 10.5869L14.8086 5.78809C14.5273 5.55957 14.2812 5.42773 13.9912 5.42773ZM13.9912 21.7139C14.2812 21.7139 14.5273 21.5908 14.8086 21.3623L20.75 16.5635C20.9609 16.3789 21.0928 16.1152 21.0928 15.7988C21.0928 15.1924 20.6094 14.7529 20.0557 14.7529C19.8008 14.7529 19.5371 14.8584 19.291 15.0605L14 19.332L8.7002 15.0605C8.44531 14.8584 8.19043 14.7529 7.93555 14.7529C7.38184 14.7529 6.89844 15.1924 6.89844 15.7988C6.89844 16.1152 7.03027 16.3789 7.24121 16.5635L13.1738 21.3535C13.4639 21.5908 13.71 21.7139 13.9912 21.7139Z"
fill="#70757A"
/>
<path
d="M14.0928 15C13.8115 15 13.5654 15.1318 13.2754 15.3604L7.34277 20.1592C7.13184 20.335 7 20.5986 7 20.9238C7 21.5215 7.4834 21.9609 8.03711 21.9609C8.29199 21.9609 8.54688 21.8643 8.80176 21.6621L14.1016 17.3906L19.3926 21.6621C19.6387 21.8643 19.9023 21.9609 20.1572 21.9609C20.7109 21.9609 21.1943 21.5215 21.1943 20.9238C21.1943 20.5986 21.0625 20.335 20.8516 20.1592L14.9102 15.3604C14.6289 15.1318 14.3828 15 14.0928 15Z"
fill="#70757A" fill="#70757A"
/> />
</svg> </svg>
</div> </div>
<div <div
class="c22" class="c23"
/> />
</div> </div>
<div <div
class="c26" class="c27"
> >
<div <div
class="c27 c28" class="c28 c29"
> >
<div <div
class="c29" class="c30"
data-testid="option-grid" data-testid="option-grid"
> >
<div <div
class="c30" class="c31"
> >
<button <button
class="c31" class="c32"
data-testid="wallet-option-walletConnect" data-testid="wallet-option-walletConnect"
> >
<div <div
class="c32" class="c33"
> >
<div <div
class="c33" class="c34"
> >
<img <img
alt="WalletConnect" alt="WalletConnect"
...@@ -1580,7 +1639,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -1580,7 +1639,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
/> />
</div> </div>
<div <div
class="c34" class="c35"
> >
WalletConnect WalletConnect
</div> </div>
...@@ -1588,17 +1647,17 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -1588,17 +1647,17 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
</button> </button>
</div> </div>
<div <div
class="c30" class="c31"
> >
<button <button
class="c31" class="c32"
data-testid="wallet-option-coinbaseWallet" data-testid="wallet-option-coinbaseWallet"
> >
<div <div
class="c32" class="c33"
> >
<div <div
class="c33" class="c34"
> >
<img <img
alt="Coinbase Wallet" alt="Coinbase Wallet"
...@@ -1606,7 +1665,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -1606,7 +1665,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
/> />
</div> </div>
<div <div
class="c34" class="c35"
> >
Coinbase Wallet Coinbase Wallet
</div> </div>
...@@ -1619,14 +1678,14 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -1619,14 +1678,14 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
class="c14" class="c14"
> >
<div <div
class="c35" class="c36"
> >
<div <div
class="c36 css-142zc9n" class="c37 css-142zc9n"
> >
By connecting a wallet, you agree to Uniswap Labs’ By connecting a wallet, you agree to Uniswap Labs’
<a <a
class="c37 c38" class="c38 c39"
href="https://uniswap.org/terms-of-service/" href="https://uniswap.org/terms-of-service/"
rel="noopener noreferrer" rel="noopener noreferrer"
target="_blank" target="_blank"
...@@ -1635,7 +1694,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i ...@@ -1635,7 +1694,7 @@ exports[`AccountDrawer tests AccountDrawer styles when isUniExtensionAvailable i
</a> </a>
and consent to its and consent to its
<a <a
class="c37 c38" class="c38 c39"
href="https://uniswap.org/privacy-policy" href="https://uniswap.org/privacy-policy"
rel="noopener noreferrer" rel="noopener noreferrer"
target="_blank" target="_blank"
......
...@@ -135,7 +135,7 @@ export function Pending({ ...@@ -135,7 +135,7 @@ export function Pending({
if (swapResult && swapResult.type === TradeFillType.Classic) { if (swapResult && swapResult.type === TradeFillType.Classic) {
txHash = swapResult.response.hash txHash = swapResult.response.hash
} else if (uniswapXOrder && uniswapXOrder.status === UniswapXOrderStatus.FILLED) { } else if (uniswapXOrder && uniswapXOrder.status === UniswapXOrderStatus.FILLED) {
txHash = uniswapXOrder.txHash txHash = uniswapXOrder.orderHash
} else { } else {
return return
} }
......
import { ComponentProps } from 'react'
export function BraveBrowserLogo(props: ComponentProps<'svg'>) {
return (
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M57.622 15.321L59.122 11.645C59.122 11.645 57.213 9.602 54.895 7.287C52.578 4.972 47.67 6.334 47.67 6.334L42.081 0H22.45L16.861 6.334C16.861 6.334 11.953 4.972 9.636 7.287C7.318 9.602 5.41 11.645 5.41 11.645L6.91 15.321L5 20.768C5 20.768 10.614 42.004 11.272 44.598C12.567 49.704 13.453 51.678 17.134 54.266C20.814 56.853 27.494 61.346 28.584 62.028C29.675 62.708 31.039 63.868 32.266 63.868C33.493 63.868 34.856 62.708 35.946 62.028C37.037 61.347 43.716 56.853 47.398 54.266C51.078 51.679 51.965 49.704 53.26 44.598C53.917 42.004 59.53 20.768 59.53 20.768L57.622 15.321Z"
fill="url(#paint0_linear_11_3292)"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M39.218 11.508C40.036 11.508 46.103 10.351 46.103 10.351C46.103 10.351 53.292 19.031 53.292 20.887C53.292 22.421 52.673 23.021 51.945 23.729C51.793 23.877 51.635 24.029 51.478 24.197L46.088 29.914C46.0301 29.9748 45.9715 30.0348 45.912 30.094C45.374 30.634 44.582 31.43 45.14 32.752L45.255 33.021C45.868 34.453 46.625 36.221 45.662 38.011C44.637 39.917 42.882 41.189 41.757 40.978C40.633 40.768 37.991 39.389 37.02 38.76C36.049 38.13 32.97 35.594 32.97 34.623C32.97 33.814 35.184 32.468 36.26 31.813C36.474 31.683 36.643 31.581 36.74 31.515C36.851 31.44 37.037 31.325 37.266 31.183C38.247 30.573 40.02 29.473 40.065 28.986C40.12 28.384 40.099 28.208 39.307 26.722C39.139 26.406 38.942 26.068 38.739 25.718C37.985 24.423 37.141 22.973 37.329 21.934C37.539 20.761 39.379 20.089 40.937 19.519C41.131 19.449 41.322 19.379 41.504 19.31L43.127 18.701C44.683 18.119 46.411 17.472 46.697 17.341C47.091 17.16 46.989 16.986 45.794 16.873C45.6006 16.854 45.4072 16.834 45.214 16.813C43.734 16.656 41.005 16.367 39.679 16.736C39.418 16.809 39.126 16.888 38.819 16.971C37.329 17.374 35.502 17.868 35.326 18.153C35.296 18.203 35.266 18.246 35.237 18.286C35.069 18.524 34.96 18.68 35.146 19.692C35.201 19.994 35.315 20.587 35.456 21.321C35.866 23.469 36.509 26.819 36.59 27.571C36.601 27.677 36.614 27.778 36.626 27.876C36.729 28.716 36.797 29.275 35.821 29.498L35.566 29.556C34.464 29.808 32.849 30.179 32.266 30.179C31.682 30.179 30.066 29.809 28.964 29.556L28.71 29.498C27.734 29.275 27.803 28.716 27.906 27.876C27.918 27.778 27.93 27.676 27.941 27.571C28.022 26.818 28.666 23.459 29.078 21.312C29.218 20.582 29.331 19.992 29.386 19.692C29.571 18.68 29.462 18.524 29.294 18.286C29.263 18.2423 29.233 18.198 29.204 18.153C29.03 17.868 27.204 17.374 25.713 16.971C25.406 16.888 25.113 16.809 24.853 16.736C23.526 16.366 20.798 16.656 19.318 16.813C19.092 16.837 18.896 16.858 18.738 16.873C17.542 16.986 17.441 17.16 17.835 17.341C18.12 17.472 19.848 18.119 21.403 18.701C22 18.924 22.573 19.138 23.027 19.31C23.21 19.379 23.4 19.448 23.595 19.52C25.153 20.09 26.993 20.761 27.203 21.934C27.39 22.973 26.546 24.423 25.793 25.718C25.589 26.068 25.393 26.406 25.224 26.722C24.433 28.208 24.412 28.384 24.467 28.986C24.511 29.474 26.283 30.573 27.265 31.183C27.494 31.325 27.68 31.44 27.791 31.515C27.889 31.581 28.057 31.683 28.271 31.813C29.347 32.467 31.561 33.813 31.561 34.623C31.561 35.593 28.483 38.13 27.511 38.76C26.541 39.39 23.899 40.768 22.774 40.978C21.65 41.188 19.894 39.917 18.87 38.012C17.907 36.221 18.663 34.453 19.276 33.022L19.391 32.752C19.95 31.43 19.158 30.634 18.619 30.094C18.5599 30.0348 18.5015 29.9748 18.444 29.914L13.054 24.197C12.896 24.03 12.738 23.877 12.586 23.729C11.858 23.022 11.24 22.421 11.24 20.887C11.24 19.032 18.429 10.351 18.429 10.351C18.429 10.351 24.495 11.508 25.313 11.508C25.966 11.508 27.226 11.075 28.54 10.623C28.873 10.509 29.209 10.393 29.54 10.283C31.175 9.73801 32.266 9.73401 32.266 9.73401C32.266 9.73401 33.356 9.73801 34.992 10.283C35.322 10.393 35.659 10.509 35.992 10.623C37.305 11.075 38.566 11.508 39.218 11.508ZM38.177 42.214C39.459 42.874 40.369 43.342 40.713 43.557C41.158 43.835 40.887 44.36 40.481 44.647C40.076 44.932 34.628 49.146 34.1 49.612L33.885 49.803C33.376 50.262 32.726 50.847 32.265 50.847C31.805 50.847 31.155 50.261 30.645 49.803L30.432 49.612C29.902 49.146 24.455 44.932 24.05 44.646C23.645 44.36 23.373 43.836 23.818 43.556C24.162 43.342 25.073 42.873 26.357 42.212L27.577 41.583C29.497 40.591 31.892 39.746 32.266 39.746C32.639 39.746 35.033 40.59 36.955 41.583C37.391 41.809 37.8 42.021 38.177 42.214Z"
fill="white"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M47.67 6.334L42.081 0H22.45L16.861 6.334C16.861 6.334 11.953 4.972 9.63605 7.287C9.63605 7.287 16.18 6.697 18.429 10.351C18.429 10.351 24.495 11.508 25.313 11.508C26.131 11.508 27.903 10.828 29.539 10.283C31.175 9.738 32.266 9.734 32.266 9.734C32.266 9.734 33.356 9.738 34.992 10.283C36.628 10.828 38.4 11.508 39.218 11.508C40.036 11.508 46.103 10.351 46.103 10.351C48.352 6.697 54.895 7.287 54.895 7.287C52.578 4.972 47.67 6.334 47.67 6.334Z"
fill="url(#paint1_linear_11_3292)"
/>
<defs>
<linearGradient
id="paint0_linear_11_3292"
x1="5.001"
y1="64.319"
x2="59.53"
y2="64.319"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#FF5500" />
<stop offset="0.41" stopColor="#FF5500" />
<stop offset="0.582" stopColor="#FF2000" />
<stop offset="1" stopColor="#FF2000" />
</linearGradient>
<linearGradient
id="paint1_linear_11_3292"
x1="10.608"
y1="11.466"
x2="54.895"
y2="11.466"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#FF452A" />
<stop offset="1" stopColor="#FF2000" />
</linearGradient>
</defs>
</svg>
)
}
import { ColumnCenter } from 'components/Column' import { ColumnCenter } from 'components/Column'
import { MobileAppLogo } from 'components/Icons/MobileAppLogo'
import { PropsWithChildren } from 'react' import { PropsWithChildren } from 'react'
import { ThemedText } from 'theme/components' import { ThemedText } from 'theme/components'
import { Image } from 'ui/src'
import { UNISWAP_LOGO } from 'ui/src/assets'
import { iconSizes } from 'ui/src/theme'
export function ModalContent({ title, subtext, children }: PropsWithChildren<{ title: string; subtext: string }>) { export function ModalContent({ title, subtext, children }: PropsWithChildren<{ title: string; subtext: string }>) {
return ( return (
<ColumnCenter gap="xl"> <ColumnCenter gap="xl">
<ColumnCenter gap="md"> <ColumnCenter gap="md">
<Image height={iconSizes.icon64} source={UNISWAP_LOGO} width={iconSizes.icon64} /> <MobileAppLogo width={64} height={64} />
<ColumnCenter gap="sm"> <ColumnCenter gap="sm">
<ThemedText.H1Medium textAlign="center">{title}</ThemedText.H1Medium> <ThemedText.H1Medium textAlign="center">{title}</ThemedText.H1Medium>
<ThemedText.BodySecondary textAlign="center" maxWidth="400px"> <ThemedText.BodySecondary textAlign="center" maxWidth="400px">
......
...@@ -3,6 +3,7 @@ import ExtensionIllustration from 'assets/images/extensionIllustration.png' ...@@ -3,6 +3,7 @@ import ExtensionIllustration from 'assets/images/extensionIllustration.png'
import WalletIllustration from 'assets/images/walletIllustration.png' import WalletIllustration from 'assets/images/walletIllustration.png'
import Column from 'components/Column' import Column from 'components/Column'
import { AppleLogo } from 'components/Icons/AppleLogo' import { AppleLogo } from 'components/Icons/AppleLogo'
import { BraveBrowserLogo } from 'components/Icons/BraveBrowserLogo'
import { GoogleChromeLogo } from 'components/Icons/GoogleChromeLogo' import { GoogleChromeLogo } from 'components/Icons/GoogleChromeLogo'
import { GooglePlayStoreLogo } from 'components/Icons/GooglePlayStoreLogo' import { GooglePlayStoreLogo } from 'components/Icons/GooglePlayStoreLogo'
import { WiggleIcon } from 'components/NavBar/DownloadApp/GetTheAppButton' import { WiggleIcon } from 'components/NavBar/DownloadApp/GetTheAppButton'
...@@ -64,7 +65,7 @@ export function GetStarted({ toAppDownload }: { toAppDownload: () => void }) { ...@@ -64,7 +65,7 @@ export function GetStarted({ toAppDownload }: { toAppDownload: () => void }) {
<IllustrationContainer> <IllustrationContainer>
<Illustration src={WalletIllustration} alt="Wallet example page" /> <Illustration src={WalletIllustration} alt="Wallet example page" />
</IllustrationContainer> </IllustrationContainer>
<CardInfo title={t('common.uniswapMobile')} details={t('common.iOSAndroid')}> <CardInfo title={t('common.mobileWallet')} details={t('common.iOSAndroid')}>
<Row gap="8px" width="auto"> <Row gap="8px" width="auto">
<WiggleIcon> <WiggleIcon>
<AppleLogo fill={theme.neutral1} /> <AppleLogo fill={theme.neutral1} />
...@@ -82,6 +83,9 @@ export function GetStarted({ toAppDownload }: { toAppDownload: () => void }) { ...@@ -82,6 +83,9 @@ export function GetStarted({ toAppDownload }: { toAppDownload: () => void }) {
</IllustrationContainer> </IllustrationContainer>
<CardInfo title={t('common.chromeExtension')} details={t('common.googleChrome')}> <CardInfo title={t('common.chromeExtension')} details={t('common.googleChrome')}>
<Row gap="8px" width="auto"> <Row gap="8px" width="auto">
<WiggleIcon>
<BraveBrowserLogo width="16px" height="16px" />
</WiggleIcon>
<WiggleIcon> <WiggleIcon>
<GoogleChromeLogo width="16px" height="16px" /> <GoogleChromeLogo width="16px" height="16px" />
</WiggleIcon> </WiggleIcon>
......
...@@ -33,6 +33,7 @@ const Nav = styled.nav` ...@@ -33,6 +33,7 @@ const Nav = styled.nav`
justify-content: center; justify-content: center;
` `
const NavContents = styled.div` const NavContents = styled.div`
max-width: ${({ theme }) => `${theme.breakpoint.xxxl}px`};
width: 100%; width: 100%;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
......
...@@ -119,7 +119,7 @@ export default function SettingsTab({ ...@@ -119,7 +119,7 @@ export default function SettingsTab({
compact?: boolean compact?: boolean
hideRoutingSettings?: boolean hideRoutingSettings?: boolean
}) { }) {
const showDeadlineSettings = !isL2ChainId(chainId) const showDeadlineSettings = isL2ChainId(chainId)
const toggleButtonNode = useRef<HTMLDivElement | null>(null) const toggleButtonNode = useRef<HTMLDivElement | null>(null)
const menuNode = useRef<HTMLDivElement | null>(null) const menuNode = useRef<HTMLDivElement | null>(null)
const isOpen = useModalIsOpen(ApplicationModal.SETTINGS) const isOpen = useModalIsOpen(ApplicationModal.SETTINGS)
......
...@@ -6,7 +6,6 @@ import Modal from 'components/Modal' ...@@ -6,7 +6,6 @@ import Modal from 'components/Modal'
import Row from 'components/Row' import Row from 'components/Row'
import { AppIcon } from 'components/WalletModal/UniswapWalletOptions' import { AppIcon } from 'components/WalletModal/UniswapWalletOptions'
import { useIsMobile } from 'hooks/screenSize' import { useIsMobile } from 'hooks/screenSize'
import useParsedQueryString from 'hooks/useParsedQueryString'
import { Trans } from 'i18n' import { Trans } from 'i18n'
import { useAtom } from 'jotai' import { useAtom } from 'jotai'
import { atomWithStorage } from 'jotai/utils' import { atomWithStorage } from 'jotai/utils'
...@@ -26,9 +25,6 @@ const ModalWrapper = styled.div` ...@@ -26,9 +25,6 @@ const ModalWrapper = styled.div`
@media screen and (max-width: ${BREAKPOINTS.sm}px) { @media screen and (max-width: ${BREAKPOINTS.sm}px) {
flex-direction: column; flex-direction: column;
} }
* {
outline: none;
}
` `
const PromoImage = styled.img` const PromoImage = styled.img`
...@@ -39,7 +35,7 @@ const PromoImage = styled.img` ...@@ -39,7 +35,7 @@ const PromoImage = styled.img`
background: url('/images/extension_promo/announcement_modal_desktop.png'); background: url('/images/extension_promo/announcement_modal_desktop.png');
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: cover; background-size: cover;
flex: 1; flex-shrink: 0;
@media screen and (max-width: ${BREAKPOINTS.sm}px) { @media screen and (max-width: ${BREAKPOINTS.sm}px) {
background: url('/images/extension_promo/announcement_modal_mobile.png'); background: url('/images/extension_promo/announcement_modal_mobile.png');
...@@ -47,7 +43,6 @@ const PromoImage = styled.img` ...@@ -47,7 +43,6 @@ const PromoImage = styled.img`
background-position: 50%; background-position: 50%;
height: 392px; height: 392px;
width: 100%; width: 100%;
flex: unset;
} }
` `
...@@ -62,7 +57,6 @@ const TextWrapper = styled(Column)` ...@@ -62,7 +57,6 @@ const TextWrapper = styled(Column)`
padding: 20px 24px; padding: 20px 24px;
gap: 16px; gap: 16px;
height: 100%; height: 100%;
flex: 1;
@media screen and (max-width: ${BREAKPOINTS.sm}px) { @media screen and (max-width: ${BREAKPOINTS.sm}px) {
gap: 12px; gap: 12px;
...@@ -101,7 +95,6 @@ const showExtensionLaunchAtom = atomWithStorage('showUniswapExtensionLaunchAtom' ...@@ -101,7 +95,6 @@ const showExtensionLaunchAtom = atomWithStorage('showUniswapExtensionLaunchAtom'
export function ExtensionLaunchModal() { export function ExtensionLaunchModal() {
const [showExtensionLaunch, setShowExtensionLaunch] = useAtom(showExtensionLaunchAtom) const [showExtensionLaunch, setShowExtensionLaunch] = useAtom(showExtensionLaunchAtom)
const isOnLandingPage = useParsedQueryString().intro === 'true'
const isMobile = useIsMobile() const isMobile = useIsMobile()
return ( return (
...@@ -109,8 +102,7 @@ export function ExtensionLaunchModal() { ...@@ -109,8 +102,7 @@ export function ExtensionLaunchModal() {
<Modal <Modal
maxWidth={isMobile ? undefined : 520} maxWidth={isMobile ? undefined : 520}
height={isMobile ? 564 : 320} height={isMobile ? 564 : 320}
isOpen={showExtensionLaunch && !isOnLandingPage} isOpen={showExtensionLaunch}
hideBorder
onDismiss={() => setShowExtensionLaunch(false)} onDismiss={() => setShowExtensionLaunch(false)}
> >
<ModalWrapper> <ModalWrapper>
......
...@@ -54,10 +54,10 @@ export const DownloadWalletOption = () => { ...@@ -54,10 +54,10 @@ export const DownloadWalletOption = () => {
<AppIcon src={UNIWALLET_ICON} alt="uniswap-app-icon" /> <AppIcon src={UNIWALLET_ICON} alt="uniswap-app-icon" />
<Row gap="xs"> <Row gap="xs">
<Column> <Column>
<Text variant="buttonLabel3" color="$white" whiteSpace="nowrap"> <Text variant="buttonLabel3" color="$black" whiteSpace="nowrap">
<Trans i18nKey="common.getUniswapWallet" /> <Trans i18nKey="common.getUniswapWallet" />
</Text> </Text>
<Text variant="body4" color="$white" whiteSpace="nowrap"> <Text variant="body4" color="$black" whiteSpace="nowrap">
<Trans i18nKey="common.availableOnIOSAndroidChrome" /> <Trans i18nKey="common.availableOnIOSAndroidChrome" />
</Text> </Text>
</Column> </Column>
......
...@@ -10,7 +10,7 @@ const StyledLink = styled(ExternalLink)` ...@@ -10,7 +10,7 @@ const StyledLink = styled(ExternalLink)`
export default function PrivacyPolicyNotice() { export default function PrivacyPolicyNotice() {
return ( return (
<ThemedText.BodySmall color="neutral2"> <ThemedText.BodySmall color="neutral2">
<Trans i18nKey="wallet.connectingAgreement" />{' '} <Trans i18nKey="wallet.connectingAgreement" />
<StyledLink href="https://uniswap.org/terms-of-service/"> <StyledLink href="https://uniswap.org/terms-of-service/">
<Trans i18nKey="common.termsOfService" />{' '} <Trans i18nKey="common.termsOfService" />{' '}
</StyledLink> </StyledLink>
......
...@@ -10,7 +10,7 @@ import styled from 'lib/styled-components' ...@@ -10,7 +10,7 @@ import styled from 'lib/styled-components'
import { BREAKPOINTS } from 'theme' import { BREAKPOINTS } from 'theme'
import { Z_INDEX } from 'theme/zIndex' import { Z_INDEX } from 'theme/zIndex'
import { Text } from 'ui/src' import { Text } from 'ui/src'
import { ScanQr } from 'ui/src/components/icons' import { Mobile, QrCode } from 'ui/src/components/icons'
import { FeatureFlags } from 'uniswap/src/features/gating/flags' import { FeatureFlags } from 'uniswap/src/features/gating/flags'
import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks'
...@@ -79,17 +79,20 @@ export function UniswapWalletOptions() { ...@@ -79,17 +79,20 @@ export function UniswapWalletOptions() {
<DownloadWalletOption /> <DownloadWalletOption />
) : null} ) : null}
<OptionContainer gap="md" onClick={() => connect({ connector: uniswapWalletConnectConnector })}> <OptionContainer gap="md" onClick={() => connect({ connector: uniswapWalletConnectConnector })}>
<ScanQr size="$icon.40" minWidth={40} color="$accent1" backgroundColor="$accent2" borderRadius={8} p={7} /> <Mobile size="$icon.40" minWidth={40} color="$accent1" backgroundColor="$accent2" borderRadius={8} p={7} />
<Row gap="xs"> <Row gap="xs">
<Column> <Column>
<Text variant="buttonLabel3" color="$neutral1" whiteSpace="nowrap"> <Text variant="buttonLabel3" color="$neutral1" whiteSpace="nowrap">
<Trans i18nKey="common.uniswapMobile" /> <Trans i18nKey="common.mobileWallet" />
</Text> </Text>
<Text variant="body4" color="$neutral2" whiteSpace="nowrap"> <Text variant="body4" color="$neutral2" whiteSpace="nowrap">
<Trans i18nKey="wallet.scanToConnect" /> <Trans i18nKey="wallet.scanToConnect" />
</Text> </Text>
</Column> </Column>
</Row> </Row>
<TagContainer>
<QrCode size={20} color="$neutral2" />
</TagContainer>
</OptionContainer> </OptionContainer>
</Column> </Column>
</Column> </Column>
......
...@@ -159,6 +159,12 @@ exports[`UniswapWalletOptions Test Download wallet option should be visible if e ...@@ -159,6 +159,12 @@ exports[`UniswapWalletOptions Test Download wallet option should be visible if e
filter: drop-shadow(0px 1.179px 3.537px rgba(255,117,249,0.24)); filter: drop-shadow(0px 1.179px 3.537px rgba(255,117,249,0.24));
} }
@media screen and (max-width:396px) {
.c11 {
display: none;
}
}
<span <span
class="t_light is_inversed _dsp_contents" class="t_light is_inversed _dsp_contents"
> >
...@@ -193,13 +199,13 @@ exports[`UniswapWalletOptions Test Download wallet option should be visible if e ...@@ -193,13 +199,13 @@ exports[`UniswapWalletOptions Test Download wallet option should be visible if e
class="c9" class="c9"
> >
<span <span
class="font_button _fontFamily-299667014 _display-inline _boxSizing-border-box _wordWrap-break-word _mt-0px _mr-0px _mb-0px _ml-0px _color-137133827 _fontSize-16px _lineHeight-24px _fontWeight-500 _whiteSpace-nowrap" class="font_button _fontFamily-299667014 _display-inline _boxSizing-border-box _wordWrap-break-word _mt-0px _mr-0px _mb-0px _ml-0px _color-137133858 _fontSize-16px _lineHeight-24px _fontWeight-500 _whiteSpace-nowrap"
data-disable-theme="true" data-disable-theme="true"
> >
Get Uniswap Wallet Get Uniswap Wallet
</span> </span>
<span <span
class="font_body _fontFamily-299667014 _display-inline _boxSizing-border-box _wordWrap-break-word _mt-0px _mr-0px _mb-0px _ml-0px _color-137133827 _fontSize-12px _lineHeight-16px _fontWeight-400 _whiteSpace-nowrap" class="font_body _fontFamily-299667014 _display-inline _boxSizing-border-box _wordWrap-break-word _mt-0px _mr-0px _mb-0px _ml-0px _color-137133858 _fontSize-12px _lineHeight-16px _fontWeight-400 _whiteSpace-nowrap"
data-disable-theme="true" data-disable-theme="true"
> >
Available on iOS, Android, and Chrome Available on iOS, Android, and Chrome
...@@ -215,14 +221,11 @@ exports[`UniswapWalletOptions Test Download wallet option should be visible if e ...@@ -215,14 +221,11 @@ exports[`UniswapWalletOptions Test Download wallet option should be visible if e
fill="none" fill="none"
stroke-width="8" stroke-width="8"
style="color: rgb(252, 114, 255); width: 40px; height: 40px; min-width: 40px; background-color: rgb(255, 239, 255); border-top-left-radius: 8px; border-top-right-radius: 8px; border-bottom-right-radius: 8px; border-bottom-left-radius: 8px; padding: 7px 7px 7px 7px;" style="color: rgb(252, 114, 255); width: 40px; height: 40px; min-width: 40px; background-color: rgb(255, 239, 255); border-top-left-radius: 8px; border-top-right-radius: 8px; border-bottom-right-radius: 8px; border-bottom-left-radius: 8px; padding: 7px 7px 7px 7px;"
viewBox="0 0 22 22" viewBox="0 0 43 43"
> >
<path <path
d="M6.92609 1.83331H3.87053C3.33028 1.83331 2.81215 2.04793 2.43013 2.42995C2.04811 2.81197 1.8335 3.33009 1.8335 3.87035V6.92591M20.1668 6.92591V3.87035C20.1668 3.33009 19.9522 2.81197 19.5702 2.42995C19.1882 2.04793 18.67 1.83331 18.1298 1.83331H15.0742M15.0742 20.1666H18.1298C18.67 20.1666 19.1882 19.952 19.5702 19.57C19.9522 19.188 20.1668 18.6699 20.1668 18.1296V15.0741M1.8335 15.0741V18.1296C1.8335 18.6699 2.04811 19.188 2.43013 19.57C2.81215 19.952 3.33028 20.1666 3.87053 20.1666H6.92609M12.1829 12.1827V14.5483M12.1829 16.9139H14.5484V12.1827M14.5482 13.3654H16.9138M16.914 15.7311V16.9139M5.67739 5.08581H9.22578C9.5524 5.08581 9.81717 5.35059 9.81717 5.67721V9.22559C9.81717 9.55221 9.5524 9.81699 9.22578 9.81699H5.67739C5.35077 9.81699 5.08599 9.55221 5.08599 9.22559V5.67721C5.08599 5.35059 5.35077 5.08581 5.67739 5.08581ZM5.67739 12.1827H9.22578C9.5524 12.1827 9.81717 12.4475 9.81717 12.7741V16.3225C9.81717 16.6491 9.5524 16.9139 9.22578 16.9139H5.67739C5.35077 16.9139 5.08599 16.6491 5.08599 16.3225V12.7741C5.08599 12.4475 5.35077 12.1827 5.67739 12.1827ZM12.7743 5.08581H16.3226C16.6493 5.08581 16.914 5.35059 16.914 5.67721V9.22559C16.914 9.55221 16.6493 9.81699 16.3226 9.81699H12.7743C12.4476 9.81699 12.1829 9.55221 12.1829 9.22559V5.67721C12.1829 5.35059 12.4476 5.08581 12.7743 5.08581Z" d="M28.3632 6.11328H14.3633C10.8633 6.11328 9.11328 7.86327 9.11328 11.3633V32.3632C9.11328 35.8632 10.8633 37.6132 14.3633 37.6132H28.3632C31.8632 37.6132 33.6132 35.8632 33.6132 32.3632V11.3633C33.6132 7.86327 31.8632 6.11328 28.3632 6.11328ZM21.3632 34.1132C20.3972 34.1132 19.6132 33.3292 19.6132 32.3632C19.6132 31.3972 20.3972 30.6132 21.3632 30.6132C22.3292 30.6132 23.1132 31.3972 23.1132 32.3632C23.1132 33.3292 22.3292 34.1132 21.3632 34.1132ZM23.9882 12.6758H18.7382C18.0137 12.6758 17.4257 12.0878 17.4257 11.3633C17.4257 10.6388 18.0137 10.0508 18.7382 10.0508H23.9882C24.7127 10.0508 25.3007 10.6388 25.3007 11.3633C25.3007 12.0878 24.7127 12.6758 23.9882 12.6758Z"
stroke="currentColor" fill="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1.75"
/> />
</svg> </svg>
<div <div
...@@ -235,7 +238,7 @@ exports[`UniswapWalletOptions Test Download wallet option should be visible if e ...@@ -235,7 +238,7 @@ exports[`UniswapWalletOptions Test Download wallet option should be visible if e
class="font_button _fontFamily-299667014 _display-inline _boxSizing-border-box _wordWrap-break-word _mt-0px _mr-0px _mb-0px _ml-0px _color-843134974 _fontSize-16px _lineHeight-24px _fontWeight-500 _whiteSpace-nowrap" class="font_button _fontFamily-299667014 _display-inline _boxSizing-border-box _wordWrap-break-word _mt-0px _mr-0px _mb-0px _ml-0px _color-843134974 _fontSize-16px _lineHeight-24px _fontWeight-500 _whiteSpace-nowrap"
data-disable-theme="true" data-disable-theme="true"
> >
Uniswap Mobile Mobile Wallet
</span> </span>
<span <span
class="font_body _fontFamily-299667014 _display-inline _boxSizing-border-box _wordWrap-break-word _mt-0px _mr-0px _mb-0px _ml-0px _color-843135005 _fontSize-12px _lineHeight-16px _fontWeight-400 _whiteSpace-nowrap" class="font_body _fontFamily-299667014 _display-inline _boxSizing-border-box _wordWrap-break-word _mt-0px _mr-0px _mb-0px _ml-0px _color-843135005 _fontSize-12px _lineHeight-16px _fontWeight-400 _whiteSpace-nowrap"
...@@ -245,6 +248,66 @@ exports[`UniswapWalletOptions Test Download wallet option should be visible if e ...@@ -245,6 +248,66 @@ exports[`UniswapWalletOptions Test Download wallet option should be visible if e
</span> </span>
</div> </div>
</div> </div>
<div
class="c11"
>
<svg
fill="none"
stroke-width="8"
style="color: rgb(125, 125, 125); width: 20px; height: 20px;"
viewBox="0 0 24 24"
>
<path
d="M9 2H3C2.44772 2 2 2.44772 2 3V9C2 9.55228 2.44772 10 3 10H9C9.55228 10 10 9.55228 10 9V3C10 2.44772 9.55228 2 9 2Z"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M9 13.9999H3C2.44772 13.9999 2 14.4476 2 14.9999V20.9999C2 21.5522 2.44772 21.9999 3 21.9999H9C9.55228 21.9999 10 21.5522 10 20.9999V14.9999C10 14.4476 9.55228 13.9999 9 13.9999Z"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M21 2H15C14.4477 2 14 2.44772 14 3V9C14 9.55228 14.4477 10 15 10H21C21.5523 10 22 9.55228 22 9V3C22 2.44772 21.5523 2 21 2Z"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M14 13.9999V17.9999"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M14 21.9999H18V13.9999"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M18 16H22"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M22 20.0001V22.0001"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
</svg>
</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -361,6 +424,12 @@ exports[`UniswapWalletOptions Test Download wallet option should not be visible ...@@ -361,6 +424,12 @@ exports[`UniswapWalletOptions Test Download wallet option should not be visible
background: #22222212; background: #22222212;
} }
@media screen and (max-width:396px) {
.c7 {
display: none;
}
}
<span <span
class=" _dsp_contents" class=" _dsp_contents"
> >
...@@ -380,14 +449,11 @@ exports[`UniswapWalletOptions Test Download wallet option should not be visible ...@@ -380,14 +449,11 @@ exports[`UniswapWalletOptions Test Download wallet option should not be visible
fill="none" fill="none"
stroke-width="8" stroke-width="8"
style="color: rgb(252, 114, 255); width: 40px; height: 40px; min-width: 40px; background-color: rgb(255, 239, 255); border-top-left-radius: 8px; border-top-right-radius: 8px; border-bottom-right-radius: 8px; border-bottom-left-radius: 8px; padding: 7px 7px 7px 7px;" style="color: rgb(252, 114, 255); width: 40px; height: 40px; min-width: 40px; background-color: rgb(255, 239, 255); border-top-left-radius: 8px; border-top-right-radius: 8px; border-bottom-right-radius: 8px; border-bottom-left-radius: 8px; padding: 7px 7px 7px 7px;"
viewBox="0 0 22 22" viewBox="0 0 43 43"
> >
<path <path
d="M6.92609 1.83331H3.87053C3.33028 1.83331 2.81215 2.04793 2.43013 2.42995C2.04811 2.81197 1.8335 3.33009 1.8335 3.87035V6.92591M20.1668 6.92591V3.87035C20.1668 3.33009 19.9522 2.81197 19.5702 2.42995C19.1882 2.04793 18.67 1.83331 18.1298 1.83331H15.0742M15.0742 20.1666H18.1298C18.67 20.1666 19.1882 19.952 19.5702 19.57C19.9522 19.188 20.1668 18.6699 20.1668 18.1296V15.0741M1.8335 15.0741V18.1296C1.8335 18.6699 2.04811 19.188 2.43013 19.57C2.81215 19.952 3.33028 20.1666 3.87053 20.1666H6.92609M12.1829 12.1827V14.5483M12.1829 16.9139H14.5484V12.1827M14.5482 13.3654H16.9138M16.914 15.7311V16.9139M5.67739 5.08581H9.22578C9.5524 5.08581 9.81717 5.35059 9.81717 5.67721V9.22559C9.81717 9.55221 9.5524 9.81699 9.22578 9.81699H5.67739C5.35077 9.81699 5.08599 9.55221 5.08599 9.22559V5.67721C5.08599 5.35059 5.35077 5.08581 5.67739 5.08581ZM5.67739 12.1827H9.22578C9.5524 12.1827 9.81717 12.4475 9.81717 12.7741V16.3225C9.81717 16.6491 9.5524 16.9139 9.22578 16.9139H5.67739C5.35077 16.9139 5.08599 16.6491 5.08599 16.3225V12.7741C5.08599 12.4475 5.35077 12.1827 5.67739 12.1827ZM12.7743 5.08581H16.3226C16.6493 5.08581 16.914 5.35059 16.914 5.67721V9.22559C16.914 9.55221 16.6493 9.81699 16.3226 9.81699H12.7743C12.4476 9.81699 12.1829 9.55221 12.1829 9.22559V5.67721C12.1829 5.35059 12.4476 5.08581 12.7743 5.08581Z" d="M28.3632 6.11328H14.3633C10.8633 6.11328 9.11328 7.86327 9.11328 11.3633V32.3632C9.11328 35.8632 10.8633 37.6132 14.3633 37.6132H28.3632C31.8632 37.6132 33.6132 35.8632 33.6132 32.3632V11.3633C33.6132 7.86327 31.8632 6.11328 28.3632 6.11328ZM21.3632 34.1132C20.3972 34.1132 19.6132 33.3292 19.6132 32.3632C19.6132 31.3972 20.3972 30.6132 21.3632 30.6132C22.3292 30.6132 23.1132 31.3972 23.1132 32.3632C23.1132 33.3292 22.3292 34.1132 21.3632 34.1132ZM23.9882 12.6758H18.7382C18.0137 12.6758 17.4257 12.0878 17.4257 11.3633C17.4257 10.6388 18.0137 10.0508 18.7382 10.0508H23.9882C24.7127 10.0508 25.3007 10.6388 25.3007 11.3633C25.3007 12.0878 24.7127 12.6758 23.9882 12.6758Z"
stroke="currentColor" fill="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1.75"
/> />
</svg> </svg>
<div <div
...@@ -400,7 +466,7 @@ exports[`UniswapWalletOptions Test Download wallet option should not be visible ...@@ -400,7 +466,7 @@ exports[`UniswapWalletOptions Test Download wallet option should not be visible
class="font_button _fontFamily-299667014 _display-inline _boxSizing-border-box _wordWrap-break-word _mt-0px _mr-0px _mb-0px _ml-0px _color-843134974 _fontSize-16px _lineHeight-24px _fontWeight-500 _whiteSpace-nowrap" class="font_button _fontFamily-299667014 _display-inline _boxSizing-border-box _wordWrap-break-word _mt-0px _mr-0px _mb-0px _ml-0px _color-843134974 _fontSize-16px _lineHeight-24px _fontWeight-500 _whiteSpace-nowrap"
data-disable-theme="true" data-disable-theme="true"
> >
Uniswap Mobile Mobile Wallet
</span> </span>
<span <span
class="font_body _fontFamily-299667014 _display-inline _boxSizing-border-box _wordWrap-break-word _mt-0px _mr-0px _mb-0px _ml-0px _color-843135005 _fontSize-12px _lineHeight-16px _fontWeight-400 _whiteSpace-nowrap" class="font_body _fontFamily-299667014 _display-inline _boxSizing-border-box _wordWrap-break-word _mt-0px _mr-0px _mb-0px _ml-0px _color-843135005 _fontSize-12px _lineHeight-16px _fontWeight-400 _whiteSpace-nowrap"
...@@ -410,6 +476,66 @@ exports[`UniswapWalletOptions Test Download wallet option should not be visible ...@@ -410,6 +476,66 @@ exports[`UniswapWalletOptions Test Download wallet option should not be visible
</span> </span>
</div> </div>
</div> </div>
<div
class="c7"
>
<svg
fill="none"
stroke-width="8"
style="color: rgb(125, 125, 125); width: 20px; height: 20px;"
viewBox="0 0 24 24"
>
<path
d="M9 2H3C2.44772 2 2 2.44772 2 3V9C2 9.55228 2.44772 10 3 10H9C9.55228 10 10 9.55228 10 9V3C10 2.44772 9.55228 2 9 2Z"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M9 13.9999H3C2.44772 13.9999 2 14.4476 2 14.9999V20.9999C2 21.5522 2.44772 21.9999 3 21.9999H9C9.55228 21.9999 10 21.5522 10 20.9999V14.9999C10 14.4476 9.55228 13.9999 9 13.9999Z"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M21 2H15C14.4477 2 14 2.44772 14 3V9C14 9.55228 14.4477 10 15 10H21C21.5523 10 22 9.55228 22 9V3C22 2.44772 21.5523 2 21 2Z"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M14 13.9999V17.9999"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M14 21.9999H18V13.9999"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M18 16H22"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M22 20.0001V22.0001"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
</svg>
</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -607,14 +733,11 @@ exports[`UniswapWalletOptions Test Extension connecter should be shown if detect ...@@ -607,14 +733,11 @@ exports[`UniswapWalletOptions Test Extension connecter should be shown if detect
fill="none" fill="none"
stroke-width="8" stroke-width="8"
style="color: rgb(252, 114, 255); width: 40px; height: 40px; min-width: 40px; background-color: rgb(255, 239, 255); border-top-left-radius: 8px; border-top-right-radius: 8px; border-bottom-right-radius: 8px; border-bottom-left-radius: 8px; padding: 7px 7px 7px 7px;" style="color: rgb(252, 114, 255); width: 40px; height: 40px; min-width: 40px; background-color: rgb(255, 239, 255); border-top-left-radius: 8px; border-top-right-radius: 8px; border-bottom-right-radius: 8px; border-bottom-left-radius: 8px; padding: 7px 7px 7px 7px;"
viewBox="0 0 22 22" viewBox="0 0 43 43"
> >
<path <path
d="M6.92609 1.83331H3.87053C3.33028 1.83331 2.81215 2.04793 2.43013 2.42995C2.04811 2.81197 1.8335 3.33009 1.8335 3.87035V6.92591M20.1668 6.92591V3.87035C20.1668 3.33009 19.9522 2.81197 19.5702 2.42995C19.1882 2.04793 18.67 1.83331 18.1298 1.83331H15.0742M15.0742 20.1666H18.1298C18.67 20.1666 19.1882 19.952 19.5702 19.57C19.9522 19.188 20.1668 18.6699 20.1668 18.1296V15.0741M1.8335 15.0741V18.1296C1.8335 18.6699 2.04811 19.188 2.43013 19.57C2.81215 19.952 3.33028 20.1666 3.87053 20.1666H6.92609M12.1829 12.1827V14.5483M12.1829 16.9139H14.5484V12.1827M14.5482 13.3654H16.9138M16.914 15.7311V16.9139M5.67739 5.08581H9.22578C9.5524 5.08581 9.81717 5.35059 9.81717 5.67721V9.22559C9.81717 9.55221 9.5524 9.81699 9.22578 9.81699H5.67739C5.35077 9.81699 5.08599 9.55221 5.08599 9.22559V5.67721C5.08599 5.35059 5.35077 5.08581 5.67739 5.08581ZM5.67739 12.1827H9.22578C9.5524 12.1827 9.81717 12.4475 9.81717 12.7741V16.3225C9.81717 16.6491 9.5524 16.9139 9.22578 16.9139H5.67739C5.35077 16.9139 5.08599 16.6491 5.08599 16.3225V12.7741C5.08599 12.4475 5.35077 12.1827 5.67739 12.1827ZM12.7743 5.08581H16.3226C16.6493 5.08581 16.914 5.35059 16.914 5.67721V9.22559C16.914 9.55221 16.6493 9.81699 16.3226 9.81699H12.7743C12.4476 9.81699 12.1829 9.55221 12.1829 9.22559V5.67721C12.1829 5.35059 12.4476 5.08581 12.7743 5.08581Z" d="M28.3632 6.11328H14.3633C10.8633 6.11328 9.11328 7.86327 9.11328 11.3633V32.3632C9.11328 35.8632 10.8633 37.6132 14.3633 37.6132H28.3632C31.8632 37.6132 33.6132 35.8632 33.6132 32.3632V11.3633C33.6132 7.86327 31.8632 6.11328 28.3632 6.11328ZM21.3632 34.1132C20.3972 34.1132 19.6132 33.3292 19.6132 32.3632C19.6132 31.3972 20.3972 30.6132 21.3632 30.6132C22.3292 30.6132 23.1132 31.3972 23.1132 32.3632C23.1132 33.3292 22.3292 34.1132 21.3632 34.1132ZM23.9882 12.6758H18.7382C18.0137 12.6758 17.4257 12.0878 17.4257 11.3633C17.4257 10.6388 18.0137 10.0508 18.7382 10.0508H23.9882C24.7127 10.0508 25.3007 10.6388 25.3007 11.3633C25.3007 12.0878 24.7127 12.6758 23.9882 12.6758Z"
stroke="currentColor" fill="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1.75"
/> />
</svg> </svg>
<div <div
...@@ -627,7 +750,7 @@ exports[`UniswapWalletOptions Test Extension connecter should be shown if detect ...@@ -627,7 +750,7 @@ exports[`UniswapWalletOptions Test Extension connecter should be shown if detect
class="font_button _fontFamily-299667014 _display-inline _boxSizing-border-box _wordWrap-break-word _mt-0px _mr-0px _mb-0px _ml-0px _color-843134974 _fontSize-16px _lineHeight-24px _fontWeight-500 _whiteSpace-nowrap" class="font_button _fontFamily-299667014 _display-inline _boxSizing-border-box _wordWrap-break-word _mt-0px _mr-0px _mb-0px _ml-0px _color-843134974 _fontSize-16px _lineHeight-24px _fontWeight-500 _whiteSpace-nowrap"
data-disable-theme="true" data-disable-theme="true"
> >
Uniswap Mobile Mobile Wallet
</span> </span>
<span <span
class="font_body _fontFamily-299667014 _display-inline _boxSizing-border-box _wordWrap-break-word _mt-0px _mr-0px _mb-0px _ml-0px _color-843135005 _fontSize-12px _lineHeight-16px _fontWeight-400 _whiteSpace-nowrap" class="font_body _fontFamily-299667014 _display-inline _boxSizing-border-box _wordWrap-break-word _mt-0px _mr-0px _mb-0px _ml-0px _color-843135005 _fontSize-12px _lineHeight-16px _fontWeight-400 _whiteSpace-nowrap"
...@@ -637,6 +760,66 @@ exports[`UniswapWalletOptions Test Extension connecter should be shown if detect ...@@ -637,6 +760,66 @@ exports[`UniswapWalletOptions Test Extension connecter should be shown if detect
</span> </span>
</div> </div>
</div> </div>
<div
class="c7"
>
<svg
fill="none"
stroke-width="8"
style="color: rgb(125, 125, 125); width: 20px; height: 20px;"
viewBox="0 0 24 24"
>
<path
d="M9 2H3C2.44772 2 2 2.44772 2 3V9C2 9.55228 2.44772 10 3 10H9C9.55228 10 10 9.55228 10 9V3C10 2.44772 9.55228 2 9 2Z"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M9 13.9999H3C2.44772 13.9999 2 14.4476 2 14.9999V20.9999C2 21.5522 2.44772 21.9999 3 21.9999H9C9.55228 21.9999 10 21.5522 10 20.9999V14.9999C10 14.4476 9.55228 13.9999 9 13.9999Z"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M21 2H15C14.4477 2 14 2.44772 14 3V9C14 9.55228 14.4477 10 15 10H21C21.5523 10 22 9.55228 22 9V3C22 2.44772 21.5523 2 21 2Z"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M14 13.9999V17.9999"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M14 21.9999H18V13.9999"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M18 16H22"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
<path
d="M22 20.0001V22.0001"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
/>
</svg>
</div>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -75,7 +75,7 @@ export default function WalletModal({ openSettings }: { openSettings: () => void ...@@ -75,7 +75,7 @@ export default function WalletModal({ openSettings }: { openSettings: () => void
const showUniswapWalletOptions = useUniswapWalletOptions() const showUniswapWalletOptions = useUniswapWalletOptions()
const connectors = useOrderedConnections(showUniswapWalletOptions) const connectors = useOrderedConnections(showUniswapWalletOptions)
const isUniExtensionAvailable = useIsUniExtensionAvailable() const isUniExtensionAvailable = useIsUniExtensionAvailable()
const [showOtherWallets, toggleShowOtherWallets] = useReducer((s) => !s, true) const [showOtherWallets, toggleShowOtherWallets] = useReducer((s) => !s, false)
return ( return (
<Wrapper data-testid="wallet-modal" isUniExtensionAvailable={isUniExtensionAvailable}> <Wrapper data-testid="wallet-modal" isUniExtensionAvailable={isUniExtensionAvailable}>
......
...@@ -288,6 +288,7 @@ ...@@ -288,6 +288,7 @@
"common.mint.failed": "Mint failed", "common.mint.failed": "Mint failed",
"common.minted": "Minted", "common.minted": "Minted",
"common.minting": "Minting", "common.minting": "Minting",
"common.mobileWallet": "Mobile Wallet",
"common.more": "More", "common.more": "More",
"common.navigationButton": "Navigation button", "common.navigationButton": "Navigation button",
"common.needHelp": "Need help?", "common.needHelp": "Need help?",
...@@ -485,7 +486,6 @@ ...@@ -485,7 +486,6 @@
"common.unavailable": "Unavailable", "common.unavailable": "Unavailable",
"common.uniGovernance": "UNI Governance", "common.uniGovernance": "UNI Governance",
"common.uniInterface": "Uniswap Interface", "common.uniInterface": "Uniswap Interface",
"common.uniswapMobile": "Uniswap Mobile",
"common.uniswapProtocol": "Uniswap Protocol", "common.uniswapProtocol": "Uniswap Protocol",
"common.uniswapTVL": "Uniswap TVL", "common.uniswapTVL": "Uniswap TVL",
"common.uniswapWallet": "Uniswap wallet", "common.uniswapWallet": "Uniswap wallet",
...@@ -583,7 +583,7 @@ ...@@ -583,7 +583,7 @@
"explore.unableToDisplayHistorical": "Unable to display historical volume data for the current chain.", "explore.unableToDisplayHistorical": "Unable to display historical volume data for the current chain.",
"explore.unableToDisplayHistoricalTVL": "Unable to display historical TVL data for the current chain.", "explore.unableToDisplayHistoricalTVL": "Unable to display historical TVL data for the current chain.",
"explore.uniVolume": "Uniswap volume", "explore.uniVolume": "Uniswap volume",
"extension.announcement": "The Uniswap Extension is here. Swap, sign transactions, and send tokens right from your browser.", "extension.announcement": "The Uniswap Extension Beta is here. Swap, sign transactions, and send tokens right from your sidebar.",
"extension.introduction": "Introducing the Uniswap Extension.", "extension.introduction": "Introducing the Uniswap Extension.",
"extension.open": "Open Uniswap Extension", "extension.open": "Open Uniswap Extension",
"fee.bestForExotic": "Best for exotic pairs.", "fee.bestForExotic": "Best for exotic pairs.",
......
...@@ -16,6 +16,8 @@ import { UniverseChainId } from 'uniswap/src/types/chains' ...@@ -16,6 +16,8 @@ import { UniverseChainId } from 'uniswap/src/types/chains'
const Container = styled(Box)` const Container = styled(Box)`
min-width: 100%; min-width: 100%;
min-height: 100vh;
height: min-content;
padding-top: ${({ theme }) => theme.navHeight}px; padding-top: ${({ theme }) => theme.navHeight}px;
` `
const LandingSwapContainer = styled(Box)` const LandingSwapContainer = styled(Box)`
...@@ -104,7 +106,6 @@ export function Hero({ scrollToRef, transition }: HeroProps) { ...@@ -104,7 +106,6 @@ export function Hero({ scrollToRef, transition }: HeroProps) {
return ( return (
<Container <Container
position="relative" position="relative"
height="100vh"
justify="center" justify="center"
style={{ transform: `translate(0px, ${translateY}px)`, opacity: opacityY }} style={{ transform: `translate(0px, ${translateY}px)`, opacity: opacityY }}
> >
......
...@@ -19,7 +19,7 @@ import { BottomSheetModalProps } from 'uniswap/src/components/modals/BottomSheet ...@@ -19,7 +19,7 @@ import { BottomSheetModalProps } from 'uniswap/src/components/modals/BottomSheet
import { HandleBar } from 'uniswap/src/components/modals/HandleBar' import { HandleBar } from 'uniswap/src/components/modals/HandleBar'
import Trace from 'uniswap/src/features/telemetry/Trace' import Trace from 'uniswap/src/features/telemetry/Trace'
import { useKeyboardLayout } from 'uniswap/src/utils/useKeyboardLayout' import { useKeyboardLayout } from 'uniswap/src/utils/useKeyboardLayout'
import { isIOS } from 'utilities/src/platform' import { isAndroid, isIOS } from 'utilities/src/platform'
/** /**
* (android only) * (android only)
...@@ -250,6 +250,8 @@ function BottomSheetModalContents({ ...@@ -250,6 +250,8 @@ function BottomSheetModalContents({
{...background} {...background}
{...backdrop} {...backdrop}
ref={modalRef} ref={modalRef}
// Adds vertical pan gesture activate offset to avoid nested scroll gesture handler conflicts on android
activeOffsetY={isAndroid ? 12 : undefined}
animatedPosition={animatedPosition} animatedPosition={animatedPosition}
backgroundStyle={backgroundStyle} backgroundStyle={backgroundStyle}
containerComponent={containerComponent} containerComponent={containerComponent}
......
...@@ -18,6 +18,7 @@ export const ServiceProviderLogoStyles = { ...@@ -18,6 +18,7 @@ export const ServiceProviderLogoStyles = {
icon: { icon: {
height: SERVICE_PROVIDER_ICON_SIZE, height: SERVICE_PROVIDER_ICON_SIZE,
width: SERVICE_PROVIDER_ICON_SIZE, width: SERVICE_PROVIDER_ICON_SIZE,
borderRadius: SERVICE_PROVIDER_ICON_BORDER_RADIUS,
}, },
uniswapLogoWrapper: { uniswapLogoWrapper: {
backgroundColor: '#FFEFF8', // #FFD8EF with 40% opacity on a white background backgroundColor: '#FFEFF8', // #FFD8EF with 40% opacity on a white background
......
...@@ -6,9 +6,8 @@ export enum DynamicConfigs { ...@@ -6,9 +6,8 @@ export enum DynamicConfigs {
// Wallet // Wallet
MobileForceUpgrade = 'force_upgrade', MobileForceUpgrade = 'force_upgrade',
OnDeviceRecovery = 'on_device_recovery', OnDeviceRecovery = 'on_device_recovery',
PollingIntervals = 'polling_intervals',
Slippage = 'slippage_configs',
UwuLink = 'uwulink_config', UwuLink = 'uwulink_config',
Swap = 'swap_config',
// Web // Web
QuickRouteChains = 'quick_route_chains', QuickRouteChains = 'quick_route_chains',
...@@ -26,13 +25,10 @@ export enum OnDeviceRecoveryConfigKey { ...@@ -26,13 +25,10 @@ export enum OnDeviceRecoveryConfigKey {
MaxMnemonicsToLoad = 'maxMnemonicsToLoad', MaxMnemonicsToLoad = 'maxMnemonicsToLoad',
} }
export enum PollingIntervalsConfigKey { export enum SwapConfigKey {
AverageL1BlockTimeMs = 'averageL1BlockTimeMs', AverageL1BlockTimeMs = 'averageL1BlockTimeMs',
AverageL2BlockTimeMs = 'averageL2BlockTimeMs', AverageL2BlockTimeMs = 'averageL2BlockTimeMs',
TradingApiSwapRequestMs = 'tradingApiSwapRequestMs', TradingApiSwapRequestMs = 'tradingApiSwapRequestMs',
}
export enum SlippageConfigKey {
MinAutoSlippageToleranceL2 = 'minAutoSlippageToleranceL2', MinAutoSlippageToleranceL2 = 'minAutoSlippageToleranceL2',
} }
...@@ -49,9 +45,8 @@ export type DynamicConfigKeys = { ...@@ -49,9 +45,8 @@ export type DynamicConfigKeys = {
// Wallet // Wallet
[DynamicConfigs.MobileForceUpgrade]: ForceUpgradeConfigKey [DynamicConfigs.MobileForceUpgrade]: ForceUpgradeConfigKey
[DynamicConfigs.OnDeviceRecovery]: OnDeviceRecoveryConfigKey [DynamicConfigs.OnDeviceRecovery]: OnDeviceRecoveryConfigKey
[DynamicConfigs.PollingIntervals]: PollingIntervalsConfigKey
[DynamicConfigs.Slippage]: SlippageConfigKey
[DynamicConfigs.UwuLink]: UwuLinkConfigKey [DynamicConfigs.UwuLink]: UwuLinkConfigKey
[DynamicConfigs.Swap]: SwapConfigKey
// Web // Web
[DynamicConfigs.QuickRouteChains]: QuickRouteChainsConfigKey [DynamicConfigs.QuickRouteChains]: QuickRouteChainsConfigKey
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
export enum MobileEventName { export enum MobileEventName {
AppRating = 'App Rating', AppRating = 'App Rating',
AutomatedOnDeviceRecoveryTriggered = 'Automated On Device Recovery Triggered', AutomatedOnDeviceRecoveryTriggered = 'Automated On Device Recovery Triggered',
AutomatedOnDeviceRecoveryMnemonicsFound = 'Automated On Device Recovery Mnemonics Found',
AutomatedOnDeviceRecoverySingleMnemonicFetched = 'Automated On Device Recovery Mnemonic Fetched',
BalancesReport = 'Balances Report', BalancesReport = 'Balances Report',
DeepLinkOpened = 'Deep Link Opened', DeepLinkOpened = 'Deep Link Opened',
ExploreFilterSelected = 'Explore Filter Selected', ExploreFilterSelected = 'Explore Filter Selected',
......
...@@ -135,6 +135,10 @@ export const ElementName = { ...@@ -135,6 +135,10 @@ export const ElementName = {
OK: 'ok', OK: 'ok',
OnboardingImportBackup: 'onboarding-import-backup', OnboardingImportBackup: 'onboarding-import-backup',
OnboardingImportSeedPhrase: 'onboarding-import-seed-phrase', OnboardingImportSeedPhrase: 'onboarding-import-seed-phrase',
OnDeviceRecoveryImportOther: 'on-device-recovery-import-other',
OnDeviceRecoveryWallet: 'on-device-recovery-wallet',
OnDeviceRecoveryModalCancel: 'on-device-recovery-modal-cancel',
OnDeviceRecoveryModalConfirm: 'on-device-recovery-modal-confirm',
OpenCameraRoll: 'open-camera-roll', OpenCameraRoll: 'open-camera-roll',
OpenNftsList: 'open-nfts-list', OpenNftsList: 'open-nfts-list',
QRCodeModalToggle: 'qr-code-modal-toggle', QRCodeModalToggle: 'qr-code-modal-toggle',
......
...@@ -382,6 +382,14 @@ export type UniverseEventProperties = { ...@@ -382,6 +382,14 @@ export type UniverseEventProperties = {
isBiometricsEnrolled: boolean | undefined isBiometricsEnrolled: boolean | undefined
isBiometricAuthEnabled: boolean isBiometricAuthEnabled: boolean
} }
[MobileEventName.AutomatedOnDeviceRecoveryMnemonicsFound]: {
mnemonicCount: number
}
[MobileEventName.AutomatedOnDeviceRecoverySingleMnemonicFetched]: {
balance: number
hasUnitag: boolean
hasENS: boolean
}
[MobileEventName.BalancesReport]: { [MobileEventName.BalancesReport]: {
total_balances_usd: number total_balances_usd: number
wallets: string[] wallets: string[]
......
...@@ -792,8 +792,11 @@ ...@@ -792,8 +792,11 @@
"swap.warning.insufficientGas.title": "You don’t have enough {{currencySymbol}} to cover the network cost", "swap.warning.insufficientGas.title": "You don’t have enough {{currencySymbol}} to cover the network cost",
"swap.warning.lowLiquidity.message": "There isn’t currently enough liquidity available between these tokens to perform a swap. Please try again later or select another token.", "swap.warning.lowLiquidity.message": "There isn’t currently enough liquidity available between these tokens to perform a swap. Please try again later or select another token.",
"swap.warning.lowLiquidity.title": "Not enough liquidity", "swap.warning.lowLiquidity.title": "Not enough liquidity",
"swap.warning.networkFee.allow": "Allow {{ inputTokenSymbol }} (one time)",
"swap.warning.networkFee.highRelativeToValue": "The network cost exceeds 10% of your total transaction value.", "swap.warning.networkFee.highRelativeToValue": "The network cost exceeds 10% of your total transaction value.",
"swap.warning.networkFee.message": "This is the cost to process your transaction on the blockchain. Uniswap does not receive any share of these fees.", "swap.warning.networkFee.message": "This is the cost to process your transaction on the blockchain. Uniswap does not receive any share of these fees.",
"swap.warning.networkFee.message.uniswapX": "This is the cost to process your transaction on the blockchain. Uniswap does not receive any share of these fees. <gradient>UniswapX</gradient> aggregates liquidity sources for better prices and gas free swaps.",
"swap.warning.networkFee.wrap": "Wrap ETH",
"swap.warning.offline.message": "You may have lost internet connection or the network may be down. Please check your internet connection and try again.", "swap.warning.offline.message": "You may have lost internet connection or the network may be down. Please check your internet connection and try again.",
"swap.warning.offline.title": "You’re offline", "swap.warning.offline.title": "You’re offline",
"swap.warning.priceImpact.message": "Due to the amount of {{outputCurrencySymbol}} liquidity currently available, the more {{inputCurrencySymbol}} you try to swap, the less {{outputCurrencySymbol}} you will receive.", "swap.warning.priceImpact.message": "Due to the amount of {{outputCurrencySymbol}} liquidity currently available, the more {{inputCurrencySymbol}} you try to swap, the less {{outputCurrencySymbol}} you will receive.",
...@@ -992,7 +995,7 @@ ...@@ -992,7 +995,7 @@
"transaction.warning.insufficientGas.modal.title.withoutNetwork": "Not enough {{tokenSymbol}}", "transaction.warning.insufficientGas.modal.title.withoutNetwork": "Not enough {{tokenSymbol}}",
"transaction.watcher.error.cancel": "Unable to cancel transaction", "transaction.watcher.error.cancel": "Unable to cancel transaction",
"transaction.watcher.error.status": "Error while checking transaction status", "transaction.watcher.error.status": "Error while checking transaction status",
"uniswapx.description": "UniswapX aggregates liquidity sources for better prices and gas free swaps.", "uniswapx.description": "<gradient>UniswapX</gradient> aggregates liquidity sources for better prices and gas free swaps.",
"uniswapx.included": "Includes <icon /> <gradient>UniswapX</gradient> <info />", "uniswapx.included": "Includes <icon /> <gradient>UniswapX</gradient> <info />",
"uniswapx.label": "UniswapX", "uniswapx.label": "UniswapX",
"unitags.banner.button.claim": "Claim now", "unitags.banner.button.claim": "Claim now",
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -15,7 +15,7 @@ export type WarningModalProps = { ...@@ -15,7 +15,7 @@ export type WarningModalProps = {
onConfirm?: () => void onConfirm?: () => void
modalName: ModalNameType modalName: ModalNameType
title: ReactNode title: ReactNode
caption?: string caption?: ReactNode
closeText?: string closeText?: string
confirmText?: string confirmText?: string
severity?: WarningSeverity severity?: WarningSeverity
...@@ -89,7 +89,7 @@ export function WarningModal({ ...@@ -89,7 +89,7 @@ export function WarningModal({
{title} {title}
</Text> </Text>
{caption && ( {caption && (
<Text color="$neutral2" textAlign="center" variant={isWeb ? 'body3' : 'body2'}> <Text color="$neutral2" textAlign="center" variant="body3">
{caption} {caption}
</Text> </Text>
)} )}
......
...@@ -32,7 +32,9 @@ export function WarningTooltip({ ...@@ -32,7 +32,9 @@ export function WarningTooltip({
<Text color="$neutral2" variant="body3"> <Text color="$neutral2" variant="body3">
{text} {text}
</Text> </Text>
<Flex alignSelf="flex-start">{button}</Flex> <Flex alignSelf="flex-start" width="100%">
{button}
</Flex>
</Flex> </Flex>
</Flex> </Flex>
<Tooltip.Arrow /> <Tooltip.Arrow />
......
...@@ -3,7 +3,7 @@ import { PopperProps } from 'ui/src' ...@@ -3,7 +3,7 @@ import { PopperProps } from 'ui/src'
export type WarningTooltipProps = { export type WarningTooltipProps = {
title?: string title?: string
text: string text: ReactNode
icon?: Maybe<JSX.Element> icon?: Maybe<JSX.Element>
button: ReactNode button: ReactNode
trigger: ReactNode trigger: ReactNode
......
...@@ -6,21 +6,23 @@ import { iconSizes } from 'ui/src/theme' ...@@ -6,21 +6,23 @@ import { iconSizes } from 'ui/src/theme'
import { NetworkLogo } from 'uniswap/src/components/CurrencyLogo/NetworkLogo' import { NetworkLogo } from 'uniswap/src/components/CurrencyLogo/NetworkLogo'
import { WalletChainId } from 'uniswap/src/types/chains' import { WalletChainId } from 'uniswap/src/types/chains'
import { NumberType } from 'utilities/src/format/types' import { NumberType } from 'utilities/src/format/types'
import { useFormattedUniswapXGasFeeInfo } from 'wallet/src/components/network/hooks'
import { useUSDValue } from 'wallet/src/features/gas/hooks' import { useUSDValue } from 'wallet/src/features/gas/hooks'
import { GasFeeResult } from 'wallet/src/features/gas/types' import { GasFeeResult } from 'wallet/src/features/gas/types'
import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext' import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext'
import { useGasFeeHighRelativeToValue } from 'wallet/src/features/transactions/swap/hooks/useGasFeeHighRelativeToValue' import { useGasFeeHighRelativeToValue } from 'wallet/src/features/transactions/swap/hooks/useGasFeeHighRelativeToValue'
import { NetworkFeeWarning } from 'wallet/src/features/transactions/swap/modals/NetworkFeeWarning' import { NetworkFeeWarning } from 'wallet/src/features/transactions/swap/modals/NetworkFeeWarning'
import { UniswapXGasBreakdown } from 'wallet/src/features/transactions/swap/trade/api/hooks/useSwapTxAndGasInfo'
export function NetworkFee({ export function NetworkFee({
chainId, chainId,
gasFee, gasFee,
preUniswapXGasFeeUSD, uniswapXGasBreakdown,
transactionUSDValue, transactionUSDValue,
}: { }: {
chainId: WalletChainId chainId: WalletChainId
gasFee: GasFeeResult gasFee: GasFeeResult
preUniswapXGasFeeUSD?: number uniswapXGasBreakdown?: UniswapXGasBreakdown
transactionUSDValue?: Maybe<CurrencyAmount<Currency>> transactionUSDValue?: Maybe<CurrencyAmount<Currency>>
}): JSX.Element { }): JSX.Element {
const { t } = useTranslation() const { t } = useTranslation()
...@@ -28,28 +30,29 @@ export function NetworkFee({ ...@@ -28,28 +30,29 @@ export function NetworkFee({
const gasFeeUSD = useUSDValue(chainId, gasFee.value ?? undefined) const gasFeeUSD = useUSDValue(chainId, gasFee.value ?? undefined)
const gasFeeFormatted = convertFiatAmountFormatted(gasFeeUSD, NumberType.FiatGasPrice) const gasFeeFormatted = convertFiatAmountFormatted(gasFeeUSD, NumberType.FiatGasPrice)
const preSavingsGasFeeFormatted = convertFiatAmountFormatted(preUniswapXGasFeeUSD, NumberType.FiatGasPrice)
const uniswapXGasFeeInfo = useFormattedUniswapXGasFeeInfo(uniswapXGasBreakdown, chainId)
const gasFeeHighRelativeToValue = useGasFeeHighRelativeToValue(gasFeeUSD, transactionUSDValue) const gasFeeHighRelativeToValue = useGasFeeHighRelativeToValue(gasFeeUSD, transactionUSDValue)
const isLoading = gasFee.loading const isLoading = gasFee.loading
return ( return (
<Flex row alignItems="center" gap="$spacing12" justifyContent="space-between"> <Flex row alignItems="center" gap="$spacing12" justifyContent="space-between">
<NetworkFeeWarning gasFeeHighRelativeToValue={gasFeeHighRelativeToValue}> <NetworkFeeWarning gasFeeHighRelativeToValue={gasFeeHighRelativeToValue} uniswapXGasFeeInfo={uniswapXGasFeeInfo}>
<Text color="$neutral2" flexShrink={1} numberOfLines={3} variant="body3"> <Text color="$neutral2" flexShrink={1} numberOfLines={3} variant="body3">
{t('transaction.networkCost.label')} {t('transaction.networkCost.label')}
</Text> </Text>
</NetworkFeeWarning> </NetworkFeeWarning>
<Flex row alignItems="center" gap={preUniswapXGasFeeUSD ? '$spacing4' : '$spacing8'}> <Flex row alignItems="center" gap={uniswapXGasBreakdown ? '$spacing4' : '$spacing8'}>
{(!preUniswapXGasFeeUSD || gasFee.error) && ( {(!uniswapXGasBreakdown || gasFee.error) && (
<NetworkLogo chainId={chainId} shape="square" size={iconSizes.icon16} /> <NetworkLogo chainId={chainId} shape="square" size={iconSizes.icon16} />
)} )}
{gasFee.error ? ( {gasFee.error ? (
<Text color="$neutral2" variant="body3"> <Text color="$neutral2" variant="body3">
{t('common.text.notAvailable')} {t('common.text.notAvailable')}
</Text> </Text>
) : preUniswapXGasFeeUSD ? ( ) : uniswapXGasBreakdown ? (
<UniswapXFee gasFee={gasFeeFormatted} preSavingsGasFee={preSavingsGasFeeFormatted} /> <UniswapXFee gasFee={gasFeeFormatted} preSavingsGasFee={uniswapXGasFeeInfo?.preSavingsGasFeeFormatted} />
) : ( ) : (
<Text <Text
color={isLoading ? '$neutral3' : gasFeeHighRelativeToValue ? '$statusCritical' : '$neutral1'} color={isLoading ? '$neutral3' : gasFeeHighRelativeToValue ? '$statusCritical' : '$neutral1'}
......
import { useMemo } from 'react'
import { WalletChainId } from 'uniswap/src/types/chains'
import { NumberType } from 'utilities/src/format/types'
import { useUSDValue } from 'wallet/src/features/gas/hooks'
import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext'
import { UniswapXGasBreakdown } from 'wallet/src/features/transactions/swap/trade/api/hooks/useSwapTxAndGasInfo'
export type FormattedUniswapXGasFeeInfo = {
approvalFeeFormatted?: string
wrapFeeFormatted?: string
swapFeeFormatted: string
preSavingsGasFeeFormatted: string
inputTokenSymbol?: string
}
export function useFormattedUniswapXGasFeeInfo(
uniswapXGasBreakdown: UniswapXGasBreakdown | undefined,
chainId: WalletChainId,
): FormattedUniswapXGasFeeInfo | undefined {
const { convertFiatAmountFormatted } = useLocalizationContext()
const approvalCostUsd = useUSDValue(chainId, uniswapXGasBreakdown?.approvalCost)
const wrapCostUsd = useUSDValue(chainId, uniswapXGasBreakdown?.wrapCost)
return useMemo(() => {
if (!uniswapXGasBreakdown) {
return undefined
}
const { approvalCost, wrapCost, inputTokenSymbol } = uniswapXGasBreakdown
// Without uniswapx, the swap would have costed approval price + classic swap fee. A separate wrap tx would not have occurred.
const preSavingsGasCostUsd =
Number(approvalCostUsd ?? 0) + Number(uniswapXGasBreakdown?.classicGasUseEstimateUSD ?? 0)
const preSavingsGasFeeFormatted = convertFiatAmountFormatted(preSavingsGasCostUsd, NumberType.FiatGasPrice)
// Swap submission will always cost 0, since it's not an on-chain tx.
const swapFeeFormatted = convertFiatAmountFormatted(0, NumberType.FiatGasPrice)
return {
approvalFeeFormatted: approvalCost
? convertFiatAmountFormatted(approvalCostUsd, NumberType.FiatGasPrice)
: undefined,
wrapFeeFormatted: wrapCost ? convertFiatAmountFormatted(wrapCostUsd, NumberType.FiatGasPrice) : undefined,
preSavingsGasFeeFormatted,
swapFeeFormatted,
inputTokenSymbol,
}
}, [uniswapXGasBreakdown, approvalCostUsd, convertFiatAmountFormatted, wrapCostUsd])
}
...@@ -35,7 +35,6 @@ type ActivityDataProps = { ...@@ -35,7 +35,6 @@ type ActivityDataProps = {
type ActivityData = { type ActivityData = {
maybeEmptyComponent: JSX.Element | null maybeEmptyComponent: JSX.Element | null
maybeLoaderComponent: JSX.Element | null
renderActivityItem: ActivityItemRenderer renderActivityItem: ActivityItemRenderer
sectionData: (TransactionDetails | SectionHeader | LoadingItem)[] | undefined sectionData: (TransactionDetails | SectionHeader | LoadingItem)[] | undefined
keyExtractor: (item: TransactionDetails | SectionHeader | LoadingItem) => string keyExtractor: (item: TransactionDetails | SectionHeader | LoadingItem) => string
...@@ -79,7 +78,7 @@ export function useActivityData({ ...@@ -79,7 +78,7 @@ export function useActivityData({
) )
}, [swapCallbacks, authTrigger]) }, [swapCallbacks, authTrigger])
const { onRetry, hasData, isLoading, isError, sectionData, keyExtractor } = useFormattedTransactionDataForActivity( const { onRetry, isError, sectionData, keyExtractor } = useFormattedTransactionDataForActivity(
owner, owner,
hideSpamTokens, hideSpamTokens,
useMergeLocalAndRemoteTransactions, useMergeLocalAndRemoteTransactions,
...@@ -111,13 +110,11 @@ export function useActivityData({ ...@@ -111,13 +110,11 @@ export function useActivityData({
</Flex> </Flex>
) )
const maybeEmptyComponent = hasData ? null : isError ? errorCard : emptyListView // We check `sectionData` instead of `hasData` because `sectionData` has either transactions or a loading skeleton.
// We want to display the loading shimmer only on first load because items have their own loading shimmer const maybeEmptyComponent = sectionData?.length ? null : isError ? errorCard : emptyListView
const maybeLoaderComponent = isLoading && !hasData ? <Loader.Transaction repeat={6} /> : null
return { return {
maybeEmptyComponent, maybeEmptyComponent,
maybeLoaderComponent,
renderActivityItem, renderActivityItem,
sectionData, sectionData,
keyExtractor, keyExtractor,
......
import { call, put, takeLatest } from 'typed-redux-saga' import { put, takeLatest } from 'typed-redux-saga'
import { AssetType } from 'uniswap/src/entities/assets' import { AssetType } from 'uniswap/src/entities/assets'
import { WalletChainId } from 'uniswap/src/types/chains'
import { WalletConnectEvent } from 'uniswap/src/types/walletConnect' import { WalletConnectEvent } from 'uniswap/src/types/walletConnect'
import { buildReceiveNotification } from 'wallet/src/features/notifications/buildReceiveNotification' import { buildReceiveNotification } from 'wallet/src/features/notifications/buildReceiveNotification'
import { pushNotification } from 'wallet/src/features/notifications/slice' import { pushNotification } from 'wallet/src/features/notifications/slice'
import { AppNotificationType } from 'wallet/src/features/notifications/types' import { AppNotificationType } from 'wallet/src/features/notifications/types'
import { getAmountsFromTrade } from 'wallet/src/features/transactions/getAmountsFromTrade' import { getAmountsFromTrade } from 'wallet/src/features/transactions/getAmountsFromTrade'
import { selectTransactions } from 'wallet/src/features/transactions/selectors'
import { finalizeTransaction } from 'wallet/src/features/transactions/slice' import { finalizeTransaction } from 'wallet/src/features/transactions/slice'
import { TransactionType } from 'wallet/src/features/transactions/types' import { TransactionDetails, TransactionType } from 'wallet/src/features/transactions/types'
import { appSelect } from 'wallet/src/state'
export function* notificationWatcher() { export function* notificationWatcher() {
yield* takeLatest(finalizeTransaction.type, pushTransactionNotification) yield* takeLatest(finalizeTransaction.type, pushTransactionNotification)
} }
export function* pushTransactionNotification(action: ReturnType<typeof finalizeTransaction>) { export function* pushTransactionNotification(action: ReturnType<typeof finalizeTransaction>) {
const { chainId, status, typeInfo, id, from, addedTime } = action.payload if (shouldSuppressNotification(action.payload)) {
return
}
const { chainId, status, typeInfo, id, from } = action.payload
const baseNotificationData = { const baseNotificationData = {
txStatus: status, txStatus: status,
...@@ -26,18 +27,15 @@ export function* pushTransactionNotification(action: ReturnType<typeof finalizeT ...@@ -26,18 +27,15 @@ export function* pushTransactionNotification(action: ReturnType<typeof finalizeT
} }
if (typeInfo.type === TransactionType.Approve) { if (typeInfo.type === TransactionType.Approve) {
const shouldSuppressNotification = yield* call(suppressApproveNotification, from, chainId, addedTime) yield* put(
if (!shouldSuppressNotification) { pushNotification({
yield* put( ...baseNotificationData,
pushNotification({ type: AppNotificationType.Transaction,
...baseNotificationData, txType: TransactionType.Approve,
type: AppNotificationType.Transaction, tokenAddress: typeInfo.tokenAddress,
txType: TransactionType.Approve, spender: typeInfo.spender,
tokenAddress: typeInfo.tokenAddress, }),
spender: typeInfo.spender, )
}),
)
}
} else if (typeInfo.type === TransactionType.Swap) { } else if (typeInfo.type === TransactionType.Swap) {
const { inputCurrencyAmountRaw, outputCurrencyAmountRaw } = getAmountsFromTrade(typeInfo) const { inputCurrencyAmountRaw, outputCurrencyAmountRaw } = getAmountsFromTrade(typeInfo)
yield* put( yield* put(
...@@ -118,20 +116,9 @@ export function* pushTransactionNotification(action: ReturnType<typeof finalizeT ...@@ -118,20 +116,9 @@ export function* pushTransactionNotification(action: ReturnType<typeof finalizeT
} }
} }
// If an approve tx is submitted with a swap tx (i.e, swap tx is added within 3 seconds of an approve tx), // If a wrap or approve tx is submitted with a swap, then suppress the notification.
// then suppress the approve notification function shouldSuppressNotification(tx: TransactionDetails) {
function* suppressApproveNotification(address: Address, chainId: WalletChainId, approveAddedTime: number) { return (
const transactions = (yield* appSelect(selectTransactions))?.[address]?.[chainId] (tx.typeInfo.type === TransactionType.Approve || tx.typeInfo.type === TransactionType.Wrap) && tx.typeInfo.swapTxId
const transactionDetails = Object.values(transactions ?? {}) )
const foundSwapTx = transactionDetails.find((tx) => {
const { type } = tx.typeInfo
if (type !== TransactionType.Swap) {
return false
}
const swapAddedTime = tx.addedTime
return swapAddedTime - approveAddedTime < 3000
})
return !!foundSwapTx
} }
...@@ -18,13 +18,14 @@ import { ...@@ -18,13 +18,14 @@ import {
} from 'wallet/src/features/transactions/TransactionDetails/FeeOnTransferFee' } from 'wallet/src/features/transactions/TransactionDetails/FeeOnTransferFee'
import { SwapFee } from 'wallet/src/features/transactions/TransactionDetails/SwapFee' import { SwapFee } from 'wallet/src/features/transactions/TransactionDetails/SwapFee'
import { Warning } from 'wallet/src/features/transactions/WarningModal/types' import { Warning } from 'wallet/src/features/transactions/WarningModal/types'
import { UniswapXGasBreakdown } from 'wallet/src/features/transactions/swap/trade/api/hooks/useSwapTxAndGasInfo'
import { SwapFeeInfo } from 'wallet/src/features/transactions/swap/trade/types' import { SwapFeeInfo } from 'wallet/src/features/transactions/swap/trade/types'
interface TransactionDetailsProps { interface TransactionDetailsProps {
banner?: ReactNode banner?: ReactNode
chainId: WalletChainId chainId: WalletChainId
gasFee: GasFeeResult gasFee: GasFeeResult
preUniswapXGasFeeUSD?: number uniswapXGasBreakdown?: UniswapXGasBreakdown
showExpandedChildren?: boolean showExpandedChildren?: boolean
swapFeeInfo?: SwapFeeInfo swapFeeInfo?: SwapFeeInfo
showWarning?: boolean showWarning?: boolean
...@@ -42,7 +43,7 @@ export function TransactionDetails({ ...@@ -42,7 +43,7 @@ export function TransactionDetails({
showExpandedChildren, showExpandedChildren,
chainId, chainId,
gasFee, gasFee,
preUniswapXGasFeeUSD, uniswapXGasBreakdown,
swapFeeInfo, swapFeeInfo,
showWarning, showWarning,
warning, warning,
...@@ -125,8 +126,8 @@ export function TransactionDetails({ ...@@ -125,8 +126,8 @@ export function TransactionDetails({
<NetworkFee <NetworkFee
chainId={chainId} chainId={chainId}
gasFee={gasFee} gasFee={gasFee}
preUniswapXGasFeeUSD={preUniswapXGasFeeUSD}
transactionUSDValue={transactionUSDValue} transactionUSDValue={transactionUSDValue}
uniswapXGasBreakdown={uniswapXGasBreakdown}
/> />
{AccountDetails} {AccountDetails}
</Flex> </Flex>
......
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Flex, Text, Tooltip } from 'ui/src' import { Flex, SpaceTokens, Text, Tooltip } from 'ui/src'
import { AlertTriangle } from 'ui/src/components/icons' import { AlertTriangle } from 'ui/src/components/icons'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { areAddressesEqual } from 'uniswap/src/utils/addresses' import { areAddressesEqual } from 'uniswap/src/utils/addresses'
...@@ -10,9 +10,11 @@ import { ContentRow } from 'wallet/src/features/transactions/TransactionRequest/ ...@@ -10,9 +10,11 @@ import { ContentRow } from 'wallet/src/features/transactions/TransactionRequest/
export function AddressFooter({ export function AddressFooter({
connectedAccountAddress, connectedAccountAddress,
activeAccountAddress, activeAccountAddress,
px = '$none',
}: { }: {
connectedAccountAddress?: string connectedAccountAddress?: string
activeAccountAddress: string activeAccountAddress: string
px?: SpaceTokens
}): JSX.Element { }): JSX.Element {
const { t } = useTranslation() const { t } = useTranslation()
...@@ -23,7 +25,7 @@ export function AddressFooter({ ...@@ -23,7 +25,7 @@ export function AddressFooter({
const showWarning = connectedAccountAddress && !areAddressesEqual(connectedAccountAddress, activeAccountAddress) const showWarning = connectedAccountAddress && !areAddressesEqual(connectedAccountAddress, activeAccountAddress)
return ( return (
<Flex grow px="$spacing8"> <Flex grow px={px}>
<ContentRow <ContentRow
label={ label={
<Flex grow row alignItems="center" gap="$spacing4"> <Flex grow row alignItems="center" gap="$spacing4">
......
/* eslint-disable complexity */
import { useCallback, useState } from 'react' import { useCallback, useState } from 'react'
import { Keyboard } from 'react-native' import { Keyboard } from 'react-native'
import { FadeIn, FadeOut } from 'react-native-reanimated' import { FadeIn, FadeOut } from 'react-native-reanimated'
...@@ -9,6 +8,7 @@ import { iconSizes } from 'ui/src/theme' ...@@ -9,6 +8,7 @@ import { iconSizes } from 'ui/src/theme'
import { CurrencyField } from 'uniswap/src/features/transactions/transactionState/types' import { CurrencyField } from 'uniswap/src/features/transactions/transactionState/types'
import { NumberType } from 'utilities/src/format/types' import { NumberType } from 'utilities/src/format/types'
import { UniswapXFee } from 'wallet/src/components/network/NetworkFee' import { UniswapXFee } from 'wallet/src/components/network/NetworkFee'
import { useFormattedUniswapXGasFeeInfo } from 'wallet/src/components/network/hooks'
import { useUSDValue } from 'wallet/src/features/gas/hooks' import { useUSDValue } from 'wallet/src/features/gas/hooks'
import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext' import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext'
import { InsufficientNativeTokenWarning } from 'wallet/src/features/transactions/InsufficientNativeTokenWarning/InsufficientNativeTokenWarning' import { InsufficientNativeTokenWarning } from 'wallet/src/features/transactions/InsufficientNativeTokenWarning/InsufficientNativeTokenWarning'
...@@ -19,7 +19,6 @@ import { GasAndWarningRowsProps } from 'wallet/src/features/transactions/swap/Ga ...@@ -19,7 +19,6 @@ import { GasAndWarningRowsProps } from 'wallet/src/features/transactions/swap/Ga
import { SwapWarningModal } from 'wallet/src/features/transactions/swap/SwapWarningModal' import { SwapWarningModal } from 'wallet/src/features/transactions/swap/SwapWarningModal'
import { useGasFeeHighRelativeToValue } from 'wallet/src/features/transactions/swap/hooks/useGasFeeHighRelativeToValue' import { useGasFeeHighRelativeToValue } from 'wallet/src/features/transactions/swap/hooks/useGasFeeHighRelativeToValue'
import { NetworkFeeWarning } from 'wallet/src/features/transactions/swap/modals/NetworkFeeWarning' import { NetworkFeeWarning } from 'wallet/src/features/transactions/swap/modals/NetworkFeeWarning'
import { UniswapXInfo } from 'wallet/src/features/transactions/swap/modals/UniswapXInfo'
import { isUniswapX } from 'wallet/src/features/transactions/swap/trade/utils' import { isUniswapX } from 'wallet/src/features/transactions/swap/trade/utils'
import { BlockedAddressWarning } from 'wallet/src/features/trm/BlockedAddressWarning' import { BlockedAddressWarning } from 'wallet/src/features/trm/BlockedAddressWarning'
import { useIsBlockedActiveAddress } from 'wallet/src/features/trm/hooks' import { useIsBlockedActiveAddress } from 'wallet/src/features/trm/hooks'
...@@ -29,7 +28,8 @@ export function GasAndWarningRows({ renderEmptyRows }: GasAndWarningRowsProps): ...@@ -29,7 +28,8 @@ export function GasAndWarningRows({ renderEmptyRows }: GasAndWarningRowsProps):
const isShortMobileDevice = useIsShortMobileDevice() const isShortMobileDevice = useIsShortMobileDevice()
const { convertFiatAmountFormatted } = useLocalizationContext() const { convertFiatAmountFormatted } = useLocalizationContext()
const { gasFee, trade } = useSwapTxContext() const swapTxContext = useSwapTxContext()
const { gasFee } = swapTxContext
const { derivedSwapInfo } = useSwapFormContext() const { derivedSwapInfo } = useSwapFormContext()
const { chainId, currencyAmountsUSDValue } = derivedSwapInfo const { chainId, currencyAmountsUSDValue } = derivedSwapInfo
...@@ -45,14 +45,13 @@ export function GasAndWarningRows({ renderEmptyRows }: GasAndWarningRowsProps): ...@@ -45,14 +45,13 @@ export function GasAndWarningRows({ renderEmptyRows }: GasAndWarningRowsProps):
const gasFeeUSD = useUSDValue(chainId, gasFee?.value) const gasFeeUSD = useUSDValue(chainId, gasFee?.value)
const gasFeeFormatted = convertFiatAmountFormatted(gasFeeUSD, NumberType.FiatGasPrice) const gasFeeFormatted = convertFiatAmountFormatted(gasFeeUSD, NumberType.FiatGasPrice)
const showUniswapXFee = Boolean(gasFeeUSD && trade && isUniswapX(trade)) const uniswapXGasFeeInfo = useFormattedUniswapXGasFeeInfo(
const preSavingsGasFeeFormatted = isUniswapX(swapTxContext) ? swapTxContext.gasFeeBreakdown : undefined,
trade && isUniswapX(trade) chainId,
? convertFiatAmountFormatted(trade.quote.quote.classicGasUseEstimateUSD, NumberType.FiatGasPrice) )
: undefined
// only show the gas fee icon and price if we have a valid fee // only show the gas fee icon and price if we have a valid fee
const showGasFee = Boolean(gasFeeUSD && !showUniswapXFee) const showGasFee = Boolean(gasFeeUSD)
const onSwapWarningClick = useCallback(() => { const onSwapWarningClick = useCallback(() => {
if (!formScreenWarning?.warning.message) { if (!formScreenWarning?.warning.message) {
...@@ -94,21 +93,26 @@ export function GasAndWarningRows({ renderEmptyRows }: GasAndWarningRowsProps): ...@@ -94,21 +93,26 @@ export function GasAndWarningRows({ renderEmptyRows }: GasAndWarningRowsProps):
)} )}
<Flex centered row> <Flex centered row>
{showUniswapXFee && (
<UniswapXInfo tooltipTrigger={<></>}>
<AnimatedFlex centered row entering={FadeIn} gap="$spacing4">
<UniswapXFee gasFee={gasFeeFormatted} preSavingsGasFee={preSavingsGasFeeFormatted} />
</AnimatedFlex>
</UniswapXInfo>
)}
{showGasFee && ( {showGasFee && (
<NetworkFeeWarning gasFeeHighRelativeToValue={gasFeeHighRelativeToValue} tooltipTrigger={<></>}> <NetworkFeeWarning
gasFeeHighRelativeToValue={gasFeeHighRelativeToValue}
tooltipTrigger={null}
uniswapXGasFeeInfo={uniswapXGasFeeInfo}
>
<AnimatedFlex centered row entering={FadeIn} gap="$spacing4"> <AnimatedFlex centered row entering={FadeIn} gap="$spacing4">
<Gas color={gasColor} size="$icon.16" /> {uniswapXGasFeeInfo ? (
<Text color={gasColor} variant="body3"> <UniswapXFee
{gasFeeFormatted} gasFee={gasFeeFormatted}
</Text> preSavingsGasFee={uniswapXGasFeeInfo.preSavingsGasFeeFormatted}
/>
) : (
<>
<Gas color={gasColor} size="$icon.16" />
<Text color={gasColor} variant="body3">
{gasFeeFormatted}
</Text>
</>
)}
</AnimatedFlex> </AnimatedFlex>
</NetworkFeeWarning> </NetworkFeeWarning>
)} )}
......
...@@ -10,6 +10,7 @@ import { CurrencyField } from 'uniswap/src/features/transactions/transactionStat ...@@ -10,6 +10,7 @@ import { CurrencyField } from 'uniswap/src/features/transactions/transactionStat
import { normalizePriceImpact } from 'utilities/src/format/normalizePriceImpact' import { normalizePriceImpact } from 'utilities/src/format/normalizePriceImpact'
import { NumberType } from 'utilities/src/format/types' import { NumberType } from 'utilities/src/format/types'
import { UniswapXFee } from 'wallet/src/components/network/NetworkFee' import { UniswapXFee } from 'wallet/src/components/network/NetworkFee'
import { useFormattedUniswapXGasFeeInfo } from 'wallet/src/components/network/hooks'
import { useUSDValue } from 'wallet/src/features/gas/hooks' import { useUSDValue } from 'wallet/src/features/gas/hooks'
import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext' import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext'
import { InsufficientNativeTokenWarning } from 'wallet/src/features/transactions/InsufficientNativeTokenWarning/InsufficientNativeTokenWarning' import { InsufficientNativeTokenWarning } from 'wallet/src/features/transactions/InsufficientNativeTokenWarning/InsufficientNativeTokenWarning'
...@@ -22,19 +23,18 @@ import { SwapWarningModal } from 'wallet/src/features/transactions/swap/SwapWarn ...@@ -22,19 +23,18 @@ import { SwapWarningModal } from 'wallet/src/features/transactions/swap/SwapWarn
import { useGasFeeHighRelativeToValue } from 'wallet/src/features/transactions/swap/hooks/useGasFeeHighRelativeToValue' import { useGasFeeHighRelativeToValue } from 'wallet/src/features/transactions/swap/hooks/useGasFeeHighRelativeToValue'
import { NetworkFeeWarning } from 'wallet/src/features/transactions/swap/modals/NetworkFeeWarning' import { NetworkFeeWarning } from 'wallet/src/features/transactions/swap/modals/NetworkFeeWarning'
import { PriceImpactWarning } from 'wallet/src/features/transactions/swap/modals/PriceImpactWarning' import { PriceImpactWarning } from 'wallet/src/features/transactions/swap/modals/PriceImpactWarning'
import { UniswapXInfo } from 'wallet/src/features/transactions/swap/modals/UniswapXInfo'
import { isUniswapX } from 'wallet/src/features/transactions/swap/trade/utils' import { isUniswapX } from 'wallet/src/features/transactions/swap/trade/utils'
import { BlockedAddressWarning } from 'wallet/src/features/trm/BlockedAddressWarning' import { BlockedAddressWarning } from 'wallet/src/features/trm/BlockedAddressWarning'
import { useIsBlockedActiveAddress } from 'wallet/src/features/trm/hooks' import { useIsBlockedActiveAddress } from 'wallet/src/features/trm/hooks'
// eslint-disable-next-line complexity
export function GasAndWarningRows({ export function GasAndWarningRows({
renderEmptyRows: _renderEmptyRows, // Web does not need to render empty rows for layout calculations renderEmptyRows: _renderEmptyRows, // Web does not need to render empty rows for layout calculations
}: GasAndWarningRowsProps): JSX.Element { }: GasAndWarningRowsProps): JSX.Element {
const { convertFiatAmountFormatted, formatPercent } = useLocalizationContext() const { convertFiatAmountFormatted, formatPercent } = useLocalizationContext()
const { t } = useTranslation() const { t } = useTranslation()
const { gasFee } = useSwapTxContext() const swapTxContext = useSwapTxContext()
const { gasFee } = swapTxContext
const { derivedSwapInfo } = useSwapFormContext() const { derivedSwapInfo } = useSwapFormContext()
const { chainId, trade, currencyAmountsUSDValue } = derivedSwapInfo const { chainId, trade, currencyAmountsUSDValue } = derivedSwapInfo
...@@ -52,13 +52,12 @@ export function GasAndWarningRows({ ...@@ -52,13 +52,12 @@ export function GasAndWarningRows({
const gasFeeUSD = useUSDValue(chainId, gasFee?.value) const gasFeeUSD = useUSDValue(chainId, gasFee?.value)
const gasFeeFormatted = convertFiatAmountFormatted(gasFeeUSD, NumberType.FiatGasPrice) const gasFeeFormatted = convertFiatAmountFormatted(gasFeeUSD, NumberType.FiatGasPrice)
const showUniswapXFee = Boolean(gasFeeUSD && trade.trade && isUniswapX(trade.trade)) const uniswapXGasFeeInfo = useFormattedUniswapXGasFeeInfo(
const preSavingsGasFeeFormatted = isUniswapX(swapTxContext) ? swapTxContext.gasFeeBreakdown : undefined,
trade.trade && isUniswapX(trade.trade) chainId,
? convertFiatAmountFormatted(trade.trade.quote.quote.classicGasUseEstimateUSD, NumberType.FiatGasPrice) )
: undefined
const showGasFee = Boolean(gasFeeUSD && !showUniswapXFee) const showGasFee = Boolean(gasFeeUSD)
const onSwapWarningClick = useCallback(() => { const onSwapWarningClick = useCallback(() => {
if (!formScreenWarning?.warning.message) { if (!formScreenWarning?.warning.message) {
...@@ -106,29 +105,28 @@ export function GasAndWarningRows({ ...@@ -106,29 +105,28 @@ export function GasAndWarningRows({
</Flex> </Flex>
)} )}
{showUniswapXFee && (
<UniswapXInfo
placement="bottom"
tooltipTrigger={
<AnimatedFlex centered row entering={FadeIn} gap="$spacing4">
<UniswapXFee gasFee={gasFeeFormatted} preSavingsGasFee={preSavingsGasFeeFormatted} />
</AnimatedFlex>
}
/>
)}
{showGasFee && ( {showGasFee && (
<NetworkFeeWarning <NetworkFeeWarning
gasFeeHighRelativeToValue={gasFeeHighRelativeToSwapValue} gasFeeHighRelativeToValue={gasFeeHighRelativeToSwapValue}
placement="bottom" placement="bottom"
tooltipTrigger={ tooltipTrigger={
<AnimatedFlex centered row entering={FadeIn} gap="$spacing4"> <AnimatedFlex centered row entering={FadeIn} gap="$spacing4">
<Gas color={gasFeeHighRelativeToSwapValue ? '$statusCritical' : '$neutral2'} size="$icon.16" /> {uniswapXGasFeeInfo ? (
<Text color={gasFeeHighRelativeToSwapValue ? '$statusCritical' : '$neutral2'} variant="body4"> <UniswapXFee
{gasFeeFormatted} gasFee={gasFeeFormatted}
</Text> preSavingsGasFee={uniswapXGasFeeInfo.preSavingsGasFeeFormatted}
/>
) : (
<>
<Gas color={gasFeeHighRelativeToSwapValue ? '$statusCritical' : '$neutral2'} size="$icon.16" />
<Text color={gasFeeHighRelativeToSwapValue ? '$statusCritical' : '$neutral2'} variant="body4">
{gasFeeFormatted}
</Text>
</>
)}
</AnimatedFlex> </AnimatedFlex>
} }
uniswapXGasFeeInfo={uniswapXGasFeeInfo}
/> />
)} )}
</Flex> </Flex>
......
...@@ -15,8 +15,8 @@ import { FeeOnTransferFeeGroupProps } from 'wallet/src/features/transactions/Tra ...@@ -15,8 +15,8 @@ import { FeeOnTransferFeeGroupProps } from 'wallet/src/features/transactions/Tra
import { TransactionDetails } from 'wallet/src/features/transactions/TransactionDetails/TransactionDetails' import { TransactionDetails } from 'wallet/src/features/transactions/TransactionDetails/TransactionDetails'
import { Warning } from 'wallet/src/features/transactions/WarningModal/types' import { Warning } from 'wallet/src/features/transactions/WarningModal/types'
import { SwapRateRatio } from 'wallet/src/features/transactions/swap/SwapRateRatio' import { SwapRateRatio } from 'wallet/src/features/transactions/swap/SwapRateRatio'
import { UniswapXGasBreakdown } from 'wallet/src/features/transactions/swap/trade/api/hooks/useSwapTxAndGasInfo'
import { Trade } from 'wallet/src/features/transactions/swap/trade/types' import { Trade } from 'wallet/src/features/transactions/swap/trade/types'
import { isUniswapX } from 'wallet/src/features/transactions/swap/trade/utils'
import { DerivedSwapInfo } from 'wallet/src/features/transactions/swap/types' import { DerivedSwapInfo } from 'wallet/src/features/transactions/swap/types'
import { getFormattedCurrencyAmount } from 'wallet/src/utils/currency' import { getFormattedCurrencyAmount } from 'wallet/src/utils/currency'
import { ValueType, getCurrencyAmount } from 'wallet/src/utils/getCurrencyAmount' import { ValueType, getCurrencyAmount } from 'wallet/src/utils/getCurrencyAmount'
...@@ -50,6 +50,7 @@ interface SwapDetailsProps { ...@@ -50,6 +50,7 @@ interface SwapDetailsProps {
derivedSwapInfo: DerivedSwapInfo<CurrencyInfo, CurrencyInfo> derivedSwapInfo: DerivedSwapInfo<CurrencyInfo, CurrencyInfo>
gasFallbackUsed?: boolean gasFallbackUsed?: boolean
gasFee: GasFeeResult gasFee: GasFeeResult
uniswapXGasBreakdown?: UniswapXGasBreakdown
newTradeRequiresAcceptance: boolean newTradeRequiresAcceptance: boolean
outputCurrencyPricePerUnitExact?: string outputCurrencyPricePerUnitExact?: string
warning?: Warning warning?: Warning
...@@ -64,6 +65,7 @@ export function SwapDetails({ ...@@ -64,6 +65,7 @@ export function SwapDetails({
customSlippageTolerance, customSlippageTolerance,
derivedSwapInfo, derivedSwapInfo,
gasFee, gasFee,
uniswapXGasBreakdown,
newTradeRequiresAcceptance, newTradeRequiresAcceptance,
outputCurrencyPricePerUnitExact, outputCurrencyPricePerUnitExact,
warning, warning,
...@@ -123,8 +125,6 @@ export function SwapDetails({ ...@@ -123,8 +125,6 @@ export function SwapDetails({
], ],
) )
const preUniswapXGasFeeUSD = isUniswapX(trade) ? trade.quote.quote.classicGasUseEstimateUSD : undefined
return ( return (
<TransactionDetails <TransactionDetails
isSwap isSwap
...@@ -140,11 +140,11 @@ export function SwapDetails({ ...@@ -140,11 +140,11 @@ export function SwapDetails({
chainId={acceptedTrade.inputAmount.currency.chainId} chainId={acceptedTrade.inputAmount.currency.chainId}
feeOnTransferProps={feeOnTransferProps} feeOnTransferProps={feeOnTransferProps}
gasFee={gasFee} gasFee={gasFee}
preUniswapXGasFeeUSD={preUniswapXGasFeeUSD}
showExpandedChildren={!!customSlippageTolerance} showExpandedChildren={!!customSlippageTolerance}
showWarning={warning && !newTradeRequiresAcceptance} showWarning={warning && !newTradeRequiresAcceptance}
swapFeeInfo={swapFeeInfo} swapFeeInfo={swapFeeInfo}
transactionUSDValue={derivedSwapInfo.currencyAmountsUSDValue[CurrencyField.OUTPUT]} transactionUSDValue={derivedSwapInfo.currencyAmountsUSDValue[CurrencyField.OUTPUT]}
uniswapXGasBreakdown={uniswapXGasBreakdown}
warning={warning} warning={warning}
onShowWarning={onShowWarning} onShowWarning={onShowWarning}
> >
......
...@@ -58,6 +58,7 @@ export function SwapReviewScreen({ hideContent }: { hideContent: boolean }): JSX ...@@ -58,6 +58,7 @@ export function SwapReviewScreen({ hideContent }: { hideContent: boolean }): JSX
const swapTxContext = useSwapTxContext() const swapTxContext = useSwapTxContext()
const { gasFee, trade } = swapTxContext const { gasFee, trade } = swapTxContext
const uniswapXGasBreakdown = isUniswapX(swapTxContext) ? swapTxContext.gasFeeBreakdown : undefined
const { const {
derivedSwapInfo, derivedSwapInfo,
...@@ -406,6 +407,7 @@ export function SwapReviewScreen({ hideContent }: { hideContent: boolean }): JSX ...@@ -406,6 +407,7 @@ export function SwapReviewScreen({ hideContent }: { hideContent: boolean }): JSX
gasFee={gasFee} gasFee={gasFee}
newTradeRequiresAcceptance={newTradeRequiresAcceptance} newTradeRequiresAcceptance={newTradeRequiresAcceptance}
outputCurrencyPricePerUnitExact={outputCurrencyPricePerUnitExact} outputCurrencyPricePerUnitExact={outputCurrencyPricePerUnitExact}
uniswapXGasBreakdown={uniswapXGasBreakdown}
warning={reviewScreenWarning?.warning} warning={reviewScreenWarning?.warning}
onAcceptTrade={onAcceptTrade} onAcceptTrade={onAcceptTrade}
onShowSlippageModal={onShowSlippageModal} onShowSlippageModal={onShowSlippageModal}
......
...@@ -6,10 +6,8 @@ import { CurrencyLogo } from 'uniswap/src/components/CurrencyLogo/CurrencyLogo' ...@@ -6,10 +6,8 @@ import { CurrencyLogo } from 'uniswap/src/components/CurrencyLogo/CurrencyLogo'
import { CurrencyInfo } from 'uniswap/src/features/dataApi/types' import { CurrencyInfo } from 'uniswap/src/features/dataApi/types'
import { CurrencyField } from 'uniswap/src/features/transactions/transactionState/types' import { CurrencyField } from 'uniswap/src/features/transactions/transactionState/types'
import { getSymbolDisplayText } from 'uniswap/src/utils/currency' import { getSymbolDisplayText } from 'uniswap/src/utils/currency'
import { buildCurrencyId, currencyAddress } from 'uniswap/src/utils/currencyId'
import { NumberType } from 'utilities/src/format/types' import { NumberType } from 'utilities/src/format/types'
import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext' import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext'
import { useCurrencyInfo } from 'wallet/src/features/tokens/useCurrencyInfo'
import { DerivedSwapInfo } from 'wallet/src/features/transactions/swap/types' import { DerivedSwapInfo } from 'wallet/src/features/transactions/swap/types'
export function TransactionAmountsReview({ export function TransactionAmountsReview({
...@@ -23,45 +21,55 @@ export function TransactionAmountsReview({ ...@@ -23,45 +21,55 @@ export function TransactionAmountsReview({
}): JSX.Element { }): JSX.Element {
const { t } = useTranslation() const { t } = useTranslation()
const colors = useSporeColors() const colors = useSporeColors()
const { convertFiatAmountFormatted, formatCurrencyAmount } = useLocalizationContext() const { convertFiatAmountFormatted, formatCurrencyAmount, formatNumberOrString } = useLocalizationContext()
const { currencyAmountsUSDValue, exactCurrencyField, trade } = acceptedDerivedSwapInfo
if (!trade.trade) { const { currencies, currencyAmounts, currencyAmountsUSDValue, exactAmountToken, exactCurrencyField } =
throw new Error('Missing required `trade` to render `TransactionAmountsReview`') acceptedDerivedSwapInfo
}
const currencyInInfo = currencies[CurrencyField.INPUT]
const currencyOutInfo = currencies[CurrencyField.OUTPUT]
const usdAmountIn =
exactCurrencyField === CurrencyField.INPUT
? currencyAmountsUSDValue[CurrencyField.INPUT]?.toExact()
: acceptedDerivedSwapInfo?.currencyAmountsUSDValue[CurrencyField.INPUT]?.toExact()
const usdAmountOut =
exactCurrencyField === CurrencyField.OUTPUT
? currencyAmountsUSDValue[CurrencyField.OUTPUT]?.toExact()
: acceptedDerivedSwapInfo?.currencyAmountsUSDValue[CurrencyField.OUTPUT]?.toExact()
const formattedFiatAmountIn = convertFiatAmountFormatted(usdAmountIn, NumberType.FiatTokenQuantity)
const formattedFiatAmountOut = convertFiatAmountFormatted(usdAmountOut, NumberType.FiatTokenQuantity)
// Token amounts const derivedCurrencyField = exactCurrencyField === CurrencyField.INPUT ? CurrencyField.OUTPUT : CurrencyField.INPUT
// On review screen, always show values directly from trade object, to match exactly what is submitted on chain
const inputCurrencyAmount = trade.trade.inputAmount
const outputCurrencyAmount = trade.trade.outputAmount
const formattedTokenAmountIn = formatCurrencyAmount({ const derivedAmount = formatCurrencyAmount({
value: inputCurrencyAmount, value: acceptedDerivedSwapInfo?.currencyAmounts[derivedCurrencyField],
type: NumberType.TokenTx, type: NumberType.TokenTx,
}) })
const formattedTokenAmountOut = formatCurrencyAmount({
value: outputCurrencyAmount, const formattedExactAmountToken = formatNumberOrString({
value: exactAmountToken,
type: NumberType.TokenTx, type: NumberType.TokenTx,
}) })
// USD amounts const [formattedTokenAmountIn, formattedTokenAmountOut] =
const usdAmountIn = currencyAmountsUSDValue[CurrencyField.INPUT]?.toExact() exactCurrencyField === CurrencyField.INPUT
const usdAmountOut = currencyAmountsUSDValue[CurrencyField.OUTPUT]?.toExact() ? [formattedExactAmountToken, derivedAmount]
const formattedFiatAmountIn = convertFiatAmountFormatted(usdAmountIn, NumberType.FiatTokenQuantity) : [derivedAmount, formattedExactAmountToken]
const formattedFiatAmountOut = convertFiatAmountFormatted(usdAmountOut, NumberType.FiatTokenQuantity)
const shouldDimInput = newTradeRequiresAcceptance && exactCurrencyField === CurrencyField.OUTPUT const shouldDimInput = newTradeRequiresAcceptance && exactCurrencyField === CurrencyField.OUTPUT
const shouldDimOutput = newTradeRequiresAcceptance && exactCurrencyField === CurrencyField.INPUT const shouldDimOutput = newTradeRequiresAcceptance && exactCurrencyField === CurrencyField.INPUT
// Rebuild currency infos directly from trade object to ensure it matches what is submitted on chain if (
const currencyInInfo = useCurrencyInfo( !currencyInInfo ||
buildCurrencyId(inputCurrencyAmount.currency.chainId, currencyAddress(inputCurrencyAmount.currency)), !currencyOutInfo ||
) !currencyAmounts[CurrencyField.INPUT] ||
const currencyOutInfo = useCurrencyInfo( !currencyAmounts[CurrencyField.OUTPUT] ||
buildCurrencyId(outputCurrencyAmount.currency.chainId, currencyAddress(outputCurrencyAmount.currency)), !acceptedDerivedSwapInfo.currencyAmounts[CurrencyField.INPUT] ||
) !acceptedDerivedSwapInfo.currencyAmounts[CurrencyField.OUTPUT]
) {
if (!currencyInInfo || !currencyOutInfo) {
// This should never happen. It's just to keep TS happy. // This should never happen. It's just to keep TS happy.
throw new Error('Missing required props in `derivedSwapInfo` to render `TransactionAmountsReview` screen.') throw new Error('Missing required props in `derivedSwapInfo` to render `TransactionAmountsReview` screen.')
} }
......
import { PropsWithChildren } from 'react' import { PropsWithChildren } from 'react'
import { useTranslation } from 'react-i18next' import { Trans, useTranslation } from 'react-i18next'
import { isWeb, useSporeColors } from 'ui/src' import { Flex, Separator, Text, UniswapXText, isWeb, useSporeColors } from 'ui/src'
import { Gas } from 'ui/src/components/icons' import { Gas } from 'ui/src/components/icons'
import { LearnMoreLink } from 'uniswap/src/components/text/LearnMoreLink' import { LearnMoreLink } from 'uniswap/src/components/text/LearnMoreLink'
import { uniswapUrls } from 'uniswap/src/constants/urls' import { uniswapUrls } from 'uniswap/src/constants/urls'
import { ModalName } from 'uniswap/src/features/telemetry/constants' import { ModalName } from 'uniswap/src/features/telemetry/constants'
import { isMobile } from 'utilities/src/platform'
import { WarningInfo } from 'wallet/src/components/modals/WarningModal/WarningInfo' import { WarningInfo } from 'wallet/src/components/modals/WarningModal/WarningInfo'
import { WarningTooltipProps } from 'wallet/src/components/modals/WarningModal/WarningTooltipProps' import { WarningTooltipProps } from 'wallet/src/components/modals/WarningModal/WarningTooltipProps'
import { UniswapXFee } from 'wallet/src/components/network/NetworkFee'
import { FormattedUniswapXGasFeeInfo } from 'wallet/src/components/network/hooks'
import { WarningSeverity } from 'wallet/src/features/transactions/WarningModal/types' import { WarningSeverity } from 'wallet/src/features/transactions/WarningModal/types'
export function NetworkFeeWarning({ export function NetworkFeeWarning({
...@@ -14,39 +17,43 @@ export function NetworkFeeWarning({ ...@@ -14,39 +17,43 @@ export function NetworkFeeWarning({
children, children,
tooltipTrigger, tooltipTrigger,
placement = 'top', placement = 'top',
uniswapXGasFeeInfo,
}: PropsWithChildren<{ }: PropsWithChildren<{
gasFeeHighRelativeToValue?: boolean gasFeeHighRelativeToValue?: boolean
tooltipTrigger?: WarningTooltipProps['trigger'] tooltipTrigger?: WarningTooltipProps['trigger']
placement?: WarningTooltipProps['placement'] placement?: WarningTooltipProps['placement']
uniswapXGasFeeInfo?: FormattedUniswapXGasFeeInfo
}>): JSX.Element { }>): JSX.Element {
const colors = useSporeColors() const colors = useSporeColors()
const { t } = useTranslation() const { t } = useTranslation()
const text = gasFeeHighRelativeToValue const showHighGasFeeUI = gasFeeHighRelativeToValue && !uniswapXGasFeeInfo
? t('swap.warning.networkFee.highRelativeToValue')
: t('swap.warning.networkFee.message')
return ( return (
<WarningInfo <WarningInfo
infoButton={ infoButton={
<LearnMoreLink uniswapXGasFeeInfo ? (
textVariant={isWeb ? 'buttonLabel4' : undefined} <UniswapXFeeContent uniswapXGasFeeInfo={uniswapXGasFeeInfo} />
url={uniswapUrls.helpArticleUrls.networkFeeInfo} ) : (
/> <LearnMoreLink
textVariant={isWeb ? 'buttonLabel4' : undefined}
url={uniswapUrls.helpArticleUrls.networkFeeInfo}
/>
)
} }
modalProps={{ modalProps={{
backgroundIconColor: colors.surface2.get(), backgroundIconColor: colors.surface2.get(),
caption: text, caption: <NetworkFeeText showHighGasFeeUI={showHighGasFeeUI} uniswapXGasFeeInfo={uniswapXGasFeeInfo} />,
closeText: t('common.button.close'), closeText: t('common.button.close'),
icon: <Gas color={gasFeeHighRelativeToValue ? '$statusCritical' : '$neutral2'} size="$icon.24" />, icon: <Gas color={showHighGasFeeUI ? '$statusCritical' : '$neutral2'} size="$icon.24" />,
modalName: ModalName.NetworkFeeInfo, modalName: ModalName.NetworkFeeInfo,
severity: WarningSeverity.None, severity: WarningSeverity.None,
title: t('transaction.networkCost.label'), title: t('transaction.networkCost.label'),
}} }}
tooltipProps={{ tooltipProps={{
text, text: <NetworkFeeText showHighGasFeeUI={showHighGasFeeUI} uniswapXGasFeeInfo={uniswapXGasFeeInfo} />,
placement, placement,
icon: gasFeeHighRelativeToValue ? <Gas color="$statusCritical" size="$icon.16" /> : null, icon: showHighGasFeeUI ? <Gas color="$statusCritical" size="$icon.16" /> : null,
}} }}
trigger={tooltipTrigger} trigger={tooltipTrigger}
> >
...@@ -54,3 +61,65 @@ export function NetworkFeeWarning({ ...@@ -54,3 +61,65 @@ export function NetworkFeeWarning({
</WarningInfo> </WarningInfo>
) )
} }
function NetworkFeeText({
showHighGasFeeUI,
uniswapXGasFeeInfo,
}: {
showHighGasFeeUI?: boolean
uniswapXGasFeeInfo?: FormattedUniswapXGasFeeInfo
}): JSX.Element {
const { t } = useTranslation()
if (uniswapXGasFeeInfo) {
return (
<Trans
components={{ gradient: <UniswapXText height={18} variant="body3" /> }}
i18nKey="swap.warning.networkFee.message.uniswapX"
/>
)
} else if (showHighGasFeeUI) {
return t('swap.warning.networkFee.highRelativeToValue')
} else {
return t('swap.warning.networkFee.message')
}
}
function UniswapXFeeContent({ uniswapXGasFeeInfo }: { uniswapXGasFeeInfo: FormattedUniswapXGasFeeInfo }): JSX.Element {
const { approvalFeeFormatted, wrapFeeFormatted, swapFeeFormatted, inputTokenSymbol } = uniswapXGasFeeInfo
const { t } = useTranslation()
return (
<Flex gap="$spacing12">
<Flex centered={isMobile} width="100%">
<LearnMoreLink
textVariant={isWeb ? 'buttonLabel4' : undefined}
url={uniswapUrls.helpArticleUrls.uniswapXInfo}
/>
</Flex>
<Separator />
{wrapFeeFormatted && (
<Flex row justifyContent="space-between" width="100%">
<Text color="$neutral2" variant="body3">
{t('swap.warning.networkFee.wrap')}
</Text>
<Text variant="body3">{wrapFeeFormatted}</Text>
</Flex>
)}
{approvalFeeFormatted && (
<Flex row justifyContent="space-between" width="100%">
<Text color="$neutral2" variant="body3">
{t('swap.warning.networkFee.allow', { inputTokenSymbol })}
</Text>
<Text variant="body3">{approvalFeeFormatted}</Text>
</Flex>
)}
<Flex row justifyContent="space-between" width="100%">
<Text color="$neutral2" variant="body3">
{t('common.button.swap')}
</Text>
<UniswapXFee gasFee={swapFeeFormatted} />
</Flex>
</Flex>
)
}
...@@ -19,8 +19,14 @@ import { useCurrencyInfo } from 'wallet/src/features/tokens/useCurrencyInfo' ...@@ -19,8 +19,14 @@ import { useCurrencyInfo } from 'wallet/src/features/tokens/useCurrencyInfo'
import { SwapTransactionDetails } from 'wallet/src/features/transactions/SummaryCards/DetailsModal/SwapTransactionDetails' import { SwapTransactionDetails } from 'wallet/src/features/transactions/SummaryCards/DetailsModal/SwapTransactionDetails'
import { isSwapTransactionInfo } from 'wallet/src/features/transactions/SummaryCards/DetailsModal/types' import { isSwapTransactionInfo } from 'wallet/src/features/transactions/SummaryCards/DetailsModal/types'
import { ErroredQueuedOrderStatus, useErroredQueuedOrders } from 'wallet/src/features/transactions/hooks' import { ErroredQueuedOrderStatus, useErroredQueuedOrders } from 'wallet/src/features/transactions/hooks'
import { useSelectAddressTransactions } from 'wallet/src/features/transactions/selectors'
import { updateTransaction } from 'wallet/src/features/transactions/slice' import { updateTransaction } from 'wallet/src/features/transactions/slice'
import { QueuedOrderStatus, TransactionDetails, TransactionStatus } from 'wallet/src/features/transactions/types' import {
QueuedOrderStatus,
TransactionDetails,
TransactionStatus,
TransactionType,
} from 'wallet/src/features/transactions/types'
import { useActiveSignerAccount } from 'wallet/src/features/wallet/hooks' import { useActiveSignerAccount } from 'wallet/src/features/wallet/hooks'
const QUEUE_STATUS_TO_MESSAGE = { const QUEUE_STATUS_TO_MESSAGE = {
...@@ -56,15 +62,23 @@ export function QueuedOrderModal(): JSX.Element | null { ...@@ -56,15 +62,23 @@ export function QueuedOrderModal(): JSX.Element | null {
} }
}, [transactionState, navigateToSwapFlow, onCancel]) }, [transactionState, navigateToSwapFlow, onCancel])
const localTransactions = useSelectAddressTransactions(account?.address ?? null)
// If a wrap tx was involved as part of the order flow, show a message indicating that the user now has WETH,
// unless the wrap failed, in which case the user still has ETH and the message should not be shown.
const showWrapMessage = useMemo(() => {
if (!currentFailedOrder || currentFailedOrder?.queueStatus === QueuedOrderStatus.WrapFailed) {
return false
}
return localTransactions?.some(
(tx) => tx.typeInfo.type === TransactionType.Wrap && tx.typeInfo.swapTxId === currentFailedOrder?.id,
)
}, [localTransactions, currentFailedOrder])
// If there are no failed orders tracked in state, return nothing. // If there are no failed orders tracked in state, return nothing.
if (!uniswapXEnabled || !currentFailedOrder || !isSwapTransactionInfo(currentFailedOrder.typeInfo)) { if (!uniswapXEnabled || !currentFailedOrder || !isSwapTransactionInfo(currentFailedOrder.typeInfo)) {
return null return null
} }
const reason = QUEUE_STATUS_TO_MESSAGE[currentFailedOrder.queueStatus] const reason = QUEUE_STATUS_TO_MESSAGE[currentFailedOrder.queueStatus]
// If a wrap tx was involved as part of the order flow, show a message indicating that the user now has WETH,
// unless the wrap failed, in which case the user still has ETH and the message should not be shown.
const showWrapMessage =
Boolean(currentFailedOrder.wrapTxHash) && currentFailedOrder.queueStatus !== QueuedOrderStatus.WrapFailed
const buttonSize = isShortMobileDevice ? 'small' : 'medium' const buttonSize = isShortMobileDevice ? 'small' : 'medium'
...@@ -84,7 +98,7 @@ export function QueuedOrderModal(): JSX.Element | null { ...@@ -84,7 +98,7 @@ export function QueuedOrderModal(): JSX.Element | null {
<Text color="$neutral2" textAlign="center" variant="body3"> <Text color="$neutral2" textAlign="center" variant="body3">
{reason} {reason}
{showWrapMessage && ' '} {showWrapMessage && ' '}
{showWrapMessage && <> {t('swap.warning.queuedOrder.wrap.message')}</>} {showWrapMessage && t('swap.warning.queuedOrder.wrap.message')}
</Text> </Text>
<LearnMoreLink <LearnMoreLink
textColor="$neutral1" textColor="$neutral1"
......
import { PropsWithChildren } from 'react' import { PropsWithChildren } from 'react'
import { useTranslation } from 'react-i18next' import { Trans, useTranslation } from 'react-i18next'
import { UniswapXText, isWeb } from 'ui/src' import { UniswapXText, isWeb } from 'ui/src'
import { UniswapX } from 'ui/src/components/icons' import { UniswapX } from 'ui/src/components/icons'
import { colors, opacify } from 'ui/src/theme' import { colors, opacify } from 'ui/src/theme'
...@@ -30,7 +30,7 @@ export function UniswapXInfo({ ...@@ -30,7 +30,7 @@ export function UniswapXInfo({
} }
modalProps={{ modalProps={{
backgroundIconColor: opacify(16, colors.uniswapXPurple), backgroundIconColor: opacify(16, colors.uniswapXPurple),
caption: t('uniswapx.description'), caption: <Trans components={{ gradient: <></> }} i18nKey="uniswapx.description" />,
closeText: t('common.button.close'), closeText: t('common.button.close'),
icon: <UniswapX size="$icon.24" />, icon: <UniswapX size="$icon.24" />,
modalName: ModalName.UniswapXInfo, modalName: ModalName.UniswapXInfo,
......
...@@ -58,7 +58,6 @@ export function* submitUniswapXOrder(params: SubmitUniswapXOrderParams) { ...@@ -58,7 +58,6 @@ export function* submitUniswapXOrder(params: SubmitUniswapXOrderParams) {
addedTime: Date.now(), addedTime: Date.now(),
status: TransactionStatus.Pending, status: TransactionStatus.Pending,
queueStatus: QueuedOrderStatus.Waiting, queueStatus: QueuedOrderStatus.Waiting,
wrapTxHash,
} satisfies UniswapXOrderDetails } satisfies UniswapXOrderDetails
yield* put(transactionActions.addTransaction(order)) yield* put(transactionActions.addTransaction(order))
......
...@@ -55,6 +55,7 @@ export function* approveAndSwap(params: SwapParams) { ...@@ -55,6 +55,7 @@ export function* approveAndSwap(params: SwapParams) {
type: TransactionType.Approve, type: TransactionType.Approve,
tokenAddress: approveTxRequest.to, tokenAddress: approveTxRequest.to,
spender: permit2Address(chainId), spender: permit2Address(chainId),
swapTxId: txId,
} }
const options = { request: approveTxRequest, submitViaPrivateRpc } const options = { request: approveTxRequest, submitViaPrivateRpc }
...@@ -73,7 +74,12 @@ export function* approveAndSwap(params: SwapParams) { ...@@ -73,7 +74,12 @@ export function* approveAndSwap(params: SwapParams) {
// Wrap Logic - UniswapX Eth-input // Wrap Logic - UniswapX Eth-input
if (wrapTxRequest) { if (wrapTxRequest) {
const inputCurrencyAmount = trade.inputAmount const inputCurrencyAmount = trade.inputAmount
const wrapResponse = yield* wrap({ txRequest: { ...wrapTxRequest, nonce }, account, inputCurrencyAmount }) const wrapResponse = yield* wrap({
txRequest: { ...wrapTxRequest, nonce },
account,
inputCurrencyAmount,
swapTxId: txId,
})
wrapTxHash = wrapResponse?.transactionResponse.hash wrapTxHash = wrapResponse?.transactionResponse.hash
} }
......
...@@ -3,12 +3,13 @@ import { RestLink } from 'apollo-link-rest' ...@@ -3,12 +3,13 @@ import { RestLink } from 'apollo-link-rest'
import { config } from 'uniswap/src/config' import { config } from 'uniswap/src/config'
import { uniswapUrls } from 'uniswap/src/constants/urls' import { uniswapUrls } from 'uniswap/src/constants/urls'
import { createNewInMemoryCache } from 'uniswap/src/data/cache' import { createNewInMemoryCache } from 'uniswap/src/data/cache'
import { REQUEST_SOURCE } from 'uniswap/src/data/constants' import { REQUEST_SOURCE, getVersionHeader } from 'uniswap/src/data/constants'
export const TRADING_API_HEADERS = { export const TRADING_API_HEADERS = {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'X-API-KEY': config.tradingApiKey, 'X-API-KEY': config.tradingApiKey,
'x-request-source': REQUEST_SOURCE, 'x-request-source': REQUEST_SOURCE,
'x-app-version': getVersionHeader(),
Origin: uniswapUrls.requestOriginUrl, Origin: uniswapUrls.requestOriginUrl,
} as const } as const
......
...@@ -12,6 +12,13 @@ import { sumGasFees } from 'wallet/src/features/transactions/swap/utils' ...@@ -12,6 +12,13 @@ import { sumGasFees } from 'wallet/src/features/transactions/swap/utils'
export type SwapTxAndGasInfo = ClassicSwapTxAndGasInfo | UniswapXSwapTxAndGasInfo export type SwapTxAndGasInfo = ClassicSwapTxAndGasInfo | UniswapXSwapTxAndGasInfo
export type UniswapXGasBreakdown = {
classicGasUseEstimateUSD?: number
approvalCost?: string
wrapCost?: string
inputTokenSymbol?: string
}
export type ClassicSwapTxAndGasInfo = { export type ClassicSwapTxAndGasInfo = {
routing: Routing.CLASSIC routing: Routing.CLASSIC
trade?: ClassicTrade trade?: ClassicTrade
...@@ -28,6 +35,7 @@ export type UniswapXSwapTxAndGasInfo = { ...@@ -28,6 +35,7 @@ export type UniswapXSwapTxAndGasInfo = {
approveTxRequest: ValidatedTransactionRequest | undefined approveTxRequest: ValidatedTransactionRequest | undefined
orderParams?: OrderRequest orderParams?: OrderRequest
gasFee: GasFeeResult gasFee: GasFeeResult
gasFeeBreakdown: UniswapXGasBreakdown
approvalError: boolean approvalError: boolean
} }
...@@ -91,6 +99,13 @@ export function useSwapTxAndGasInfo({ derivedSwapInfo }: { derivedSwapInfo: Deri ...@@ -91,6 +99,13 @@ export function useSwapTxAndGasInfo({ derivedSwapInfo }: { derivedSwapInfo: Deri
if (trade?.routing === Routing.DUTCH_V2) { if (trade?.routing === Routing.DUTCH_V2) {
const signature = swapTxInfo.permitSignature const signature = swapTxInfo.permitSignature
const orderParams = signature ? { signature, quote: trade.quote.quote, routing: Routing.DUTCH_V2 } : undefined const orderParams = signature ? { signature, quote: trade.quote.quote, routing: Routing.DUTCH_V2 } : undefined
const gasFeeBreakdown: UniswapXGasBreakdown = {
// TODO(API-324): next version of trading api schema will break the following line; update the type's field to be a string instead
classicGasUseEstimateUSD: trade.quote.quote.classicGasUseEstimateUSD,
approvalCost: tokenApprovalInfo?.gasFee,
wrapCost: swapTxInfo.gasFeeResult.value,
inputTokenSymbol: trade.inputAmount.currency.wrapped.symbol,
}
return { return {
routing: Routing.DUTCH_V2, routing: Routing.DUTCH_V2,
...@@ -99,6 +114,7 @@ export function useSwapTxAndGasInfo({ derivedSwapInfo }: { derivedSwapInfo: Deri ...@@ -99,6 +114,7 @@ export function useSwapTxAndGasInfo({ derivedSwapInfo }: { derivedSwapInfo: Deri
approveTxRequest, approveTxRequest,
orderParams, orderParams,
gasFee, gasFee,
gasFeeBreakdown,
approvalError, approvalError,
} }
} else { } else {
......
...@@ -4,7 +4,7 @@ import { useMemo } from 'react' ...@@ -4,7 +4,7 @@ import { useMemo } from 'react'
import { uniswapUrls } from 'uniswap/src/constants/urls' import { uniswapUrls } from 'uniswap/src/constants/urls'
import { useRestQuery } from 'uniswap/src/data/rest' import { useRestQuery } from 'uniswap/src/data/rest'
import { isMainnetChainId } from 'uniswap/src/features/chains/utils' import { isMainnetChainId } from 'uniswap/src/features/chains/utils'
import { DynamicConfigs, PollingIntervalsConfigKey } from 'uniswap/src/features/gating/configs' import { DynamicConfigs, SwapConfigKey } from 'uniswap/src/features/gating/configs'
import { FeatureFlags } from 'uniswap/src/features/gating/flags' import { FeatureFlags } from 'uniswap/src/features/gating/flags'
import { useDynamicConfigValue, useFeatureFlag } from 'uniswap/src/features/gating/hooks' import { useDynamicConfigValue, useFeatureFlag } from 'uniswap/src/features/gating/hooks'
import { CurrencyField } from 'uniswap/src/features/transactions/transactionState/types' import { CurrencyField } from 'uniswap/src/features/transactions/transactionState/types'
...@@ -253,14 +253,14 @@ const FALLBACK_L2_BLOCK_TIME_MS = 3000 ...@@ -253,14 +253,14 @@ const FALLBACK_L2_BLOCK_TIME_MS = 3000
function usePollingIntervalByChain(chainId?: WalletChainId): number { function usePollingIntervalByChain(chainId?: WalletChainId): number {
const averageL1BlockTimeMs = useDynamicConfigValue( const averageL1BlockTimeMs = useDynamicConfigValue(
DynamicConfigs.PollingIntervals, DynamicConfigs.Swap,
PollingIntervalsConfigKey.AverageL1BlockTimeMs, SwapConfigKey.AverageL1BlockTimeMs,
FALLBACK_L1_BLOCK_TIME_MS, FALLBACK_L1_BLOCK_TIME_MS,
) )
const averageL2BlockTimeMs = useDynamicConfigValue( const averageL2BlockTimeMs = useDynamicConfigValue(
DynamicConfigs.PollingIntervals, DynamicConfigs.Swap,
PollingIntervalsConfigKey.AverageL2BlockTimeMs, SwapConfigKey.AverageL2BlockTimeMs,
FALLBACK_L2_BLOCK_TIME_MS, FALLBACK_L2_BLOCK_TIME_MS,
) )
......
...@@ -3,7 +3,7 @@ import { providers } from 'ethers' ...@@ -3,7 +3,7 @@ import { providers } from 'ethers'
import { useEffect, useMemo, useRef } from 'react' import { useEffect, useMemo, useRef } from 'react'
import { uniswapUrls } from 'uniswap/src/constants/urls' import { uniswapUrls } from 'uniswap/src/constants/urls'
import { useRestQuery } from 'uniswap/src/data/rest' import { useRestQuery } from 'uniswap/src/data/rest'
import { DynamicConfigs, PollingIntervalsConfigKey } from 'uniswap/src/features/gating/configs' import { DynamicConfigs, SwapConfigKey } from 'uniswap/src/features/gating/configs'
import { useDynamicConfigValue } from 'uniswap/src/features/gating/hooks' import { useDynamicConfigValue } from 'uniswap/src/features/gating/hooks'
import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send'
import { CurrencyField } from 'uniswap/src/features/transactions/transactionState/types' import { CurrencyField } from 'uniswap/src/features/transactions/transactionState/types'
...@@ -116,8 +116,8 @@ export function useTransactionRequestInfo({ ...@@ -116,8 +116,8 @@ export function useTransactionRequestInfo({
// We will remove this cast in follow up change to dynamic config typing // We will remove this cast in follow up change to dynamic config typing
const tradingApiSwapRequestMs = useDynamicConfigValue( const tradingApiSwapRequestMs = useDynamicConfigValue(
DynamicConfigs.PollingIntervals, DynamicConfigs.Swap,
PollingIntervalsConfigKey.TradingApiSwapRequestMs, SwapConfigKey.TradingApiSwapRequestMs,
FALLBACK_SWAP_REQUEST_POLL_INTERVAL_MS, FALLBACK_SWAP_REQUEST_POLL_INTERVAL_MS,
) )
......
import { useMemo } from 'react' import { useMemo } from 'react'
import { isMainnetChainId, toSupportedChainId } from 'uniswap/src/features/chains/utils' import { isMainnetChainId, toSupportedChainId } from 'uniswap/src/features/chains/utils'
import { DynamicConfigs, SlippageConfigKey } from 'uniswap/src/features/gating/configs' import { DynamicConfigs, SwapConfigKey } from 'uniswap/src/features/gating/configs'
import { useDynamicConfigValue } from 'uniswap/src/features/gating/hooks' import { useDynamicConfigValue } from 'uniswap/src/features/gating/hooks'
import { MAX_AUTO_SLIPPAGE_TOLERANCE, MIN_AUTO_SLIPPAGE_TOLERANCE } from 'wallet/src/constants/transactions' import { MAX_AUTO_SLIPPAGE_TOLERANCE, MIN_AUTO_SLIPPAGE_TOLERANCE } from 'wallet/src/constants/transactions'
import { import {
...@@ -63,7 +63,11 @@ export function useSetTradeSlippage( ...@@ -63,7 +63,11 @@ export function useSetTradeSlippage(
function useCalculateAutoSlippage(trade: Maybe<Trade>): number { function useCalculateAutoSlippage(trade: Maybe<Trade>): number {
const outputAmountUSD = useUSDCValue(trade?.outputAmount)?.toExact() const outputAmountUSD = useUSDCValue(trade?.outputAmount)?.toExact()
const minAutoSlippageToleranceL2 = useSlippageValueFromDynamicConfig(SlippageConfigKey.MinAutoSlippageToleranceL2) const minAutoSlippageToleranceL2 = useDynamicConfigValue(
DynamicConfigs.Swap,
SwapConfigKey.MinAutoSlippageToleranceL2,
0,
)
return useMemo<number>(() => { return useMemo<number>(() => {
const quote = getClassicQuoteFromResponse(trade?.quote) const quote = getClassicQuoteFromResponse(trade?.quote)
...@@ -110,10 +114,3 @@ function calculateAutoSlippage({ ...@@ -110,10 +114,3 @@ function calculateAutoSlippage({
return Number(suggestedSlippageTolerance.toFixed(2)) return Number(suggestedSlippageTolerance.toFixed(2))
} }
function useSlippageValueFromDynamicConfig(configName: SlippageConfigKey): number {
const slippageValue = useDynamicConfigValue(DynamicConfigs.Slippage, configName, '')
// Format as % number
return parseInt(slippageValue, 10)
}
import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import { providers } from 'ethers' import { providers } from 'ethers'
import { useCallback } from 'react' import { useCallback } from 'react'
import { CurrencyField } from 'uniswap/src/features/transactions/transactionState/types'
import { WalletChainId } from 'uniswap/src/types/chains' import { WalletChainId } from 'uniswap/src/types/chains'
import { useAsyncData } from 'utilities/src/react/hooks' import { useAsyncData } from 'utilities/src/react/hooks'
import { Trade } from 'wallet/src/features/transactions/swap/trade/types'
import { isUniswapX } from 'wallet/src/features/transactions/swap/trade/utils' import { isUniswapX } from 'wallet/src/features/transactions/swap/trade/utils'
import { DerivedSwapInfo } from 'wallet/src/features/transactions/swap/types' import { DerivedSwapInfo } from 'wallet/src/features/transactions/swap/types'
import { getWethContract } from 'wallet/src/features/transactions/swap/wrapSaga' import { getWethContract } from 'wallet/src/features/transactions/swap/wrapSaga'
...@@ -16,18 +14,11 @@ export function useWrapTransactionRequest(derivedSwapInfo: DerivedSwapInfo): pro ...@@ -16,18 +14,11 @@ export function useWrapTransactionRequest(derivedSwapInfo: DerivedSwapInfo): pro
const address = useActiveAccountAddressWithThrow() const address = useActiveAccountAddressWithThrow()
const { chainId, wrapType, currencyAmounts, trade } = derivedSwapInfo const { chainId, wrapType, currencyAmounts, trade } = derivedSwapInfo
const provider = useProvider(chainId) const provider = useProvider(chainId)
const isUniswapXWrap = Boolean(trade.trade && isUniswapX(trade.trade) && trade.trade.needsWrap)
const transactionFetcher = useCallback( const transactionFetcher = useCallback(
() => () => getWrapTransactionRequest(provider, isUniswapXWrap, chainId, address, wrapType, currencyAmounts.input),
getWrapTransactionRequest( [provider, isUniswapXWrap, chainId, address, wrapType, currencyAmounts.input],
provider,
trade.trade,
chainId,
address,
wrapType,
currencyAmounts[CurrencyField.INPUT],
),
[address, chainId, wrapType, currencyAmounts, provider, trade.trade],
) )
return useAsyncData(transactionFetcher).data return useAsyncData(transactionFetcher).data
...@@ -35,13 +26,12 @@ export function useWrapTransactionRequest(derivedSwapInfo: DerivedSwapInfo): pro ...@@ -35,13 +26,12 @@ export function useWrapTransactionRequest(derivedSwapInfo: DerivedSwapInfo): pro
const getWrapTransactionRequest = async ( const getWrapTransactionRequest = async (
provider: providers.Provider | null, provider: providers.Provider | null,
trade: Trade | null, isUniswapXWrap: boolean,
chainId: WalletChainId, chainId: WalletChainId,
address: Address, address: Address,
wrapType: WrapType, wrapType: WrapType,
currencyAmountIn: Maybe<CurrencyAmount<Currency>>, currencyAmountIn: Maybe<CurrencyAmount<Currency>>,
): Promise<providers.TransactionRequest | undefined> => { ): Promise<providers.TransactionRequest | undefined> => {
const isUniswapXWrap = trade && isUniswapX(trade) && trade.needsWrap
if (!currencyAmountIn || !provider || (wrapType === WrapType.NotApplicable && !isUniswapXWrap)) { if (!currencyAmountIn || !provider || (wrapType === WrapType.NotApplicable && !isUniswapXWrap)) {
return return
} }
......
...@@ -13,6 +13,7 @@ const wrapTxInfo: WrapTransactionInfo = { ...@@ -13,6 +13,7 @@ const wrapTxInfo: WrapTransactionInfo = {
type: TransactionType.Wrap, type: TransactionType.Wrap,
unwrapped: false, unwrapped: false,
currencyAmountRaw: '200000', currencyAmountRaw: '200000',
swapTxId: undefined,
} }
const unwrapTxInfo: WrapTransactionInfo = { const unwrapTxInfo: WrapTransactionInfo = {
......
...@@ -13,6 +13,8 @@ import { createMonitoredSaga } from 'wallet/src/utils/saga' ...@@ -13,6 +13,8 @@ import { createMonitoredSaga } from 'wallet/src/utils/saga'
export type WrapParams = { export type WrapParams = {
txId?: string txId?: string
// The id that will be used for the swap submitted after the wrap, if applicable.
swapTxId?: string
txRequest: providers.TransactionRequest txRequest: providers.TransactionRequest
account: Account account: Account
inputCurrencyAmount: CurrencyAmount<Currency> inputCurrencyAmount: CurrencyAmount<Currency>
...@@ -24,7 +26,7 @@ export async function getWethContract(chainId: WalletChainId, provider: provider ...@@ -24,7 +26,7 @@ export async function getWethContract(chainId: WalletChainId, provider: provider
export function* wrap(params: WrapParams) { export function* wrap(params: WrapParams) {
try { try {
const { account, inputCurrencyAmount, txRequest, txId } = params const { account, inputCurrencyAmount, txRequest, txId, swapTxId } = params
let typeInfo: TransactionTypeInfo let typeInfo: TransactionTypeInfo
if (inputCurrencyAmount.currency.isNative) { if (inputCurrencyAmount.currency.isNative) {
...@@ -32,12 +34,14 @@ export function* wrap(params: WrapParams) { ...@@ -32,12 +34,14 @@ export function* wrap(params: WrapParams) {
type: TransactionType.Wrap, type: TransactionType.Wrap,
unwrapped: false, unwrapped: false,
currencyAmountRaw: inputCurrencyAmount.quotient.toString(), currencyAmountRaw: inputCurrencyAmount.quotient.toString(),
swapTxId,
} }
} else { } else {
typeInfo = { typeInfo = {
type: TransactionType.Wrap, type: TransactionType.Wrap,
unwrapped: true, unwrapped: true,
currencyAmountRaw: inputCurrencyAmount.quotient.toString(), currencyAmountRaw: inputCurrencyAmount.quotient.toString(),
swapTxId,
} }
} }
......
import { providers } from 'ethers' import { providers } from 'ethers'
import { useState } from 'react' import { useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { iconSizes } from 'ui/src/theme'
import { ElementName, ModalName } from 'uniswap/src/features/telemetry/constants' import { ElementName, ModalName } from 'uniswap/src/features/telemetry/constants'
import { CurrencyField } from 'uniswap/src/features/transactions/transactionState/types' import { CurrencyField } from 'uniswap/src/features/transactions/transactionState/types'
import { NumberType } from 'utilities/src/format/types' import { NumberType } from 'utilities/src/format/types'
import { AccountDetails } from 'wallet/src/components/accounts/AccountDetails'
import { WarningModal } from 'wallet/src/components/modals/WarningModal/WarningModal' import { WarningModal } from 'wallet/src/components/modals/WarningModal/WarningModal'
import { useAppFiatCurrencyInfo } from 'wallet/src/features/fiatCurrency/hooks' import { useAppFiatCurrencyInfo } from 'wallet/src/features/fiatCurrency/hooks'
import { GasFeeResult } from 'wallet/src/features/gas/types' import { GasFeeResult } from 'wallet/src/features/gas/types'
import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext' import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext'
import { TransactionDetails } from 'wallet/src/features/transactions/TransactionDetails/TransactionDetails' import { TransactionDetails } from 'wallet/src/features/transactions/TransactionDetails/TransactionDetails'
import { AddressFooter } from 'wallet/src/features/transactions/TransactionRequest/AddressFooter'
import { TransactionReview } from 'wallet/src/features/transactions/TransactionReview/TransactionReview' import { TransactionReview } from 'wallet/src/features/transactions/TransactionReview/TransactionReview'
import { WarningSeverity } from 'wallet/src/features/transactions/WarningModal/types' import { WarningSeverity } from 'wallet/src/features/transactions/WarningModal/types'
import { ParsedWarnings } from 'wallet/src/features/transactions/hooks/useParsedTransactionWarnings' import { ParsedWarnings } from 'wallet/src/features/transactions/hooks/useParsedTransactionWarnings'
...@@ -119,7 +118,7 @@ export function TransferReview({ ...@@ -119,7 +118,7 @@ export function TransferReview({
recipient={recipient} recipient={recipient}
transactionDetails={ transactionDetails={
<TransactionDetails <TransactionDetails
AccountDetails={<AccountDetails address={userAddress} iconSize={iconSizes.icon20} />} AccountDetails={<AddressFooter activeAccountAddress={userAddress} />}
chainId={chainId} chainId={chainId}
gasFee={gasFee} gasFee={gasFee}
showWarning={Boolean(transferWarning)} showWarning={Boolean(transferWarning)}
......
...@@ -77,9 +77,6 @@ export interface UniswapXOrderDetails extends BaseTransactionDetails { ...@@ -77,9 +77,6 @@ export interface UniswapXOrderDetails extends BaseTransactionDetails {
// Used to track status of the order before it is submitted // Used to track status of the order before it is submitted
queueStatus?: QueuedOrderStatus queueStatus?: QueuedOrderStatus
// The txHash of the wrap transaction submitted before the order
wrapTxHash?: string
} }
export interface ClassicTransactionDetails extends BaseTransactionDetails { export interface ClassicTransactionDetails extends BaseTransactionDetails {
...@@ -207,6 +204,8 @@ export interface ApproveTransactionInfo extends BaseTransactionInfo { ...@@ -207,6 +204,8 @@ export interface ApproveTransactionInfo extends BaseTransactionInfo {
spender: string spender: string
approvalAmount?: string approvalAmount?: string
dappInfo?: DappInfoTransactionDetails dappInfo?: DappInfoTransactionDetails
// The id of the swap TransactionDetails object submitted after this approval on the current client, if applicable.
swapTxId?: string
} }
export interface BaseSwapTransactionInfo extends BaseTransactionInfo { export interface BaseSwapTransactionInfo extends BaseTransactionInfo {
...@@ -244,6 +243,9 @@ export interface WrapTransactionInfo extends BaseTransactionInfo { ...@@ -244,6 +243,9 @@ export interface WrapTransactionInfo extends BaseTransactionInfo {
type: TransactionType.Wrap type: TransactionType.Wrap
unwrapped: boolean unwrapped: boolean
currencyAmountRaw: string currencyAmountRaw: string
// The id of the swap TransactionDetails object submitted after this wrap on the current client, if applicable.
// Currently, this will only be set for wraps that are part of a UniswapX native-input swap.
swapTxId?: string
} }
export interface SendTokenTransactionInfo extends BaseTransactionInfo { export interface SendTokenTransactionInfo extends BaseTransactionInfo {
......
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