diff --git a/.husky/pre-commit b/.husky/pre-commit index 0b80bcea0f4..f6571f4af95 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,19 @@ #!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" -yarn g:run-fast-checks \ No newline at end of file +yarn g:run-fast-checks + +if command -v git-secrets &> /dev/null +then # only run if git-secrets is installed + # Initialise git-secrets configuration + git-secrets --register-aws > /dev/null + + echo "Running git-secrets..." + # Scans all files that are about to be committed. + git-secrets --pre_commit_hook -- "$@" +fi + +if command -v trufflehog &> /dev/null +then # only run if trufflehog is installed + trufflehog git file://. --since-commit HEAD --only-verified --fail +fi diff --git a/.yarn/patches/@tanstack-react-query-npm-5.51.16-8fa6414eca.patch b/.yarn/patches/@tanstack-react-query-npm-5.51.16-8fa6414eca.patch new file mode 100644 index 00000000000..bfeeff81c70 --- /dev/null +++ b/.yarn/patches/@tanstack-react-query-npm-5.51.16-8fa6414eca.patch @@ -0,0 +1,30 @@ +diff --git a/package.json b/package.json +index e4b37644f3a62171deaff6dbf7731979ce751c78..7b2ca64565c0c6318ba01ff26cb4fad1c7419b0d 100644 +--- a/package.json ++++ b/package.json +@@ -15,22 +15,9 @@ + "url": "https://github.com/sponsors/tannerlinsley" + }, + "type": "module", +- "types": "build/legacy/index.d.ts", +- "main": "build/legacy/index.cjs", +- "module": "build/legacy/index.js", +- "exports": { +- ".": { +- "import": { +- "types": "./build/modern/index.d.ts", +- "default": "./build/modern/index.js" +- }, +- "require": { +- "types": "./build/modern/index.d.cts", +- "default": "./build/modern/index.cjs" +- } +- }, +- "./package.json": "./package.json" +- }, ++ "types": "build/modern/index.d.ts", ++ "main": "build/modern/index.cjs", ++ "module": "build/modern/index.js", + "sideEffects": false, + "files": [ + "build", diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 00000000000..f70773659eb --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1 @@ +* @uniswap/web-admins diff --git a/RELEASE b/RELEASE index 462c1439bb8..0395a5cd972 100644 --- a/RELEASE +++ b/RELEASE @@ -1,11 +1,63 @@ -We are back with some new updates! Here’s the latest: - -Onboarding Improvements: New unfunded wallets will experience our upgraded homepage, which gives a preview of our token explore page, as well as a card stack of onboarding steps to complete. - -Haptic Touch Settings: Users can now toggle their haptic touch preferences on the Settings page. - -Other changes: - -- Improved context menus on Swap Activity Items -- Increased fiat onramp options for stablecoins on the Polygon network -- Various bug fixes and performance improvements +IPFS hash of the deployment: +- CIDv0: `QmdkgTrLeXsNsutYMS3KcRCpLA69uupUtXk4fbLJTtxitL` +- CIDv1: `bafybeihfa45bbn7mpgu5phtqvg5w3s3bmcabkb5kdp6gkndkcnunwdbffu` + +The latest release is always mirrored at [app.uniswap.org](https://app.uniswap.org). + +You can also access the Uniswap Interface from an IPFS gateway. +**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: +- https://bafybeihfa45bbn7mpgu5phtqvg5w3s3bmcabkb5kdp6gkndkcnunwdbffu.ipfs.dweb.link/ +- https://bafybeihfa45bbn7mpgu5phtqvg5w3s3bmcabkb5kdp6gkndkcnunwdbffu.ipfs.cf-ipfs.com/ +- [ipfs://QmdkgTrLeXsNsutYMS3KcRCpLA69uupUtXk4fbLJTtxitL/](ipfs://QmdkgTrLeXsNsutYMS3KcRCpLA69uupUtXk4fbLJTtxitL/) + +## 5.44.0 (2024-08-28) + + +### Features + +* **web:** adding v4 everywhere feature flag (#10886) 5b065e9 +* **web:** enhanced dropdown component in prep for v4 changes (#11070) 6e4565c +* **web:** new pools page and rename old pools pages (#11004) 7b774cc +* **web:** tamaguify explore page (charts) (incl. snapshots) (#11117) 8485f71 +* **web:** tamaguify explore page (tables) (incl. snapshots) (#11118) e29104d +* **web:** use uniswap currency info (#11064) 00da3f5 + + +### Bug Fixes + +* **web:** add error policy all to balances web query (#11176) 1100abe +* **web:** dont double format amountOut (#11111) d4d3df2 +* **web:** extraneous useClickOutside for DropdownSelector components (#11109) 501adb9 +* **web:** fallback to common bases (#11140) 0fac4f6 +* **web:** fix button label on add/v2 page (#11156) 31b7462 +* **web:** fix modal height for absolute-positioned modal contents (#11152) 0b2919c +* **web:** fix switchChain for single-chain wallets (#11342) 9621efe +* **web:** remove redirect from landing page when connected (#11207) dc75f2a +* **web:** remove second language selection menu (#11263) 62eeedf +* **web:** tdp pdp tamagui staging hotfix (#11311) fa0312e +* **web:** Use neutralContrast for Add Liq and Preview buttons - staging (#11315) ca38bad +* **web:** Use neutralContrast for Swap button (#11065) 962f3e5 +* **web:** use reduceRight instead of findLastIndex for activeIndex (#11201) 1adceb3 +* **web:** use updated Arb Xv2 experiment name & update UniswapX SDK (#11058) a54ba3e +* **web:** Volume Explore chart TimeSelector colors - staging (#11322) 8e2a763 + + +### Continuous Integration + +* **web:** update sitemaps 3c8a16c + + +### Code Refactoring + +* **web:** tamaguify buy form (#10981) 3743d77 + + +### Tests + +* **web:** useCurrencyInfo (#11085) 92adc3b + + diff --git a/VERSION b/VERSION index 099880bcba3..80799a01cc8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -mobile/1.33 \ No newline at end of file +web/5.44.0 \ No newline at end of file diff --git a/apps/extension/jest-setup.js b/apps/extension/jest-setup.js index 82ba3fa4ea8..cd65e145579 100644 --- a/apps/extension/jest-setup.js +++ b/apps/extension/jest-setup.js @@ -2,9 +2,11 @@ import 'utilities/src/logger/mocks' import { chrome } from 'jest-chrome' import { AppearanceSettingType } from 'wallet/src/features/appearance/slice' -import { TextEncoder, TextDecoder } from 'util'; +import { TextEncoder, TextDecoder } from 'util' +import { mockSharedPersistQueryClientProvider } from 'uniswap/src/test/mocks/mockSharedPersistQueryClientProvider' +import { mockUIAssets } from 'ui/src/test/mocks/mockUIAssets' -process.env.IS_UNISWAP_EXTENSION = true +process.env.IS_UNISWAP_EXTENSION = true global.TextEncoder = TextEncoder; global.TextDecoder = TextDecoder; @@ -69,3 +71,7 @@ jest.mock('wallet/src/features/appearance/hooks', () => { useSelectedColorScheme: () => 'light', } }) + +jest.mock('uniswap/src/data/apiClients/SharedPersistQueryClientProvider', () => mockSharedPersistQueryClientProvider) + +mockUIAssets() diff --git a/apps/extension/package.json b/apps/extension/package.json index 967b3abed31..9993a19b51e 100644 --- a/apps/extension/package.json +++ b/apps/extension/package.json @@ -11,7 +11,7 @@ "@sentry/react": "7.80.0", "@sentry/webpack-plugin": "2.10.3", "@svgr/webpack": "8.0.1", - "@tamagui/core": "1.108.2", + "@tamagui/core": "1.108.4", "@types/uuid": "9.0.1", "@uniswap/analytics-events": "2.36.0", "@uniswap/universal-router-sdk": "2.2.0", @@ -26,7 +26,7 @@ "react-i18next": "14.1.0", "react-native": "0.73.6", "react-native-gesture-handler": "2.15.0", - "react-native-reanimated": "npm:react-native-reanimated@3.8.1", + "react-native-reanimated": "3.15.0", "react-native-svg": "15.1.0", "react-native-web": "0.19.10", "react-qr-code": "2.0.12", @@ -74,7 +74,7 @@ "serve": "^14.2.0", "statsig-js": "4.41.0", "swc-loader": "^0.2.3", - "tamagui-loader": "1.108.2", + "tamagui-loader": "1.108.4", "typescript": "5.3.3", "webpack": "5.90.0", "webpack-cli": "^5.0.1", @@ -88,8 +88,8 @@ "env:local:download": "bash ../../scripts/downloadEnvLocal.sh web-local-envs ../../.env", "env:local:upload": "bash ../../scripts/uploadEnvLocal.sh web-local-envs ../../.env", "format": "../../scripts/prettier.sh", - "lint": "eslint . --ext ts,tsx --max-warnings=0", - "lint:fix": "eslint . --ext ts,tsx --fix", + "lint": "NODE_OPTIONS=--max_old_space_size=8192 eslint . --ext ts,tsx --max-warnings=0", + "lint:fix": "NODE_OPTIONS=--max-old-space-size=8192 eslint . --ext ts,tsx --fix", "start": "webpack serve --config webpack.config.js", "start:absolute": "yarn start:absolute:mac", "start:absolute:mac": "yarn start --output-path /Users/Shared/stretch", diff --git a/apps/extension/src/app/OnboardingApp.tsx b/apps/extension/src/app/OnboardingApp.tsx index 99ae9d0ba08..6cec729150a 100644 --- a/apps/extension/src/app/OnboardingApp.tsx +++ b/apps/extension/src/app/OnboardingApp.tsx @@ -46,6 +46,7 @@ import i18n from 'uniswap/src/i18n/i18n' import { ExtensionOnboardingFlow } from 'uniswap/src/types/screens/extension' import { ErrorBoundary } from 'wallet/src/components/ErrorBoundary/ErrorBoundary' import { LocalizationContextProvider } from 'wallet/src/features/language/LocalizationContext' +import { WalletUniswapProvider } from 'wallet/src/features/transactions/contexts/WalletUniswapContext' import { SharedProvider } from 'wallet/src/provider' const supportsSidePanel = checksIfSupportsSidePanel() @@ -178,8 +179,10 @@ export default function OnboardingApp(): JSX.Element { - - + + + + diff --git a/apps/extension/src/app/PopupApp.tsx b/apps/extension/src/app/PopupApp.tsx index cbb527860bf..e8d9b541be9 100644 --- a/apps/extension/src/app/PopupApp.tsx +++ b/apps/extension/src/app/PopupApp.tsx @@ -27,6 +27,7 @@ import { logger } from 'utilities/src/logger/logger' import { ErrorBoundary } from 'wallet/src/components/ErrorBoundary/ErrorBoundary' import { LocalizationContextProvider } from 'wallet/src/features/language/LocalizationContext' import { syncAppWithDeviceLanguage } from 'wallet/src/features/language/slice' +import { WalletUniswapProvider } from 'wallet/src/features/transactions/contexts/WalletUniswapContext' import { SharedProvider } from 'wallet/src/provider' getLocalUserId() @@ -132,10 +133,12 @@ export default function PopupApp(): JSX.Element { - - - - + + + + + + diff --git a/apps/extension/src/app/SidebarApp.tsx b/apps/extension/src/app/SidebarApp.tsx index 7b4757eff40..814bdea941c 100644 --- a/apps/extension/src/app/SidebarApp.tsx +++ b/apps/extension/src/app/SidebarApp.tsx @@ -14,6 +14,7 @@ import { AccountSwitcherScreen } from 'src/app/features/accounts/AccountSwitcher import { DappContextProvider } from 'src/app/features/dapp/DappContext' import { addRequest } from 'src/app/features/dappRequests/saga' import { ReceiveScreen } from 'src/app/features/receive/ReceiveScreen' +import { SendFlow } from 'src/app/features/send/SendFlow' import { DevMenuScreen } from 'src/app/features/settings/DevMenuScreen' import { SettingsPrivacyScreen } from 'src/app/features/settings/SettingsPrivacyScreen' import { RemoveRecoveryPhraseVerify } from 'src/app/features/settings/SettingsRecoveryPhraseScreen/RemoveRecoveryPhraseVerify' @@ -23,7 +24,6 @@ import { SettingsScreen } from 'src/app/features/settings/SettingsScreen' import { SettingsScreenWrapper } from 'src/app/features/settings/SettingsScreenWrapper' import { SettingsChangePasswordScreen } from 'src/app/features/settings/password/SettingsChangePasswordScreen' import { SwapFlowScreen } from 'src/app/features/swap/SwapFlowScreen' -import { TransferFlowScreen } from 'src/app/features/transfer/TransferFlowScreen' import { useIsWalletUnlocked } from 'src/app/hooks/useIsWalletUnlocked' import { MainContent, WebNavigation } from 'src/app/navigation' import { AppRoutes, RemoveRecoveryPhraseRoutes, SettingsRoutes } from 'src/app/navigation/constants' @@ -50,6 +50,7 @@ import { useInterval } from 'utilities/src/time/timing' import { ErrorBoundary } from 'wallet/src/components/ErrorBoundary/ErrorBoundary' import { LocalizationContextProvider } from 'wallet/src/features/language/LocalizationContext' import { syncAppWithDeviceLanguage } from 'wallet/src/features/language/slice' +import { WalletUniswapProvider } from 'wallet/src/features/transactions/contexts/WalletUniswapContext' import { SharedProvider } from 'wallet/src/provider' getLocalUserId() @@ -118,8 +119,8 @@ const router = sentryCreateHashRouter([ ], }, { - path: AppRoutes.Transfer, - element: , + path: AppRoutes.Send, + element: , }, { path: AppRoutes.Swap, @@ -246,11 +247,13 @@ export default function SidebarApp(): JSX.Element { - - - - - + + + + + + + diff --git a/apps/extension/src/app/components/OptionalStrictMode.tsx b/apps/extension/src/app/components/OptionalStrictMode.tsx deleted file mode 100644 index 75de22e68ca..00000000000 --- a/apps/extension/src/app/components/OptionalStrictMode.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { StrictMode } from 'react' - -// TODO(EXT-1229): We had to remove `React.StrictMode` because it's not -// currently supported by Reanimated Web. We should consider re-enabling -// once Reanimated fixes this. -export function OptionalStrictMode(props: { children: React.ReactNode }): JSX.Element { - return process.env.ENABLE_STRICT_MODE ? {props.children} : <>{props.children} -} diff --git a/apps/extension/src/app/components/Trace/TraceUserProperties.tsx b/apps/extension/src/app/components/Trace/TraceUserProperties.tsx index 0d66f9f6f7f..2f5f28ca040 100644 --- a/apps/extension/src/app/components/Trace/TraceUserProperties.tsx +++ b/apps/extension/src/app/components/Trace/TraceUserProperties.tsx @@ -1,18 +1,13 @@ import { useEffect } from 'react' import { useColorScheme } from 'react-native' +import { useHideSmallBalancesSetting, useHideSpamTokensSetting } from 'uniswap/src/features/settings/hooks' import { ExtensionUserPropertyName, setUserProperty } from 'uniswap/src/features/telemetry/user' // eslint-disable-next-line no-restricted-imports import { analytics } from 'utilities/src/telemetry/analytics/analytics' import { useAppFiatCurrencyInfo } from 'wallet/src/features/fiatCurrency/hooks' import { useGatingUserPropertyUsernames } from 'wallet/src/features/gating/userPropertyHooks' import { useCurrentLanguage } from 'wallet/src/features/language/hooks' -import { - useActiveAccount, - useHideSmallBalancesSetting, - useHideSpamTokensSetting, - useSignerAccounts, - useViewOnlyAccounts, -} from 'wallet/src/features/wallet/hooks' +import { useActiveAccount, useSignerAccounts, useViewOnlyAccounts } from 'wallet/src/features/wallet/hooks' /** Component that tracks UserProperties during the lifetime of the app */ export function TraceUserProperties(): null { diff --git a/apps/extension/src/app/components/modal/InfoModal.tsx b/apps/extension/src/app/components/modal/InfoModal.tsx index e254a9e8a53..fd8190f76e8 100644 --- a/apps/extension/src/app/components/modal/InfoModal.tsx +++ b/apps/extension/src/app/components/modal/InfoModal.tsx @@ -2,10 +2,10 @@ import { ReactNode } from 'react' import { Anchor, Button, Flex, Text, TouchableArea, useSporeColors } from 'ui/src' import { X } from 'ui/src/components/icons' import { zIndices } from 'ui/src/theme' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' import { ModalNameType } from 'uniswap/src/features/telemetry/constants' -export interface BottomModalProps { +export interface ModalProps { name: ModalNameType isOpen: boolean showCloseButton?: boolean @@ -33,17 +33,11 @@ export function InfoModal({ onButtonPress, linkText, linkUrl, -}: React.PropsWithChildren): JSX.Element { +}: React.PropsWithChildren): JSX.Element { const colors = useSporeColors() return ( - + {showCloseButton && ( )} - + ) } diff --git a/apps/extension/src/app/components/tabs/NftsTab.tsx b/apps/extension/src/app/components/tabs/NftsTab.tsx index 9bf383ca2e3..2ad38989523 100644 --- a/apps/extension/src/app/components/tabs/NftsTab.tsx +++ b/apps/extension/src/app/components/tabs/NftsTab.tsx @@ -3,11 +3,11 @@ import { memo, useCallback } from 'react' import { useSelector } from 'react-redux' import { ContextMenu, Flex } from 'ui/src' import { fromGraphQLChain } from 'uniswap/src/features/chains/utils' +import { selectNftsVisibility } from 'uniswap/src/features/favorites/selectors' import { ElementName, SectionName } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { UniverseChainId } from 'uniswap/src/types/chains' import { NftsList } from 'wallet/src/components/nfts/NftsList' -import { selectNftsVisibility } from 'wallet/src/features/favorites/selectors' import { NFTViewer } from 'wallet/src/features/images/NFTViewer' import { ESTIMATED_NFT_LIST_ITEM_SIZE } from 'wallet/src/features/nfts/constants' import { NFTItem } from 'wallet/src/features/nfts/types' diff --git a/apps/extension/src/app/features/accounts/AccountItem.tsx b/apps/extension/src/app/features/accounts/AccountItem.tsx index d4891bab844..dd38f50df86 100644 --- a/apps/extension/src/app/features/accounts/AccountItem.tsx +++ b/apps/extension/src/app/features/accounts/AccountItem.tsx @@ -9,6 +9,7 @@ import { CopySheets, Edit, TrashFilled, TripleDots } from 'ui/src/components/ico import { iconSizes } from 'ui/src/theme' import { ElementName, ModalName } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' +import { WarningSeverity } from 'uniswap/src/features/transactions/WarningModal/types' import { setClipboard } from 'uniswap/src/utils/clipboard' import { NumberType } from 'utilities/src/format/types' import { AddressDisplay } from 'wallet/src/components/accounts/AddressDisplay' @@ -16,7 +17,6 @@ import { WarningModal } from 'wallet/src/components/modals/WarningModal/WarningM import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext' import { pushNotification } from 'wallet/src/features/notifications/slice' import { AppNotificationType, CopyNotificationType } from 'wallet/src/features/notifications/types' -import { WarningSeverity } from 'wallet/src/features/transactions/WarningModal/types' import { EditAccountAction, editAccountActions } from 'wallet/src/features/wallet/accounts/editAccountSaga' import { useActiveAccountWithThrow, useDisplayName, useSignerAccounts } from 'wallet/src/features/wallet/hooks' import { DisplayNameType } from 'wallet/src/features/wallet/types' @@ -127,22 +127,21 @@ export function AccountItem({ address, onAccountSelect, balanceUSD }: AccountIte return ( <> - {showRemoveWalletModal && ( - } - modalName={ModalName.RemoveWallet} - severity={WarningSeverity.High} - title={t('account.wallet.remove.title', { name: displayName?.name ?? '' })} - onClose={() => setShowRemoveWalletModal(false)} - onConfirm={onRemoveWallet} - /> - )} - {showEditLabelModal && setShowEditLabelModal(false)} />} + } + isOpen={showRemoveWalletModal} + modalName={ModalName.RemoveWallet} + severity={WarningSeverity.High} + title={t('account.wallet.remove.title', { name: displayName?.name ?? '' })} + onClose={() => setShowRemoveWalletModal(false)} + onConfirm={onRemoveWallet} + /> + setShowEditLabelModal(false)} /> - {showEditLabelModal && setShowEditLabelModal(false)} />} - {showRemoveWalletModal && ( - } - modalName={ModalName.RemoveWallet} - severity={WarningSeverity.High} - title={t('account.wallet.button.import')} - onClose={() => setShowRemoveWalletModal(false)} - onConfirm={onNavigateToRemoveWallet} - /> - )} - {showCreateWalletModal && ( - - )} + setShowEditLabelModal(false)} + /> + } + isOpen={showRemoveWalletModal} + modalName={ModalName.RemoveWallet} + severity={WarningSeverity.High} + title={t('account.wallet.button.import')} + onClose={() => setShowRemoveWalletModal(false)} + onConfirm={onNavigateToRemoveWallet} + /> + diff --git a/apps/extension/src/app/features/accounts/CreateWalletModal.tsx b/apps/extension/src/app/features/accounts/CreateWalletModal.tsx index 2ce86ea5e32..ce74e9ecf68 100644 --- a/apps/extension/src/app/features/accounts/CreateWalletModal.tsx +++ b/apps/extension/src/app/features/accounts/CreateWalletModal.tsx @@ -4,20 +4,26 @@ import { OpaqueColorValue } from 'react-native' import { Button, Flex, Text, getUniconColors, useIsDarkMode } from 'ui/src' import { iconSizes, opacify } from 'ui/src/theme' import { TextInput } from 'uniswap/src/components/input/TextInput' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' import { ModalName } from 'uniswap/src/features/telemetry/constants' import { shortenAddress } from 'uniswap/src/utils/addresses' import { AccountIcon } from 'wallet/src/components/accounts/AccountIcon' import { SignerMnemonicAccount } from 'wallet/src/features/wallet/accounts/types' type CreateWalletModalProps = { + isOpen: boolean pendingWallet?: SignerMnemonicAccount onCancel: () => void onConfirm: (walletLabel: string) => void } // Expects a pending account to be created before opening this modal -export function CreateWalletModal({ pendingWallet, onCancel, onConfirm }: CreateWalletModalProps): JSX.Element | null { +export function CreateWalletModal({ + isOpen, + pendingWallet, + onCancel, + onConfirm, +}: CreateWalletModalProps): JSX.Element | null { const { t } = useTranslation() const isDark = useIsDarkMode() @@ -46,7 +52,7 @@ export function CreateWalletModal({ pendingWallet, onCancel, onConfirm }: Create }, [uniconColor]) return ( - + {onboardingAccountAddress && } @@ -86,6 +92,6 @@ export function CreateWalletModal({ pendingWallet, onCancel, onConfirm }: Create - + ) } diff --git a/apps/extension/src/app/features/accounts/EditLabelModal.tsx b/apps/extension/src/app/features/accounts/EditLabelModal.tsx index f88bb47a421..97b0471125f 100644 --- a/apps/extension/src/app/features/accounts/EditLabelModal.tsx +++ b/apps/extension/src/app/features/accounts/EditLabelModal.tsx @@ -4,7 +4,7 @@ import { useDispatch } from 'react-redux' import { Button, Flex, Text } from 'ui/src' import { iconSizes } from 'ui/src/theme' import { TextInput } from 'uniswap/src/components/input/TextInput' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' import { ModalName } from 'uniswap/src/features/telemetry/constants' import { shortenAddress } from 'utilities/src/addresses' import { AccountIcon } from 'wallet/src/components/accounts/AccountIcon' @@ -13,11 +13,12 @@ import { useDisplayName } from 'wallet/src/features/wallet/hooks' import { DisplayNameType } from 'wallet/src/features/wallet/types' type EditLabelModalProps = { + isOpen: boolean address: Address onClose: () => void } -export function EditLabelModal({ address, onClose }: EditLabelModalProps): JSX.Element { +export function EditLabelModal({ isOpen, address, onClose }: EditLabelModalProps): JSX.Element { const { t } = useTranslation() const dispatch = useDispatch() @@ -39,7 +40,7 @@ export function EditLabelModal({ address, onClose }: EditLabelModalProps): JSX.E }, [address, dispatch, inputText, onClose]) return ( - + @@ -69,6 +70,6 @@ export function EditLabelModal({ address, onClose }: EditLabelModalProps): JSX.E - + ) } diff --git a/apps/extension/src/app/features/accounts/__snapshots__/AccountSwitcherScreen.test.tsx.snap b/apps/extension/src/app/features/accounts/__snapshots__/AccountSwitcherScreen.test.tsx.snap index cfbafc0cdba..174d0b56392 100644 --- a/apps/extension/src/app/features/accounts/__snapshots__/AccountSwitcherScreen.test.tsx.snap +++ b/apps/extension/src/app/features/accounts/__snapshots__/AccountSwitcherScreen.test.tsx.snap @@ -15,6 +15,36 @@ exports[`AccountSwitcherScreen renders correctly 1`] = ` + +

+ + +

+ + +

+
@@ -219,6 +249,36 @@ exports[`AccountSwitcherScreen renders correctly 1`] = ` + +

+ + +

+ + +

+
diff --git a/apps/extension/src/app/features/dappRequests/DappRequestContent.tsx b/apps/extension/src/app/features/dappRequests/DappRequestContent.tsx index 2a34ff6b4f2..e1b83a4c126 100644 --- a/apps/extension/src/app/features/dappRequests/DappRequestContent.tsx +++ b/apps/extension/src/app/features/dappRequests/DappRequestContent.tsx @@ -6,16 +6,16 @@ import { NetworksFooter } from 'src/app/features/dappRequests/requestContent/Net import { DappRequestStoreItem } from 'src/app/features/dappRequests/slice' import { Anchor, AnimatePresence, Button, Flex, Text, UniversalImage, UniversalImageResizeMode, styled } from 'ui/src' import { iconSizes } from 'ui/src/theme' +import { GasFeeResult } from 'uniswap/src/features/gas/types' +import { useOnChainNativeCurrencyBalance } from 'uniswap/src/features/portfolio/api' +import { TransactionTypeInfo } from 'uniswap/src/features/transactions/types/transactionDetails' import { UniverseChainId, WalletChainId } from 'uniswap/src/types/chains' import { formatDappURL } from 'utilities/src/format/urls' import { logger } from 'utilities/src/logger/logger' import { DappIconPlaceholder } from 'wallet/src/components/WalletConnect/DappIconPlaceholder' import { useUSDValue } from 'wallet/src/features/gas/hooks' -import { GasFeeResult } from 'wallet/src/features/gas/types' -import { useOnChainNativeCurrencyBalance } from 'wallet/src/features/portfolio/api' import { AddressFooter } from 'wallet/src/features/transactions/TransactionRequest/AddressFooter' import { NetworkFeeFooter } from 'wallet/src/features/transactions/TransactionRequest/NetworkFeeFooter' -import { TransactionTypeInfo } from 'wallet/src/features/transactions/types' import { hasSufficientFundsIncludingGas } from 'wallet/src/features/transactions/utils' import { useActiveAccountWithThrow } from 'wallet/src/features/wallet/hooks' diff --git a/apps/extension/src/app/features/dappRequests/DappRequestQueue.tsx b/apps/extension/src/app/features/dappRequests/DappRequestQueue.tsx new file mode 100644 index 00000000000..d824ba3e555 --- /dev/null +++ b/apps/extension/src/app/features/dappRequests/DappRequestQueue.tsx @@ -0,0 +1,212 @@ +import { memo } from 'react' +import { Trans, useTranslation } from 'react-i18next' +import { useDispatch, useSelector } from 'react-redux' +import { AnimatedPane, DappRequestContent } from 'src/app/features/dappRequests/DappRequestContent' +import { + DappRequestQueueProvider, + useDappRequestQueueContext, +} from 'src/app/features/dappRequests/DappRequestQueueContext' +import { ConnectionRequestContent } from 'src/app/features/dappRequests/requestContent/Connection/ConnectionRequestContent' +import { EthSendRequestContent } from 'src/app/features/dappRequests/requestContent/EthSend/EthSend' +import { PersonalSignRequestContent } from 'src/app/features/dappRequests/requestContent/PersonalSign/PersonalSignRequestContent' +import { SignTypedDataRequestContent } from 'src/app/features/dappRequests/requestContent/SignTypeData/SignTypedDataRequestContent' +import { rejectAllRequests } from 'src/app/features/dappRequests/saga' +import { isDappRequestStoreItemForEthSendTxn } from 'src/app/features/dappRequests/slice' +import { + isGetAccountRequest, + isRequestAccountRequest, + isRequestPermissionsRequest, + isSignMessageRequest, + isSignTypedDataRequest, +} from 'src/app/features/dappRequests/types/DappRequestTypes' +import { ExtensionState } from 'src/store/extensionReducer' +import { AnimatePresence, Flex, Text, TouchableArea, useSporeColors } from 'ui/src' +import { ReceiptText, RotatableChevron } from 'ui/src/components/icons' +import { iconSizes, zIndices } from 'ui/src/theme' +import { Modal } from 'uniswap/src/components/modals/Modal' +import { ModalName } from 'uniswap/src/features/telemetry/constants' + +const REJECT_MESSAGE_HEIGHT = 48 + +export function DappRequestQueue(): JSX.Element { + const pendingDappRequests = useSelector((state: ExtensionState) => state.dappRequests.pending) + const areRequestsPending = pendingDappRequests.length > 0 + + return ( + + + + + + ) +} + +function DappRequestQueueContent(): JSX.Element { + const { t } = useTranslation() + const colors = useSporeColors() + const dispatch = useDispatch() + + const { totalRequestCount, onPressPrevious, onPressNext, currentIndex, increasing } = useDappRequestQueueContext() + + const disabledPrevious = currentIndex <= 0 + const disabledNext = currentIndex >= totalRequestCount - 1 + + const onRejectAll = async (): Promise => { + dispatch(rejectAllRequests()) + } + + return ( + + + {totalRequestCount > 1 && ( + + + + + + ), + }} + i18nKey="dapp.request.reject.info" + values={{ totalRequestCount }} + /> + + + + + {t('dapp.request.reject.action')} + + + + )} + + 1 ? 12 : 0} + width="100%" + > + {totalRequestCount > 1 && ( + + + + + + {currentIndex + 1} + + + / + + + + + {totalRequestCount} + + + + + + + + )} + + + + ) +} + +const DappRequest = memo(function _DappRequest(): JSX.Element | null { + const { t } = useTranslation() + const { request } = useDappRequestQueueContext() + + if (!request) { + return null + } + + if (isSignMessageRequest(request.dappRequest)) { + return + } + if (isSignTypedDataRequest(request.dappRequest)) { + return + } + if (isDappRequestStoreItemForEthSendTxn(request)) { + return + } + if ( + isGetAccountRequest(request.dappRequest) || + isRequestAccountRequest(request.dappRequest) || + isRequestPermissionsRequest(request.dappRequest) + ) { + return + } + + return +}) diff --git a/apps/extension/src/app/features/dappRequests/DappRequestQueueContext.tsx b/apps/extension/src/app/features/dappRequests/DappRequestQueueContext.tsx index 858ad40914b..bf5adb0674a 100644 --- a/apps/extension/src/app/features/dappRequests/DappRequestQueueContext.tsx +++ b/apps/extension/src/app/features/dappRequests/DappRequestQueueContext.tsx @@ -14,7 +14,7 @@ import { ExtensionState } from 'src/store/extensionReducer' import { ExtensionEventName } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { DappRequestAction } from 'uniswap/src/features/telemetry/types' -import { TransactionTypeInfo } from 'wallet/src/features/transactions/types' +import { TransactionTypeInfo } from 'uniswap/src/features/transactions/types/transactionDetails' import { Account } from 'wallet/src/features/wallet/accounts/types' import { useActiveAccountWithThrow } from 'wallet/src/features/wallet/hooks' diff --git a/apps/extension/src/app/features/dappRequests/DappRequestWrapper.tsx b/apps/extension/src/app/features/dappRequests/DappRequestWrapper.tsx deleted file mode 100644 index 4bdd2560139..00000000000 --- a/apps/extension/src/app/features/dappRequests/DappRequestWrapper.tsx +++ /dev/null @@ -1,189 +0,0 @@ -import { memo } from 'react' -import { Trans, useTranslation } from 'react-i18next' -import { useDispatch } from 'react-redux' -import { AnimatedPane, DappRequestContent } from 'src/app/features/dappRequests/DappRequestContent' -import { useDappRequestQueueContext } from 'src/app/features/dappRequests/DappRequestQueueContext' -import { ConnectionRequestContent } from 'src/app/features/dappRequests/requestContent/Connection/ConnectionRequestContent' -import { EthSendRequestContent } from 'src/app/features/dappRequests/requestContent/EthSend/EthSend' -import { PersonalSignRequestContent } from 'src/app/features/dappRequests/requestContent/PersonalSign/PersonalSignRequestContent' -import { SignTypedDataRequestContent } from 'src/app/features/dappRequests/requestContent/SignTypeData/SignTypedDataRequestContent' -import { rejectAllRequests } from 'src/app/features/dappRequests/saga' -import { isDappRequestStoreItemForEthSendTxn } from 'src/app/features/dappRequests/slice' -import { - isGetAccountRequest, - isRequestAccountRequest, - isRequestPermissionsRequest, - isSignMessageRequest, - isSignTypedDataRequest, -} from 'src/app/features/dappRequests/types/DappRequestTypes' -import { AnimatePresence, Flex, Text, TouchableArea, useSporeColors } from 'ui/src' -import { ReceiptText, RotatableChevron } from 'ui/src/components/icons' -import { iconSizes, zIndices } from 'ui/src/theme' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' -import { ModalName } from 'uniswap/src/features/telemetry/constants' - -const REJECT_MESSAGE_HEIGHT = 48 - -export function DappRequestWrapper(): JSX.Element { - const { t } = useTranslation() - const colors = useSporeColors() - const dispatch = useDispatch() - - const { totalRequestCount, onPressPrevious, onPressNext, currentIndex, increasing } = useDappRequestQueueContext() - - const disabledPrevious = currentIndex <= 0 - const disabledNext = currentIndex >= totalRequestCount - 1 - - const onRejectAll = async (): Promise => { - dispatch(rejectAllRequests()) - } - - return ( - - - - {totalRequestCount > 1 && ( - - - - - - ), - }} - i18nKey="dapp.request.reject.info" - values={{ totalRequestCount }} - /> - - - - - {t('dapp.request.reject.action')} - - - - )} - - 1 ? REJECT_MESSAGE_HEIGHT + 12 : 0} - > - {totalRequestCount > 1 && ( - - - - - - {currentIndex + 1} - - - / - - - - - {totalRequestCount} - - - - - - - - )} - - - - - ) -} - -const DappRequest = memo(function _DappRequest(): JSX.Element { - const { t } = useTranslation() - const { request } = useDappRequestQueueContext() - - if (request) { - if (isSignMessageRequest(request.dappRequest)) { - return - } - if (isSignTypedDataRequest(request.dappRequest)) { - return - } - if (isDappRequestStoreItemForEthSendTxn(request)) { - return - } - if ( - isGetAccountRequest(request.dappRequest) || - isRequestAccountRequest(request.dappRequest) || - isRequestPermissionsRequest(request.dappRequest) - ) { - return - } - } - - return -}) diff --git a/apps/extension/src/app/features/dappRequests/requestContent/EthSend/Approve/ApproveRequestContent.tsx b/apps/extension/src/app/features/dappRequests/requestContent/EthSend/Approve/ApproveRequestContent.tsx index 3189aa68922..fe7f5be8da7 100644 --- a/apps/extension/src/app/features/dappRequests/requestContent/EthSend/Approve/ApproveRequestContent.tsx +++ b/apps/extension/src/app/features/dappRequests/requestContent/EthSend/Approve/ApproveRequestContent.tsx @@ -14,10 +14,10 @@ import { CurrencyLogo } from 'uniswap/src/components/CurrencyLogo/CurrencyLogo' import { LearnMoreLink } from 'uniswap/src/components/text/LearnMoreLink' import { uniswapUrls } from 'uniswap/src/constants/urls' import { CurrencyInfo } from 'uniswap/src/features/dataApi/types' +import { GasFeeResult } from 'uniswap/src/features/gas/types' +import { useCurrencyInfo } from 'uniswap/src/features/tokens/useCurrencyInfo' +import { TransactionType, TransactionTypeInfo } from 'uniswap/src/features/transactions/types/transactionDetails' import { buildCurrencyId } from 'uniswap/src/utils/currencyId' -import { GasFeeResult } from 'wallet/src/features/gas/types' -import { useCurrencyInfo } from 'wallet/src/features/tokens/useCurrencyInfo' -import { TransactionType, TransactionTypeInfo } from 'wallet/src/features/transactions/types' import { useNoYoloParser } from 'wallet/src/utils/useNoYoloParser' function useDappRequestTokenRecipientInfo(request: DappRequestBaseType, dappUrl: string): Maybe { diff --git a/apps/extension/src/app/features/dappRequests/requestContent/EthSend/EthSend.tsx b/apps/extension/src/app/features/dappRequests/requestContent/EthSend/EthSend.tsx index 70ebc898f52..85ad5e1dc01 100644 --- a/apps/extension/src/app/features/dappRequests/requestContent/EthSend/EthSend.tsx +++ b/apps/extension/src/app/features/dappRequests/requestContent/EthSend/EthSend.tsx @@ -8,11 +8,11 @@ import { SwapRequestContent } from 'src/app/features/dappRequests/requestContent import { DappRequestStoreItemForEthSendTxn } from 'src/app/features/dappRequests/slice' import { isApproveRequest, isLPRequest, isSwapRequest } from 'src/app/features/dappRequests/types/DappRequestTypes' import { PollingInterval } from 'uniswap/src/constants/misc' +import { GasFeeResult, GasSpeed } from 'uniswap/src/features/gas/types' +import { TransactionTypeInfo } from 'uniswap/src/features/transactions/types/transactionDetails' import { logger } from 'utilities/src/logger/logger' import { formatExternalTxnWithGasEstimates } from 'wallet/src/features/gas/formatExternalTxnWithGasEstimates' import { useTransactionGasFee } from 'wallet/src/features/gas/hooks' -import { GasFeeResult, GasSpeed } from 'wallet/src/features/gas/types' -import { TransactionTypeInfo } from 'wallet/src/features/transactions/types' interface EthSendRequestContentProps { request: DappRequestStoreItemForEthSendTxn @@ -113,5 +113,5 @@ export function EthSendRequestContent({ request }: EthSendRequestContentProps): } function isInvalidGasFeeResultForEthSend(gasFeeResult: GasFeeResult): boolean { - return !!gasFeeResult.error || (!gasFeeResult.loading && (!gasFeeResult.params || !gasFeeResult.value)) + return !!gasFeeResult.error || (!gasFeeResult.isLoading && (!gasFeeResult.params || !gasFeeResult.value)) } diff --git a/apps/extension/src/app/features/dappRequests/requestContent/EthSend/FallbackEthSend/FallbackEthSend.tsx b/apps/extension/src/app/features/dappRequests/requestContent/EthSend/FallbackEthSend/FallbackEthSend.tsx index 8a192838cff..003fbe120b4 100644 --- a/apps/extension/src/app/features/dappRequests/requestContent/EthSend/FallbackEthSend/FallbackEthSend.tsx +++ b/apps/extension/src/app/features/dappRequests/requestContent/EthSend/FallbackEthSend/FallbackEthSend.tsx @@ -8,8 +8,8 @@ import { SendTransactionRequest } from 'src/app/features/dappRequests/types/Dapp import { useCopyToClipboard } from 'src/app/hooks/useOnCopyToClipboard' import { Anchor, Flex, Text, TouchableArea } from 'ui/src' import { AnimatedCopySheets, ExternalLink } from 'ui/src/components/icons' +import { GasFeeResult } from 'uniswap/src/features/gas/types' import { ellipseMiddle, shortenAddress } from 'utilities/src/addresses' -import { GasFeeResult } from 'wallet/src/features/gas/types' import { CopyNotificationType } from 'wallet/src/features/notifications/types' import { ContentRow } from 'wallet/src/features/transactions/TransactionRequest/ContentRow' import { diff --git a/apps/extension/src/app/features/dappRequests/requestContent/EthSend/LP/LPRequestContent.tsx b/apps/extension/src/app/features/dappRequests/requestContent/EthSend/LP/LPRequestContent.tsx index ea1615cc2c5..3d879ce4db3 100644 --- a/apps/extension/src/app/features/dappRequests/requestContent/EthSend/LP/LPRequestContent.tsx +++ b/apps/extension/src/app/features/dappRequests/requestContent/EthSend/LP/LPRequestContent.tsx @@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next' import { DappRequestContent } from 'src/app/features/dappRequests/DappRequestContent' import { LPSendTransactionRequest } from 'src/app/features/dappRequests/types/DappRequestTypes' import { Flex, Text } from 'ui/src' -import { GasFeeResult } from 'wallet/src/features/gas/types' +import { GasFeeResult } from 'uniswap/src/features/gas/types' interface LPRequestContentProps { transactionGasFeeResult: GasFeeResult diff --git a/apps/extension/src/app/features/dappRequests/requestContent/EthSend/Swap/SwapDisplay.tsx b/apps/extension/src/app/features/dappRequests/requestContent/EthSend/Swap/SwapDisplay.tsx index 41417c79495..3bf51d909e6 100644 --- a/apps/extension/src/app/features/dappRequests/requestContent/EthSend/Swap/SwapDisplay.tsx +++ b/apps/extension/src/app/features/dappRequests/requestContent/EthSend/Swap/SwapDisplay.tsx @@ -6,12 +6,12 @@ import { iconSizes } from 'ui/src/theme' import { CurrencyLogo } from 'uniswap/src/components/CurrencyLogo/CurrencyLogo' import { SplitLogo } from 'uniswap/src/components/CurrencyLogo/SplitLogo' import { CurrencyInfo } from 'uniswap/src/features/dataApi/types' +import { GasFeeResult } from 'uniswap/src/features/gas/types' +import { ValueType, getCurrencyAmount } from 'uniswap/src/features/tokens/getCurrencyAmount' +import { useUSDCValue } from 'uniswap/src/features/transactions/swap/hooks/useUSDCPrice' import { WalletChainId } from 'uniswap/src/types/chains' import { NumberType } from 'utilities/src/format/types' -import { GasFeeResult } from 'wallet/src/features/gas/types' import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext' -import { useUSDCValue } from 'wallet/src/features/transactions/swap/trade/hooks/useUSDCPrice' -import { ValueType, getCurrencyAmount } from 'wallet/src/utils/getCurrencyAmount' export function SwapDisplay({ inputAmount, diff --git a/apps/extension/src/app/features/dappRequests/requestContent/EthSend/Swap/SwapRequestContent.tsx b/apps/extension/src/app/features/dappRequests/requestContent/EthSend/Swap/SwapRequestContent.tsx index 41df2bf2d7e..a1fa06da81a 100644 --- a/apps/extension/src/app/features/dappRequests/requestContent/EthSend/Swap/SwapRequestContent.tsx +++ b/apps/extension/src/app/features/dappRequests/requestContent/EthSend/Swap/SwapRequestContent.tsx @@ -20,12 +20,12 @@ import { import { DEFAULT_NATIVE_ADDRESS } from 'uniswap/src/constants/chains' import { toSupportedChainId } from 'uniswap/src/features/chains/utils' import { CurrencyInfo } from 'uniswap/src/features/dataApi/types' +import { GasFeeResult } from 'uniswap/src/features/gas/types' +import { useCurrencyInfo, useNativeCurrencyInfo } from 'uniswap/src/features/tokens/useCurrencyInfo' +import { TransactionType, TransactionTypeInfo } from 'uniswap/src/features/transactions/types/transactionDetails' import { UniverseChainId, WalletChainId } from 'uniswap/src/types/chains' import { buildCurrencyId } from 'uniswap/src/utils/currencyId' import { assert } from 'utilities/src/errors' -import { GasFeeResult } from 'wallet/src/features/gas/types' -import { useCurrencyInfo, useNativeCurrencyInfo } from 'wallet/src/features/tokens/useCurrencyInfo' -import { TransactionType, TransactionTypeInfo } from 'wallet/src/features/transactions/types' function extractPathValues(commands: UniversalRouterCommand[]): { inputAddress: string | undefined diff --git a/apps/extension/src/app/features/dappRequests/requestContent/__snapshots__/NetworkFooter.test.tsx.snap b/apps/extension/src/app/features/dappRequests/requestContent/__snapshots__/NetworkFooter.test.tsx.snap index 7d0966c6195..d39af9b3c6b 100644 --- a/apps/extension/src/app/features/dappRequests/requestContent/__snapshots__/NetworkFooter.test.tsx.snap +++ b/apps/extension/src/app/features/dappRequests/requestContent/__snapshots__/NetworkFooter.test.tsx.snap @@ -34,9 +34,8 @@ exports[`NetworksFooter renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -52,9 +58,8 @@ exports[`NetworksFooter renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -70,9 +82,8 @@ exports[`NetworksFooter renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -88,9 +106,8 @@ exports[`NetworksFooter renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -106,9 +130,8 @@ exports[`NetworksFooter renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -124,9 +154,8 @@ exports[`NetworksFooter renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -142,9 +178,8 @@ exports[`NetworksFooter renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -160,9 +202,8 @@ exports[`NetworksFooter renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -178,9 +226,8 @@ exports[`NetworksFooter renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -196,9 +250,8 @@ exports[`NetworksFooter renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -214,9 +274,8 @@ exports[`NetworksFooter renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -266,9 +332,8 @@ exports[`NetworksFooter renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -284,9 +356,8 @@ exports[`NetworksFooter renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -302,9 +380,8 @@ exports[`NetworksFooter renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -320,9 +404,8 @@ exports[`NetworksFooter renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -338,9 +428,8 @@ exports[`NetworksFooter renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -356,9 +452,8 @@ exports[`NetworksFooter renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -374,9 +476,8 @@ exports[`NetworksFooter renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -392,9 +500,8 @@ exports[`NetworksFooter renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -410,9 +524,8 @@ exports[`NetworksFooter renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -428,9 +548,8 @@ exports[`NetworksFooter renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -446,9 +572,8 @@ exports[`NetworksFooter renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
diff --git a/apps/extension/src/app/features/dappRequests/saga.ts b/apps/extension/src/app/features/dappRequests/saga.ts index 2e808861c6e..cfcfffa7225 100644 --- a/apps/extension/src/app/features/dappRequests/saga.ts +++ b/apps/extension/src/app/features/dappRequests/saga.ts @@ -28,11 +28,15 @@ import { navigate } from 'src/app/navigation/state' import { dappResponseMessageChannel } from 'src/background/messagePassing/messageChannels' import { call, put, select, take } from 'typed-redux-saga' import { hexadecimalStringToInt, toSupportedChainId } from 'uniswap/src/features/chains/utils' +import { + TransactionOriginType, + TransactionType, + TransactionTypeInfo, +} from 'uniswap/src/features/transactions/types/transactionDetails' import { logger } from 'utilities/src/logger/logger' import { pushNotification } from 'wallet/src/features/notifications/slice' import { AppNotificationType } from 'wallet/src/features/notifications/types' import { SendTransactionParams, sendTransaction } from 'wallet/src/features/transactions/sendTransactionSaga' -import { TransactionType, TransactionTypeInfo } from 'wallet/src/features/transactions/types' import { getProvider, getSignerManager } from 'wallet/src/features/wallet/context' import { selectActiveAccount } from 'wallet/src/features/wallet/selectors' import { signMessage, signTypedDataMessage } from 'wallet/src/features/wallet/signing/signing' @@ -245,7 +249,10 @@ export function* handleSendTransaction( chainId: lastChainId, account, options: { request: transactionRequest }, - typeInfo: transactionTypeInfo ?? { type: TransactionType.Unknown }, + typeInfo: transactionTypeInfo ?? { + type: TransactionType.Unknown, + }, + transactionOriginType: TransactionOriginType.External, } const { transactionResponse } = yield* call(sendTransaction, sendTransactionParams) diff --git a/apps/extension/src/app/features/home/HomeScreen.tsx b/apps/extension/src/app/features/home/HomeScreen.tsx index d7ea1d91a31..19b859ac72d 100644 --- a/apps/extension/src/app/features/home/HomeScreen.tsx +++ b/apps/extension/src/app/features/home/HomeScreen.tsx @@ -1,3 +1,4 @@ +import { useApolloClient } from '@apollo/client' import { SharedEventName } from '@uniswap/analytics-events' import { memo, useCallback, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' @@ -16,8 +17,9 @@ import { navigate } from 'src/app/navigation/state' import { Flex, Loader, Text, TouchableArea, styled } from 'ui/src' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { logger } from 'utilities/src/logger/logger' -import { ONE_SECOND_MS } from 'utilities/src/time/time' +import { ONE_MINUTE_MS, ONE_SECOND_MS } from 'utilities/src/time/time' import { useTimeout } from 'utilities/src/time/timing' +import { NFTS_TAB_DATA_DEPENDENCIES } from 'wallet/src/components/nfts/NftsList' import { PendingNotificationBadge } from 'wallet/src/features/notifications/components/PendingNotificationBadge' import { useSelectAddressHasNotifications } from 'wallet/src/features/notifications/hooks' import { setNotificationStatus } from 'wallet/src/features/notifications/slice' @@ -29,6 +31,8 @@ export const HomeScreen = memo(function _HomeScreen(): JSX.Element { const { t } = useTranslation() const [showTabs, setShowTabs] = useState(false) + const apolloClient = useApolloClient() + // The tabs are too slow to render on the first load, so we delay them to speed up the perceived loading time. useTimeout(() => setShowTabs(true), 0) @@ -85,6 +89,27 @@ export const HomeScreen = memo(function _HomeScreen(): JSX.Element { } }, [dispatch, address, hasNotifications, selectedTab]) + const [lastNftFetchTime, setLastNftFetchTime] = useState(0) + + useEffect(() => { + // NFTs tab is first fetched on mount, so we need to set the last fetch time here + setLastNftFetchTime(Date.now()) + }, []) + + const shouldRefetchNfts = useCallback(() => { + const now = Date.now() + return now - lastNftFetchTime >= ONE_MINUTE_MS + }, [lastNftFetchTime]) + + const maybeRefetchNfts = useCallback(() => { + if (shouldRefetchNfts()) { + setLastNftFetchTime(Date.now()) + apolloClient.refetchQueries({ include: NFTS_TAB_DATA_DEPENDENCIES }).catch((e) => { + logger.error('Error refetching NFTs tab data', e) + }) + } + }, [apolloClient, shouldRefetchNfts]) + return ( {address ? ( @@ -110,7 +135,13 @@ export const HomeScreen = memo(function _HomeScreen(): JSX.Element { {t('home.tokens.title')} - setSelectedTab(HomeTabs.NFTs)}> + { + setSelectedTab(HomeTabs.NFTs) + maybeRefetchNfts() + }} + > {t('home.nfts.title')} diff --git a/apps/extension/src/app/features/home/PortfolioActionButtons.tsx b/apps/extension/src/app/features/home/PortfolioActionButtons.tsx index 17e1babe0f4..525bced6b66 100644 --- a/apps/extension/src/app/features/home/PortfolioActionButtons.tsx +++ b/apps/extension/src/app/features/home/PortfolioActionButtons.tsx @@ -73,7 +73,7 @@ export const PortfolioActionButtons = memo(function _PortfolioActionButtons(): J screen: ExtensionScreens.Home, element: ElementName.Send, }) - navigate(AppRoutes.Transfer) + navigate(AppRoutes.Send) } const onSwapClick = (): void => { diff --git a/apps/extension/src/app/features/lockScreen/Locked.tsx b/apps/extension/src/app/features/lockScreen/Locked.tsx index cbdf544e654..6342b8974df 100644 --- a/apps/extension/src/app/features/lockScreen/Locked.tsx +++ b/apps/extension/src/app/features/lockScreen/Locked.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next' import { useDispatch } from 'react-redux' import { Input } from 'src/app/components/Input' import { PasswordInput } from 'src/app/components/PasswordInput' -import { BottomModalProps, InfoModal } from 'src/app/components/modal/InfoModal' +import { InfoModal, ModalProps } from 'src/app/components/modal/InfoModal' import { useSagaStatus } from 'src/app/hooks/useSagaStatus' import { OnboardingRoutes, TopLevelRoutes } from 'src/app/navigation/constants' import { focusOrCreateOnboardingTab } from 'src/app/navigation/utils' @@ -109,7 +109,7 @@ export function Locked(): JSX.Element { } }, [isIncorrectPassword]) - const modalProps: Record = { + const modalProps: Record = { [ForgotPasswordModalStep.Initial]: { buttonText: t('extension.lock.button.reset'), description: t('extension.lock.password.reset.initial.description'), diff --git a/apps/extension/src/app/features/onboarding/OnboardingScreenFrame.tsx b/apps/extension/src/app/features/onboarding/OnboardingScreenFrame.tsx index e8bbd4a98c1..9e9d151ef60 100644 --- a/apps/extension/src/app/features/onboarding/OnboardingScreenFrame.tsx +++ b/apps/extension/src/app/features/onboarding/OnboardingScreenFrame.tsx @@ -7,6 +7,7 @@ export function OnboardingScreenFrame({ Icon, children, nextButtonEnabled, + nextButtonIcon, nextButtonText = i18n.t('common.button.next'), nextButtonTheme = 'primary', onBack, @@ -74,7 +75,13 @@ export function OnboardingScreenFrame({ {Boolean(onSubmit) && nextButtonText && ( - )} diff --git a/apps/extension/src/app/features/onboarding/OnboardingScreenProps.tsx b/apps/extension/src/app/features/onboarding/OnboardingScreenProps.tsx index af3ad90dfb8..a5c2b15329c 100644 --- a/apps/extension/src/app/features/onboarding/OnboardingScreenProps.tsx +++ b/apps/extension/src/app/features/onboarding/OnboardingScreenProps.tsx @@ -4,6 +4,7 @@ export type OnboardingScreenProps = { Icon?: JSX.Element children?: JSX.Element nextButtonEnabled?: boolean + nextButtonIcon?: JSX.Element nextButtonText?: string nextButtonTheme?: ThemeNames onBack?: () => void diff --git a/apps/extension/src/app/features/onboarding/Password.tsx b/apps/extension/src/app/features/onboarding/Password.tsx index 9eee86e24b8..119c71b38f8 100644 --- a/apps/extension/src/app/features/onboarding/Password.tsx +++ b/apps/extension/src/app/features/onboarding/Password.tsx @@ -41,10 +41,14 @@ export function Password({ } = usePasswordForm() const onSubmit = useCallback(async () => { + if (!enableNext) { + return + } + if (checkSubmit()) { await onComplete(password) } - }, [onComplete, password, checkSubmit]) + }, [onComplete, password, checkSubmit, enableNext]) const handleBack = useCallback(() => { // reset the pending mnemonic when going back from password screen @@ -88,6 +92,7 @@ export function Password({ value={password} onBlur={onPasswordBlur} onChangeText={onChangePassword} + onSubmitEditing={onSubmit} /> { + generateInitialAddresses().catch((error) => { + logger.error(error, { + tags: { file: 'PasswordImport.tsx', function: 'generateInitialAddresses' }, + }) + }) + // We only want this to run once on component mount + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + const onSubmit = useCallback( async (password: string) => { const { validMnemonic } = validateMnemonic(mnemonicString) @@ -29,14 +38,9 @@ export function PasswordImport({ } goToNextStep() - - // TODO: EXT-1164 - Move Keyring methods to workers to not block main thread during onboarding - // start running the validation after going to next step since they clog the main thread with work - // plus just a bit of extra leeway since animations can take just a tad extra to finish - await sleep(ONBOARDING_PANE_TRANSITION_DURATION_WITH_LEEWAY) - await generateImportedAccountsByMnemonic(validMnemonic, password, BackupType.Manual) + await importMnemonicToKeychain({ mnemonic: validMnemonic, password, allowOverwrite: true }) }, - [mnemonicString, goToNextStep, generateImportedAccountsByMnemonic], + [mnemonicString, goToNextStep, importMnemonicToKeychain], ) return diff --git a/apps/extension/src/app/features/onboarding/create/NameWallet.tsx b/apps/extension/src/app/features/onboarding/create/NameWallet.tsx index 8fd4496fb18..0dae9d74e66 100644 --- a/apps/extension/src/app/features/onboarding/create/NameWallet.tsx +++ b/apps/extension/src/app/features/onboarding/create/NameWallet.tsx @@ -1,4 +1,5 @@ import { useState } from 'react' +import { useTranslation } from 'react-i18next' import { Input } from 'src/app/components/Input' import { saveDappConnection } from 'src/app/features/dapp/actions' import { OnboardingScreen } from 'src/app/features/onboarding/OnboardingScreen' @@ -12,6 +13,7 @@ import { shortenAddress } from 'uniswap/src/utils/addresses' import { useOnboardingContext } from 'wallet/src/features/onboarding/OnboardingContext' export function NameWallet(): JSX.Element { + const { t } = useTranslation() const { getOnboardingAccount, setPendingWalletName } = useOnboardingContext() const onboardingAccount = getOnboardingAccount() @@ -43,9 +45,9 @@ export function NameWallet(): JSX.Element { onboardingAccountAddress ? : undefined } nextButtonEnabled={true} - nextButtonText="Finish" - subtitle="This nickname is only visible to you" - title="Give your wallet a name" + nextButtonText={t('onboarding.name.wallet.button.text')} + subtitle={t('onboarding.name.wallet.subtitle')} + title={t('onboarding.name.wallet.title')} onBack={goToPreviousStep} onSubmit={onSubmit} > diff --git a/apps/extension/src/app/features/onboarding/create/ViewMnemonic.tsx b/apps/extension/src/app/features/onboarding/create/ViewMnemonic.tsx index dc1a48af1a8..a81cef66b9d 100644 --- a/apps/extension/src/app/features/onboarding/create/ViewMnemonic.tsx +++ b/apps/extension/src/app/features/onboarding/create/ViewMnemonic.tsx @@ -3,6 +3,7 @@ import { Trans, useTranslation } from 'react-i18next' import { MnemonicViewer } from 'src/app/components/MnemonicViewer' import { OnboardingScreen } from 'src/app/features/onboarding/OnboardingScreen' import { useOnboardingSteps } from 'src/app/features/onboarding/OnboardingSteps' +import { useSubmitOnEnter } from 'src/app/features/onboarding/utils' import { TopLevelRoutes } from 'src/app/navigation/constants' import { navigate } from 'src/app/navigation/state' import { CheckBox, Circle, Flex, IconProps, Square, Text } from 'ui/src' @@ -42,7 +43,16 @@ export function ViewMnemonic(): JSX.Element { } }, [onboardingAccountMnemonic, retrieveOnboardingAccountMnemonic]) + // On Info step, next button should be enabled if mnemonic has been created. + // On View step, next button should be enabled if disclaimer is checked and mnemonic has been created. + const shouldEnableNextButton = + viewStep === ViewStep.View ? !!onboardingAccountAddress && disclaimerChecked : !!onboardingAccountAddress + const onSubmit = (): void => { + if (!shouldEnableNextButton) { + return + } + if (viewStep === ViewStep.Info) { setViewStep(ViewStep.View) return @@ -53,10 +63,7 @@ export function ViewMnemonic(): JSX.Element { } } - // On view step, next button should be enabled if mnemonic has been created. - // On disclaimer step, next button should be enabled if disclaimer is checked and mnemonic has been created. - const shouldEnableNextButton = - viewStep === ViewStep.View ? !!onboardingAccountAddress && disclaimerChecked : !!onboardingAccountAddress + useSubmitOnEnter(onSubmit) return ( { - if (isEmptyMnemonic) { - return - } - - if (isResetting) { - // Remove all accounts before importing mnemonic. - await dispatch( - editAccountActions.trigger({ - type: EditAccountAction.Remove, - accounts, - }), - ) - } - - addOnboardingAccountMnemonic(mnemonic) - goToNextStep() - }, [accounts, dispatch, goToNextStep, isResetting, mnemonic, addOnboardingAccountMnemonic, isEmptyMnemonic]) - - const debouncedMnemonic = useDebounce(mnemonic, 500) - const { error: mnemonicValidationError, invalidWordCount } = useMemo(() => { - const mnemonicString = debouncedMnemonic.join(' ').toLowerCase() + const mnemonicString = mnemonic.join(' ').toLowerCase() if (!mnemonicString.trim()) { return { error: undefined, invalidWordCount: undefined } } return validateMnemonic(mnemonicString) - }, [debouncedMnemonic]) + }, [mnemonic]) const errorMessageToDisplay = useMemo(() => { // If all cells are filled, but there is an error, display the invalid phrase error @@ -170,6 +149,29 @@ export function ImportMnemonic(): JSX.Element { return undefined }, [expanded, mnemonic, mnemonicValidationError, t, invalidWordCount]) + const debouncedErrorMessageToDisplay = useDebounce(errorMessageToDisplay, 500) + + const enableSubmit = !isEmptyMnemonic && !mnemonicValidationError && !errorMessageToDisplay + + const onSubmit = useCallback(async () => { + if (!enableSubmit) { + return + } + + if (isResetting) { + // Remove all accounts before importing mnemonic. + await dispatch( + editAccountActions.trigger({ + type: EditAccountAction.Remove, + accounts, + }), + ) + } + + addOnboardingAccountMnemonic(mnemonic) + goToNextStep() + }, [accounts, dispatch, goToNextStep, isResetting, mnemonic, addOnboardingAccountMnemonic, enableSubmit]) + return ( - {errorMessageToDisplay ?? DUMMY_TEXT} {/* To prevent layout shift */} + {debouncedErrorMessageToDisplay ?? DUMMY_TEXT} {/* To prevent layout shift */} @@ -239,6 +241,7 @@ export function ImportMnemonic(): JSX.Element { handleKeyPress={handleKeyPress} index={index} word={word} + onSubmitEditing={onSubmit} /> ), @@ -276,8 +279,12 @@ const RecoveryPhraseWord = forwardRef< handleBlur: (index: number) => (event: NativeSyntheticEvent) => void handleChange: (index: number) => (event: NativeSyntheticEvent) => void handleKeyPress: (index: number) => (e: NativeSyntheticEvent) => void + onSubmitEditing: () => void } ->(function _RecoveryPhraseWord({ word, index, handleBlur, handleChange, handleKeyPress }, ref): JSX.Element { +>(function _RecoveryPhraseWord( + { word, index, handleBlur, handleChange, handleKeyPress, onSubmitEditing }, + ref, +): JSX.Element { const debouncedWord = useDebounce(word, 500) const showError = isValidMnemonicWord(debouncedWord) @@ -312,6 +319,7 @@ const RecoveryPhraseWord = forwardRef< onBlur={handleBlur(index)} onChange={handleChange(index)} onKeyPress={handleKeyPress(index)} + onSubmitEditing={onSubmitEditing} {...(showError && { backgroundColor: '$DEP_accentCriticalSoft', color: '$statusCritical', diff --git a/apps/extension/src/app/features/onboarding/import/SelectWallets.tsx b/apps/extension/src/app/features/onboarding/import/SelectWallets.tsx index c795ad6c297..6d91a19edb5 100644 --- a/apps/extension/src/app/features/onboarding/import/SelectWallets.tsx +++ b/apps/extension/src/app/features/onboarding/import/SelectWallets.tsx @@ -1,10 +1,11 @@ -import { useCallback } from 'react' +import { useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' import { SelectWalletsSkeleton } from 'src/app/components/loading/SelectWalletSkeleton' import { saveDappConnection } from 'src/app/features/dapp/actions' import { OnboardingScreen } from 'src/app/features/onboarding/OnboardingScreen' import { useOnboardingSteps } from 'src/app/features/onboarding/OnboardingSteps' -import { Flex, ScrollView, Square, Text } from 'ui/src' +import { useSubmitOnEnter } from 'src/app/features/onboarding/utils' +import { Flex, ScrollView, SpinningLoader, Square, Text } from 'ui/src' import { WalletFilled } from 'ui/src/components/icons' import { iconSizes } from 'ui/src/theme' import { UNISWAP_WEB_URL } from 'uniswap/src/constants/urls' @@ -12,6 +13,7 @@ import { FeatureFlags } from 'uniswap/src/features/gating/flags' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' import Trace from 'uniswap/src/features/telemetry/Trace' import { ExtensionOnboardingFlow, ExtensionOnboardingScreens } from 'uniswap/src/types/screens/extension' +import { useAsyncData } from 'utilities/src/react/hooks' import WalletPreviewCard from 'wallet/src/components/WalletPreviewCard/WalletPreviewCard' import { useOnboardingContext } from 'wallet/src/features/onboarding/OnboardingContext' import { useImportableAccounts } from 'wallet/src/features/onboarding/hooks/useImportableAccounts' @@ -20,28 +22,41 @@ import { useSelectAccounts } from 'wallet/src/features/onboarding/hooks/useSelec export function SelectWallets({ flow }: { flow: ExtensionOnboardingFlow }): JSX.Element { const { t } = useTranslation() const shouldAutoConnect = useFeatureFlag(FeatureFlags.ExtensionAutoConnect) + const [buttonClicked, setButtonClicked] = useState(false) const { goToNextStep, goToPreviousStep } = useOnboardingSteps() - const { selectImportedAccounts } = useOnboardingContext() + const { getGeneratedAddresses, generateAccountsAndImportAddresses } = useOnboardingContext() - const { importableAccounts, isLoading, showError, refetch } = useImportableAccounts() + const { data: generatedAddresses } = useAsyncData(getGeneratedAddresses) + + const { importableAccounts, isLoading, showError, refetch } = useImportableAccounts(generatedAddresses) const { selectedAddresses, toggleAddressSelection } = useSelectAccounts(importableAccounts) + const enableSubmit = showError || (selectedAddresses.length > 0 && !isLoading) + const onSubmit = useCallback(async () => { - const importedAccounts = await selectImportedAccounts(selectedAddresses) + if (!enableSubmit) { + return + } + + setButtonClicked(true) + const importedAccounts = await generateAccountsAndImportAddresses(selectedAddresses) // TODO(EXT-1375): figure out how to better auto connect existing wallets that may have connected via WC or some other method. // Once that's solved the feature flag can be turned on/removed. - if (shouldAutoConnect && importedAccounts[0]) { + if (shouldAutoConnect && importedAccounts?.[0]) { await saveDappConnection(UNISWAP_WEB_URL, importedAccounts[0]) } goToNextStep() - }, [selectImportedAccounts, selectedAddresses, goToNextStep, shouldAutoConnect]) + setButtonClicked(false) + }, [generateAccountsAndImportAddresses, selectedAddresses, goToNextStep, shouldAutoConnect, enableSubmit]) const title = showError ? t('onboarding.selectWallets.title.error') : t('onboarding.selectWallets.title.default') + useSubmitOnEnter(showError ? refetch : onSubmit) + return ( } - nextButtonEnabled={showError || (selectedAddresses.length > 0 && !isLoading)} - nextButtonText={showError ? t('common.button.retry') : t('common.button.continue')} - nextButtonTheme={showError ? 'secondary' : 'primary'} + nextButtonEnabled={enableSubmit} + nextButtonIcon={buttonClicked ? : undefined} + nextButtonText={ + showError + ? t('common.button.retry') + : buttonClicked + ? t('onboarding.importMnemonic.button.importing') + : t('common.button.continue') + } + nextButtonTheme={showError ? 'secondary' : buttonClicked ? 'accentSecondary' : 'primary'} title={title} onBack={goToPreviousStep} onSubmit={showError ? refetch : onSubmit} > - + {showError ? ( {t('onboarding.selectWallets.error')} - ) : isLoading ? ( + ) : !importableAccounts?.length ? ( diff --git a/apps/extension/src/app/features/onboarding/scan/ScanToOnboard.tsx b/apps/extension/src/app/features/onboarding/scan/ScanToOnboard.tsx index d5b0cd88341..03b87ec8e30 100644 --- a/apps/extension/src/app/features/onboarding/scan/ScanToOnboard.tsx +++ b/apps/extension/src/app/features/onboarding/scan/ScanToOnboard.tsx @@ -8,7 +8,7 @@ import { withSequence, withSpring, } from 'react-native-reanimated' -import { SpringConfig } from 'react-native-reanimated/lib/typescript/reanimated2/animation/springUtils' +import { SpringConfig } from 'react-native-reanimated/lib/typescript/animation/springUtils' import QRCode from 'react-qr-code' //TODO(EXT-476): Replace with custom QR code designs import { OnboardingScreen } from 'src/app/features/onboarding/OnboardingScreen' import { useOnboardingSteps } from 'src/app/features/onboarding/OnboardingSteps' diff --git a/apps/extension/src/app/features/onboarding/utils.ts b/apps/extension/src/app/features/onboarding/utils.ts index 7e0c93ddb42..c7c618c798a 100644 --- a/apps/extension/src/app/features/onboarding/utils.ts +++ b/apps/extension/src/app/features/onboarding/utils.ts @@ -1,2 +1,22 @@ +import { useEffect } from 'react' + export const ONBOARDING_CONTENT_WIDTH = 460 export const ONBOARDING_INITIAL_FRAME_HEIGHT = 636 + +export function useSubmitOnEnter(onSubmit: () => void): void { + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent): void => { + if (event.key === 'Enter') { + onSubmit() + } + } + + // Add event listener for keydown + window.addEventListener('keydown', handleKeyDown) + + // Cleanup event listener on component unmount + return (): void => { + window.removeEventListener('keydown', handleKeyDown) + } + }, [onSubmit]) +} diff --git a/apps/extension/src/app/features/receive/__snapshots__/ReceiveScreen.test.tsx.snap b/apps/extension/src/app/features/receive/__snapshots__/ReceiveScreen.test.tsx.snap index 24f97eb5d58..6fb7dc7a372 100644 --- a/apps/extension/src/app/features/receive/__snapshots__/ReceiveScreen.test.tsx.snap +++ b/apps/extension/src/app/features/receive/__snapshots__/ReceiveScreen.test.tsx.snap @@ -6010,9 +6010,8 @@ exports[`ReceiveScreen renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -6028,9 +6034,8 @@ exports[`ReceiveScreen renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -6046,9 +6058,8 @@ exports[`ReceiveScreen renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -6064,9 +6082,8 @@ exports[`ReceiveScreen renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -6082,9 +6106,8 @@ exports[`ReceiveScreen renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -6100,9 +6130,8 @@ exports[`ReceiveScreen renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -6118,9 +6154,8 @@ exports[`ReceiveScreen renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -6136,9 +6178,8 @@ exports[`ReceiveScreen renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -6154,9 +6202,8 @@ exports[`ReceiveScreen renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -6172,9 +6226,8 @@ exports[`ReceiveScreen renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -6190,9 +6250,8 @@ exports[`ReceiveScreen renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -12236,9 +12302,8 @@ exports[`ReceiveScreen renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -12254,9 +12326,8 @@ exports[`ReceiveScreen renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -12272,9 +12350,8 @@ exports[`ReceiveScreen renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -12290,9 +12374,8 @@ exports[`ReceiveScreen renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -12308,9 +12398,8 @@ exports[`ReceiveScreen renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -12326,9 +12422,8 @@ exports[`ReceiveScreen renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -12344,9 +12446,8 @@ exports[`ReceiveScreen renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -12362,9 +12470,8 @@ exports[`ReceiveScreen renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -12380,9 +12494,8 @@ exports[`ReceiveScreen renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -12398,9 +12518,8 @@ exports[`ReceiveScreen renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
@@ -12416,9 +12542,8 @@ exports[`ReceiveScreen renders without error 1`] = ` class="_display-flex _alignItems-stretch _flexBasis-auto _boxSizing-border-box _position-relative _minHeight-0px _minWidth-0px _flexShrink-0 _flexDirection-column _borderTopColor-568007293 _borderRightColor-568007293 _borderBottomColor-568007293 _borderLeftColor-568007293 _borderTopLeftRadius-8px _borderTopRightRadius-8px _borderBottomRightRadius-8px _borderBottomLeftRadius-8px _borderTopWidth-2px _borderRightWidth-2px _borderBottomWidth-2px _borderLeftWidth-2px _ml--8px _borderBottomStyle-solid _borderTopStyle-solid _borderLeftStyle-solid _borderRightStyle-solid" >
+
diff --git a/apps/extension/src/app/features/transfer/TransferFlowScreen.tsx b/apps/extension/src/app/features/send/SendFlow.tsx similarity index 67% rename from apps/extension/src/app/features/transfer/TransferFlowScreen.tsx rename to apps/extension/src/app/features/send/SendFlow.tsx index 6a8a3daba90..babe47d9a63 100644 --- a/apps/extension/src/app/features/transfer/TransferFlowScreen.tsx +++ b/apps/extension/src/app/features/send/SendFlow.tsx @@ -1,18 +1,18 @@ import { useTranslation } from 'react-i18next' import { ScreenHeader } from 'src/app/components/layout/ScreenHeader' import { SCREEN_ITEM_HORIZONTAL_PAD } from 'src/app/constants' -import { SendFormScreen } from 'src/app/features/transfer/SendFormScreen/SendFormScreen' -import { TransferContextProvider } from 'src/app/features/transfer/TransferContext' +import { SendFormScreen } from 'src/app/features/send/SendFormScreen/SendFormScreen' import { useExtensionNavigation } from 'src/app/navigation/utils' import { Flex } from 'ui/src' import { X } from 'ui/src/components/icons' +import { SendContextProvider } from 'wallet/src/features/transactions/contexts/SendContext' -export function TransferFlowScreen(): JSX.Element { +export function SendFlow(): JSX.Element { const { t } = useTranslation() const { navigateBack, locationState } = useExtensionNavigation() return ( - + @@ -21,6 +21,6 @@ export function TransferFlowScreen(): JSX.Element { - + ) } diff --git a/apps/extension/src/app/features/transfer/SendFormScreen/RecipientPanel.tsx b/apps/extension/src/app/features/send/SendFormScreen/RecipientPanel.tsx similarity index 84% rename from apps/extension/src/app/features/transfer/SendFormScreen/RecipientPanel.tsx rename to apps/extension/src/app/features/send/SendFormScreen/RecipientPanel.tsx index 0257b0247a3..9206f0af929 100644 --- a/apps/extension/src/app/features/transfer/SendFormScreen/RecipientPanel.tsx +++ b/apps/extension/src/app/features/send/SendFormScreen/RecipientPanel.tsx @@ -1,7 +1,6 @@ import { useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' import { Keyboard } from 'react-native' -import { useTransferContext } from 'src/app/features/transfer/TransferContext' import { Flex, Separator, Text, TouchableArea } from 'ui/src' import { RotatableChevron, WalletFilled } from 'ui/src/components/icons' import { iconSizes, spacing } from 'ui/src/theme' @@ -11,11 +10,7 @@ import { RecipientList } from 'wallet/src/components/RecipientSearch/RecipientLi import { RecipientSelectSpeedBumps } from 'wallet/src/components/RecipientSearch/RecipientSelectSpeedBumps' import { useFilteredRecipientSections } from 'wallet/src/components/RecipientSearch/hooks' import { AddressDisplay } from 'wallet/src/components/accounts/AddressDisplay' -import { selectRecipient } from 'wallet/src/features/transactions/transactionState/transactionState' -import { - useOnToggleShowRecipientSelector, - useSetShowRecipientSelector, -} from 'wallet/src/features/transactions/transfer/hooks/useOnToggleShowRecipientSelector' +import { useSendContext } from 'wallet/src/features/transactions/contexts/SendContext' type RecipientPanelProps = { chainId?: WalletChainId @@ -27,9 +22,20 @@ export function RecipientPanel({ chainId }: RecipientPanelProps): JSX.Element { const [pattern, setPattern] = useState('') const [selectedRecipient, setSelectedRecipient] = useState() const [checkSpeedBumps, setCheckSpeedBumps] = useState(false) - const { recipient, dispatch, showRecipientSelector } = useTransferContext() - const onToggleShowRecipientSelector = useOnToggleShowRecipientSelector(dispatch) - const setShowRecipientSelector = useSetShowRecipientSelector(dispatch) + + const { recipient, showRecipientSelector, updateSendForm } = useSendContext() + + const onSetShowRecipientSelector = useCallback( + (show: boolean) => { + updateSendForm({ showRecipientSelector: show }) + }, + [updateSendForm], + ) + + const onToggleShowRecipientSelector = useCallback(() => { + onSetShowRecipientSelector(!showRecipientSelector) + }, [onSetShowRecipientSelector, showRecipientSelector]) + const sections = useFilteredRecipientSections(pattern) const onSelectRecipient = useCallback((newRecipient: string) => { @@ -41,12 +47,12 @@ export function RecipientPanel({ chainId }: RecipientPanelProps): JSX.Element { if (!selectedRecipient) { return } - dispatch(selectRecipient({ recipient: selectedRecipient })) - setShowRecipientSelector(false) - }, [dispatch, selectedRecipient, setShowRecipientSelector]) + updateSendForm({ recipient: selectedRecipient }) + onSetShowRecipientSelector(false) + }, [selectedRecipient, updateSendForm, onSetShowRecipientSelector]) const onClose = (): void => { - setShowRecipientSelector(false) + updateSendForm({ showRecipientSelector: false }) } const noPatternOrFavorites = !pattern && sections.length === 0 @@ -70,7 +76,7 @@ export function RecipientPanel({ chainId }: RecipientPanelProps): JSX.Element { value={pattern ?? ''} onChangeText={setPattern} onDismiss={() => Keyboard.dismiss()} - onFocus={() => setShowRecipientSelector(true)} + onFocus={() => onSetShowRecipientSelector(true)} /> {showRecipientSelector && ( diff --git a/apps/extension/src/app/features/transfer/SendFormScreen/ReviewButton.tsx b/apps/extension/src/app/features/send/SendFormScreen/ReviewButton.tsx similarity index 86% rename from apps/extension/src/app/features/transfer/SendFormScreen/ReviewButton.tsx rename to apps/extension/src/app/features/send/SendFormScreen/ReviewButton.tsx index 3a239ee69b6..a7788ca6109 100644 --- a/apps/extension/src/app/features/transfer/SendFormScreen/ReviewButton.tsx +++ b/apps/extension/src/app/features/send/SendFormScreen/ReviewButton.tsx @@ -1,11 +1,11 @@ import { useTranslation } from 'react-i18next' -import { useTransferContext } from 'src/app/features/transfer/TransferContext' import { Button, Flex, Text, isWeb } from 'ui/src' import Trace from 'uniswap/src/features/telemetry/Trace' import { ElementName } from 'uniswap/src/features/telemetry/constants' import { NativeCurrency } from 'uniswap/src/features/tokens/NativeCurrency' +import { WarningLabel } from 'uniswap/src/features/transactions/WarningModal/types' import { TestID } from 'uniswap/src/test/fixtures/testIDs' -import { WarningLabel } from 'wallet/src/features/transactions/WarningModal/types' +import { useSendContext } from 'wallet/src/features/transactions/contexts/SendContext' type ReviewButtonProps = { onPress: () => void @@ -17,8 +17,8 @@ export function ReviewButton({ onPress, disabled }: ReviewButtonProps): JSX.Elem const { warnings, - derivedTransferInfo: { chainId }, - } = useTransferContext() + derivedSendInfo: { chainId }, + } = useSendContext() const nativeCurrencySymbol = NativeCurrency.onChain(chainId).symbol diff --git a/apps/extension/src/app/features/send/SendFormScreen/SendFormScreen.tsx b/apps/extension/src/app/features/send/SendFormScreen/SendFormScreen.tsx new file mode 100644 index 00000000000..9e6d19542cc --- /dev/null +++ b/apps/extension/src/app/features/send/SendFormScreen/SendFormScreen.tsx @@ -0,0 +1,189 @@ +import { useCallback } from 'react' +import { RecipientPanel } from 'src/app/features/send/SendFormScreen/RecipientPanel' +import { ReviewButton } from 'src/app/features/send/SendFormScreen/ReviewButton' +import { Flex, Separator, useSporeColors } from 'ui/src' +import { Modal } from 'uniswap/src/components/modals/Modal' +import Trace from 'uniswap/src/features/telemetry/Trace' +import { ModalName, SectionName } from 'uniswap/src/features/telemetry/constants' +import { useUSDCValue } from 'uniswap/src/features/transactions/swap/hooks/useUSDCPrice' +import { CurrencyField } from 'uniswap/src/types/currency' +import { InsufficientNativeTokenWarning } from 'wallet/src/features/transactions/InsufficientNativeTokenWarning/InsufficientNativeTokenWarning' +import { SendScreen, useSendContext } from 'wallet/src/features/transactions/contexts/SendContext' +import { GasFeeRow } from 'wallet/src/features/transactions/send/GasFeeRow' +import { SendAmountInput } from 'wallet/src/features/transactions/send/SendAmountInput' +import { SendReviewDetails } from 'wallet/src/features/transactions/send/SendReviewDetails' +import { TokenSelectorPanel } from 'wallet/src/features/transactions/send/TokenSelectorPanel' +import { useShowSendNetworkNotification } from 'wallet/src/features/transactions/send/hooks/useShowSendNetworkNotification' +import { useUSDTokenUpdater } from 'wallet/src/features/transactions/swap/trade/hooks/useUSDTokenUpdater' +import { createTransactionId } from 'wallet/src/features/transactions/utils' +import { BlockedAddressWarning } from 'wallet/src/features/trm/BlockedAddressWarning' +import { useIsBlocked, useIsBlockedActiveAddress } from 'wallet/src/features/trm/hooks' + +export function SendFormScreen(): JSX.Element { + const colors = useSporeColors() + + const { + derivedSendInfo, + selectingCurrencyField, + exactAmountToken, + isFiatInput, + warnings, + gasFee, + showRecipientSelector, + screen, + setScreen, + recipient, + updateSendForm, + onSelectCurrency, + } = useSendContext() + + const { currencyInInfo, currencyBalances, currencyAmounts, chainId, exactAmountFiat } = derivedSendInfo + + // When a user changes networks or visits the send screen, show a network notification + useShowSendNetworkNotification({ chainId: currencyInInfo?.currency.chainId }) + + // Sync fiat and token amounts + const onFiatAmountUpdated = useCallback( + (amount: string): void => { + updateSendForm({ exactAmountFiat: amount }) + }, + [updateSendForm], + ) + + const onTokenAmountUpdated = useCallback( + (amount: string): void => { + updateSendForm({ exactAmountToken: amount }) + }, + [updateSendForm], + ) + + useUSDTokenUpdater({ + onFiatAmountUpdated, + onTokenAmountUpdated, + isFiatInput: Boolean(isFiatInput), + exactAmountToken, + exactAmountFiat, + currency: currencyInInfo?.currency, + }) + + const currencyUSDValue = useUSDCValue(currencyAmounts[CurrencyField.INPUT]) + + const exactValue = isFiatInput ? exactAmountFiat : exactAmountToken + const showTokenSelector = selectingCurrencyField === CurrencyField.INPUT + + // blocked addresses + const { isBlocked: isActiveBlocked, isBlockedLoading: isActiveBlockedLoading } = useIsBlockedActiveAddress() + const { isBlocked: isRecipientBlocked, isBlockedLoading: isRecipientBlockedLoading } = useIsBlocked(recipient) + const isBlocked = isActiveBlocked || isRecipientBlocked + const isBlockedLoading = isActiveBlockedLoading || isRecipientBlockedLoading + + const onPressReview = useCallback(() => { + const txId = createTransactionId() + updateSendForm({ txId }) + setScreen(SendScreen.SendReview) + }, [setScreen, updateSendForm]) + + const onSetExactAmount = useCallback( + (amount: string) => { + updateSendForm(isFiatInput ? { exactAmountFiat: amount } : { exactAmountToken: amount }) + }, + [isFiatInput, updateSendForm], + ) + + const onSetMax = useCallback( + (amount: string) => { + updateSendForm({ exactAmountToken: amount, isFiatInput: false, focusOnCurrencyField: null }) + }, + [updateSendForm], + ) + + const onHideTokenSelector = useCallback(() => { + updateSendForm({ selectingCurrencyField: undefined }) + }, [updateSendForm]) + + const onShowTokenSelector = useCallback(() => { + updateSendForm({ selectingCurrencyField: CurrencyField.INPUT }) + }, [updateSendForm]) + + const onToggleFiatInput = useCallback(() => { + updateSendForm({ isFiatInput: !isFiatInput }) + }, [isFiatInput, updateSendForm]) + + const inputShadowProps = { + shadowColor: colors.surface3.val, + shadowRadius: 10, + shadowOpacity: 0.04, + zIndex: 1, + } + + return ( + + + + + + + + + + + + + + {!showRecipientSelector && ( + <> + {isBlocked && ( + + )} + + + + + )} + + + ) +} diff --git a/apps/extension/src/app/features/settings/SettingsRecoveryPhraseScreen/ViewRecoveryPhraseScreen.tsx b/apps/extension/src/app/features/settings/SettingsRecoveryPhraseScreen/ViewRecoveryPhraseScreen.tsx index 297bce48b86..10a827d9c7c 100644 --- a/apps/extension/src/app/features/settings/SettingsRecoveryPhraseScreen/ViewRecoveryPhraseScreen.tsx +++ b/apps/extension/src/app/features/settings/SettingsRecoveryPhraseScreen/ViewRecoveryPhraseScreen.tsx @@ -84,12 +84,11 @@ export function SettingsViewRecoveryPhraseScreen(): JSX.Element { title={t('setting.recoveryPhrase.view.warning.title')} onNextPressed={showPasswordModal} > - {viewStep === ViewStep.Password && ( - setViewStep(ViewStep.Warning)} - onNext={() => setViewStep(ViewStep.Reveal)} - /> - )} + setViewStep(ViewStep.Warning)} + onNext={() => setViewStep(ViewStep.Reveal)} + /> + {title} diff --git a/apps/extension/src/app/features/settings/password/EnterPasswordModal.tsx b/apps/extension/src/app/features/settings/password/EnterPasswordModal.tsx index de9c21fbf3a..a54a7ecad12 100644 --- a/apps/extension/src/app/features/settings/password/EnterPasswordModal.tsx +++ b/apps/extension/src/app/features/settings/password/EnterPasswordModal.tsx @@ -3,11 +3,19 @@ import { useTranslation } from 'react-i18next' import { PasswordInput } from 'src/app/components/PasswordInput' import { Button, Flex, Square, Text, inputStyles, useSporeColors } from 'ui/src' import { Lock } from 'ui/src/components/icons' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' import { ModalName } from 'uniswap/src/features/telemetry/constants' import { Keyring } from 'wallet/src/features/wallet/Keyring/Keyring' -export function EnterPasswordModal({ onNext, onClose }: { onNext: () => void; onClose: () => void }): JSX.Element { +export function EnterPasswordModal({ + isOpen, + onNext, + onClose, +}: { + isOpen: boolean + onNext: () => void + onClose: () => void +}): JSX.Element { const { t } = useTranslation() const colors = useSporeColors() @@ -30,11 +38,12 @@ export function EnterPasswordModal({ onNext, onClose }: { onNext: () => void; on } return ( - @@ -64,6 +73,6 @@ export function EnterPasswordModal({ onNext, onClose }: { onNext: () => void; on {t('common.button.continue')} - + ) } diff --git a/apps/extension/src/app/features/swap/SwapFlowScreen.tsx b/apps/extension/src/app/features/swap/SwapFlowScreen.tsx index aa84c74a807..8e49713f411 100644 --- a/apps/extension/src/app/features/swap/SwapFlowScreen.tsx +++ b/apps/extension/src/app/features/swap/SwapFlowScreen.tsx @@ -1,23 +1,24 @@ import { useExtensionNavigation } from 'src/app/navigation/utils' import { Flex } from 'ui/src' -import { SwapFlow } from 'wallet/src/features/transactions/swap/SwapFlow' +import { useHighestBalanceNativeCurrencyId } from 'uniswap/src/features/dataApi/balances' +import { usePortfolioValueModifiers } from 'wallet/src/features/dataApi/balances' +import { WalletSwapFlow } from 'wallet/src/features/transactions/swap/WalletSwapFlow' import { useSwapPrefilledState } from 'wallet/src/features/transactions/swap/hooks/useSwapPrefilledState' +import { prepareSwapFormState } from 'wallet/src/features/transactions/swap/utils' import { useActiveAccountWithThrow } from 'wallet/src/features/wallet/hooks' export function SwapFlowScreen(): JSX.Element { const { navigateBack, locationState } = useExtensionNavigation() - - const swapPrefilledState = useSwapPrefilledState(locationState?.initialTransactionState) const account = useActiveAccountWithThrow() + const valueModifiers = usePortfolioValueModifiers(account.address) + const inputCurrencyId = useHighestBalanceNativeCurrencyId(account.address, valueModifiers) + const initialState = prepareSwapFormState({ inputCurrencyId }) + + const swapPrefilledState = useSwapPrefilledState(locationState?.initialTransactionState ?? initialState) return ( - + ) } diff --git a/apps/extension/src/app/features/transfer/SendFormScreen/SendFormScreen.tsx b/apps/extension/src/app/features/transfer/SendFormScreen/SendFormScreen.tsx deleted file mode 100644 index b01f91400ca..00000000000 --- a/apps/extension/src/app/features/transfer/SendFormScreen/SendFormScreen.tsx +++ /dev/null @@ -1,161 +0,0 @@ -import { useCallback } from 'react' -import { GasFeeRow } from 'src/app/features/transfer/SendFormScreen/GasFeeRow' -import { RecipientPanel } from 'src/app/features/transfer/SendFormScreen/RecipientPanel' -import { ReviewButton } from 'src/app/features/transfer/SendFormScreen/ReviewButton' -import { SendReviewScreen } from 'src/app/features/transfer/SendReviewScreen/SendReviewScreen' -import { TransferScreen, useTransferContext } from 'src/app/features/transfer/TransferContext' -import { Flex, Separator, useSporeColors } from 'ui/src' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' -import Trace from 'uniswap/src/features/telemetry/Trace' -import { ModalName, SectionName } from 'uniswap/src/features/telemetry/constants' -import { CurrencyField } from 'uniswap/src/features/transactions/transactionState/types' -import { TokenSelectorFlow } from 'uniswap/src/features/transactions/transfer/types' -import { InsufficientNativeTokenWarning } from 'wallet/src/features/transactions/InsufficientNativeTokenWarning/InsufficientNativeTokenWarning' -import { useTokenFormActionHandlers } from 'wallet/src/features/transactions/hooks/useTokenFormActionHandlers' -import { useTokenSelectorActionHandlers } from 'wallet/src/features/transactions/hooks/useTokenSelectorActionHandlers' -import { useUSDCValue } from 'wallet/src/features/transactions/swap/trade/hooks/useUSDCPrice' -import { useUSDTokenUpdater } from 'wallet/src/features/transactions/swap/trade/hooks/useUSDTokenUpdater' -import { transactionStateActions } from 'wallet/src/features/transactions/transactionState/transactionState' -import { TokenSelectorPanel } from 'wallet/src/features/transactions/transfer/TokenSelectorPanel' -import { TransferAmountInput } from 'wallet/src/features/transactions/transfer/TransferAmountInput' -import { useShowSendNetworkNotification } from 'wallet/src/features/transactions/transfer/hooks/useShowSendNetworkNotification' -import { createTransactionId } from 'wallet/src/features/transactions/utils' -import { BlockedAddressWarning } from 'wallet/src/features/trm/BlockedAddressWarning' -import { useIsBlocked, useIsBlockedActiveAddress } from 'wallet/src/features/trm/hooks' - -export function SendFormScreen(): JSX.Element { - const colors = useSporeColors() - const { - dispatch, - derivedTransferInfo, - selectingCurrencyField, - exactAmountToken, - exactAmountFiat, - isFiatInput, - warnings, - gasFee, - showRecipientSelector, - screen, - setScreen, - recipient, - } = useTransferContext() - - const { currencyInInfo, currencyBalances, currencyAmounts, chainId } = derivedTransferInfo - - useShowSendNetworkNotification({ chainId: currencyInInfo?.currency.chainId }) - - const { onSetExactAmount, onSetMax, onToggleFiatInput } = useTokenFormActionHandlers(dispatch) - const { onSelectCurrency, onHideTokenSelector, onShowTokenSelector } = useTokenSelectorActionHandlers( - dispatch, - TokenSelectorFlow.Transfer, - ) - - const currencyUSDValue = useUSDCValue(currencyAmounts[CurrencyField.INPUT]) - - // Sync fiat and token amounts - useUSDTokenUpdater(dispatch, Boolean(isFiatInput), exactAmountToken, exactAmountFiat ?? '', currencyInInfo?.currency) - - const exactValue = isFiatInput ? exactAmountFiat : exactAmountToken - - const showTokenSelector = selectingCurrencyField === CurrencyField.INPUT - - // blocked addresses - const { isBlocked: isActiveBlocked, isBlockedLoading: isActiveBlockedLoading } = useIsBlockedActiveAddress() - const { isBlocked: isRecipientBlocked, isBlockedLoading: isRecipientBlockedLoading } = useIsBlocked(recipient) - const isBlocked = isActiveBlocked || isRecipientBlocked - const isBlockedLoading = isActiveBlockedLoading || isRecipientBlockedLoading - - const onPressReview = useCallback(() => { - const txId = createTransactionId() - dispatch(transactionStateActions.setTxId(txId)) - setScreen(TransferScreen.SendReview) - }, [dispatch, setScreen]) - - const inputShadowProps = { - shadowColor: colors.surface3.val, - shadowRadius: 10, - shadowOpacity: 0.04, - zIndex: 1, - } - - return ( - - {screen === TransferScreen.SendReview && ( - - - - )} - - - onShowTokenSelector(CurrencyField.INPUT)} - /> - {!showTokenSelector && ( - <> - - - - )} - - {!showTokenSelector && ( - <> - - - - {!showRecipientSelector && ( - <> - {isBlocked && ( - - )} - - - - - )} - - )} - - - ) -} diff --git a/apps/extension/src/app/features/transfer/SendReviewScreen/SendDetails.tsx b/apps/extension/src/app/features/transfer/SendReviewScreen/SendDetails.tsx deleted file mode 100644 index 3a45cfb57d6..00000000000 --- a/apps/extension/src/app/features/transfer/SendReviewScreen/SendDetails.tsx +++ /dev/null @@ -1,198 +0,0 @@ -import { providers } from 'ethers' -import { useState } from 'react' -import { useTranslation } from 'react-i18next' -import { Button, Flex, Separator, Text, useSporeColors } from 'ui/src' -import { useDeviceDimensions } from 'ui/src/hooks/useDeviceDimensions' -import { iconSizes } from 'ui/src/theme' -import { CurrencyLogo } from 'uniswap/src/components/CurrencyLogo/CurrencyLogo' -import { AccountType } from 'uniswap/src/features/accounts/types' -import { ElementName, ModalName } from 'uniswap/src/features/telemetry/constants' -import { CurrencyField } from 'uniswap/src/features/transactions/transactionState/types' -import { NumberType } from 'utilities/src/format/types' -import { AccountIcon } from 'wallet/src/components/accounts/AccountIcon' -import { AddressDisplay } from 'wallet/src/components/accounts/AddressDisplay' -import { Arrow } from 'wallet/src/components/icons/Arrow' -import { WarningModal } from 'wallet/src/components/modals/WarningModal/WarningModal' -import { NFTTransfer } from 'wallet/src/components/nfts/NFTTransfer' -import { useAppFiatCurrencyInfo } from 'wallet/src/features/fiatCurrency/hooks' -import { GasFeeResult } from 'wallet/src/features/gas/types' -import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext' -import { TransactionDetails } from 'wallet/src/features/transactions/TransactionDetails/TransactionDetails' -import { WarningSeverity } from 'wallet/src/features/transactions/WarningModal/types' -import { ParsedWarnings } from 'wallet/src/features/transactions/hooks/useParsedTransactionWarnings' -import { useUSDCValue } from 'wallet/src/features/transactions/swap/trade/hooks/useUSDCPrice' -import { DerivedTransferInfo } from 'wallet/src/features/transactions/transfer/types' -import { useActiveAccountWithThrow, useAvatar } from 'wallet/src/features/wallet/hooks' - -interface TransferFormProps { - derivedTransferInfo: DerivedTransferInfo - txRequest?: providers.TransactionRequest - gasFee: GasFeeResult - onReviewSubmit: () => void - warnings: ParsedWarnings -} - -/** - * TODO: MOB-2563 https://linear.app/uniswap/issue/MOB-2563/consolidate-all-transfer-logic-ext-mob - * Re-use this component when implemting shared review UI on mobile, and move to shared package. - */ -export function SendDetails({ - derivedTransferInfo, - gasFee, - onReviewSubmit, - txRequest, - warnings, -}: TransferFormProps): JSX.Element | null { - const { t } = useTranslation() - const { fullHeight } = useDeviceDimensions() - const colors = useSporeColors() - - const { formatCurrencyAmount, formatNumberOrString, convertFiatAmountFormatted } = useLocalizationContext() - - const account = useActiveAccountWithThrow() - - const [showWarningModal, setShowWarningModal] = useState(false) - const currency = useAppFiatCurrencyInfo() - - const onShowWarning = (): void => { - setShowWarningModal(true) - } - - const onCloseWarning = (): void => { - setShowWarningModal(false) - } - - const { - currencyAmounts, - recipient, - isFiatInput = false, - currencyInInfo, - nftIn, - chainId, - exactAmountFiat, - } = derivedTransferInfo - - const { avatar } = useAvatar(recipient) - - const inputCurrencyUSDValue = useUSDCValue(currencyAmounts[CurrencyField.INPUT]) - - const { blockingWarning } = warnings - - const actionButtonDisabled = - !!blockingWarning || !gasFee.value || !!gasFee.error || !txRequest || account.type === AccountType.Readonly - - const actionButtonProps = { - disabled: actionButtonDisabled, - label: t('send.review.summary.button.title'), - name: ElementName.Send, - onPress: onReviewSubmit, - } - - const transferWarning = warnings.warnings.find((warning) => warning.severity >= WarningSeverity.Medium) - - const formattedCurrencyAmount = formatCurrencyAmount({ - value: currencyAmounts[CurrencyField.INPUT], - type: NumberType.TokenTx, - }) - const formattedAmountIn = isFiatInput - ? formatNumberOrString({ - value: exactAmountFiat, - type: NumberType.FiatTokenQuantity, - currencyCode: currency.code, - }) - : formattedCurrencyAmount - - const formattedInputFiatValue = convertFiatAmountFormatted( - inputCurrencyUSDValue?.toExact(), - NumberType.FiatTokenQuantity, - ) - - if (!recipient) { - throw new Error('Invalid render of SendDetails with no recipient') - } - - return ( - <> - {showWarningModal && transferWarning?.title && ( - - )} - - {currencyInInfo ? ( - - - - - {formattedAmountIn} {!isFiatInput ? currencyInInfo.currency.symbol : ''} - - - {isFiatInput ? ( - - {formattedCurrencyAmount} {currencyInInfo.currency.symbol} - - ) : ( - inputCurrencyUSDValue && ( - - {formattedInputFiatValue} - - ) - )} - - - - ) : ( - nftIn && ( - - - - ) - )} - - - - {recipient && ( - - - - - )} - - - - - - - - ) -} diff --git a/apps/extension/src/app/features/transfer/SendReviewScreen/SendReviewScreen.tsx b/apps/extension/src/app/features/transfer/SendReviewScreen/SendReviewScreen.tsx deleted file mode 100644 index 694d145911d..00000000000 --- a/apps/extension/src/app/features/transfer/SendReviewScreen/SendReviewScreen.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import { useCallback } from 'react' -import { useTranslation } from 'react-i18next' -import { useDispatch } from 'react-redux' -import { SendDetails } from 'src/app/features/transfer/SendReviewScreen/SendDetails' -import { TransferScreen, useTransferContext } from 'src/app/features/transfer/TransferContext' -import { Flex, Text, TouchableArea } from 'ui/src' -import { X } from 'ui/src/components/icons' -import Trace from 'uniswap/src/features/telemetry/Trace' -import { SectionName } from 'uniswap/src/features/telemetry/constants' -import { CurrencyField } from 'uniswap/src/features/transactions/transactionState/types' -import { currencyAddress } from 'uniswap/src/utils/currencyId' -import { logger } from 'utilities/src/logger/logger' -import { useWalletNavigation } from 'wallet/src/contexts/WalletNavigationContext' -import { pushNotification } from 'wallet/src/features/notifications/slice' -import { AppNotificationType } from 'wallet/src/features/notifications/types' -import { useUSDCValue } from 'wallet/src/features/transactions/swap/trade/hooks/useUSDCPrice' -import { - useTransferERC20Callback, - useTransferNFTCallback, -} from 'wallet/src/features/transactions/transfer/hooks/useTransferCallback' - -export function SendReviewScreen(): JSX.Element { - const dispatch = useDispatch() - const { t } = useTranslation() - - const { navigateToAccountActivityList } = useWalletNavigation() - - const { derivedTransferInfo, warnings, txRequest, gasFee, setScreen } = useTransferContext() - const { txId, chainId, recipient, currencyInInfo, currencyAmounts, nftIn } = derivedTransferInfo - - // for transfer analytics - const currencyAmountUSD = useUSDCValue(currencyAmounts[CurrencyField.INPUT]) - - const triggerTransferPendingNotification = useCallback(() => { - if (!currencyInInfo) { - // This should never happen. Just keeping TS happy. - logger.error(new Error('Missing `currencyInInfo` when triggering transfer pending notification'), { - tags: { file: 'SendReviewScreen.tsx', function: 'triggerTransferPendingNotification' }, - }) - } else { - dispatch( - pushNotification({ - type: AppNotificationType.TransferCurrencyPending, - currencyInfo: currencyInInfo, - }), - ) - } - }, [currencyInInfo, dispatch]) - - const onNext = useCallback((): void => { - triggerTransferPendingNotification() - navigateToAccountActivityList() - }, [navigateToAccountActivityList, triggerTransferPendingNotification]) - - const transferERC20Callback = useTransferERC20Callback( - txId, - chainId, - recipient, - currencyInInfo ? currencyAddress(currencyInInfo.currency) : undefined, - currencyAmounts[CurrencyField.INPUT]?.quotient.toString(), - txRequest, - onNext, - currencyAmountUSD, - ) - - const transferNFTCallback = useTransferNFTCallback( - txId, - chainId, - recipient, - nftIn?.nftContract?.address, - nftIn?.tokenId, - txRequest, - onNext, - ) - - const onTransfer = (): void => { - nftIn ? transferNFTCallback?.() : transferERC20Callback?.() - } - - const onPrev = (): void => { - setScreen(TransferScreen.SendForm) - } - - return ( - - - - {t('send.review.modal.title')} - - - - - - - - ) -} diff --git a/apps/extension/src/app/features/transfer/TransferContext.tsx b/apps/extension/src/app/features/transfer/TransferContext.tsx deleted file mode 100644 index cbe25e4cc43..00000000000 --- a/apps/extension/src/app/features/transfer/TransferContext.tsx +++ /dev/null @@ -1,118 +0,0 @@ -import { TransactionRequest } from '@ethersproject/providers' -import { providers } from 'ethers' -import React, { createContext, ReactNode, useContext, useMemo, useReducer, useState } from 'react' -import { useTranslation } from 'react-i18next' -import { AnyAction } from 'redux' -import { TransactionState } from 'uniswap/src/features/transactions/transactionState/types' -import { useTransactionGasFee } from 'wallet/src/features/gas/hooks' -import { GasFeeResult, GasSpeed } from 'wallet/src/features/gas/types' -import { - ParsedWarnings, - useParsedSendWarnings, -} from 'wallet/src/features/transactions/hooks/useParsedTransactionWarnings' -import { useTransactionGasWarning } from 'wallet/src/features/transactions/hooks/useTransactionGasWarning' -import { - INITIAL_TRANSACTION_STATE, - transactionStateReducer, -} from 'wallet/src/features/transactions/transactionState/transactionState' -import { useDerivedTransferInfo } from 'wallet/src/features/transactions/transfer/hooks/useDerivedTransferInfo' -import { useTransferTransactionRequest } from 'wallet/src/features/transactions/transfer/hooks/useTransferTransactionRequest' -import { useTransferWarnings } from 'wallet/src/features/transactions/transfer/hooks/useTransferWarnings' -import { WarningAction } from 'wallet/src/features/transactions/WarningModal/types' -import { useActiveAccountWithThrow } from 'wallet/src/features/wallet/hooks' - -export enum TransferScreen { - SendForm, - SendReview, -} - -export enum TransferEntryType { - Fiat, - Crypto, -} - -type TransferContextState = { - screen: TransferScreen - setScreen: (newScreen: TransferScreen) => void - dispatch: React.Dispatch - derivedTransferInfo: ReturnType - gasFee: GasFeeResult - warnings: ParsedWarnings - txRequest: TransactionRequest | undefined -} & TransactionState - -export const TransferContext = createContext(undefined) - -export function TransferContextProvider({ - prefilledTransactionState, - children, -}: { - prefilledTransactionState?: TransactionState - children: ReactNode -}): JSX.Element { - const { t } = useTranslation() - - const account = useActiveAccountWithThrow() - - // state and reducers - const [transferFormState, dispatch] = useReducer(transactionStateReducer, { - ...(prefilledTransactionState ?? INITIAL_TRANSACTION_STATE), - showRecipientSelector: false, - }) - const [screen, setScreen] = useState(TransferScreen.SendForm) - - // derived info based on transfer state - const derivedTransferInfo = useDerivedTransferInfo(transferFormState) - - const warnings = useTransferWarnings(t, derivedTransferInfo) - - const txRequest = useTransferTransactionRequest(derivedTransferInfo) - - const gasFee = useTransactionGasFee( - txRequest, - GasSpeed.Urgent, - warnings.some((warning) => warning.action === WarningAction.DisableReview), - ) - - const txRequestWithGasSettings = useMemo( - (): providers.TransactionRequest => ({ ...txRequest, ...gasFee.params }), - [gasFee.params, txRequest], - ) - - const gasWarning = useTransactionGasWarning({ - account, - derivedInfo: derivedTransferInfo, - gasFee: gasFee?.value, - }) - - const allSendWarnings = useMemo(() => { - return !gasWarning ? warnings : [...warnings, gasWarning] - }, [warnings, gasWarning]) - - const parsedSendWarnings = useParsedSendWarnings(allSendWarnings) - - const state: TransferContextState = useMemo(() => { - return { - derivedTransferInfo, - screen, - setScreen, - dispatch, - gasFee, - warnings: parsedSendWarnings, - txRequest: txRequestWithGasSettings, - ...transferFormState, - } - }, [derivedTransferInfo, gasFee, parsedSendWarnings, screen, transferFormState, txRequestWithGasSettings]) - - return {children} -} - -export const useTransferContext = (): TransferContextState => { - const transferContext = useContext(TransferContext) - - if (transferContext === undefined) { - throw new Error('`useTransferContext` must be used inside of `TransferContextProvider`') - } - - return transferContext -} diff --git a/apps/extension/src/app/features/warnings/StorageWarningModal.tsx b/apps/extension/src/app/features/warnings/StorageWarningModal.tsx index dc7c3f5e642..0bcb7f11511 100644 --- a/apps/extension/src/app/features/warnings/StorageWarningModal.tsx +++ b/apps/extension/src/app/features/warnings/StorageWarningModal.tsx @@ -5,8 +5,8 @@ import { AppRoutes, SettingsRoutes } from 'src/app/navigation/constants' import { useExtensionNavigation } from 'src/app/navigation/utils' import { spacing } from 'ui/src/theme' import { ModalName } from 'uniswap/src/features/telemetry/constants' +import { WarningSeverity } from 'uniswap/src/features/transactions/WarningModal/types' import { WarningModal } from 'wallet/src/components/modals/WarningModal/WarningModal' -import { WarningSeverity } from 'wallet/src/features/transactions/WarningModal/types' export type StorageWarningModalProps = { isOnboarding: boolean @@ -16,14 +16,12 @@ export function StorageWarningModal({ isOnboarding }: StorageWarningModalProps): const { navigateTo } = useExtensionNavigation() const { showStorageWarning, onStorageWarningClose } = useCheckLowStorage({ isOnboarding }) - if (!showStorageWarning) { - return null - } return ( void { const state: SidebarLocationState = args ? { initialTransactionState: initialState } : undefined - navigate(AppRoutes.Transfer, { state }) + navigate(AppRoutes.Send, { state }) }, []) } diff --git a/apps/extension/src/app/navigation/constants.ts b/apps/extension/src/app/navigation/constants.ts index 7ada8b59b50..f1d9da0edf3 100644 --- a/apps/extension/src/app/navigation/constants.ts +++ b/apps/extension/src/app/navigation/constants.ts @@ -21,7 +21,7 @@ export enum AppRoutes { Requests = 'requests', Settings = 'settings', Swap = 'swap', - Transfer = 'transfer', + Send = 'send', } export enum HomeQueryParams { diff --git a/apps/extension/src/app/navigation/index.tsx b/apps/extension/src/app/navigation/index.tsx index 2708834cef6..4da4bb238f3 100644 --- a/apps/extension/src/app/navigation/index.tsx +++ b/apps/extension/src/app/navigation/index.tsx @@ -1,8 +1,7 @@ import { useCallback, useMemo, useRef } from 'react' import { useSelector } from 'react-redux' import { Outlet, useLocation } from 'react-router-dom' -import { DappRequestQueueProvider } from 'src/app/features/dappRequests/DappRequestQueueContext' -import { DappRequestWrapper } from 'src/app/features/dappRequests/DappRequestWrapper' +import { DappRequestQueue } from 'src/app/features/dappRequests/DappRequestQueue' import { HomeScreen } from 'src/app/features/home/HomeScreen' import { Locked } from 'src/app/features/lockScreen/Locked' import { NotificationToastWrapper } from 'src/app/features/notifications/NotificationToastWrapper' @@ -14,7 +13,6 @@ import { AppRoutes } from 'src/app/navigation/constants' import { useRouterState } from 'src/app/navigation/state' import { focusOrCreateOnboardingTab } from 'src/app/navigation/utils' import { isOnboardedSelector } from 'src/app/utils/isOnboardedSelector' -import { ExtensionState } from 'src/store/extensionReducer' import { AnimatePresence, Flex, SpinningLoader, styled } from 'ui/src' import { useIsChromeWindowFocusedWithTimeout } from 'uniswap/src/extension/useIsChromeWindowFocused' import { useAsyncData } from 'utilities/src/react/hooks' @@ -60,7 +58,7 @@ const routeDirections = { [AppRoutes.Requests]: Direction.Right, [AppRoutes.Receive]: Direction.Down, [AppRoutes.Settings]: Direction.Right, - [AppRoutes.Transfer]: Direction.Down, + [AppRoutes.Send]: Direction.Down, } satisfies Record const getAppRouteFromPathName = (pathname: string): AppRoutes | null => { @@ -200,8 +198,6 @@ function LoggedIn(): JSX.Element { **/ const outletContents = Outlet({}) const contents = useConstant(outletContents) - const pendingDappRequests = useSelector((state: ExtensionState) => state.dappRequests.pending) - const areRequestsPending = pendingDappRequests.length > 0 // To avoid excessive API calls, we pause the transaction history updater a short time after the window loses focus. const isChromeWindowFocused = useIsChromeWindowFocusedWithTimeout(30 * ONE_SECOND_MS) @@ -214,11 +210,7 @@ function LoggedIn(): JSX.Element { {isChromeWindowFocused && } - {areRequestsPending && ( - - - - )} + ) } diff --git a/apps/extension/src/app/navigation/utils.ts b/apps/extension/src/app/navigation/utils.ts index f690045e889..178842daea3 100644 --- a/apps/extension/src/app/navigation/utils.ts +++ b/apps/extension/src/app/navigation/utils.ts @@ -4,7 +4,7 @@ import { navigate } from 'src/app/navigation/state' import { onboardingMessageChannel } from 'src/background/messagePassing/messageChannels' import { OnboardingMessageType } from 'src/background/messagePassing/types/ExtensionMessages' import { uniswapUrls } from 'uniswap/src/constants/urls' -import { TransactionState } from 'uniswap/src/features/transactions/transactionState/types' +import { TransactionState } from 'uniswap/src/features/transactions/types/transactionState' import { logger } from 'utilities/src/logger/logger' import { escapeRegExp } from 'utilities/src/primitives/string' import { getTokenUrl } from 'wallet/src/utils/linking' diff --git a/apps/extension/src/background/backgroundDappRequests.ts b/apps/extension/src/background/backgroundDappRequests.ts index 12f142cafd3..47e9f920ce3 100644 --- a/apps/extension/src/background/backgroundDappRequests.ts +++ b/apps/extension/src/background/backgroundDappRequests.ts @@ -29,6 +29,7 @@ import { ExtensionEthMethods } from 'src/contentScript/methodHandlers/requestMet import { hexadecimalStringToInt, toSupportedChainId } from 'uniswap/src/features/chains/utils' import { ExtensionEventName } from 'uniswap/src/features/telemetry/constants/extension' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' +import { WindowEthereumRequestProperties } from 'uniswap/src/features/telemetry/types' import { RPCType } from 'uniswap/src/types/chains' import { logger } from 'utilities/src/logger/logger' import { Keyring } from 'wallet/src/features/wallet/Keyring/Keyring' @@ -132,9 +133,25 @@ export function initMessageBridge(): void { }) }) - contentScriptUtilityMessageChannel.addMessageListener(ContentScriptUtilityMessageType.InfoLog, async (message) => { - logger.info(message.fileName, message.functionName, message.message, message.tags) - }) + contentScriptUtilityMessageChannel.addMessageListener( + ContentScriptUtilityMessageType.AnalyticsLog, + async (message) => { + const properties: WindowEthereumRequestProperties = { + method: message.tags?.method ?? '', + dappUrl: message.tags?.dappUrl ?? '', + } + const eventName = message.message + switch (eventName) { + case ExtensionEventName.UnsupportedMethodRequest: + case ExtensionEventName.UnrecognizedMethodRequest: + case ExtensionEventName.DeprecatedMethodRequest: + sendAnalyticsEvent(eventName, properties) + break + default: + break + } + }, + ) contentScriptUtilityMessageChannel.addMessageListener(ContentScriptUtilityMessageType.FocusOnboardingTab, () => { focusOrCreateOnboardingTab().catch((error) => diff --git a/apps/extension/src/background/messagePassing/messageChannels.ts b/apps/extension/src/background/messagePassing/messageChannels.ts index ffadf741f2f..122f4ce21e2 100644 --- a/apps/extension/src/background/messagePassing/messageChannels.ts +++ b/apps/extension/src/background/messagePassing/messageChannels.ts @@ -63,6 +63,8 @@ import { SidebarOpenedMessageSchema, } from 'src/background/messagePassing/types/ExtensionMessages' import { + AnalyticsLog, + AnalyticsLogSchema, BackgroundToSidePanelRequestType, ContentScriptUtilityMessageType, DappRequestMessage, @@ -74,8 +76,6 @@ import { ExtensionToDappRequestType, FocusOnboardingMessage, FocusOnboardingMessageSchema, - InfoLog, - InfoLogSchema, TabActivatedRequest, TabActivatedRequestSchema, UpdateConnectionRequest, @@ -296,7 +296,7 @@ export function createExternalDappMessagePort( type ContentScriptUtilityMessageSchemas = { [ContentScriptUtilityMessageType.FocusOnboardingTab]: FocusOnboardingMessage [ContentScriptUtilityMessageType.ErrorLog]: ErrorLog - [ContentScriptUtilityMessageType.InfoLog]: InfoLog + [ContentScriptUtilityMessageType.AnalyticsLog]: AnalyticsLog } const contentScriptUtilityMessageParsers: MessageParsers< ContentScriptUtilityMessageType, @@ -305,7 +305,7 @@ const contentScriptUtilityMessageParsers: MessageParsers< [ContentScriptUtilityMessageType.FocusOnboardingTab]: (message): FocusOnboardingMessage => FocusOnboardingMessageSchema.parse(message), [ContentScriptUtilityMessageType.ErrorLog]: (message): ErrorLog => ErrorLogSchema.parse(message), - [ContentScriptUtilityMessageType.InfoLog]: (message): InfoLog => InfoLogSchema.parse(message), + [ContentScriptUtilityMessageType.AnalyticsLog]: (message): AnalyticsLog => AnalyticsLogSchema.parse(message), } export function createContentScriptUtilityMessageChannel(): TypedRuntimeMessageChannel< diff --git a/apps/extension/src/background/messagePassing/types/requests.ts b/apps/extension/src/background/messagePassing/types/requests.ts index f9ac4e49b62..f94ec5590a5 100644 --- a/apps/extension/src/background/messagePassing/types/requests.ts +++ b/apps/extension/src/background/messagePassing/types/requests.ts @@ -8,7 +8,7 @@ import { z } from 'zod' export enum ContentScriptUtilityMessageType { FocusOnboardingTab = 'FocusOnboardingTab', ErrorLog = 'Error', - InfoLog = 'Info', + AnalyticsLog = 'AnalyticsLog', } export const ErrorLogSchema = MessageSchema.extend({ @@ -20,14 +20,12 @@ export const ErrorLogSchema = MessageSchema.extend({ }) export type ErrorLog = z.infer -export const InfoLogSchema = MessageSchema.extend({ - type: z.literal(ContentScriptUtilityMessageType.InfoLog), - fileName: z.string(), - functionName: z.string(), +export const AnalyticsLogSchema = MessageSchema.extend({ + type: z.literal(ContentScriptUtilityMessageType.AnalyticsLog), message: z.string(), tags: z.record(z.string()), }) -export type InfoLog = z.infer +export type AnalyticsLog = z.infer export const FocusOnboardingMessageSchema = MessageSchema.extend({ type: z.literal(ContentScriptUtilityMessageType.FocusOnboardingTab), diff --git a/apps/extension/src/contentScript/injected.ts b/apps/extension/src/contentScript/injected.ts index 85ad15cc1cf..84bf0e7816f 100644 --- a/apps/extension/src/contentScript/injected.ts +++ b/apps/extension/src/contentScript/injected.ts @@ -9,10 +9,10 @@ import { } from 'src/background/messagePassing/messageChannels' import { addWindowMessageListener } from 'src/background/messagePassing/messageUtils' import { + AnalyticsLog, ContentScriptUtilityMessageType, ErrorLog, ExtensionToDappRequestType, - InfoLog, } from 'src/background/messagePassing/types/requests' import { ExtensionEthMethodHandler } from 'src/contentScript/methodHandlers/ExtensionEthMethodHandler' import { ProviderDirectMethodHandler } from 'src/contentScript/methodHandlers/ProviderDirectMethodHandler' @@ -36,6 +36,7 @@ import { logger } from 'utilities/src/logger/logger' import { arraysAreEqual } from 'utilities/src/primitives/array' import { walletContextValue } from 'wallet/src/features/wallet/context' +import { ExtensionEventName } from 'uniswap/src/features/telemetry/constants' import { getValidAddress } from 'uniswap/src/utils/addresses' import { ZodError } from 'zod' @@ -161,7 +162,7 @@ addWindowMessageListener(isValidWindowEthereumRequest, as if (isDeprecatedMethod(request.method)) { postDeprecatedMethodError(source, request.requestId, request.method) - await logInfo('injected.ts', 'WindowEthereumRequest', 'Deprecated method', { + await passAnalytics(ExtensionEventName.DeprecatedMethodRequest, { method: request.method, dappUrl, }) @@ -170,7 +171,7 @@ addWindowMessageListener(isValidWindowEthereumRequest, as if (isUnsupportedMethod(request.method)) { postUnknownMethodError(source, request.requestId, request.method) - await logInfo('injected.ts', 'WindowEthereumRequest', 'Unsupported method', { + await passAnalytics(ExtensionEventName.UnsupportedMethodRequest, { method: request.method, dappUrl, }) @@ -178,7 +179,7 @@ addWindowMessageListener(isValidWindowEthereumRequest, as } // Handle any methods we don't know how to handle and are not in the metamask API - await logInfo('injected.ts', 'WindowEthereumRequest', 'Unrecognized method', { + await passAnalytics(ExtensionEventName.UnrecognizedMethodRequest, { method: request.method, dappUrl, }) @@ -250,16 +251,10 @@ async function logError( await contentScriptUtilityMessageChannel.sendMessage(message) } -async function logInfo( - fileName: string, - functionName: string, - message: string, - tags: Record, -): Promise { - const logMessage: InfoLog = { - type: ContentScriptUtilityMessageType.InfoLog, - fileName, - functionName, +// These go to Amplitude instead of Sentry since they are informational +async function passAnalytics(message: string, tags: Record): Promise { + const logMessage: AnalyticsLog = { + type: ContentScriptUtilityMessageType.AnalyticsLog, message, tags, } diff --git a/apps/extension/src/env.d.ts b/apps/extension/src/env.d.ts index fd6eabefe81..e2d3c2d91ed 100644 --- a/apps/extension/src/env.d.ts +++ b/apps/extension/src/env.d.ts @@ -1,8 +1,12 @@ -import { config } from 'ui/src/tamagui.config' +import { config, TamaguiGroupNames } from 'ui/src/tamagui.config' type Conf = typeof config declare module 'tamagui' { // eslint-disable-next-line @typescript-eslint/no-empty-interface interface TamaguiCustomConfig extends Conf {} + + interface TypeOverride { + groupNames(): TamaguiGroupNames + } } diff --git a/apps/extension/src/manifest.json b/apps/extension/src/manifest.json index de5cebb56c9..a2efdcf5d83 100644 --- a/apps/extension/src/manifest.json +++ b/apps/extension/src/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "Uniswap Extension", "description": "The Uniswap Extension is a self-custody crypto wallet that's built for swapping.", - "version": "1.3.0", + "version": "1.5.0", "minimum_chrome_version": "116", "icons": { "16": "assets/icon16.png", diff --git a/apps/extension/src/onboarding/onboarding.tsx b/apps/extension/src/onboarding/onboarding.tsx index a583e37a96b..d05b2d5612a 100644 --- a/apps/extension/src/onboarding/onboarding.tsx +++ b/apps/extension/src/onboarding/onboarding.tsx @@ -1,8 +1,8 @@ // eslint-disable-next-line @typescript-eslint/triple-slash-reference /// +import React from 'react' import { createRoot } from 'react-dom/client' -import { OptionalStrictMode } from 'src/app/components/OptionalStrictMode' import OnboardingApp from 'src/app/OnboardingApp' import { initializeSentry, SentryAppNameTag } from 'src/app/sentry' import { getLocalUserId } from 'src/app/utils/storage' @@ -28,11 +28,10 @@ async function initOnboarding(): Promise { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const container = document.getElementById('onboarding-root')! const root = createRoot(container) - root.render( - + - , + , ) } diff --git a/apps/extension/src/popup/popup.tsx b/apps/extension/src/popup/popup.tsx index 8fff4d84eca..7f208c82264 100644 --- a/apps/extension/src/popup/popup.tsx +++ b/apps/extension/src/popup/popup.tsx @@ -1,8 +1,8 @@ // eslint-disable-next-line @typescript-eslint/triple-slash-reference /// +import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' -import { OptionalStrictMode } from 'src/app/components/OptionalStrictMode' import PopupApp from 'src/app/PopupApp' import { initializeSentry, SentryAppNameTag } from 'src/app/sentry' import { getLocalUserId } from 'src/app/utils/storage' @@ -29,9 +29,9 @@ async function initPopup(): Promise { const root = createRoot(container) root.render( - + - , + , ) } diff --git a/apps/extension/src/sidebar/sidebar.tsx b/apps/extension/src/sidebar/sidebar.tsx index 4d254f4c36e..5af90a80eea 100644 --- a/apps/extension/src/sidebar/sidebar.tsx +++ b/apps/extension/src/sidebar/sidebar.tsx @@ -4,9 +4,9 @@ import 'src/app/utils/devtools' import 'symbol-observable' // Needed by `reduxed-chrome-storage` as polyfill, order matters +import React from 'react' import { createRoot } from 'react-dom/client' import SidebarApp from 'src/app/SidebarApp' -import { OptionalStrictMode } from 'src/app/components/OptionalStrictMode' import { onboardingMessageChannel } from 'src/background/messagePassing/messageChannels' import { OnboardingMessageType } from 'src/background/messagePassing/types/ExtensionMessages' import { initializeReduxStore } from 'src/store/store' @@ -26,11 +26,10 @@ async function initSidebar(): Promise { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const container = window.document.querySelector('#root')! const root = createRoot(container) - root.render( - + - , + , ) } diff --git a/apps/extension/src/store/migrations.test.ts b/apps/extension/src/store/migrations.test.ts index 8194727a13a..8c6b7c93b73 100644 --- a/apps/extension/src/store/migrations.test.ts +++ b/apps/extension/src/store/migrations.test.ts @@ -5,6 +5,7 @@ import { getSchema, initialSchema, v0Schema, + v10Schema, v1Schema, v2Schema, v3Schema, @@ -13,23 +14,30 @@ import { v6Schema, v7Schema, v8Schema, + v9Schema, } from 'src/store/schema' +import { initialFavoritesState } from 'uniswap/src/features/favorites/slice' +import { initialSearchHistoryState } from 'uniswap/src/features/search/searchHistorySlice' +import { initialUserSettingsState } from 'uniswap/src/features/settings/slice' +import { initialTokensState } from 'uniswap/src/features/tokens/slice/slice' +import { initialTransactionsState } from 'uniswap/src/features/transactions/slice' +import { TransactionStatus, TransactionType } from 'uniswap/src/features/transactions/types/transactionDetails' import { UniverseChainId } from 'uniswap/src/types/chains' import { getAllKeysOfNestedObject } from 'utilities/src/primitives/objects' import { initialAppearanceSettingsState } from 'wallet/src/features/appearance/slice' import { initialBehaviorHistoryState } from 'wallet/src/features/behaviorHistory/slice' -import { initialFavoritesState } from 'wallet/src/features/favorites/slice' import { initialFiatCurrencyState } from 'wallet/src/features/fiatCurrency/slice' import { initialLanguageState } from 'wallet/src/features/language/slice' import { initialNotificationsState } from 'wallet/src/features/notifications/slice' -import { initialSearchHistoryState } from 'wallet/src/features/search/searchHistorySlice' -import { initialTokensState } from 'wallet/src/features/tokens/tokensSlice' -import { initialTransactionsState } from 'wallet/src/features/transactions/slice' -import { TransactionStatus, TransactionType } from 'wallet/src/features/transactions/types' import { initialWalletState } from 'wallet/src/features/wallet/slice' import { createMigrate } from 'wallet/src/state/createMigrate' import { HAYDEN_ETH_ADDRESS } from 'wallet/src/state/walletMigrations' -import { testActivatePendingAccounts, testAddedHapticSetting } from 'wallet/src/state/walletMigrationsTests' +import { + testActivatePendingAccounts, + testAddedHapticSetting, + testMovedUserSettings, + testRemoveHoldToSwap, +} from 'wallet/src/state/walletMigrationsTests' expect.extend({ toIncludeSameMembers }) @@ -80,6 +88,7 @@ describe('Redux state migrations', () => { tokenLists: {}, tokens: initialTokensState, transactions: initialTransactionsState, + userSettings: initialUserSettingsState, wallet: initialWalletState, _persist: { version: EXTENSION_STATE_VERSION, @@ -221,4 +230,12 @@ describe('Redux state migrations', () => { expect(v9.behaviorHistory.hasUsedExplore).toBe(false) expect(v9.behaviorHistory.hasViewedWelcomeWalletCard).toBe(false) }) + + it('migrates from v9 to v10', async () => { + testMovedUserSettings(migrations[10], v9Schema) + }) + + it('migrates v10 to v11', async () => { + testRemoveHoldToSwap(migrations[11], v10Schema) + }) }) diff --git a/apps/extension/src/store/migrations.ts b/apps/extension/src/store/migrations.ts index f6fda8d3bb7..3b750fa4b68 100644 --- a/apps/extension/src/store/migrations.ts +++ b/apps/extension/src/store/migrations.ts @@ -9,6 +9,8 @@ import { deleteBetaOnboardingState, deleteDefaultFavoritesFromFavoritesState, deleteExtensionOnboardingState, + deleteHoldToSwapBehaviorHistory, + moveUserSettings, removeUniconV2BehaviorState, removeWalletIsUnlockedState, } from 'wallet/src/state/walletMigrations' @@ -26,6 +28,8 @@ export const migrations = { 7: deleteDefaultFavoritesFromFavoritesState, 8: addHapticSetting, 9: addExploreAndWelcomeBehaviorHistory, + 10: moveUserSettings, + 11: deleteHoldToSwapBehaviorHistory, } -export const EXTENSION_STATE_VERSION = 9 +export const EXTENSION_STATE_VERSION = 11 diff --git a/apps/extension/src/store/schema.ts b/apps/extension/src/store/schema.ts index b6517a6ee9b..2242d5ad78d 100644 --- a/apps/extension/src/store/schema.ts +++ b/apps/extension/src/store/schema.ts @@ -122,4 +122,32 @@ export const v9Schema = { behaviorHistory: { ...v8Schema.behaviorHistory, hasViewedWelcomeWalletCard: false, hasUsedExplore: false }, } -export const getSchema = (): typeof v9Schema => v9Schema +export const v10Schema = { + ...v9Schema, + wallet: { + ...v9Schema.wallet, + settings: { + swapProtection: v9Schema.wallet.settings.swapProtection, + }, + }, + userSettings: { + hideSmallBalances: v9Schema.wallet.settings.hideSmallBalances, + hideSpamTokens: v9Schema.wallet.settings.hideSpamTokens, + }, +} + +const v11SchemaIntermediate = { + ...v10Schema, + behaviorHistory: { + ...v10Schema.behaviorHistory, + hasViewedReviewScreen: undefined, + hasSubmittedHoldToSwap: undefined, + }, +} + +delete v11SchemaIntermediate.behaviorHistory.hasViewedReviewScreen +delete v11SchemaIntermediate.behaviorHistory.hasSubmittedHoldToSwap + +export const v11Schema = v11SchemaIntermediate + +export const getSchema = (): typeof v11Schema => v11Schema diff --git a/apps/extension/tsconfig.json b/apps/extension/tsconfig.json index c87e5f89d74..4ca06406cec 100644 --- a/apps/extension/tsconfig.json +++ b/apps/extension/tsconfig.json @@ -15,6 +15,9 @@ { "path": "../../packages/ui" }, + { + "path": "../../packages/uniswap" + }, { "path": "../../packages/utilities" }, diff --git a/apps/mobile/android/app/build.gradle b/apps/mobile/android/app/build.gradle index e825787fa4b..476fde76bdc 100644 --- a/apps/mobile/android/app/build.gradle +++ b/apps/mobile/android/app/build.gradle @@ -90,6 +90,8 @@ if (isCI && datadogPropertiesAvailable && !isDetox) { apply from: "../../../../node_modules/@datadog/mobile-react-native/datadog-sourcemaps.gradle" } +def currentVersionName = "1.34" + android { ndkVersion rootProject.ext.ndkVersion @@ -137,17 +139,17 @@ android { dev { isDefault(true) applicationIdSuffix ".dev" - versionName "1.33" + versionName currentVersionName dimension "variant" } beta { applicationIdSuffix ".beta" - versionName "1.33" + versionName currentVersionName dimension "variant" } prod { dimension "variant" - versionName "1.33" + versionName currentVersionName } } diff --git a/apps/mobile/android/app/src/main/assets/PendingSend.riv b/apps/mobile/android/app/src/main/assets/PendingSend.riv deleted file mode 100644 index f4e4bd42470..00000000000 Binary files a/apps/mobile/android/app/src/main/assets/PendingSend.riv and /dev/null differ diff --git a/apps/mobile/android/app/src/main/assets/PendingSwap.riv b/apps/mobile/android/app/src/main/assets/PendingSwap.riv deleted file mode 100644 index fa2f5ff9238..00000000000 Binary files a/apps/mobile/android/app/src/main/assets/PendingSwap.riv and /dev/null differ diff --git a/apps/mobile/android/app/src/main/res/raw/pending_send.riv b/apps/mobile/android/app/src/main/res/raw/pending_send.riv deleted file mode 100644 index f4e4bd42470..00000000000 Binary files a/apps/mobile/android/app/src/main/res/raw/pending_send.riv and /dev/null differ diff --git a/apps/mobile/android/app/src/main/res/raw/pending_swap.riv b/apps/mobile/android/app/src/main/res/raw/pending_swap.riv deleted file mode 100644 index fa2f5ff9238..00000000000 Binary files a/apps/mobile/android/app/src/main/res/raw/pending_swap.riv and /dev/null differ diff --git a/apps/mobile/ios/Podfile.lock b/apps/mobile/ios/Podfile.lock index eada28f99d3..83ec0cf3e0c 100644 --- a/apps/mobile/ios/Podfile.lock +++ b/apps/mobile/ios/Podfile.lock @@ -1983,10 +1983,6 @@ PODS: - ReactNativePerformance (4.1.2): - React-Core - RecaptchaInterop (100.0.0) - - rive-react-native (7.0.0): - - React-Core - - RiveRuntime (= 5.10.0) - - RiveRuntime (5.10.0) - RNCAsyncStorage (1.17.10): - React-Core - RNCMaskedView (0.2.9): @@ -2025,7 +2021,19 @@ PODS: - React-Core - RNPermissions (3.6.0): - React-Core - - RNReanimated (3.8.1): + - RNReanimated (3.15.0): + - glog + - RCT-Folly (= 2022.05.16.00) + - React-Core + - ReactCommon/turbomodule/core + - RNReanimated/reanimated (= 3.15.0) + - RNReanimated/worklets (= 3.15.0) + - RNReanimated/reanimated (3.15.0): + - glog + - RCT-Folly (= 2022.05.16.00) + - React-Core + - ReactCommon/turbomodule/core + - RNReanimated/worklets (3.15.0): - glog - RCT-Folly (= 2022.05.16.00) - React-Core @@ -2037,7 +2045,7 @@ PODS: - RNSentry (5.5.0): - React-Core - Sentry/HybridSDK (= 8.7.1) - - RNSVG (13.8.0): + - RNSVG (15.1.0): - React-Core - SDWebImage (5.15.8): - SDWebImage/Core (= 5.15.8) @@ -2049,6 +2057,8 @@ PODS: - SentryPrivate (= 8.7.1) - SentryPrivate (8.7.1) - SocketRocket (0.6.1) + - sparkfabrik-react-native-idfa-aaid (1.2.0): + - React - UIImageColors (2.1.0) - Yoga (1.14.0) - ZXingObjC/Core (3.6.9) @@ -2151,7 +2161,6 @@ DEPENDENCIES: - React-utils (from `../../../node_modules/react-native/ReactCommon/react/utils`) - ReactCommon/turbomodule/core (from `../../../node_modules/react-native/ReactCommon`) - "ReactNativePerformance (from `../../../node_modules/@shopify/react-native-performance`)" - - rive-react-native (from `../../../node_modules/rive-react-native`) - "RNCAsyncStorage (from `../../../node_modules/@react-native-async-storage/async-storage`)" - "RNCMaskedView (from `../../../node_modules/@react-native-masked-view/masked-view`)" - RNDeviceInfo (from `../../../node_modules/react-native-device-info`) @@ -2169,6 +2178,7 @@ DEPENDENCIES: - RNScreens (from `../../../node_modules/react-native-screens`) - "RNSentry (from `../../../node_modules/@sentry/react-native`)" - RNSVG (from `../../../node_modules/react-native-svg`) + - "sparkfabrik-react-native-idfa-aaid (from `../../../node_modules/@sparkfabrik/react-native-idfa-aaid`)" - UIImageColors (= 2.1.0) - Yoga (from `../../../node_modules/react-native/ReactCommon/yoga`) @@ -2209,7 +2219,6 @@ SPEC REPOS: - PLCrashReporter - PromisesObjC - RecaptchaInterop - - RiveRuntime - SDWebImage - SDWebImageWebPCoder - Sentry @@ -2390,8 +2399,6 @@ EXTERNAL SOURCES: :path: "../../../node_modules/react-native/ReactCommon" ReactNativePerformance: :path: "../../../node_modules/@shopify/react-native-performance" - rive-react-native: - :path: "../../../node_modules/rive-react-native" RNCAsyncStorage: :path: "../../../node_modules/@react-native-async-storage/async-storage" RNCMaskedView: @@ -2426,6 +2433,8 @@ EXTERNAL SOURCES: :path: "../../../node_modules/@sentry/react-native" RNSVG: :path: "../../../node_modules/react-native-svg" + sparkfabrik-react-native-idfa-aaid: + :path: "../../../node_modules/@sparkfabrik/react-native-idfa-aaid" Yoga: :path: "../../../node_modules/react-native/ReactCommon/yoga" @@ -2550,8 +2559,6 @@ SPEC CHECKSUMS: ReactCommon: 2aa35648354bd4c4665b9a5084a7d37097b89c10 ReactNativePerformance: ab7dee4c4862623d72c1530a9fc71b55458edf71 RecaptchaInterop: 7d1a4a01a6b2cb1610a47ef3f85f0c411434cb21 - rive-react-native: 125db990f050d72c76aa37dc6c5cfaaf89f66086 - RiveRuntime: a859cd24f1100d924a5229567228063dd8a19a93 RNCAsyncStorage: 0c357f3156fcb16c8589ede67cc036330b6698ca RNCMaskedView: 949696f25ec596bfc697fc88e6f95cf0c79669b6 RNDeviceInfo: 0a7c1d2532aa7691f9b9925a27e43af006db4dae @@ -2565,15 +2572,16 @@ SPEC CHECKSUMS: RNImageColors: 9ac05083b52d5c350e6972650ae3ba0e556466c1 RNLocalize: d4b8af4e442d4bcca54e68fc687a2129b4d71a81 RNPermissions: de7b7c3fe1680d974ac7a85e3e97aa539c0e68ea - RNReanimated: 8763d306762d558ebc0df4cbf67128dcadfa6299 + RNReanimated: 7171bba9a3f9ecfe5bdccb04ea0063bcc6c4c12c RNScreens: b6b64d956af3715adbfe84808694ae82d3fec74f RNSentry: 4fb2cd7d2d6cb94423c24884488206ef881da136 - RNSVG: c1e76b81c76cdcd34b4e1188852892dc280eb902 + RNSVG: 50cf2c7018e57cf5d3522d98d0a3a4dd6bf9d093 SDWebImage: cb032eba469c54e0000e78bcb0a13cdde0a52798 SDWebImageWebPCoder: 908b83b6adda48effe7667cd2b7f78c897e5111d Sentry: 11776f6a25a128808d793d0d41bb7ad873b5ae4f SentryPrivate: b3c448eacdabe9eab7679a2e0af609c608f91572 SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 + sparkfabrik-react-native-idfa-aaid: 1b72a6264a2175473e309ffa6434db87c58af264 UIImageColors: d2ef3b0877d203cbb06489eeb78ea8b7788caabe Yoga: 805bf71192903b20fc14babe48080582fee65a80 ZXingObjC: 8898711ab495761b2dbbdec76d90164a6d7e14c5 diff --git a/apps/mobile/ios/RiveAssets/pending_send.riv b/apps/mobile/ios/RiveAssets/pending_send.riv deleted file mode 100644 index f4e4bd42470..00000000000 Binary files a/apps/mobile/ios/RiveAssets/pending_send.riv and /dev/null differ diff --git a/apps/mobile/ios/RiveAssets/pending_swap.riv b/apps/mobile/ios/RiveAssets/pending_swap.riv deleted file mode 100644 index fa2f5ff9238..00000000000 Binary files a/apps/mobile/ios/RiveAssets/pending_swap.riv and /dev/null differ diff --git a/apps/mobile/ios/Uniswap.xcodeproj/project.pbxproj b/apps/mobile/ios/Uniswap.xcodeproj/project.pbxproj index c7829057860..ce942e7b29b 100644 --- a/apps/mobile/ios/Uniswap.xcodeproj/project.pbxproj +++ b/apps/mobile/ios/Uniswap.xcodeproj/project.pbxproj @@ -146,8 +146,6 @@ 2F50877AC4F0BB2556A74B60 /* libPods-Uniswap-UniswapTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 89A1B8962666C68EE8B75C18 /* libPods-Uniswap-UniswapTests.a */; }; 5EFB78362B1E585000E77EAC /* ConvertQuery.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5EFB78352B1E585000E77EAC /* ConvertQuery.graphql.swift */; }; 5FF6D300AEE2EB390A272D0E /* libPods-WidgetIntentExtension.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 71A42CE7FF1299C666E6FC79 /* libPods-WidgetIntentExtension.a */; }; - 681301B22A3726EE00A5BF43 /* pending_send.riv in Resources */ = {isa = PBXBuildFile; fileRef = 681301AE2A3726EE00A5BF43 /* pending_send.riv */; }; - 681301B42A3726EE00A5BF43 /* pending_swap.riv in Resources */ = {isa = PBXBuildFile; fileRef = 681301B02A3726EE00A5BF43 /* pending_swap.riv */; }; 6BC7D07E2B5FF02400617C95 /* ScantasticEncryption.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BC7D07B2B5FF02400617C95 /* ScantasticEncryption.m */; }; 6BC7D07F2B5FF02400617C95 /* ScantasticEncryption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BC7D07C2B5FF02400617C95 /* ScantasticEncryption.swift */; }; 6BC7D0802B5FF02400617C95 /* EncryptionUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BC7D07D2B5FF02400617C95 /* EncryptionUtils.swift */; }; @@ -458,8 +456,6 @@ 56FE9C9AF785221B7E3F4C04 /* Pods-Uniswap.dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Uniswap.dev.xcconfig"; path = "Target Support Files/Pods-Uniswap/Pods-Uniswap.dev.xcconfig"; sourceTree = ""; }; 5EFB78352B1E585000E77EAC /* ConvertQuery.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConvertQuery.graphql.swift; sourceTree = ""; }; 62CEA9F2D5176D20A6402A3E /* Pods-Uniswap.beta.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Uniswap.beta.xcconfig"; path = "Target Support Files/Pods-Uniswap/Pods-Uniswap.beta.xcconfig"; sourceTree = ""; }; - 681301AE2A3726EE00A5BF43 /* pending_send.riv */ = {isa = PBXFileReference; lastKnownFileType = file; path = pending_send.riv; sourceTree = ""; }; - 681301B02A3726EE00A5BF43 /* pending_swap.riv */ = {isa = PBXFileReference; lastKnownFileType = file; path = pending_swap.riv; sourceTree = ""; }; 6BC7D07B2B5FF02400617C95 /* ScantasticEncryption.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScantasticEncryption.m; sourceTree = ""; }; 6BC7D07C2B5FF02400617C95 /* ScantasticEncryption.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScantasticEncryption.swift; sourceTree = ""; }; 6BC7D07D2B5FF02400617C95 /* EncryptionUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EncryptionUtils.swift; sourceTree = ""; }; @@ -921,7 +917,6 @@ 8E566D9F2AA1095000D4AA76 /* Components */, 07B067692A7D6EC8001DD9B9 /* Widget */, 03DD298C2A4CE34B00E3E0F5 /* Appearance */, - E3C8C9DD291C4D2C000E00EA /* RiveAssets */, F35AFD3627EE49230011A725 /* Uniswap.entitlements */, 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 9FEC9B8A2A858CF1003CD019 /* AppDelegate.m */, @@ -1177,15 +1172,6 @@ path = Pods; sourceTree = ""; }; - E3C8C9DD291C4D2C000E00EA /* RiveAssets */ = { - isa = PBXGroup; - children = ( - 681301AE2A3726EE00A5BF43 /* pending_send.riv */, - 681301B02A3726EE00A5BF43 /* pending_swap.riv */, - ); - path = RiveAssets; - sourceTree = ""; - }; F35AFD3C27EE49990011A725 /* OneSignalNotificationServiceExtension */ = { isa = PBXGroup; children = ( @@ -1470,8 +1456,6 @@ A32F9FBD272343C9002CFCDB /* GoogleService-Info.plist in Resources */, 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 77CF6065C8A24FE48204A2C1 /* SplashScreen.storyboard in Resources */, - 681301B42A3726EE00A5BF43 /* pending_swap.riv in Resources */, - 681301B22A3726EE00A5BF43 /* pending_send.riv in Resources */, AC0EE0982BD826E700BCCF07 /* PrivacyInfo.xcprivacy in Resources */, AEE498F72A85AD86000DDF8E /* Basel-Book.ttf in Resources */, 0767E02F2A61BBDC0042ADA2 /* Basel-Regular.otf in Resources */, @@ -2205,7 +2189,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 1.34; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; @@ -2258,7 +2242,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 1.34; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = schemes.WidgetsCore; @@ -2311,7 +2295,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 1.34; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = schemes.WidgetsCore; @@ -2364,7 +2348,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 1.34; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = schemes.WidgetsCore; @@ -2402,7 +2386,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 1.34; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; @@ -2438,7 +2422,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 1.34; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = schemes.WidgetsCoreTests; @@ -2473,7 +2457,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 1.34; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = schemes.WidgetsCoreTests; @@ -2508,7 +2492,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 1.34; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = schemes.WidgetsCoreTests; @@ -2555,7 +2539,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.33; + MARKETING_VERSION = 1.34; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; @@ -2601,7 +2585,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.33; + MARKETING_VERSION = 1.34; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.widgets; @@ -2647,7 +2631,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.33; + MARKETING_VERSION = 1.34; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.dev.widgets; @@ -2693,7 +2677,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.33; + MARKETING_VERSION = 1.34; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.beta.widgets; @@ -2735,7 +2719,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.33; + MARKETING_VERSION = 1.34; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; @@ -2778,7 +2762,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.33; + MARKETING_VERSION = 1.34; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.WidgetIntentExtension; @@ -2821,7 +2805,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.33; + MARKETING_VERSION = 1.34; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.dev.WidgetIntentExtension; @@ -2864,7 +2848,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.33; + MARKETING_VERSION = 1.34; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.beta.WidgetIntentExtension; @@ -2900,7 +2884,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.33; + MARKETING_VERSION = 1.34; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -2938,7 +2922,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.33; + MARKETING_VERSION = 1.34; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -3018,11 +3002,7 @@ ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = "$(inherited)"; OTHER_CPLUSPLUSFLAGS = "$(inherited)"; - OTHER_LDFLAGS = ( - "$(inherited)", - "-Wl", - "-ld_classic", - ); + OTHER_LDFLAGS = "$(inherited)"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../../../node_modules/react-native"; SDKROOT = iphoneos; USE_HERMES = true; @@ -3085,11 +3065,7 @@ MTL_ENABLE_DEBUG_INFO = NO; OTHER_CFLAGS = "$(inherited)"; OTHER_CPLUSPLUSFLAGS = "$(inherited)"; - OTHER_LDFLAGS = ( - "$(inherited)", - "-Wl", - "-ld_classic", - ); + OTHER_LDFLAGS = "$(inherited)"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../../../node_modules/react-native"; SDKROOT = iphoneos; USE_HERMES = true; @@ -3124,7 +3100,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.33; + MARKETING_VERSION = 1.34; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; @@ -3168,7 +3144,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.33; + MARKETING_VERSION = 1.34; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.OneSignalNotificationServiceExtension; @@ -3239,11 +3215,7 @@ MTL_ENABLE_DEBUG_INFO = NO; OTHER_CFLAGS = "$(inherited)"; OTHER_CPLUSPLUSFLAGS = "$(inherited)"; - OTHER_LDFLAGS = ( - "$(inherited)", - "-Wl", - "-ld_classic", - ); + OTHER_LDFLAGS = "$(inherited)"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../../../node_modules/react-native"; SDKROOT = iphoneos; USE_HERMES = true; @@ -3272,7 +3244,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.33; + MARKETING_VERSION = 1.34; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -3343,7 +3315,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.33; + MARKETING_VERSION = 1.34; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.beta.OneSignalNotificationServiceExtension; @@ -3414,11 +3386,7 @@ MTL_ENABLE_DEBUG_INFO = NO; OTHER_CFLAGS = "$(inherited)"; OTHER_CPLUSPLUSFLAGS = "$(inherited)"; - OTHER_LDFLAGS = ( - "$(inherited)", - "-Wl", - "-ld_classic", - ); + OTHER_LDFLAGS = "$(inherited)"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../../../node_modules/react-native"; SDKROOT = iphoneos; USE_HERMES = true; @@ -3447,7 +3415,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.33; + MARKETING_VERSION = 1.34; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -3518,7 +3486,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.33; + MARKETING_VERSION = 1.34; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.dev.OneSignalNotificationServiceExtension; diff --git a/apps/mobile/jest-setup.js b/apps/mobile/jest-setup.js index 8fdc2757570..3a5fff1b2af 100644 --- a/apps/mobile/jest-setup.js +++ b/apps/mobile/jest-setup.js @@ -10,6 +10,8 @@ import { localizeMock as mockRNLocalize } from 'react-native-localize/mock' import { TextDecoder, TextEncoder } from 'util' import { AppearanceSettingType } from 'wallet/src/features/appearance/slice' import { mockLocalizationContext } from 'wallet/src/test/mocks/utils' +import { mockSharedPersistQueryClientProvider } from 'uniswap/src/test/mocks/mockSharedPersistQueryClientProvider' +import { mockUIAssets } from 'ui/src/test/mocks/mockUIAssets' global.TextEncoder = TextEncoder global.TextDecoder = TextDecoder @@ -124,3 +126,7 @@ jest.mock('wallet/src/features/appearance/hooks', () => { }) jest.mock('openai') + +jest.mock('uniswap/src/data/apiClients/SharedPersistQueryClientProvider', () => mockSharedPersistQueryClientProvider) + +mockUIAssets() diff --git a/apps/mobile/package.json b/apps/mobile/package.json index d48d1849931..fc5f20dcf89 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -84,6 +84,7 @@ "@shopify/react-native-performance": "4.1.2", "@shopify/react-native-performance-navigation": "3.0.0", "@shopify/react-native-skia": "1.2.0", + "@sparkfabrik/react-native-idfa-aaid": "1.2.0", "@uniswap/analytics": "1.7.0", "@uniswap/analytics-events": "2.36.0", "@uniswap/ethers-rs-mobile": "0.0.5", @@ -133,7 +134,7 @@ "react-native-onesignal": "4.5.2", "react-native-pager-view": "6.0.1", "react-native-permissions": "3.6.0", - "react-native-reanimated": "3.8.1", + "react-native-reanimated": "3.15.0", "react-native-restart": "0.0.27", "react-native-safe-area-context": "4.9.0", "react-native-screens": "3.30.1", @@ -149,7 +150,6 @@ "redux-mock-store": "1.5.4", "redux-persist": "6.0.0", "redux-saga": "1.2.2", - "rive-react-native": "7.0.0", "typed-redux-saga": "1.5.0", "uniswap": "workspace:^", "utilities": "workspace:^", @@ -164,8 +164,7 @@ "@datadog/datadog-ci": "2.39.0", "@faker-js/faker": "7.6.0", "@storybook/react": "7.0.2", - "@tamagui/babel-plugin": "1.108.2", - "@testing-library/react-hooks": "7.0.2", + "@tamagui/babel-plugin": "1.108.4", "@testing-library/react-native": "11.5.0", "@types/redux-mock-store": "1.0.6", "@uniswap/eslint-config": "workspace:^", diff --git a/apps/mobile/src/app/App.tsx b/apps/mobile/src/app/App.tsx index f4ea522ccd1..6966d851d36 100644 --- a/apps/mobile/src/app/App.tsx +++ b/apps/mobile/src/app/App.tsx @@ -1,10 +1,16 @@ import { ApolloProvider } from '@apollo/client' -import { DatadogProvider, DatadogProviderConfiguration, DdRum, SdkVerbosity } from '@datadog/mobile-react-native' +import { + DatadogProvider, + DatadogProviderConfiguration, + DdRum, + DdSdkReactNative, + SdkVerbosity, +} from '@datadog/mobile-react-native' import { BottomSheetModalProvider } from '@gorhom/bottom-sheet' import * as Sentry from '@sentry/react-native' import { PerformanceProfiler, RenderPassReport } from '@shopify/react-native-performance' import { MMKVWrapper } from 'apollo3-cache-persist' -import { PropsWithChildren, default as React, StrictMode, useCallback, useEffect } from 'react' +import { PropsWithChildren, default as React, StrictMode, useCallback, useEffect, useState } from 'react' import { I18nextProvider } from 'react-i18next' import { LogBox, NativeModules, StatusBar } from 'react-native' import appsFlyer from 'react-native-appsflyer' @@ -43,10 +49,15 @@ import { getSentryEnvironment, getSentryTracesSamplingRate, getStatsigEnvironmen import { flexStyles, useHapticFeedback, useIsDarkMode } from 'ui/src' import { config } from 'uniswap/src/config' import { uniswapUrls } from 'uniswap/src/constants/urls' +import { selectFavoriteTokens } from 'uniswap/src/features/favorites/selectors' import { DUMMY_STATSIG_SDK_KEY, StatsigCustomAppValue } from 'uniswap/src/features/gating/constants' import { Experiments } from 'uniswap/src/features/gating/experiments' import { FeatureFlags, WALLET_FEATURE_FLAG_NAMES, getFeatureFlagName } from 'uniswap/src/features/gating/flags' -import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' +import { + getFeatureFlagWithExposureLoggingDisabled, + useFeatureFlag, + useFeatureFlagWithExposureLoggingDisabled, +} from 'uniswap/src/features/gating/hooks' import { loadStatsigOverrides } from 'uniswap/src/features/gating/overrides/customPersistedOverrides' import { Statsig, StatsigOptions, StatsigProvider, StatsigUser } from 'uniswap/src/features/gating/sdk/statsig' import Trace from 'uniswap/src/features/telemetry/Trace' @@ -56,6 +67,7 @@ import { UnitagUpdaterContextProvider } from 'uniswap/src/features/unitags/conte import i18n from 'uniswap/src/i18n/i18n' import { CurrencyId } from 'uniswap/src/types/currency' import { isDetoxBuild, isJestRun } from 'utilities/src/environment/constants' +import { attachUnhandledRejectionHandler } from 'utilities/src/logger/Datadog' import { registerConsoleOverrides } from 'utilities/src/logger/console' import { logger } from 'utilities/src/logger/logger' import { useAsyncData } from 'utilities/src/react/hooks' @@ -67,13 +79,13 @@ import { usePersistedApolloClient } from 'wallet/src/data/apollo/usePersistedApo import { initFirebaseAppCheck } from 'wallet/src/features/appCheck' import { useCurrentAppearanceSetting } from 'wallet/src/features/appearance/hooks' import { selectHapticsEnabled } from 'wallet/src/features/appearance/slice' -import { selectFavoriteTokens } from 'wallet/src/features/favorites/selectors' import { useAppFiatCurrencyInfo } from 'wallet/src/features/fiatCurrency/hooks' import { LocalizationContextProvider } from 'wallet/src/features/language/LocalizationContext' import { useCurrentLanguageInfo } from 'wallet/src/features/language/hooks' import { syncAppWithDeviceLanguage } from 'wallet/src/features/language/slice' import { clearNotificationQueue } from 'wallet/src/features/notifications/slice' import { TransactionHistoryUpdater } from 'wallet/src/features/transactions/TransactionHistoryUpdater' +import { WalletUniswapProvider } from 'wallet/src/features/transactions/contexts/WalletUniswapContext' import { Account } from 'wallet/src/features/wallet/accounts/types' import { WalletContextProvider } from 'wallet/src/features/wallet/context' import { useAccounts } from 'wallet/src/features/wallet/hooks' @@ -125,6 +137,15 @@ datadogConfig.site = 'US1' datadogConfig.longTaskThresholdMs = 100 datadogConfig.nativeCrashReportEnabled = true datadogConfig.verbosity = SdkVerbosity.INFO +// Datadog does not expose event type, hence we can not type return +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +datadogConfig.errorEventMapper = (event) => { + // this is Sentry error, which is caused by the not complete closing of their SDK + if (event.message.includes('Native is disabled')) { + return null + } + return event +} // Log boxes on simulators can block detox tap event when they cover buttons placed at // the bottom of the screen and cause tests to fail. @@ -137,14 +158,33 @@ initAppsFlyer() initFirebaseAppCheck() function App(): JSX.Element | null { + // Here Statsig is not yet initialised + const [isDatadogEnabled, setIsDatadogEnabled] = useState(false) + useEffect(() => { + if (!__DEV__ && !isDetoxBuild && isDatadogEnabled) { + // We can not use both Datadog and Sentry because their error catchers conflict. + // We need to wait until Statsig loads feature flags to chose Datadog or Sentry. + // If we initialise Sentry async - some of its features do not work properly (for some reason) + // Hence we always initiliase and later close it if Datadog is enabled. + Sentry.close().catch(() => undefined) + attachUnhandledRejectionHandler() + } + }, [isDatadogEnabled]) + // We want to ensure deviceID is used as the identifier to link with analytics const fetchAndSetDeviceId = useCallback(async () => { const uniqueId = await getUniqueId() - Sentry.setUser({ - id: uniqueId, - }) + if (isDatadogEnabled) { + DdSdkReactNative.setUser({ + id: uniqueId, + }).catch(() => undefined) + } else { + Sentry.setUser({ + id: uniqueId, + }) + } return uniqueId - }, []) + }, [isDatadogEnabled]) const deviceId = useAsyncData(fetchAndSetDeviceId).data @@ -161,7 +201,10 @@ function App(): JSX.Element | null { api: uniswapUrls.statsigProxyUrl, disableAutoMetricsLogging: true, disableErrorLogging: true, - initCompletionCallback: loadStatsigOverrides, + initCompletionCallback: () => { + loadStatsigOverrides() + setIsDatadogEnabled(Statsig.checkGate(getFeatureFlagName(FeatureFlags.Datadog))) + }, }, sdkKey: DUMMY_STATSIG_SDK_KEY, user: { @@ -200,7 +243,7 @@ function App(): JSX.Element | null { } function DatadogProviderWrapper({ children }: PropsWithChildren): JSX.Element { - const datadogEnabled = useFeatureFlag(FeatureFlags.Datadog) + const datadogEnabled = useFeatureFlagWithExposureLoggingDisabled(FeatureFlags.Datadog) if (isDetoxBuild || isJestRun || !datadogEnabled) { return <>{children} @@ -210,10 +253,9 @@ function DatadogProviderWrapper({ children }: PropsWithChildren): JSX.Element { function SentryTags({ children }: PropsWithChildren): JSX.Element { useEffect(() => { - const isDatadogEnabled = Statsig.checkGateWithExposureLoggingDisabled(getFeatureFlagName(FeatureFlags.Datadog)) + const isDatadogEnabled = getFeatureFlagWithExposureLoggingDisabled(FeatureFlags.Datadog) for (const [_, flagKey] of WALLET_FEATURE_FLAG_NAMES.entries()) { - Sentry.setTag(`featureFlag.${flagKey}`, Statsig.checkGateWithExposureLoggingDisabled(flagKey)) if (isDatadogEnabled) { DdRum.addFeatureFlagEvaluation( // Datadog has a limited set of accepted symbols in feature flags @@ -221,14 +263,12 @@ function SentryTags({ children }: PropsWithChildren): JSX.Element { flagKey.replaceAll('-', '_'), Statsig.checkGateWithExposureLoggingDisabled(flagKey), ).catch(() => undefined) + } else { + Sentry.setTag(`featureFlag.${flagKey}`, Statsig.checkGateWithExposureLoggingDisabled(flagKey)) } } for (const experiment of Object.values(Experiments)) { - Sentry.setTag( - `experiment.${experiment}`, - Statsig.getExperimentWithExposureLoggingDisabled(experiment).getGroupName(), - ) if (isDatadogEnabled) { DdRum.addFeatureFlagEvaluation( // Datadog has a limited set of accepted symbols in feature flags @@ -236,6 +276,11 @@ function SentryTags({ children }: PropsWithChildren): JSX.Element { `experiment_${experiment.replaceAll('-', '_')}`, Statsig.getExperimentWithExposureLoggingDisabled(experiment).getGroupName(), ).catch(() => undefined) + } else { + Sentry.setTag( + `experiment.${experiment}`, + Statsig.getExperimentWithExposureLoggingDisabled(experiment).getGroupName(), + ) } } }, []) @@ -281,12 +326,14 @@ function AppOuter(): JSX.Element | null { > - - - - - - + + + + + + + + diff --git a/apps/mobile/src/app/hooks.test.ts b/apps/mobile/src/app/hooks.test.ts deleted file mode 100644 index a7c575d4e8d..00000000000 --- a/apps/mobile/src/app/hooks.test.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { renderHook } from '@testing-library/react-hooks' -import { LayoutChangeEvent } from 'react-native' -import { act } from 'react-test-renderer' -import { useShouldShowNativeKeyboard } from 'src/app/hooks' - -describe(useShouldShowNativeKeyboard, () => { - it('returns false if layout calculation is pending', () => { - const { result } = renderHook(() => useShouldShowNativeKeyboard()) - - expect(result.current.showNativeKeyboard).toBe(false) - }) - - it('returns isLayoutPending as true if layout calculation is pending', () => { - const { result } = renderHook(() => useShouldShowNativeKeyboard()) - - expect(result.current.isLayoutPending).toBe(true) - }) - - it("shouldn't show native keyboard if decimal pad is rendered below the input panel", async () => { - const { result } = renderHook(() => useShouldShowNativeKeyboard()) - - await act(async () => { - result.current.onInputPanelLayout({ - nativeEvent: { layout: { height: 100 } }, - } as LayoutChangeEvent) - result.current.onDecimalPadLayout({ - nativeEvent: { layout: { y: 200 } }, - } as LayoutChangeEvent) - }) - - expect(result.current.showNativeKeyboard).toBe(false) - expect(result.current.maxContentHeight).toBeDefined() - expect(result.current.isLayoutPending).toBe(false) - }) - - it('should show native keyboard if decimal pad is rendered above the input panel', async () => { - const { result } = renderHook(() => useShouldShowNativeKeyboard()) - - await act(async () => { - result.current.onInputPanelLayout({ - nativeEvent: { layout: { height: 100 } }, - } as LayoutChangeEvent) - result.current.onDecimalPadLayout({ - nativeEvent: { layout: { y: 50 } }, - } as LayoutChangeEvent) - }) - - expect(result.current.showNativeKeyboard).toBe(true) - expect(result.current.maxContentHeight).not.toBeDefined() - expect(result.current.isLayoutPending).toBe(false) - }) -}) diff --git a/apps/mobile/src/app/hooks.ts b/apps/mobile/src/app/hooks.ts index 463915935cd..7a60cf8f553 100644 --- a/apps/mobile/src/app/hooks.ts +++ b/apps/mobile/src/app/hooks.ts @@ -1,46 +1,5 @@ import { useFocusEffect } from '@react-navigation/core' import { useCallback, useRef, useState } from 'react' -import { LayoutChangeEvent } from 'react-native' -import { spacing } from 'ui/src/theme' - -const MIN_INPUT_DECIMAL_PAD_GAP = spacing.spacing8 - -export function useShouldShowNativeKeyboard(): { - onInputPanelLayout: (event: LayoutChangeEvent) => void - onDecimalPadLayout: (event: LayoutChangeEvent) => void - isLayoutPending: boolean - showNativeKeyboard: boolean - maxContentHeight?: number -} { - const [containerHeight, setContainerHeight] = useState() - const [decimalPadY, setDecimalPadY] = useState() - - const onInputPanelLayout = (event: LayoutChangeEvent): void => { - if (containerHeight === undefined) { - setContainerHeight(event.nativeEvent.layout.height) - } - } - - const onDecimalPadLayout = (event: LayoutChangeEvent): void => { - if (decimalPadY === undefined) { - setDecimalPadY(event.nativeEvent.layout.y) - } - } - - const isLayoutPending = containerHeight === undefined || decimalPadY === undefined - - // If decimal pad renders below the input panel, we need to show the native keyboard - const showNativeKeyboard = isLayoutPending ? false : containerHeight + MIN_INPUT_DECIMAL_PAD_GAP > decimalPadY - - return { - onInputPanelLayout, - onDecimalPadLayout, - isLayoutPending, - showNativeKeyboard, - // can be used to imitate flexGrow=1 for the input panel - maxContentHeight: isLayoutPending || showNativeKeyboard ? undefined : decimalPadY - MIN_INPUT_DECIMAL_PAD_GAP, - } -} const getNativeComponentKey = (): string => `native-component-${Math.random().toString()}` diff --git a/apps/mobile/src/app/migrations.test.ts b/apps/mobile/src/app/migrations.test.ts index 79961ee70dd..df0b5125b9f 100644 --- a/apps/mobile/src/app/migrations.test.ts +++ b/apps/mobile/src/app/migrations.test.ts @@ -73,6 +73,9 @@ import { v6Schema, v70Schema, v71Schema, + v72Schema, + v73Schema, + v74Schema, v7Schema, v8Schema, v9Schema, @@ -85,27 +88,34 @@ import { initialModalsState } from 'src/features/modals/modalSlice' import { initialTweaksState } from 'src/features/tweaks/slice' import { initialWalletConnectState } from 'src/features/walletConnect/walletConnectSlice' import { AccountType } from 'uniswap/src/features/accounts/types' +import { initialFavoritesState } from 'uniswap/src/features/favorites/slice' +import { initialSearchHistoryState } from 'uniswap/src/features/search/searchHistorySlice' +import { initialUserSettingsState } from 'uniswap/src/features/settings/slice' import { ModalName } from 'uniswap/src/features/telemetry/constants' +import { initialTokensState } from 'uniswap/src/features/tokens/slice/slice' +import { initialTransactionsState } from 'uniswap/src/features/transactions/slice' +import { TransactionStatus, TransactionType } from 'uniswap/src/features/transactions/types/transactionDetails' +import { transactionDetails } from 'uniswap/src/test/fixtures' import { UniverseChainId, WalletChainId } from 'uniswap/src/types/chains' import { getAllKeysOfNestedObject } from 'utilities/src/primitives/objects' import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants' import { initialAppearanceSettingsState } from 'wallet/src/features/appearance/slice' import { initialBehaviorHistoryState } from 'wallet/src/features/behaviorHistory/slice' -import { initialFavoritesState } from 'wallet/src/features/favorites/slice' import { initialFiatCurrencyState } from 'wallet/src/features/fiatCurrency/slice' import { initialLanguageState } from 'wallet/src/features/language/slice' import { initialNotificationsState } from 'wallet/src/features/notifications/slice' -import { initialSearchHistoryState } from 'wallet/src/features/search/searchHistorySlice' import { initialTelemetryState } from 'wallet/src/features/telemetry/slice' -import { initialTokensState } from 'wallet/src/features/tokens/tokensSlice' -import { initialTransactionsState } from 'wallet/src/features/transactions/slice' -import { TransactionStatus, TransactionType } from 'wallet/src/features/transactions/types' import { Account, SignerMnemonicAccount } from 'wallet/src/features/wallet/accounts/types' import { initialWalletState, SwapProtectionSetting } from 'wallet/src/features/wallet/slice' import { createMigrate } from 'wallet/src/state/createMigrate' import { HAYDEN_ETH_ADDRESS } from 'wallet/src/state/walletMigrations' -import { testActivatePendingAccounts, testAddedHapticSetting } from 'wallet/src/state/walletMigrationsTests' -import { fiatPurchaseTransactionInfo, signerMnemonicAccount, transactionDetails } from 'wallet/src/test/fixtures' +import { + testActivatePendingAccounts, + testAddedHapticSetting, + testMovedUserSettings, + testRemoveHoldToSwap, +} from 'wallet/src/state/walletMigrationsTests' +import { signerMnemonicAccount } from 'wallet/src/test/fixtures' expect.extend({ toIncludeSameMembers }) @@ -114,14 +124,17 @@ const account = signerMnemonicAccount() const txDetailsConfirmed = transactionDetails({ status: TransactionStatus.Success, }) -const fiatOnRampTxDetailsFailed = transactionDetails({ - status: TransactionStatus.Failed, - typeInfo: fiatPurchaseTransactionInfo({ +const fiatOnRampTxDetailsFailed = { + ...transactionDetails({ + status: TransactionStatus.Failed, + }), + typeInfo: { + type: TransactionType.FiatPurchaseDeprecated, explorerUrl: 'https://buy-sandbox.moonpay.com/transaction_receipt?transactionId=d6c32bb5-7cd9-4c22-8f46-6bbe786c599f', id: 'd6c32bb5-7cd9-4c22-8f46-6bbe786c599f', - }), -}) + }, +} describe('Redux state migrations', () => { it('is able to perform all migrations starting from the initial schema', async () => { @@ -175,6 +188,7 @@ describe('Redux state migrations', () => { tokens: initialTokensState, transactions: initialTransactionsState, tweaks: initialTweaksState, + userSettings: initialUserSettingsState, wallet: initialWalletState, walletConnect: initialWalletConnectState, _persist: { @@ -923,7 +937,7 @@ describe('Redux state migrations', () => { }, // expect this payload to change typeInfo: { - type: TransactionType.FiatPurchase, + type: TransactionType.FiatPurchaseDeprecated, explorerUrl: 'explorer', outputTokenAddress: '0xtokenAddress', outputCurrencyAmountFormatted: 50, @@ -935,7 +949,7 @@ describe('Redux state migrations', () => { hash: '0x123', } const expectedTypeInfo = { - type: TransactionType.FiatPurchase, + type: TransactionType.FiatPurchaseDeprecated, explorerUrl: 'explorer', inputCurrency: undefined, inputCurrencyAmount: 25, @@ -1457,4 +1471,75 @@ describe('Redux state migrations', () => { expect(v72.behaviorHistory.hasViewedWelcomeWalletCard).toBe(false) expect(v72.behaviorHistory.hasUsedExplore).toBe(false) }) + + it('migrates from v72 to v73', async () => { + testMovedUserSettings(migrations[73], v72Schema) + }) + + it('migrates from v73 to v74', () => { + const oldFiatOnRampTxDetails = { + chainId: UniverseChainId.Mainnet, + id: '0', + from: account.address, + options: { + request: {}, + }, + typeInfo: { + type: TransactionType.FiatPurchaseDeprecated, + explorerUrl: 'explorer', + inputCurrencyAmount: 25, + outputSymbol: 'USDC', + }, + status: TransactionStatus.Pending, + addedTime: 1487076708000, + hash: '0x123', + } + const transactions = { + [account.address]: { + [UniverseChainId.Mainnet]: { + '0': oldFiatOnRampTxDetails, + '1': txDetailsConfirmed, + }, + [UniverseChainId.Goerli]: { + '0': oldFiatOnRampTxDetails, + '1': { + ...oldFiatOnRampTxDetails, + typeInfo: { + ...oldFiatOnRampTxDetails.typeInfo, + type: TransactionType.Send, + }, + }, + '2': { + ...oldFiatOnRampTxDetails, + typeInfo: { + ...oldFiatOnRampTxDetails.typeInfo, + type: TransactionType.Receive, + }, + }, + '3': txDetailsConfirmed, + }, + }, + } + const v73Stub = { ...v73Schema, transactions } + + const v74 = migrations[74](v73Stub) + + expect(v74.transactions[account.address][UniverseChainId.Mainnet]['0']).toBe(undefined) + expect(v74.transactions[account.address][UniverseChainId.Mainnet]['1']).toEqual(txDetailsConfirmed) + + expect(v74.transactions[account.address][UniverseChainId.Goerli]['0']).toBe(undefined) + expect(v74.transactions[account.address][UniverseChainId.Goerli]['1'].typeInfo).toEqual({ + ...oldFiatOnRampTxDetails.typeInfo, + type: TransactionType.Send, + }) + expect(v74.transactions[account.address][UniverseChainId.Goerli]['2'].typeInfo).toEqual({ + ...oldFiatOnRampTxDetails.typeInfo, + type: TransactionType.Receive, + }) + expect(v74.transactions[account.address][UniverseChainId.Goerli]['3']).toEqual(txDetailsConfirmed) + }) + + it('migrates from v74 to v75', () => { + testRemoveHoldToSwap(migrations[75], v74Schema) + }) }) diff --git a/apps/mobile/src/app/migrations.ts b/apps/mobile/src/app/migrations.ts index f1ef425fe3a..b82be69e39c 100644 --- a/apps/mobile/src/app/migrations.ts +++ b/apps/mobile/src/app/migrations.ts @@ -7,12 +7,16 @@ import dayjs from 'dayjs' import { AccountType } from 'uniswap/src/features/accounts/types' import { toSupportedChainId } from 'uniswap/src/features/chains/utils' import { ModalName } from 'uniswap/src/features/telemetry/constants' +import { TransactionsState } from 'uniswap/src/features/transactions/slice' +import { + ChainIdToTxIdToDetails, + TransactionStatus, + TransactionType, +} from 'uniswap/src/features/transactions/types/transactionDetails' import { UniverseChainId, WalletChainId } from 'uniswap/src/types/chains' import { initialFiatCurrencyState } from 'wallet/src/features/fiatCurrency/slice' import { initialLanguageState } from 'wallet/src/features/language/slice' import { getNFTAssetKey } from 'wallet/src/features/nfts/utils' -import { TransactionStateMap } from 'wallet/src/features/transactions/slice' -import { ChainIdToTxIdToDetails, TransactionStatus, TransactionType } from 'wallet/src/features/transactions/types' import { Account } from 'wallet/src/features/wallet/accounts/types' import { SwapProtectionSetting } from 'wallet/src/features/wallet/slice' import { @@ -23,6 +27,8 @@ import { deleteBetaOnboardingState, deleteDefaultFavoritesFromFavoritesState, deleteExtensionOnboardingState, + deleteHoldToSwapBehaviorHistory, + moveUserSettings, removeUniconV2BehaviorState, removeWalletIsUnlockedState, } from 'wallet/src/state/walletMigrations' @@ -296,34 +302,31 @@ export const migrations = { { byChainId: {} }, ) - const transactionState: TransactionStateMap | undefined = newState?.transactions - const newTransactionState = Object.keys(transactionState ?? {}).reduce( - (tempState, address) => { - const txs = transactionState?.[address] - if (!txs) { - return tempState - } - - const newAddressTxState = Object.keys(txs).reduce((tempAddressState, chainIdString) => { - const chainId = toSupportedChainId(chainIdString) - if (!chainId) { - return tempAddressState - } + const transactionState: TransactionsState | undefined = newState?.transactions + const newTransactionState = Object.keys(transactionState ?? {}).reduce((tempState, address) => { + const txs = transactionState?.[address] + if (!txs) { + return tempState + } - const txInfo = txs[chainId] - if (!txInfo) { - return tempAddressState - } + const newAddressTxState = Object.keys(txs).reduce((tempAddressState, chainIdString) => { + const chainId = toSupportedChainId(chainIdString) + if (!chainId) { + return tempAddressState + } - tempAddressState[chainId] = txInfo + const txInfo = txs[chainId] + if (!txInfo) { return tempAddressState - }, {}) + } - tempState[address] = newAddressTxState - return tempState - }, - {}, - ) + tempAddressState[chainId] = txInfo + return tempAddressState + }, {}) + + tempState[address] = newAddressTxState + return tempState + }, {}) return { ...newState, @@ -439,7 +442,7 @@ export const migrations = { continue } - if (txDetails.typeInfo.type !== TransactionType.FiatPurchase) { + if (txDetails.typeInfo.type !== TransactionType.FiatPurchaseDeprecated) { newTransactionState[address] ??= {} newTransactionState[address][chainId] ??= {} newTransactionState[address][chainId][txId] = txDetails @@ -461,7 +464,7 @@ export const migrations = { } = txDetails.typeInfo const newTypeInfo = { - type: TransactionType.FiatPurchase, + type: TransactionType.FiatPurchaseDeprecated, explorerUrl, inputCurrency: undefined, inputCurrencyAmount: outputCurrencyAmountFormatted / outputCurrencyAmountPrice, @@ -557,7 +560,8 @@ export const migrations = { newTransactionState[address] ??= {} newTransactionState[address][chainId] ??= {} newTransactionState[address][chainId][txId] = - txDetails.typeInfo.type === TransactionType.FiatPurchase && txDetails.status === TransactionStatus.Failed + txDetails.typeInfo.type === TransactionType.FiatPurchaseDeprecated && + txDetails.status === TransactionStatus.Failed ? { ...txDetails, typeInfo: { @@ -906,6 +910,32 @@ export const migrations = { 71: addHapticSetting, 72: addExploreAndWelcomeBehaviorHistory, + + 73: moveUserSettings, + + 74: function deleteOldOnRampTxData(state: any) { + const newState = { ...state } + + const transactionsState = newState.transactions + + const addresses = Object.keys(transactionsState ?? {}) + for (const address of addresses) { + const chainIds = Object.keys(transactionsState[address] ?? {}) + for (const chainId of chainIds) { + const transactions = transactionsState[address][chainId] + const txIds = Object.keys(transactions ?? {}) + for (const txId of txIds) { + if (transactions[txId]?.typeInfo?.type === TransactionType.FiatPurchaseDeprecated) { + delete transactionsState[address][chainId][txId] + } + } + } + } + + return { ...newState, transactions: transactionsState } + }, + + 75: deleteHoldToSwapBehaviorHistory, } -export const MOBILE_STATE_VERSION = 72 +export const MOBILE_STATE_VERSION = 75 diff --git a/apps/mobile/src/app/modals/AccountSwitcherModal.test.tsx b/apps/mobile/src/app/modals/AccountSwitcherModal.test.tsx index 9c9f94bf8d5..243bbda2ee0 100644 --- a/apps/mobile/src/app/modals/AccountSwitcherModal.test.tsx +++ b/apps/mobile/src/app/modals/AccountSwitcherModal.test.tsx @@ -3,8 +3,8 @@ import { AccountSwitcher } from 'src/app/modals/AccountSwitcherModal' import { preloadedMobileState, preloadedModalsState } from 'src/test/fixtures' import { cleanup, render } from 'src/test/test-utils' import { ModalName } from 'uniswap/src/features/telemetry/constants' +import { noOpFunction } from 'utilities/src/test/utils' import { ACCOUNT } from 'wallet/src/test/fixtures' -import { noOpFunction } from 'wallet/src/test/mocks' const preloadedState = preloadedMobileState({ account: ACCOUNT, @@ -13,7 +13,7 @@ const preloadedState = preloadedMobileState({ }), }) -// TODO [MOB-259]: Figure out how to do snapshot tests when there is a BottomSheetModal +// TODO [MOB-259]: Figure out how to do snapshot tests when there is a Modal describe(AccountSwitcher, () => { it('renders correctly', async () => { const tree = render(, { preloadedState }) diff --git a/apps/mobile/src/app/modals/AccountSwitcherModal.tsx b/apps/mobile/src/app/modals/AccountSwitcherModal.tsx index 9166937c2ad..6e86a69a08e 100644 --- a/apps/mobile/src/app/modals/AccountSwitcherModal.tsx +++ b/apps/mobile/src/app/modals/AccountSwitcherModal.tsx @@ -12,7 +12,7 @@ import { Button, Flex, Text, TouchableArea, useDeviceInsets, useSporeColors } fr import { useDeviceDimensions } from 'ui/src/hooks/useDeviceDimensions' import { spacing } from 'ui/src/theme' import { ActionSheetModal, MenuItemProp } from 'uniswap/src/components/modals/ActionSheetModal' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' import { AccountType } from 'uniswap/src/features/accounts/types' import { ElementName, ModalName, WalletEventName } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' @@ -35,8 +35,8 @@ export function AccountSwitcherModal(): JSX.Element { const colors = useSporeColors() return ( - dispatch(closeModal({ name: ModalName.AccountSwitcher }))} > @@ -47,13 +47,13 @@ export function AccountSwitcherModal(): JSX.Element { }} /> - + ) } /** * Exported for testing only. - * TODO [MOB-259] Once testing works with the BottomSheetModal stop exporting this component. + * TODO [MOB-259] Once testing works with the Modal stop exporting this component. */ export function AccountSwitcher({ onClose }: { onClose: () => void }): JSX.Element | null { const insets = useDeviceInsets() diff --git a/apps/mobile/src/app/modals/AppModals.tsx b/apps/mobile/src/app/modals/AppModals.tsx index 005668f9205..87e035a4f7c 100644 --- a/apps/mobile/src/app/modals/AppModals.tsx +++ b/apps/mobile/src/app/modals/AppModals.tsx @@ -1,12 +1,14 @@ import React, { useCallback } from 'react' import { useDispatch } from 'react-redux' import { AccountSwitcherModal } from 'src/app/modals/AccountSwitcherModal' +import { BackupReminderModal } from 'src/app/modals/BackupReminderModal' import { ExperimentsModal } from 'src/app/modals/ExperimentsModal' import { ExploreModal } from 'src/app/modals/ExploreModal' +import { KoreaCexTransferInfoModal } from 'src/app/modals/KoreaCexTransferInfoModal' +import { LazyModalRenderer } from 'src/app/modals/LazyModalRenderer' +import { SendTokenModal } from 'src/app/modals/SendTokenModal' import { SwapModal } from 'src/app/modals/SwapModal' -import { TransferTokenModal } from 'src/app/modals/TransferTokenModal' import { ViewOnlyExplainerModal } from 'src/app/modals/ViewOnlyExplainerModal' -import { LazyModalRenderer } from 'src/app/modals/utils' import { RemoveWalletModal } from 'src/components/RemoveWallet/RemoveWalletModal' import { WalletConnectModals } from 'src/components/Requests/WalletConnectModals' import { RestoreWalletModal } from 'src/components/RestoreWalletModal/RestoreWalletModal' @@ -32,6 +34,10 @@ export function AppModals(): JSX.Element { return ( <> + + + + @@ -65,7 +71,7 @@ export function AppModals(): JSX.Element { - + @@ -99,6 +105,10 @@ export function AppModals(): JSX.Element { + + + + ) } diff --git a/apps/mobile/src/app/modals/BackupReminderModal.tsx b/apps/mobile/src/app/modals/BackupReminderModal.tsx new file mode 100644 index 00000000000..4e2b5e19bcb --- /dev/null +++ b/apps/mobile/src/app/modals/BackupReminderModal.tsx @@ -0,0 +1,83 @@ +import { useState } from 'react' +import { useTranslation } from 'react-i18next' +import { useDispatch } from 'react-redux' +import { navigate } from 'src/app/navigation/rootNavigation' +import { closeModal } from 'src/features/modals/modalSlice' +import { LockPreviewImage } from 'src/features/onboarding/LockPreviewImage' +import { Button, Flex, Text } from 'ui/src' +import { Modal } from 'uniswap/src/components/modals/Modal' +import { ModalName } from 'uniswap/src/features/telemetry/constants' +import { WarningSeverity } from 'uniswap/src/features/transactions/WarningModal/types' +import { ImportType, OnboardingEntryPoint } from 'uniswap/src/types/onboarding' +import { MobileScreens, OnboardingScreens } from 'uniswap/src/types/screens/mobile' +import { WarningModal } from 'wallet/src/components/modals/WarningModal/WarningModal' +import { setBackupReminderLastSeenTs } from 'wallet/src/features/behaviorHistory/slice' + +export function BackupReminderModal(): JSX.Element { + const { t } = useTranslation() + const dispatch = useDispatch() + const [isShowingWarningModal, setIsShowingWarningModal] = useState(false) + + const showWarningModal = (): void => { + setIsShowingWarningModal(true) + } + + const hideWarningModal = (): void => { + setIsShowingWarningModal(false) + } + + const onClose = (): void => { + dispatch(setBackupReminderLastSeenTs(Date.now())) + dispatch(closeModal({ name: ModalName.BackupReminder })) + } + + const onPressBackup = (): void => { + navigate(MobileScreens.OnboardingStack, { + screen: OnboardingScreens.Backup, + params: { importType: ImportType.BackupOnly, entryPoint: OnboardingEntryPoint.BackupCard }, + }) + onClose() + } + + return !isShowingWarningModal ? ( + + + + + {t('onboarding.backup.reminder.title')} + + {t('onboarding.backup.reminder.description')} + + + + + + + + + ) : ( + + ) +} diff --git a/apps/mobile/src/app/modals/ExperimentsModal.tsx b/apps/mobile/src/app/modals/ExperimentsModal.tsx index 201347e2a80..2b5654a16dc 100644 --- a/apps/mobile/src/app/modals/ExperimentsModal.tsx +++ b/apps/mobile/src/app/modals/ExperimentsModal.tsx @@ -9,7 +9,7 @@ import { setCustomEndpoint } from 'src/features/tweaks/slice' import { Accordion, Button, Flex, Text, useDeviceInsets } from 'ui/src' import { spacing } from 'ui/src/theme' import { TextInput } from 'uniswap/src/components/input/TextInput' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' import { ModalName } from 'uniswap/src/features/telemetry/constants' import { AccordionHeader, GatingOverrides } from 'wallet/src/components/gating/GatingOverrides' @@ -42,7 +42,7 @@ export function ExperimentsModal(): JSX.Element { } return ( - - + ) } diff --git a/apps/mobile/src/app/modals/ExploreModal.tsx b/apps/mobile/src/app/modals/ExploreModal.tsx index fcd7fda8845..61e31623ec9 100644 --- a/apps/mobile/src/app/modals/ExploreModal.tsx +++ b/apps/mobile/src/app/modals/ExploreModal.tsx @@ -3,7 +3,7 @@ import { useDispatch } from 'react-redux' import { ExploreStackNavigator } from 'src/app/navigation/navigation' import { closeModal } from 'src/features/modals/modalSlice' import { useSporeColors } from 'ui/src' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' import { ModalName } from 'uniswap/src/features/telemetry/constants' export function ExploreModal(): JSX.Element { @@ -15,7 +15,7 @@ export function ExploreModal(): JSX.Element { } return ( - - + ) } diff --git a/apps/mobile/src/app/modals/KoreaCexTransferInfoModal.tsx b/apps/mobile/src/app/modals/KoreaCexTransferInfoModal.tsx new file mode 100644 index 00000000000..4fb371eb3e1 --- /dev/null +++ b/apps/mobile/src/app/modals/KoreaCexTransferInfoModal.tsx @@ -0,0 +1,53 @@ +import React from 'react' +import { useTranslation } from 'react-i18next' +import { useDispatch } from 'react-redux' +import { Action } from 'redux' +import { closeModal } from 'src/features/modals/modalSlice' +import { Button, Flex, Image, Text, useIsDarkMode, useSporeColors } from 'ui/src' +import { CEX_TRANSFER_MODAL_BG_DARK, CEX_TRANSFER_MODAL_BG_LIGHT } from 'ui/src/assets' +import { Modal } from 'uniswap/src/components/modals/Modal' +import { uniswapUrls } from 'uniswap/src/constants/urls' +import { ModalName } from 'uniswap/src/features/telemetry/constants' +import { openURL } from 'uniswap/src/utils/link' + +const BG_IMAGE_MAX_HEIGHT = 80 + +export function KoreaCexTransferInfoModal(): JSX.Element { + const dispatch = useDispatch() + const color = useSporeColors() + const { t } = useTranslation() + const isDarkMode = useIsDarkMode() + + return ( + dispatch(closeModal({ name: ModalName.KoreaCexTransferInfoModal }))} + > + + + + + + {t('fiatOnRamp.cexTransferModal.title')} + + {t('fiatOnRamp.cexTransferModal.description')} + + + + + + ) +} diff --git a/apps/mobile/src/app/modals/utils.test.tsx b/apps/mobile/src/app/modals/LazyModalRenderer.test.tsx similarity index 94% rename from apps/mobile/src/app/modals/utils.test.tsx rename to apps/mobile/src/app/modals/LazyModalRenderer.test.tsx index 41824d74b93..74e92081eb4 100644 --- a/apps/mobile/src/app/modals/utils.test.tsx +++ b/apps/mobile/src/app/modals/LazyModalRenderer.test.tsx @@ -1,6 +1,6 @@ import React from 'react' import { Text } from 'react-native' -import { LazyModalRenderer } from 'src/app/modals/utils' +import { LazyModalRenderer } from 'src/app/modals/LazyModalRenderer' import { preloadedMobileState, preloadedModalsState } from 'src/test/fixtures' import { renderWithProviders } from 'src/test/render' import { ModalName } from 'uniswap/src/features/telemetry/constants' diff --git a/apps/mobile/src/app/modals/utils.tsx b/apps/mobile/src/app/modals/LazyModalRenderer.tsx similarity index 55% rename from apps/mobile/src/app/modals/utils.tsx rename to apps/mobile/src/app/modals/LazyModalRenderer.tsx index 65328ec0c50..f9fab34f1ea 100644 --- a/apps/mobile/src/app/modals/utils.tsx +++ b/apps/mobile/src/app/modals/LazyModalRenderer.tsx @@ -1,6 +1,8 @@ -import { useSelector } from 'react-redux' +import { useDispatch, useSelector } from 'react-redux' import { ModalsState } from 'src/features/modals/ModalsState' +import { closeModal } from 'src/features/modals/modalSlice' import { selectModalState } from 'src/features/modals/selectModalState' +import { ErrorBoundary } from 'wallet/src/components/ErrorBoundary/ErrorBoundary' /** * Delays evaluating `children` until modal is open @@ -10,10 +12,14 @@ import { selectModalState } from 'src/features/modals/selectModalState' export function LazyModalRenderer({ name, children, + disableErrorBoundary = false, }: { name: keyof ModalsState children: JSX.Element + disableErrorBoundary?: boolean }): JSX.Element | null { + const dispatch = useDispatch() + const modalState = useSelector(selectModalState(name)) if (!modalState.isOpen) { @@ -21,5 +27,13 @@ export function LazyModalRenderer({ return null } - return children + if (disableErrorBoundary) { + return children + } + + return ( + dispatch(closeModal({ name }))}> + {children} + + ) } diff --git a/apps/mobile/src/app/modals/SendTokenModal.tsx b/apps/mobile/src/app/modals/SendTokenModal.tsx new file mode 100644 index 00000000000..c2ea9077109 --- /dev/null +++ b/apps/mobile/src/app/modals/SendTokenModal.tsx @@ -0,0 +1,6 @@ +import React from 'react' +import { SendFlow } from 'src/features/send/SendFlow' + +export function SendTokenModal(): JSX.Element { + return +} diff --git a/apps/mobile/src/app/modals/SwapModal.tsx b/apps/mobile/src/app/modals/SwapModal.tsx index 58c33ecf4f8..2a0340a0ec9 100644 --- a/apps/mobile/src/app/modals/SwapModal.tsx +++ b/apps/mobile/src/app/modals/SwapModal.tsx @@ -7,9 +7,8 @@ import { selectModalState } from 'src/features/modals/selectModalState' import { useWalletRestore } from 'src/features/wallet/hooks' import { ModalName } from 'uniswap/src/features/telemetry/constants' import { updateSwapStartTimestamp } from 'uniswap/src/features/timing/slice' -import { SwapFlow } from 'wallet/src/features/transactions/swap/SwapFlow' +import { WalletSwapFlow } from 'wallet/src/features/transactions/swap/WalletSwapFlow' import { useSwapPrefilledState } from 'wallet/src/features/transactions/swap/hooks/useSwapPrefilledState' -import { useActiveAccountWithThrow } from 'wallet/src/features/wallet/hooks' export function SwapModal(): JSX.Element { const appDispatch = useDispatch() @@ -30,12 +29,10 @@ export function SwapModal(): JSX.Element { const { requiredForTransactions: requiresBiometrics } = useBiometricAppSettings() const { trigger: biometricsTrigger } = useBiometricPrompt() - const account = useActiveAccountWithThrow() return ( - } - account={account} authTrigger={requiresBiometrics ? biometricsTrigger : undefined} openWalletRestoreModal={openWalletRestoreModal} prefilledState={swapPrefilledState} diff --git a/apps/mobile/src/app/modals/TransferTokenModal.tsx b/apps/mobile/src/app/modals/TransferTokenModal.tsx deleted file mode 100644 index fe78578df73..00000000000 --- a/apps/mobile/src/app/modals/TransferTokenModal.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import React, { useCallback } from 'react' -import { useDispatch, useSelector } from 'react-redux' -import { closeModal } from 'src/features/modals/modalSlice' -import { selectModalState } from 'src/features/modals/selectModalState' -import { TransferFlow } from 'src/features/transactions/transfer/TransferFlow' -import { TransferFlow as TransferFlowRewrite } from 'src/features/transactions/transfer/transferRewrite/TransferFlow' -import { useSporeColors } from 'ui/src' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' -import { FeatureFlags } from 'uniswap/src/features/gating/flags' -import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' -import { ModalName } from 'uniswap/src/features/telemetry/constants' - -export function TransferTokenModal(): JSX.Element { - const colors = useSporeColors() - const appDispatch = useDispatch() - const modalState = useSelector(selectModalState(ModalName.Send)) - - const onClose = useCallback((): void => { - appDispatch(closeModal({ name: ModalName.Send })) - }, [appDispatch]) - - const isSendRewriteEnabled = useFeatureFlag(FeatureFlags.SendRewrite) - - return isSendRewriteEnabled ? ( - - ) : ( - - - - ) -} diff --git a/apps/mobile/src/app/modals/ViewOnlyExplainerModal.tsx b/apps/mobile/src/app/modals/ViewOnlyExplainerModal.tsx index 5266bad6bd3..c401d103807 100644 --- a/apps/mobile/src/app/modals/ViewOnlyExplainerModal.tsx +++ b/apps/mobile/src/app/modals/ViewOnlyExplainerModal.tsx @@ -5,7 +5,7 @@ import { closeModal, openModal } from 'src/features/modals/modalSlice' import { Button, Flex, Text, useIsDarkMode } from 'ui/src' import ViewOnlyWalletDark from 'ui/src/assets/graphics/view-only-wallet-dark.svg' import ViewOnlyWalletLight from 'ui/src/assets/graphics/view-only-wallet-light.svg' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' import { ModalName } from 'uniswap/src/features/telemetry/constants' import { ImportType, OnboardingEntryPoint } from 'uniswap/src/types/onboarding' import { MobileScreens, OnboardingScreens } from 'uniswap/src/types/screens/mobile' @@ -39,7 +39,7 @@ export function ViewOnlyExplainerModal(): JSX.Element { const WalletImage = isDarkMode ? ViewOnlyWalletDark : ViewOnlyWalletLight return ( - + @@ -69,6 +69,6 @@ export function ViewOnlyExplainerModal(): JSX.Element { - + ) } diff --git a/apps/mobile/src/app/modals/__snapshots__/AccountSwitcherModal.test.tsx.snap b/apps/mobile/src/app/modals/__snapshots__/AccountSwitcherModal.test.tsx.snap index afa1023a9c4..f668cc06697 100644 --- a/apps/mobile/src/app/modals/__snapshots__/AccountSwitcherModal.test.tsx.snap +++ b/apps/mobile/src/app/modals/__snapshots__/AccountSwitcherModal.test.tsx.snap @@ -21,6 +21,7 @@ exports[`AccountSwitcher renders correctly 1`] = ` } > > = ({ children, on const initialRoute = navigationRef.getCurrentRoute()?.name as MobileAppScreen setRouteName(initialRoute) - DdRumReactNavigationTracking.startTrackingViews(navigationRef.current) + if (!__DEV__) { + DdRumReactNavigationTracking.startTrackingViews(navigationRef.current) + } }} onStateChange={(): void => { const previousRouteName = routeName diff --git a/apps/mobile/src/app/navigation/types.ts b/apps/mobile/src/app/navigation/types.ts index b56fef04414..4ef29b403ec 100644 --- a/apps/mobile/src/app/navigation/types.ts +++ b/apps/mobile/src/app/navigation/types.ts @@ -19,6 +19,10 @@ type NFTItemScreenParams = { fallbackData?: NFTItem } +export type BackupFormParams = { + address: Address +} + export type CloudBackupFormParams = { address: Address password: string @@ -83,10 +87,8 @@ export type SharedUnitagScreenParams = { export type OnboardingStackParamList = { [OnboardingScreens.AppLoading]: undefined - [OnboardingScreens.BackupManual]: OnboardingStackBaseParams - [OnboardingScreens.BackupCloudPasswordCreate]: { - address: Address - } & OnboardingStackBaseParams + [OnboardingScreens.BackupManual]: BackupFormParams & OnboardingStackBaseParams + [OnboardingScreens.BackupCloudPasswordCreate]: BackupFormParams & OnboardingStackBaseParams [OnboardingScreens.BackupCloudPasswordConfirm]: CloudBackupFormParams & OnboardingStackBaseParams [OnboardingScreens.BackupCloudProcessing]: CloudBackupFormParams & OnboardingStackBaseParams [OnboardingScreens.Backup]: OnboardingStackBaseParams diff --git a/apps/mobile/src/app/schema.ts b/apps/mobile/src/app/schema.ts index 6bab1f72ea0..90c159f3253 100644 --- a/apps/mobile/src/app/schema.ts +++ b/apps/mobile/src/app/schema.ts @@ -548,6 +548,36 @@ export const v72Schema = { }, } +export const v73Schema = { + ...v72Schema, + wallet: { + ...v72Schema.wallet, + settings: { + swapProtection: v72Schema.wallet.settings.swapProtection, + }, + }, + userSettings: { + hideSmallBalances: v72Schema.wallet.settings.hideSmallBalances, + hideSpamTokens: v72Schema.wallet.settings.hideSpamTokens, + }, +} + +export const v74Schema = { ...v73Schema } + +const v75SchemaIntermediate = { + ...v74Schema, + behaviorHistory: { + ...v74Schema.behaviorHistory, + hasViewedReviewScreen: undefined, + hasSubmittedHoldToSwap: undefined, + }, +} + +delete v75SchemaIntermediate.behaviorHistory.hasViewedReviewScreen +delete v75SchemaIntermediate.behaviorHistory.hasSubmittedHoldToSwap + +export const v75Schema = v75SchemaIntermediate + // TODO: [MOB-201] use function with typed output when API reducers are removed from rootReducer // export const getSchema = (): RootState => v0Schema -export const getSchema = (): typeof v72Schema => v72Schema +export const getSchema = (): typeof v75Schema => v75Schema diff --git a/apps/mobile/src/components/NFT/NftView.tsx b/apps/mobile/src/components/NFT/NftView.tsx index 2884773ec21..6707be4e1b1 100644 --- a/apps/mobile/src/components/NFT/NftView.tsx +++ b/apps/mobile/src/components/NFT/NftView.tsx @@ -23,6 +23,7 @@ export function NftView({ tokenId: item.tokenId, owner, isSpam: item.isSpam, + showNotification: true, }) return ( diff --git a/apps/mobile/src/components/PriceExplorer/PriceExplorerAnimatedNumber.tsx b/apps/mobile/src/components/PriceExplorer/PriceExplorerAnimatedNumber.tsx index a1b303195d8..cfa5669fd41 100644 --- a/apps/mobile/src/components/PriceExplorer/PriceExplorerAnimatedNumber.tsx +++ b/apps/mobile/src/components/PriceExplorer/PriceExplorerAnimatedNumber.tsx @@ -13,8 +13,7 @@ import Animated, { } from 'react-native-reanimated' import { ValueAndFormattedWithAnimation } from 'src/components/PriceExplorer/usePrice' import { PriceNumberOfDigits } from 'src/components/PriceExplorer/usePriceHistory' -import { useSporeColors } from 'ui/src' -import { TextLoaderWrapper } from 'ui/src/components/text/Text' +import { TextLoaderWrapper, useSporeColors } from 'ui/src' import { fonts } from 'ui/src/theme' import { FiatCurrencyInfo } from 'uniswap/src/features/fiatOnRamp/types' import { TestID } from 'uniswap/src/test/fixtures/testIDs' diff --git a/apps/mobile/src/components/PriceExplorer/__snapshots__/Text.test.tsx.snap b/apps/mobile/src/components/PriceExplorer/__snapshots__/Text.test.tsx.snap index bb0ea151f03..6c6beeda549 100644 --- a/apps/mobile/src/components/PriceExplorer/__snapshots__/Text.test.tsx.snap +++ b/apps/mobile/src/components/PriceExplorer/__snapshots__/Text.test.tsx.snap @@ -293,10 +293,10 @@ exports[`RelativeChangeText renders loading state 1`] = ` style={ { "backgroundColor": "#F9F9F9", - "borderBottomLeftRadius": 4, - "borderBottomRightRadius": 4, - "borderTopLeftRadius": 4, - "borderTopRightRadius": 4, + "borderBottomLeftRadius": 999999, + "borderBottomRightRadius": 999999, + "borderTopLeftRadius": 999999, + "borderTopRightRadius": 999999, "bottom": "5%", "flexDirection": "column", "left": 0, @@ -326,8 +326,8 @@ exports[`RelativeChangeText renders without error 1`] = ` > + {currentScreenState === ScannerModalState.ScanQr && ( )} @@ -100,6 +95,6 @@ export function RecipientScanModal({ onSelectRecipient, onClose }: Props): JSX.E - + ) } diff --git a/apps/mobile/src/components/RecipientSelect/RecipientSelect.tsx b/apps/mobile/src/components/RecipientSelect/RecipientSelect.tsx index 4da3106a9a8..c941c1e2acc 100644 --- a/apps/mobile/src/components/RecipientSelect/RecipientSelect.tsx +++ b/apps/mobile/src/components/RecipientSelect/RecipientSelect.tsx @@ -7,7 +7,6 @@ import { Flex, Text, TouchableArea, useSporeColors } from 'ui/src' import ScanQRIcon from 'ui/src/assets/icons/scan.svg' import { AnimatedFlex } from 'ui/src/components/layout/AnimatedFlex' import { iconSizes } from 'ui/src/theme' -import { useBottomSheetContext } from 'uniswap/src/components/modals/BottomSheetContext' import { TestID } from 'uniswap/src/test/fixtures/testIDs' import { WalletChainId } from 'uniswap/src/types/chains' import { RecipientList } from 'wallet/src/components/RecipientSearch/RecipientList' @@ -21,6 +20,8 @@ interface RecipientSelectProps { recipient?: string focusInput?: boolean chainId?: WalletChainId + renderedInModal?: boolean + hideBackButton?: boolean } function QRScannerIconButton({ onPress }: { onPress: () => void }): JSX.Element { @@ -39,9 +40,10 @@ export function _RecipientSelect({ recipient, focusInput, chainId, + renderedInModal, + hideBackButton, }: RecipientSelectProps): JSX.Element { const { t } = useTranslation() - const { isSheetReady } = useBottomSheetContext() const inputRef = useRef(null) const [pattern, setPattern] = useState('') @@ -83,16 +85,19 @@ export function _RecipientSelect({ return ( <> - - - - {t('send.recipient.header')} - - + + {!renderedInModal && ( + + + {t('send.recipient.header')} + + + )} } + hideBackButton={hideBackButton} placeholder={t('send.recipient.input.placeholder')} value={pattern ?? ''} onBack={recipient ? onHideRecipientSelector : undefined} @@ -108,7 +113,7 @@ export function _RecipientSelect({ ) : ( // Show either suggested recipients or filtered sections based on query - isSheetReady && + )} {showQRScanner && } diff --git a/apps/mobile/src/components/RecipientSelect/hooks.test.ts b/apps/mobile/src/components/RecipientSelect/hooks.test.ts index 4a23d96d482..9de94f44f01 100644 --- a/apps/mobile/src/components/RecipientSelect/hooks.test.ts +++ b/apps/mobile/src/components/RecipientSelect/hooks.test.ts @@ -3,19 +3,14 @@ import { waitFor } from '@testing-library/react-native' import { toIncludeSameMembers } from 'jest-extended' import { MobileState } from 'src/app/mobileReducer' import { renderHookWithProviders } from 'src/test/render' +import { TransactionsState } from 'uniswap/src/features/transactions/slice' +import { TransactionStatus } from 'uniswap/src/features/transactions/types/transactionDetails' +import { sendTokenTransactionInfo, transactionDetails } from 'uniswap/src/test/fixtures' import { UniverseChainId, WalletChainId } from 'uniswap/src/types/chains' import { useRecipients } from 'wallet/src/components/RecipientSearch/hooks' import { SearchableRecipient } from 'wallet/src/features/address/types' -import { TransactionStateMap } from 'wallet/src/features/transactions/slice' -import { TransactionStatus } from 'wallet/src/features/transactions/types' import { SwapProtectionSetting } from 'wallet/src/features/wallet/slice' -import { - SAMPLE_SEED_ADDRESS_1, - SAMPLE_SEED_ADDRESS_2, - sendTokenTransactionInfo, - signerMnemonicAccount, - transactionDetails, -} from 'wallet/src/test/fixtures' +import { SAMPLE_SEED_ADDRESS_1, SAMPLE_SEED_ADDRESS_2, signerMnemonicAccount } from 'wallet/src/test/fixtures' expect.extend({ toIncludeSameMembers }) @@ -42,7 +37,7 @@ const sendTxDetailsFailed = transactionDetails({ type PreloadedStateProps = { watchedAddresses?: Address[] hasInactiveAccounts?: boolean - transactions?: TransactionStateMap + transactions?: TransactionsState } const getPreloadedState = (props?: PreloadedStateProps): PreloadedState => { @@ -62,8 +57,6 @@ const getPreloadedState = (props?: PreloadedStateProps): PreloadedState + - + ) } diff --git a/apps/mobile/src/components/Requests/ConnectedDapps/DappConnectedNetworksModal.tsx b/apps/mobile/src/components/Requests/ConnectedDapps/DappConnectedNetworksModal.tsx index bce5adb51ec..1994bada371 100644 --- a/apps/mobile/src/components/Requests/ConnectedDapps/DappConnectedNetworksModal.tsx +++ b/apps/mobile/src/components/Requests/ConnectedDapps/DappConnectedNetworksModal.tsx @@ -9,7 +9,7 @@ import { WalletConnectSession, removeSession } from 'src/features/walletConnect/ import { Button, Flex, Text } from 'ui/src' import { iconSizes } from 'ui/src/theme' import { NetworkLogo } from 'uniswap/src/components/CurrencyLogo/NetworkLogo' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' import { UNIVERSE_CHAIN_INFO } from 'uniswap/src/constants/chains' import { ModalName } from 'uniswap/src/features/telemetry/constants' import { WalletConnectEvent } from 'uniswap/src/types/walletConnect' @@ -58,7 +58,7 @@ export function DappConnectedNetworkModal({ session, onClose }: DappConnectedNet } return ( - + @@ -102,6 +102,6 @@ export function DappConnectedNetworkModal({ session, onClose }: DappConnectedNet - + ) } diff --git a/apps/mobile/src/components/Requests/ModalWithOverlay/ModalWithOverlay.tsx b/apps/mobile/src/components/Requests/ModalWithOverlay/ModalWithOverlay.tsx index b0b5550e94e..6955772abb9 100644 --- a/apps/mobile/src/components/Requests/ModalWithOverlay/ModalWithOverlay.tsx +++ b/apps/mobile/src/components/Requests/ModalWithOverlay/ModalWithOverlay.tsx @@ -15,14 +15,14 @@ import { AnimatedStyle, useDerivedValue } from 'react-native-reanimated' import { ScrollDownOverlay } from 'src/components/Requests/ModalWithOverlay/ScrollDownOverlay' import { Button, Flex, useDeviceInsets } from 'ui/src' import { spacing } from 'ui/src/theme' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' -import { BottomSheetModalProps } from 'uniswap/src/components/modals/BottomSheetModalProps' +import { Modal } from 'uniswap/src/components/modals/Modal' +import { ModalProps } from 'uniswap/src/components/modals/ModalProps' import { TestID } from 'uniswap/src/test/fixtures/testIDs' const MEASURE_LAYOUT_TIMEOUT = 100 type ModalWithOverlayProps = PropsWithChildren< - BottomSheetModalProps & { + ModalProps & { confirmationButtonText?: string scrollDownButtonText?: string onReject: () => void @@ -107,7 +107,7 @@ export function ModalWithOverlay({ ) return ( - + - + ) } diff --git a/apps/mobile/src/components/Requests/RequestModal/ClientDetails.tsx b/apps/mobile/src/components/Requests/RequestModal/ClientDetails.tsx index 156a8c25602..4451c8371ee 100644 --- a/apps/mobile/src/components/Requests/RequestModal/ClientDetails.tsx +++ b/apps/mobile/src/components/Requests/RequestModal/ClientDetails.tsx @@ -1,12 +1,12 @@ import React from 'react' -import { LinkButton } from 'src/components/buttons/LinkButton' import { DappHeaderIcon } from 'src/components/Requests/DappHeaderIcon' import { HeaderText } from 'src/components/Requests/RequestModal/HeaderText' +import { LinkButton } from 'src/components/buttons/LinkButton' import { WalletConnectRequest } from 'src/features/walletConnect/walletConnectSlice' import { Flex, useSporeColors } from 'ui/src' import { iconSizes } from 'ui/src/theme' +import { useCurrencyInfo } from 'uniswap/src/features/tokens/useCurrencyInfo' import { formatDappURL } from 'utilities/src/format/urls' -import { useCurrencyInfo } from 'wallet/src/features/tokens/useCurrencyInfo' export interface PermitInfo { currencyId: string diff --git a/apps/mobile/src/components/Requests/RequestModal/HeaderText.tsx b/apps/mobile/src/components/Requests/RequestModal/HeaderText.tsx index fb50999b54e..aee719d8396 100644 --- a/apps/mobile/src/components/Requests/RequestModal/HeaderText.tsx +++ b/apps/mobile/src/components/Requests/RequestModal/HeaderText.tsx @@ -3,8 +3,8 @@ import React from 'react' import { Trans } from 'react-i18next' import { WalletConnectRequest } from 'src/features/walletConnect/walletConnectSlice' import { Text } from 'ui/src' +import { ValueType, getCurrencyAmount } from 'uniswap/src/features/tokens/getCurrencyAmount' import { EthMethod, UwULinkMethod } from 'uniswap/src/types/walletConnect' -import { ValueType, getCurrencyAmount } from 'wallet/src/utils/getCurrencyAmount' export function HeaderText({ request, diff --git a/apps/mobile/src/components/Requests/RequestModal/RequestDetails.tsx b/apps/mobile/src/components/Requests/RequestModal/RequestDetails.tsx index e17064f599e..ea78c13827b 100644 --- a/apps/mobile/src/components/Requests/RequestModal/RequestDetails.tsx +++ b/apps/mobile/src/components/Requests/RequestModal/RequestDetails.tsx @@ -7,11 +7,11 @@ import { SignRequest, WalletConnectRequest, isTransactionRequest } from 'src/fea import { Flex, Text, useSporeColors } from 'ui/src' import { TextVariantTokens, iconSizes } from 'ui/src/theme' import { toSupportedChainId } from 'uniswap/src/features/chains/utils' +import { useENS } from 'uniswap/src/features/ens/useENS' import { UniverseChainId, WalletChainId } from 'uniswap/src/types/chains' import { EthMethod, EthTransaction } from 'uniswap/src/types/walletConnect' import { getValidAddress, shortenAddress } from 'uniswap/src/utils/addresses' import { logger } from 'utilities/src/logger/logger' -import { useENS } from 'wallet/src/features/ens/useENS' import { ContentRow } from 'wallet/src/features/transactions/TransactionRequest/ContentRow' import { SpendingDetails, diff --git a/apps/mobile/src/components/Requests/RequestModal/UwULinkErc20SendModal.tsx b/apps/mobile/src/components/Requests/RequestModal/UwULinkErc20SendModal.tsx index 1eefd9fdda1..b6c694a72b5 100644 --- a/apps/mobile/src/components/Requests/RequestModal/UwULinkErc20SendModal.tsx +++ b/apps/mobile/src/components/Requests/RequestModal/UwULinkErc20SendModal.tsx @@ -9,16 +9,16 @@ import { iconSizes, spacing } from 'ui/src/theme' import { TokenLogo } from 'uniswap/src/components/CurrencyLogo/TokenLogo' import { UNIVERSE_CHAIN_INFO } from 'uniswap/src/constants/chains' import { CurrencyInfo } from 'uniswap/src/features/dataApi/types' +import { GasFeeResult } from 'uniswap/src/features/gas/types' +import { useOnChainCurrencyBalance } from 'uniswap/src/features/portfolio/api' import { ModalName } from 'uniswap/src/features/telemetry/constants' import { NativeCurrency } from 'uniswap/src/features/tokens/NativeCurrency' +import { useCurrencyInfo } from 'uniswap/src/features/tokens/useCurrencyInfo' import { buildCurrencyId } from 'uniswap/src/utils/currencyId' import { NumberType } from 'utilities/src/format/types' import { NetworkFee } from 'wallet/src/components/network/NetworkFee' -import { GasFeeResult } from 'wallet/src/features/gas/types' import { RemoteImage } from 'wallet/src/features/images/RemoteImage' import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext' -import { useOnChainCurrencyBalance } from 'wallet/src/features/portfolio/api' -import { useCurrencyInfo } from 'wallet/src/features/tokens/useCurrencyInfo' import { useActiveAccountAddressWithThrow } from 'wallet/src/features/wallet/hooks' type Props = { diff --git a/apps/mobile/src/components/Requests/RequestModal/WalletConnectRequestModal.tsx b/apps/mobile/src/components/Requests/RequestModal/WalletConnectRequestModal.tsx index e2e2a7599cf..5c527840fc4 100644 --- a/apps/mobile/src/components/Requests/RequestModal/WalletConnectRequestModal.tsx +++ b/apps/mobile/src/components/Requests/RequestModal/WalletConnectRequestModal.tsx @@ -18,13 +18,13 @@ import { wcWeb3Wallet } from 'src/features/walletConnect/saga' import { selectDidOpenFromDeepLink } from 'src/features/walletConnect/selectors' import { signWcRequestActions } from 'src/features/walletConnect/signWcRequestSaga' import { WalletConnectRequest, isTransactionRequest } from 'src/features/walletConnect/walletConnectSlice' +import { GasSpeed } from 'uniswap/src/features/gas/types' import { MobileEventName, ModalName } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { EthMethod, UwULinkMethod, WCEventType, WCRequestOutcome } from 'uniswap/src/types/walletConnect' import { areAddressesEqual } from 'uniswap/src/utils/addresses' import { formatExternalTxnWithGasEstimates } from 'wallet/src/features/gas/formatExternalTxnWithGasEstimates' import { useTransactionGasFee } from 'wallet/src/features/gas/hooks' -import { GasSpeed } from 'wallet/src/features/gas/types' import { useIsBlocked, useIsBlockedActiveAddress } from 'wallet/src/features/trm/hooks' import { useSignerAccounts } from 'wallet/src/features/wallet/hooks' @@ -48,9 +48,9 @@ export function WalletConnectRequestModal({ onClose, request }: Props): JSX.Elem const didOpenFromDeepLink = useSelector(selectDidOpenFromDeepLink) const chainId = request.chainId - const tx: providers.TransactionRequest | null = useMemo(() => { + const tx: providers.TransactionRequest | undefined = useMemo(() => { if (!isTransactionRequest(request)) { - return null + return undefined } return { ...request.transaction, chainId } @@ -87,7 +87,7 @@ export function WalletConnectRequestModal({ onClose, request }: Props): JSX.Elem } if (methodCostsGas(request)) { - return !!(tx && hasSufficientFunds && gasFee.value && !gasFee.error && !gasFee.loading) + return !!(tx && hasSufficientFunds && gasFee.value && !gasFee.error && !gasFee.isLoading) } if (isTransactionRequest(request)) { diff --git a/apps/mobile/src/components/Requests/RequestModal/WalletConnectRequestModalContent.tsx b/apps/mobile/src/components/Requests/RequestModal/WalletConnectRequestModalContent.tsx index 6949a25b15d..6ec08a0d6b9 100644 --- a/apps/mobile/src/components/Requests/RequestModal/WalletConnectRequestModalContent.tsx +++ b/apps/mobile/src/components/Requests/RequestModal/WalletConnectRequestModalContent.tsx @@ -16,12 +16,12 @@ import { Flex, Text, useSporeColors } from 'ui/src' import AlertTriangle from 'ui/src/assets/icons/alert-triangle.svg' import { iconSizes } from 'ui/src/theme' import { BaseCard } from 'uniswap/src/components/BaseCard/BaseCard' +import { GasFeeResult } from 'uniswap/src/features/gas/types' import { NativeCurrency } from 'uniswap/src/features/tokens/NativeCurrency' import { EthMethod, isPrimaryTypePermit } from 'uniswap/src/types/walletConnect' import { buildCurrencyId } from 'uniswap/src/utils/currencyId' import { logger } from 'utilities/src/logger/logger' import { useUSDValue } from 'wallet/src/features/gas/hooks' -import { GasFeeResult } from 'wallet/src/features/gas/types' import { AddressFooter } from 'wallet/src/features/transactions/TransactionRequest/AddressFooter' import { NetworkFeeFooter } from 'wallet/src/features/transactions/TransactionRequest/NetworkFeeFooter' import { BlockedAddressWarning } from 'wallet/src/features/trm/BlockedAddressWarning' diff --git a/apps/mobile/src/components/Requests/RequestModal/hooks.ts b/apps/mobile/src/components/Requests/RequestModal/hooks.ts index 2f8066028ac..6dde5ba1459 100644 --- a/apps/mobile/src/components/Requests/RequestModal/hooks.ts +++ b/apps/mobile/src/components/Requests/RequestModal/hooks.ts @@ -1,10 +1,10 @@ import { useMemo } from 'react' +import { GasFeeResult } from 'uniswap/src/features/gas/types' +import { useOnChainNativeCurrencyBalance } from 'uniswap/src/features/portfolio/api' import { NativeCurrency } from 'uniswap/src/features/tokens/NativeCurrency' +import { ValueType, getCurrencyAmount } from 'uniswap/src/features/tokens/getCurrencyAmount' import { UniverseChainId, WalletChainId } from 'uniswap/src/types/chains' -import { GasFeeResult } from 'wallet/src/features/gas/types' -import { useOnChainNativeCurrencyBalance } from 'wallet/src/features/portfolio/api' import { hasSufficientFundsIncludingGas } from 'wallet/src/features/transactions/utils' -import { ValueType, getCurrencyAmount } from 'wallet/src/utils/getCurrencyAmount' export function useHasSufficientFunds({ account, diff --git a/apps/mobile/src/components/Requests/ScanSheet/WalletConnectModal.tsx b/apps/mobile/src/components/Requests/ScanSheet/WalletConnectModal.tsx index e09a79922f7..8465d18ec47 100644 --- a/apps/mobile/src/components/Requests/ScanSheet/WalletConnectModal.tsx +++ b/apps/mobile/src/components/Requests/ScanSheet/WalletConnectModal.tsx @@ -21,7 +21,7 @@ import { Flex, Text, TouchableArea, useHapticFeedback, useIsDarkMode, useSporeCo import Scan from 'ui/src/assets/icons/receive.svg' import ScanQRIcon from 'ui/src/assets/icons/scan.svg' import { iconSizes } from 'ui/src/theme' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' import { FeatureFlags } from 'uniswap/src/features/gating/flags' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' import Trace from 'uniswap/src/features/telemetry/Trace' @@ -233,12 +233,7 @@ export function WalletConnectModal({ } return ( - + <> {currentScreenState === ScannerModalState.ConnectedDapps && ( - + ) } diff --git a/apps/mobile/src/components/Requests/Uwulink/utils.ts b/apps/mobile/src/components/Requests/Uwulink/utils.ts index 041ad6adac1..0a09b881032 100644 --- a/apps/mobile/src/components/Requests/Uwulink/utils.ts +++ b/apps/mobile/src/components/Requests/Uwulink/utils.ts @@ -14,8 +14,8 @@ import { import { areAddressesEqual } from 'uniswap/src/utils/addresses' import { ContractManager } from 'wallet/src/features/contracts/ContractManager' import { ProviderManager } from 'wallet/src/features/providers/ProviderManager' -import { getTokenTransferRequest } from 'wallet/src/features/transactions/transfer/hooks/useTransferTransactionRequest' -import { TransferCurrencyParams } from 'wallet/src/features/transactions/transfer/types' +import { getTokenSendRequest } from 'wallet/src/features/transactions/send/hooks/useSendTransactionRequest' +import { SendCurrencyParams } from 'wallet/src/features/transactions/send/types' import { Account } from 'wallet/src/features/wallet/accounts/types' // This type must match the format in statsig dynamic config for uwulink @@ -214,7 +214,7 @@ async function toTokenTransferRequest( contractManager: ContractManager, ): Promise { const provider = providerManager.getProvider(request.chainId, RPCType.Public) - const params: TransferCurrencyParams = { + const params: SendCurrencyParams = { type: AssetType.Currency, account, chainId: request.chainId, @@ -222,6 +222,6 @@ async function toTokenTransferRequest( tokenAddress: request.tokenAddress, amountInWei: request.amount.toString(), } - const transaction = await getTokenTransferRequest(params, provider, contractManager) + const transaction = await getTokenSendRequest(params, provider, contractManager) return transaction as EthTransaction } diff --git a/apps/mobile/src/components/Requests/WalletConnectModals.tsx b/apps/mobile/src/components/Requests/WalletConnectModals.tsx index 8a0bf942ecb..d5c0e91d2ee 100644 --- a/apps/mobile/src/components/Requests/WalletConnectModals.tsx +++ b/apps/mobile/src/components/Requests/WalletConnectModals.tsx @@ -7,22 +7,29 @@ import { WalletConnectModal } from 'src/components/Requests/ScanSheet/WalletConn import { closeModal } from 'src/features/modals/modalSlice' import { useWalletConnect } from 'src/features/walletConnect/useWalletConnect' import { + WalletConnectRequest, removePendingSession, removeRequest, setDidOpenFromDeepLink, - WalletConnectRequest, } from 'src/features/walletConnect/walletConnectSlice' import { useAppStateTrigger } from 'src/utils/useAppStateTrigger' import { Flex, useSporeColors } from 'ui/src' import EyeIcon from 'ui/src/assets/icons/eye.svg' import { iconSizes } from 'ui/src/theme' import { ModalName } from 'uniswap/src/features/telemetry/constants' +import { WarningSeverity } from 'uniswap/src/features/transactions/WarningModal/types' import { areAddressesEqual } from 'uniswap/src/utils/addresses' +import { ErrorBoundary } from 'wallet/src/components/ErrorBoundary/ErrorBoundary' import { AccountDetails } from 'wallet/src/components/accounts/AccountDetails' import { WarningModal } from 'wallet/src/components/modals/WarningModal/WarningModal' -import { WarningSeverity } from 'wallet/src/features/transactions/WarningModal/types' import { useActiveAccount, useActiveAccountAddressWithThrow, useSignerAccounts } from 'wallet/src/features/wallet/hooks' +const WalletConnectModalName = { + Scan: ModalName.WalletConnectScan, + PendingSession: 'wallet-connect-pending-session', + Request: 'wallet-connect-request-modal', +} as const + export function WalletConnectModals(): JSX.Element { const activeAccount = useActiveAccount() const dispatch = useDispatch() @@ -62,12 +69,37 @@ export function WalletConnectModals(): JSX.Element { return ( <> {modalState.isOpen && ( - + dispatch(closeModal({ name: ModalName.WalletConnectScan }))} + > + + )} {pendingSession ? ( - + + + + ) : null} + {currRequest ? ( + + dispatch(removeRequest({ requestInternalId: currRequest.internalId, account: currRequest.account })) + } + > + {' '} + ) : null} - {currRequest ? : null} ) } @@ -100,6 +132,7 @@ function RequestModal({ currRequest }: RequestModalProps): JSX.Element { icon={ } + isOpen={!isRequestFromSignerAccount} modalName={ModalName.WCViewOnlyWarning} severity={WarningSeverity.None} title={t('walletConnect.request.warning.title')} diff --git a/apps/mobile/src/components/RestoreWalletModal/RestoreWalletModal.tsx b/apps/mobile/src/components/RestoreWalletModal/RestoreWalletModal.tsx index 6445b7550db..67312b99fee 100644 --- a/apps/mobile/src/components/RestoreWalletModal/RestoreWalletModal.tsx +++ b/apps/mobile/src/components/RestoreWalletModal/RestoreWalletModal.tsx @@ -6,7 +6,7 @@ import { closeAllModals, closeModal } from 'src/features/modals/modalSlice' import { Button, Flex, Text, useSporeColors } from 'ui/src' import LockIcon from 'ui/src/assets/icons/lock.svg' import { iconSizes, opacify } from 'ui/src/theme' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' import { ModalName } from 'uniswap/src/features/telemetry/constants' import { TestID } from 'uniswap/src/test/fixtures/testIDs' import { ImportType, OnboardingEntryPoint } from 'uniswap/src/types/onboarding' @@ -33,7 +33,7 @@ export function RestoreWalletModal(): JSX.Element | null { } return ( - + - + ) } diff --git a/apps/mobile/src/components/Settings/BiometricAuthWarningModal.tsx b/apps/mobile/src/components/Settings/BiometricAuthWarningModal.tsx index c26a32da8ce..6c72da675f1 100644 --- a/apps/mobile/src/components/Settings/BiometricAuthWarningModal.tsx +++ b/apps/mobile/src/components/Settings/BiometricAuthWarningModal.tsx @@ -2,17 +2,18 @@ import React from 'react' import { useTranslation } from 'react-i18next' import { useBiometricName } from 'src/features/biometrics/hooks' import { ModalName } from 'uniswap/src/features/telemetry/constants' +import { WarningSeverity } from 'uniswap/src/features/transactions/WarningModal/types' import { isAndroid } from 'utilities/src/platform' import { WarningModal, WarningModalProps } from 'wallet/src/components/modals/WarningModal/WarningModal' -import { WarningSeverity } from 'wallet/src/features/transactions/WarningModal/types' type Props = { + isOpen: boolean isTouchIdDevice: boolean onConfirm: WarningModalProps['onConfirm'] onClose: WarningModalProps['onClose'] } -export function BiometricAuthWarningModal({ isTouchIdDevice, onConfirm, onClose }: Props): JSX.Element { +export function BiometricAuthWarningModal({ isOpen, isTouchIdDevice, onConfirm, onClose }: Props): JSX.Element { const { t } = useTranslation() const biometricsMethod = useBiometricName(isTouchIdDevice) return ( @@ -24,6 +25,7 @@ export function BiometricAuthWarningModal({ isTouchIdDevice, onConfirm, onClose } closeText={t('common.button.back')} confirmText={t('common.button.skip')} + isOpen={isOpen} modalName={ModalName.FaceIDWarning} severity={WarningSeverity.Low} title={t('settings.setting.biometrics.warning.title')} diff --git a/apps/mobile/src/components/TokenBalanceList/TokenBalanceItemContextMenu.tsx b/apps/mobile/src/components/TokenBalanceList/TokenBalanceItemContextMenu.tsx index 09b3cc3d30c..d83a279ebc5 100644 --- a/apps/mobile/src/components/TokenBalanceList/TokenBalanceItemContextMenu.tsx +++ b/apps/mobile/src/components/TokenBalanceList/TokenBalanceItemContextMenu.tsx @@ -1,4 +1,5 @@ import React, { memo, useMemo } from 'react' +import { useTranslation } from 'react-i18next' import ContextMenu from 'react-native-context-menu-view' import { borderRadii } from 'ui/src/theme' import { SafetyLevel } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' @@ -12,10 +13,13 @@ export const TokenBalanceItemContextMenu = memo(function _TokenBalanceItem({ portfolioBalance: PortfolioBalance children: React.ReactNode }) { + const { t } = useTranslation() + const { menuActions, onContextMenuPress } = useTokenContextMenu({ currencyId: portfolioBalance.currencyInfo.currencyId, isBlocked: portfolioBalance.currencyInfo.safetyLevel === SafetyLevel.Blocked, portfolioBalance, + tokenSymbolForNotification: t('walletConnect.request.details.label.token'), }) const style = useMemo(() => ({ borderRadius: borderRadii.rounded16 }), []) diff --git a/apps/mobile/src/components/TokenDetails/BuyNativeTokenModal.tsx b/apps/mobile/src/components/TokenDetails/BuyNativeTokenModal.tsx index 99c22097327..4f89986c4fe 100644 --- a/apps/mobile/src/components/TokenDetails/BuyNativeTokenModal.tsx +++ b/apps/mobile/src/components/TokenDetails/BuyNativeTokenModal.tsx @@ -2,12 +2,12 @@ import { useTranslation } from 'react-i18next' import { Flex, Text } from 'ui/src' import { iconSizes } from 'ui/src/theme' import { CurrencyLogo } from 'uniswap/src/components/CurrencyLogo/CurrencyLogo' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' import { LearnMoreLink } from 'uniswap/src/components/text/LearnMoreLink' import { uniswapUrls } from 'uniswap/src/constants/urls' import { ModalName } from 'uniswap/src/features/telemetry/constants' +import { useCurrencyInfo, useNativeCurrencyInfo } from 'uniswap/src/features/tokens/useCurrencyInfo' import { WalletChainId } from 'uniswap/src/types/chains' -import { useCurrencyInfo, useNativeCurrencyInfo } from 'wallet/src/features/tokens/useCurrencyInfo' import { BuyNativeTokenButton } from 'wallet/src/features/transactions/InsufficientNativeTokenWarning/BuyNativeTokenButton' export function BuyNativeTokenModal({ @@ -27,7 +27,7 @@ export function BuyNativeTokenModal({ } return ( - + @@ -54,6 +54,6 @@ export function BuyNativeTokenModal({ - + ) } diff --git a/apps/mobile/src/components/TokenDetails/TokenDetailsFavoriteButton.tsx b/apps/mobile/src/components/TokenDetails/TokenDetailsFavoriteButton.tsx index 64b204aa93a..40f9a341cde 100644 --- a/apps/mobile/src/components/TokenDetails/TokenDetailsFavoriteButton.tsx +++ b/apps/mobile/src/components/TokenDetails/TokenDetailsFavoriteButton.tsx @@ -4,7 +4,7 @@ import { Favorite } from 'src/components/icons/Favorite' import { useToggleFavoriteCallback } from 'src/features/favorites/hooks' import { TouchableArea } from 'ui/src' import { iconSizes } from 'ui/src/theme' -import { selectFavoriteTokens } from 'wallet/src/features/favorites/selectors' +import { selectFavoriteTokens } from 'uniswap/src/features/favorites/selectors' export function TokenDetailsFavoriteButton({ currencyId }: { currencyId: string }): JSX.Element { const id = currencyId.toLowerCase() diff --git a/apps/mobile/src/components/TokenDetails/TokenDetailsStats.tsx b/apps/mobile/src/components/TokenDetails/TokenDetailsStats.tsx index 105554d544f..81d20e2cbde 100644 --- a/apps/mobile/src/components/TokenDetails/TokenDetailsStats.tsx +++ b/apps/mobile/src/components/TokenDetails/TokenDetailsStats.tsx @@ -23,13 +23,15 @@ function StatsRow({ }): JSX.Element { return ( - - {statsIcon} - - {label} - + + {statsIcon} + + + {label} + + - {children} + {children} ) } @@ -62,7 +64,7 @@ export function TokenDetailsMarketData({ label={t('token.stats.marketCap')} statsIcon={} > - + {convertFiatAmountFormatted(marketCap, NumberType.FiatTokenStats)} @@ -70,7 +72,7 @@ export function TokenDetailsMarketData({ label={t('token.stats.fullyDilutedValuation')} statsIcon={} > - + {convertFiatAmountFormatted(fullyDilutedValuation, NumberType.FiatTokenStats)} @@ -78,7 +80,7 @@ export function TokenDetailsMarketData({ label={t('token.stats.volume')} statsIcon={} > - + {convertFiatAmountFormatted(volume, NumberType.FiatTokenStats)} @@ -86,7 +88,7 @@ export function TokenDetailsMarketData({ label={t('token.stats.priceHighYear')} statsIcon={} > - + {convertFiatAmountFormatted(priceHight52W, NumberType.FiatTokenDetails)} @@ -94,7 +96,7 @@ export function TokenDetailsMarketData({ label={t('token.stats.priceLowYear')} statsIcon={} > - + {convertFiatAmountFormatted(priceLow52W, NumberType.FiatTokenDetails)} diff --git a/apps/mobile/src/components/TokenSelector/TokenFiatOnRampList.tsx b/apps/mobile/src/components/TokenSelector/TokenFiatOnRampList.tsx index c307f436eff..e960f3146e7 100644 --- a/apps/mobile/src/components/TokenSelector/TokenFiatOnRampList.tsx +++ b/apps/mobile/src/components/TokenSelector/TokenFiatOnRampList.tsx @@ -7,10 +7,10 @@ import { BaseCard } from 'uniswap/src/components/BaseCard/BaseCard' import { TokenOptionItem } from 'uniswap/src/components/TokenSelector/TokenOptionItem' import { useBottomSheetFocusHook } from 'uniswap/src/components/modals/hooks' import { FiatOnRampCurrency } from 'uniswap/src/features/fiatOnRamp/types' +import { useTokenWarningDismissed } from 'uniswap/src/features/tokens/slice/hooks' import { CurrencyId } from 'uniswap/src/types/currency' import { NumberType } from 'utilities/src/format/types' import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext' -import { useTokenWarningDismissed } from 'wallet/src/features/tokens/safetyHooks' interface Props { onSelectCurrency: (currency: FiatOnRampCurrency) => void diff --git a/apps/mobile/src/components/Trace/TraceUserProperties.test.tsx b/apps/mobile/src/components/Trace/TraceUserProperties.test.tsx index 4ca85ab54b6..f7515049ed8 100644 --- a/apps/mobile/src/components/Trace/TraceUserProperties.test.tsx +++ b/apps/mobile/src/components/Trace/TraceUserProperties.test.tsx @@ -7,6 +7,7 @@ import { AuthMethod } from 'src/features/telemetry/utils' import * as versionUtils from 'src/utils/version' import * as useIsDarkModeFile from 'ui/src/hooks/useIsDarkMode' import { AccountType } from 'uniswap/src/features/accounts/types' +import * as userSettingsHooks from 'uniswap/src/features/settings/hooks' import { MobileUserPropertyName } from 'uniswap/src/features/telemetry/user' // eslint-disable-next-line no-restricted-imports import { analytics } from 'utilities/src/telemetry/analytics/analytics' @@ -83,8 +84,8 @@ describe('TraceUserProperties', () => { mockFn(walletHooks, 'useViewOnlyAccounts', ['address1', 'address2']) mockFn(walletHooks, 'useSwapProtectionSetting', SwapProtectionSetting.On) mockFn(walletHooks, 'useSignerAccounts', [signerAccount1, signerAccount2, signerAccount3]) - mockFn(walletHooks, 'useHideSpamTokensSetting', true) - mockFn(walletHooks, 'useHideSmallBalancesSetting', false) + mockFn(userSettingsHooks, 'useHideSpamTokensSetting', true) + mockFn(userSettingsHooks, 'useHideSmallBalancesSetting', false) mockFn(biometricHooks, 'useBiometricAppSettings', { requiredForAppAccess: true, requiredForTransactions: true, diff --git a/apps/mobile/src/components/Trace/TraceUserProperties.tsx b/apps/mobile/src/components/Trace/TraceUserProperties.tsx index 070b25361dc..a2bbc7eeb70 100644 --- a/apps/mobile/src/components/Trace/TraceUserProperties.tsx +++ b/apps/mobile/src/components/Trace/TraceUserProperties.tsx @@ -5,6 +5,7 @@ import { useBiometricAppSettings, useDeviceSupportsBiometricAuth } from 'src/fea import { getAuthMethod } from 'src/features/telemetry/utils' import { getFullAppVersion } from 'src/utils/version' import { useIsDarkMode } from 'ui/src' +import { useHideSmallBalancesSetting, useHideSpamTokensSetting } from 'uniswap/src/features/settings/hooks' import { MobileUserPropertyName, setUserProperty } from 'uniswap/src/features/telemetry/user' import { isAndroid } from 'utilities/src/platform' import { selectAllowAnalytics } from 'wallet/src/features/telemetry/selectors' @@ -17,8 +18,6 @@ import { Keyring } from 'wallet/src/features/wallet/Keyring/Keyring' import { BackupType } from 'wallet/src/features/wallet/accounts/types' import { useActiveAccount, - useHideSmallBalancesSetting, - useHideSpamTokensSetting, useSignerAccounts, useSwapProtectionSetting, useViewOnlyAccounts, diff --git a/apps/mobile/src/components/accounts/__snapshots__/AccountCardItem.test.tsx.snap b/apps/mobile/src/components/accounts/__snapshots__/AccountCardItem.test.tsx.snap index 771ee4ca86d..3dd216939a9 100644 --- a/apps/mobile/src/components/accounts/__snapshots__/AccountCardItem.test.tsx.snap +++ b/apps/mobile/src/components/accounts/__snapshots__/AccountCardItem.test.tsx.snap @@ -70,6 +70,7 @@ exports[`AccountCardItem renders correctly 1`] = ` } > diff --git a/apps/mobile/src/components/buttons/__snapshots__/CloseButton.test.tsx.snap b/apps/mobile/src/components/buttons/__snapshots__/CloseButton.test.tsx.snap index e52eadd8b5e..31edfdaa97e 100644 --- a/apps/mobile/src/components/buttons/__snapshots__/CloseButton.test.tsx.snap +++ b/apps/mobile/src/components/buttons/__snapshots__/CloseButton.test.tsx.snap @@ -29,8 +29,8 @@ exports[`CloseButton renders without error 1`] = ` > diff --git a/apps/mobile/src/components/explore/hooks.test.ts b/apps/mobile/src/components/explore/hooks.test.ts index 96e42dc0d5f..cff933aad46 100644 --- a/apps/mobile/src/components/explore/hooks.test.ts +++ b/apps/mobile/src/components/explore/hooks.test.ts @@ -4,9 +4,9 @@ import configureMockStore from 'redux-mock-store' import { useExploreTokenContextMenu } from 'src/components/explore/hooks' import { renderHookWithProviders } from 'src/test/render' import { Resolvers } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' +import { FavoritesState } from 'uniswap/src/features/favorites/slice' import { SectionName } from 'uniswap/src/features/telemetry/constants' -import { CurrencyField } from 'uniswap/src/features/transactions/transactionState/types' -import { FavoritesState } from 'wallet/src/features/favorites/slice' +import { CurrencyField } from 'uniswap/src/types/currency' import { SAMPLE_SEED_ADDRESS_1 } from 'wallet/src/test/fixtures' import { cleanup } from 'wallet/src/test/test-utils' diff --git a/apps/mobile/src/components/explore/hooks.ts b/apps/mobile/src/components/explore/hooks.ts index e422a93953f..12fa6c9e75f 100644 --- a/apps/mobile/src/components/explore/hooks.ts +++ b/apps/mobile/src/components/explore/hooks.ts @@ -10,9 +10,9 @@ import { openModal } from 'src/features/modals/modalSlice' import { AssetType } from 'uniswap/src/entities/assets' import { ElementName, ModalName, SectionNameType } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' -import { CurrencyField, TransactionState } from 'uniswap/src/features/transactions/transactionState/types' +import { TransactionState } from 'uniswap/src/features/transactions/types/transactionState' import { WalletChainId } from 'uniswap/src/types/chains' -import { CurrencyId } from 'uniswap/src/types/currency' +import { CurrencyField, CurrencyId } from 'uniswap/src/types/currency' import { currencyIdToAddress } from 'uniswap/src/utils/currencyId' import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants' import { useWalletNavigation } from 'wallet/src/contexts/WalletNavigationContext' diff --git a/apps/mobile/src/components/explore/search/SearchEmptySection.tsx b/apps/mobile/src/components/explore/search/SearchEmptySection.tsx index 9b40864b21c..84b6ed8ae77 100644 --- a/apps/mobile/src/components/explore/search/SearchEmptySection.tsx +++ b/apps/mobile/src/components/explore/search/SearchEmptySection.tsx @@ -12,10 +12,9 @@ import ClockIcon from 'ui/src/assets/icons/clock.svg' import { TrendUp } from 'ui/src/components/icons' import { AnimatedFlex } from 'ui/src/components/layout/AnimatedFlex' import { iconSizes } from 'ui/src/theme' -import { SearchResultType } from 'uniswap/src/features/search/SearchResult' -import { WalletSearchResult } from 'wallet/src/features/search/SearchResult' -import { clearSearchHistory } from 'wallet/src/features/search/searchHistorySlice' -import { selectSearchHistory } from 'wallet/src/features/search/selectSearchHistory' +import { SearchResultType, WalletSearchResult } from 'uniswap/src/features/search/SearchResult' +import { clearSearchHistory } from 'uniswap/src/features/search/searchHistorySlice' +import { selectSearchHistory } from 'uniswap/src/features/search/selectSearchHistory' const TrendUpIcon = @@ -48,7 +47,14 @@ export function SearchEmptySection(): JSX.Element { + } title={t('explore.search.section.recent')} /> diff --git a/apps/mobile/src/components/explore/search/SearchPopularNFTCollections.tsx b/apps/mobile/src/components/explore/search/SearchPopularNFTCollections.tsx index 4a78b2c2531..3ccf24bc7d2 100644 --- a/apps/mobile/src/components/explore/search/SearchPopularNFTCollections.tsx +++ b/apps/mobile/src/components/explore/search/SearchPopularNFTCollections.tsx @@ -4,8 +4,7 @@ import { SearchNFTCollectionItem } from 'src/components/explore/search/items/Sea import { getSearchResultId, gqlNFTToNFTCollectionSearchResult } from 'src/components/explore/search/utils' import { Flex, Loader } from 'ui/src' import { useSearchPopularNftCollectionsQuery } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' -import { SearchResultType } from 'uniswap/src/features/search/SearchResult' -import { NFTCollectionSearchResult } from 'wallet/src/features/search/SearchResult' +import { NFTCollectionSearchResult, SearchResultType } from 'uniswap/src/features/search/SearchResult' function isNFTCollectionSearchResult(result: NFTCollectionSearchResult | null): result is NFTCollectionSearchResult { return (result as NFTCollectionSearchResult).type === SearchResultType.NFTCollection diff --git a/apps/mobile/src/components/explore/search/SearchResultsSection.tsx b/apps/mobile/src/components/explore/search/SearchResultsSection.tsx index d330aaa015e..20dc78c8247 100644 --- a/apps/mobile/src/components/explore/search/SearchResultsSection.tsx +++ b/apps/mobile/src/components/explore/search/SearchResultsSection.tsx @@ -25,12 +25,15 @@ import { BaseCard } from 'uniswap/src/components/BaseCard/BaseCard' import { UNIVERSE_CHAIN_INFO } from 'uniswap/src/constants/chains' import { useExploreSearchQuery } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { SearchContext } from 'uniswap/src/features/search/SearchContext' -import { SearchResultType, TokenSearchResult } from 'uniswap/src/features/search/SearchResult' +import { + NFTCollectionSearchResult, + SearchResultType, + TokenSearchResult, +} from 'uniswap/src/features/search/SearchResult' import i18n from 'uniswap/src/i18n/i18n' import { UniverseChainId } from 'uniswap/src/types/chains' import { getValidAddress } from 'uniswap/src/utils/addresses' import { logger } from 'utilities/src/logger/logger' -import { NFTCollectionSearchResult } from 'wallet/src/features/search/SearchResult' const ICON_SIZE = '$icon.24' const ICON_COLOR = '$neutral2' diff --git a/apps/mobile/src/components/explore/search/hooks.ts b/apps/mobile/src/components/explore/search/hooks.ts index 46628095830..088e181831e 100644 --- a/apps/mobile/src/components/explore/search/hooks.ts +++ b/apps/mobile/src/components/explore/search/hooks.ts @@ -1,11 +1,10 @@ import { useMemo } from 'react' -import { SearchResultType } from 'uniswap/src/features/search/SearchResult' +import { useENS } from 'uniswap/src/features/ens/useENS' +import { SearchResultType, WalletSearchResult } from 'uniswap/src/features/search/SearchResult' import { useUnitagByAddress, useUnitagByName } from 'uniswap/src/features/unitags/hooks' import { UniverseChainId } from 'uniswap/src/types/chains' import { getValidAddress } from 'uniswap/src/utils/addresses' -import { useENS } from 'wallet/src/features/ens/useENS' -import { WalletSearchResult } from 'wallet/src/features/search/SearchResult' -import { useIsSmartContractAddress } from 'wallet/src/features/transactions/transfer/hooks/useIsSmartContractAddress' +import { useIsSmartContractAddress } from 'wallet/src/features/transactions/send/hooks/useIsSmartContractAddress' // eslint-disable-next-line complexity export function useWalletSearchResults(query: string): { diff --git a/apps/mobile/src/components/explore/search/items/SearchENSAddressItem.tsx b/apps/mobile/src/components/explore/search/items/SearchENSAddressItem.tsx index b96593250ea..79b90a2592e 100644 --- a/apps/mobile/src/components/explore/search/items/SearchENSAddressItem.tsx +++ b/apps/mobile/src/components/explore/search/items/SearchENSAddressItem.tsx @@ -3,12 +3,12 @@ import { useTranslation } from 'react-i18next' import { SearchWalletItemBase } from 'src/components/explore/search/items/SearchWalletItemBase' import { Flex, Text } from 'ui/src' import { imageSizes } from 'ui/src/theme' +import { useENSAvatar, useENSName } from 'uniswap/src/features/ens/api' +import { getCompletedENSName } from 'uniswap/src/features/ens/useENS' import { SearchContext } from 'uniswap/src/features/search/SearchContext' +import { ENSAddressSearchResult } from 'uniswap/src/features/search/SearchResult' import { sanitizeAddressText, shortenAddress } from 'uniswap/src/utils/addresses' import { AccountIcon } from 'wallet/src/components/accounts/AccountIcon' -import { useENSAvatar, useENSName } from 'wallet/src/features/ens/api' -import { getCompletedENSName } from 'wallet/src/features/ens/useENS' -import { ENSAddressSearchResult } from 'wallet/src/features/search/SearchResult' type SearchENSAddressItemProps = { searchResult: ENSAddressSearchResult diff --git a/apps/mobile/src/components/explore/search/items/SearchEtherscanItem.tsx b/apps/mobile/src/components/explore/search/items/SearchEtherscanItem.tsx index 28b155634dc..4378e567fbc 100644 --- a/apps/mobile/src/components/explore/search/items/SearchEtherscanItem.tsx +++ b/apps/mobile/src/components/explore/search/items/SearchEtherscanItem.tsx @@ -3,13 +3,13 @@ import { useDispatch } from 'react-redux' import { getBlockExplorerIcon } from 'src/components/icons/BlockExplorerIcon' import { Flex, ImpactFeedbackStyle, Text, TouchableArea, useSporeColors } from 'ui/src' import { iconSizes } from 'ui/src/theme' +import { EtherscanSearchResult } from 'uniswap/src/features/search/SearchResult' +import { addToSearchHistory } from 'uniswap/src/features/search/searchHistorySlice' import { TestID } from 'uniswap/src/test/fixtures/testIDs' import { UniverseChainId } from 'uniswap/src/types/chains' import { shortenAddress } from 'uniswap/src/utils/addresses' import { openUri } from 'uniswap/src/utils/linking' import { Arrow } from 'wallet/src/components/icons/Arrow' -import { EtherscanSearchResult } from 'wallet/src/features/search/SearchResult' -import { addToSearchHistory } from 'wallet/src/features/search/searchHistorySlice' import { ExplorerDataType, getExplorerLink } from 'wallet/src/utils/linking' type SearchEtherscanItemProps = { diff --git a/apps/mobile/src/components/explore/search/items/SearchNFTCollectionItem.tsx b/apps/mobile/src/components/explore/search/items/SearchNFTCollectionItem.tsx index 8361107aefb..6cafa1537d1 100644 --- a/apps/mobile/src/components/explore/search/items/SearchNFTCollectionItem.tsx +++ b/apps/mobile/src/components/explore/search/items/SearchNFTCollectionItem.tsx @@ -5,14 +5,13 @@ import { Flex, ImpactFeedbackStyle, Text, TouchableArea } from 'ui/src' import { Verified } from 'ui/src/components/icons' import { iconSizes } from 'ui/src/theme' import { SearchContext } from 'uniswap/src/features/search/SearchContext' -import { SearchResultType } from 'uniswap/src/features/search/SearchResult' +import { NFTCollectionSearchResult, SearchResultType } from 'uniswap/src/features/search/SearchResult' +import { addToSearchHistory } from 'uniswap/src/features/search/searchHistorySlice' import { MobileEventName } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { TestID } from 'uniswap/src/test/fixtures/testIDs' import { MobileScreens } from 'uniswap/src/types/screens/mobile' import { NFTViewer } from 'wallet/src/features/images/NFTViewer' -import { NFTCollectionSearchResult } from 'wallet/src/features/search/SearchResult' -import { addToSearchHistory } from 'wallet/src/features/search/searchHistorySlice' type NFTCollectionItemProps = { collection: NFTCollectionSearchResult diff --git a/apps/mobile/src/components/explore/search/items/SearchTokenItem.tsx b/apps/mobile/src/components/explore/search/items/SearchTokenItem.tsx index b10b5d33e75..f1644bf164e 100644 --- a/apps/mobile/src/components/explore/search/items/SearchTokenItem.tsx +++ b/apps/mobile/src/components/explore/search/items/SearchTokenItem.tsx @@ -10,13 +10,13 @@ import WarningIcon from 'uniswap/src/components/icons/WarningIcon' import { SafetyLevel } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { SearchContext } from 'uniswap/src/features/search/SearchContext' import { SearchResultType, TokenSearchResult } from 'uniswap/src/features/search/SearchResult' +import { addToSearchHistory } from 'uniswap/src/features/search/searchHistorySlice' import { MobileEventName, SectionName } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { TestID } from 'uniswap/src/test/fixtures/testIDs' import { WalletChainId } from 'uniswap/src/types/chains' import { shortenAddress } from 'uniswap/src/utils/addresses' import { buildCurrencyId, buildNativeCurrencyId } from 'uniswap/src/utils/currencyId' -import { addToSearchHistory } from 'wallet/src/features/search/searchHistorySlice' type SearchTokenItemProps = { token: TokenSearchResult diff --git a/apps/mobile/src/components/explore/search/items/SearchUnitagItem.tsx b/apps/mobile/src/components/explore/search/items/SearchUnitagItem.tsx index d8331ff4d13..f3aa95593cc 100644 --- a/apps/mobile/src/components/explore/search/items/SearchUnitagItem.tsx +++ b/apps/mobile/src/components/explore/search/items/SearchUnitagItem.tsx @@ -3,10 +3,10 @@ import { SearchWalletItemBase } from 'src/components/explore/search/items/Search import { Flex, Text } from 'ui/src' import { imageSizes } from 'ui/src/theme' import { SearchContext } from 'uniswap/src/features/search/SearchContext' +import { UnitagSearchResult } from 'uniswap/src/features/search/SearchResult' import { sanitizeAddressText, shortenAddress } from 'uniswap/src/utils/addresses' import { AccountIcon } from 'wallet/src/components/accounts/AccountIcon' import { DisplayNameText } from 'wallet/src/components/accounts/DisplayNameText' -import { UnitagSearchResult } from 'wallet/src/features/search/SearchResult' import { useAvatar } from 'wallet/src/features/wallet/hooks' import { DisplayNameType } from 'wallet/src/features/wallet/types' diff --git a/apps/mobile/src/components/explore/search/items/SearchWalletByAddressItem.tsx b/apps/mobile/src/components/explore/search/items/SearchWalletByAddressItem.tsx index dceb54b26c1..080f9ca12fc 100644 --- a/apps/mobile/src/components/explore/search/items/SearchWalletByAddressItem.tsx +++ b/apps/mobile/src/components/explore/search/items/SearchWalletByAddressItem.tsx @@ -2,11 +2,11 @@ import React from 'react' import { SearchWalletItemBase } from 'src/components/explore/search/items/SearchWalletItemBase' import { Flex, Text } from 'ui/src' import { imageSizes } from 'ui/src/theme' +import { useENSAvatar, useENSName } from 'uniswap/src/features/ens/api' import { SearchContext } from 'uniswap/src/features/search/SearchContext' +import { WalletByAddressSearchResult } from 'uniswap/src/features/search/SearchResult' import { sanitizeAddressText, shortenAddress } from 'uniswap/src/utils/addresses' import { AccountIcon } from 'wallet/src/components/accounts/AccountIcon' -import { useENSAvatar, useENSName } from 'wallet/src/features/ens/api' -import { WalletByAddressSearchResult } from 'wallet/src/features/search/SearchResult' type SearchWalletByAddressItemProps = { searchResult: WalletByAddressSearchResult diff --git a/apps/mobile/src/components/explore/search/items/SearchWalletItemBase.tsx b/apps/mobile/src/components/explore/search/items/SearchWalletItemBase.tsx index 1003855b407..ac8a4fabf3d 100644 --- a/apps/mobile/src/components/explore/search/items/SearchWalletItemBase.tsx +++ b/apps/mobile/src/components/explore/search/items/SearchWalletItemBase.tsx @@ -6,13 +6,12 @@ import { useEagerExternalProfileNavigation } from 'src/app/navigation/hooks' import { useToggleWatchedWalletCallback } from 'src/features/favorites/hooks' import { disableOnPress } from 'src/utils/disableOnPress' import { ImpactFeedbackStyle, TouchableArea } from 'ui/src' +import { selectWatchedAddressSet } from 'uniswap/src/features/favorites/selectors' import { SearchContext } from 'uniswap/src/features/search/SearchContext' -import { SearchResultType } from 'uniswap/src/features/search/SearchResult' +import { SearchResultType, WalletSearchResult, extractDomain } from 'uniswap/src/features/search/SearchResult' +import { addToSearchHistory } from 'uniswap/src/features/search/searchHistorySlice' import { MobileEventName } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' -import { selectWatchedAddressSet } from 'wallet/src/features/favorites/selectors' -import { WalletSearchResult, extractDomain } from 'wallet/src/features/search/SearchResult' -import { addToSearchHistory } from 'wallet/src/features/search/searchHistorySlice' type SearchWalletItemBaseProps = { searchResult: WalletSearchResult diff --git a/apps/mobile/src/components/explore/search/types.tsx b/apps/mobile/src/components/explore/search/types.tsx index a4e4c7c3256..4666ddecf7c 100644 --- a/apps/mobile/src/components/explore/search/types.tsx +++ b/apps/mobile/src/components/explore/search/types.tsx @@ -1,5 +1,5 @@ import { SEARCH_RESULT_HEADER_KEY } from 'src/components/explore/search/constants' -import { SearchResult } from 'wallet/src/features/search/SearchResult' +import { SearchResult } from 'uniswap/src/features/search/SearchResult' // Header type used to render header text instead of SearchResult item diff --git a/apps/mobile/src/components/explore/search/utils.ts b/apps/mobile/src/components/explore/search/utils.ts index 16aba4fde91..caf0bfb4719 100644 --- a/apps/mobile/src/components/explore/search/utils.ts +++ b/apps/mobile/src/components/explore/search/utils.ts @@ -2,9 +2,12 @@ import { SEARCH_RESULT_HEADER_KEY } from 'src/components/explore/search/constant import { SearchResultOrHeader } from 'src/components/explore/search/types' import { Chain, ExploreSearchQuery } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { fromGraphQLChain } from 'uniswap/src/features/chains/utils' -import { SearchResultType, TokenSearchResult } from 'uniswap/src/features/search/SearchResult' -import { NFTCollectionSearchResult } from 'wallet/src/features/search/SearchResult' -import { searchResultId } from 'wallet/src/features/search/searchHistorySlice' +import { + NFTCollectionSearchResult, + SearchResultType, + TokenSearchResult, +} from 'uniswap/src/features/search/SearchResult' +import { searchResultId } from 'uniswap/src/features/search/searchHistorySlice' const MAX_TOKEN_RESULTS_COUNT = 4 diff --git a/apps/mobile/src/components/forceUpgrade/ForceUpgradeModal.tsx b/apps/mobile/src/components/forceUpgrade/ForceUpgradeModal.tsx index 8a1f069873e..56cee578b19 100644 --- a/apps/mobile/src/components/forceUpgrade/ForceUpgradeModal.tsx +++ b/apps/mobile/src/components/forceUpgrade/ForceUpgradeModal.tsx @@ -5,13 +5,13 @@ import { SeedPhraseDisplay } from 'src/components/mnemonic/SeedPhraseDisplay' import { APP_STORE_LINK } from 'src/constants/urls' import { UpgradeStatus } from 'src/features/forceUpgrade/types' import { Flex, Text, TouchableArea, useSporeColors } from 'ui/src' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' import { DynamicConfigs, ForceUpgradeConfigKey } from 'uniswap/src/features/gating/configs' import { useDynamicConfigValue } from 'uniswap/src/features/gating/hooks' import { ModalName } from 'uniswap/src/features/telemetry/constants' +import { WarningSeverity } from 'uniswap/src/features/transactions/WarningModal/types' import { openUri } from 'uniswap/src/utils/linking' import { WarningModal } from 'wallet/src/components/modals/WarningModal/WarningModal' -import { WarningSeverity } from 'wallet/src/features/transactions/WarningModal/types' import { SignerMnemonicAccount } from 'wallet/src/features/wallet/accounts/types' import { useSignerAccounts } from 'wallet/src/features/wallet/hooks' @@ -60,36 +60,32 @@ export function ForceUpgradeModal(): JSX.Element { setShowSeedPhrase(false) } + // We do not add explicit error boundary here as we can not hide or replace + // the force upgrade screen on error, hence we fallback to the global error boundary return ( <> - {isVisible && ( - - - {t('forceUpgrade.description')} + + + {t('forceUpgrade.description')} + + {mnemonicId && ( + + {t('forceUpgrade.action.recoveryPhrase')} - {mnemonicId && ( - - {t('forceUpgrade.action.recoveryPhrase')} - - )} - - )} + )} + {mnemonicId && showSeedPhrase && ( - + @@ -100,7 +96,7 @@ export function ForceUpgradeModal(): JSX.Element { - + )} ) diff --git a/apps/mobile/src/components/home/FeedTab.tsx b/apps/mobile/src/components/home/FeedTab.tsx index 38d5612b80c..80a1ffeca45 100644 --- a/apps/mobile/src/components/home/FeedTab.tsx +++ b/apps/mobile/src/components/home/FeedTab.tsx @@ -13,13 +13,13 @@ import { Flex, Text, useDeviceInsets, useSporeColors } from 'ui/src' import { NoTransactions } from 'ui/src/components/icons' import { BaseCard } from 'uniswap/src/components/BaseCard/BaseCard' import { GQLQueries } from 'uniswap/src/data/graphql/uniswap-data-api/queries' +import { selectWatchedAddressSet } from 'uniswap/src/features/favorites/selectors' +import { useHideSpamTokensSetting } from 'uniswap/src/features/settings/hooks' import { ModalName } from 'uniswap/src/features/telemetry/constants' import { isAndroid } from 'utilities/src/platform' import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants' import { useFormattedTransactionDataForFeed } from 'wallet/src/features/activity/hooks' -import { selectWatchedAddressSet } from 'wallet/src/features/favorites/selectors' import { generateActivityItemRenderer } from 'wallet/src/features/transactions/SummaryCards/utils' -import { useHideSpamTokensSetting } from 'wallet/src/features/wallet/hooks' export const FEED_TAB_DATA_DEPENDENCIES = [GQLQueries.FeedTransactionList] diff --git a/apps/mobile/src/components/home/HomeExploreTab.tsx b/apps/mobile/src/components/home/HomeExploreTab.tsx index 75016407560..ba351534b60 100644 --- a/apps/mobile/src/components/home/HomeExploreTab.tsx +++ b/apps/mobile/src/components/home/HomeExploreTab.tsx @@ -1,3 +1,4 @@ +import { ReactNavigationPerformanceView } from '@shopify/react-native-performance-navigation' import { ForwardedRef, forwardRef, memo, useCallback, useEffect, useMemo, useState } from 'react' import { FlatList, LayoutRectangle, RefreshControl } from 'react-native' import Animated from 'react-native-reanimated' @@ -21,6 +22,7 @@ import { Experiments, OnboardingRedesignHomeScreenProperties } from 'uniswap/src import { useExperimentValue } from 'uniswap/src/features/gating/hooks' import { MobileEventName } from 'uniswap/src/features/telemetry/constants' import { useTranslation } from 'uniswap/src/i18n' +import { MobileScreens } from 'uniswap/src/types/screens/mobile' import { isAndroid } from 'utilities/src/platform' import { selectHasUsedExplore } from 'wallet/src/features/behaviorHistory/selectors' import { useAppFiatCurrency } from 'wallet/src/features/fiatCurrency/hooks' @@ -124,27 +126,32 @@ export const HomeExploreTab = memo( }, [refreshing, headerHeight, onRefresh, colors.neutral3, insets.top]) return ( - // Negative top margin used to offset padding from tab bar that's difficult to change - - >} - ListFooterComponent={FooterElement} - data={tokenDataList} - estimatedItemSize={ESTIMATED_ITEM_SIZE} - initialNumToRender={20} - maxToRenderPerBatch={20} - refreshControl={refreshControl} - refreshing={refreshing} - renderItem={renderToken} - showsVerticalScrollIndicator={false} - updateCellsBatchingPeriod={10} - onContentSizeChange={onContentSizeChange} - onRefresh={onRefresh} - onScroll={scrollHandler} - {...containerProps} - /> - + + + >} + ListFooterComponent={FooterElement} + data={tokenDataList} + estimatedItemSize={ESTIMATED_ITEM_SIZE} + initialNumToRender={20} + maxToRenderPerBatch={20} + refreshControl={refreshControl} + refreshing={refreshing} + renderItem={renderToken} + showsVerticalScrollIndicator={false} + updateCellsBatchingPeriod={10} + onContentSizeChange={onContentSizeChange} + onRefresh={onRefresh} + onScroll={scrollHandler} + {...containerProps} + /> + + ) }), ) diff --git a/apps/mobile/src/components/home/TokensTab.tsx b/apps/mobile/src/components/home/TokensTab.tsx index 97793200c6e..ab0857faa56 100644 --- a/apps/mobile/src/components/home/TokensTab.tsx +++ b/apps/mobile/src/components/home/TokensTab.tsx @@ -12,6 +12,8 @@ import { NoTokens } from 'ui/src/components/icons' import { BaseCard } from 'uniswap/src/components/BaseCard/BaseCard' import { GQLQueries } from 'uniswap/src/data/graphql/uniswap-data-api/queries' import { useCexTransferProviders } from 'uniswap/src/features/fiatOnRamp/useCexTransferProviders' +import { FeatureFlags } from 'uniswap/src/features/gating/flags' +import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' import { ModalName } from 'uniswap/src/features/telemetry/constants' import { CurrencyId } from 'uniswap/src/types/currency' import { MobileScreens } from 'uniswap/src/types/screens/mobile' @@ -44,6 +46,8 @@ export const TokensTab = memo( const startProfilerTimer = useStartProfiler() const cexTransferProviders = useCexTransferProviders() + const disableForKorea = useFeatureFlag(FeatureFlags.DisableFiatOnRampKorea) + const onPressToken = useCallback( (currencyId: CurrencyId): void => { startProfilerTimer({ source: MobileScreens.Home }) @@ -57,8 +61,10 @@ export const TokensTab = memo( }, [dispatch]) const onPressBuy = useCallback(() => { - dispatch(openModal({ name: ModalName.FiatOnRampAggregator })) - }, [dispatch]) + dispatch( + openModal({ name: disableForKorea ? ModalName.KoreaCexTransferInfoModal : ModalName.FiatOnRampAggregator }), + ) + }, [disableForKorea, dispatch]) const onPressReceive = useCallback(() => { dispatch( diff --git a/apps/mobile/src/components/home/introCards/FundWalletModal.tsx b/apps/mobile/src/components/home/introCards/FundWalletModal.tsx index 9f14d7563ff..48d9c686e79 100644 --- a/apps/mobile/src/components/home/introCards/FundWalletModal.tsx +++ b/apps/mobile/src/components/home/introCards/FundWalletModal.tsx @@ -7,8 +7,10 @@ import { CRYPTO_PURCHASE_BACKGROUND_DARK, CRYPTO_PURCHASE_BACKGROUND_LIGHT } fro import { ArrowDownCircle, Buy } from 'ui/src/components/icons' import { borderRadii, iconSizes, spacing } from 'ui/src/theme' import { ActionCard, ActionCardItem } from 'uniswap/src/components/misc/ActionCard' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' import { useCexTransferProviders } from 'uniswap/src/features/fiatOnRamp/useCexTransferProviders' +import { FeatureFlags } from 'uniswap/src/features/gating/flags' +import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' import { ElementName, ModalName } from 'uniswap/src/features/telemetry/constants' import { useTranslation } from 'uniswap/src/i18n' import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants' @@ -20,6 +22,8 @@ export function FundWalletModal({ onClose }: { onClose: () => void }): JSX.Eleme const dispatch = useDispatch() const cexTransferProviders = useCexTransferProviders() + const disableForKorea = useFeatureFlag(FeatureFlags.DisableFiatOnRampKorea) + const BackgroundImageWrapperCallback = useCallback( ({ children }: { children: React.ReactNode }) => { return ( @@ -35,9 +39,16 @@ export function FundWalletModal({ onClose }: { onClose: () => void }): JSX.Eleme ) const onPressBuy = useCallback(() => { - dispatch(openModal({ name: ModalName.FiatOnRampAggregator })) - }, [dispatch]) + onClose() + dispatch( + openModal({ + name: disableForKorea ? ModalName.KoreaCexTransferInfoModal : ModalName.FiatOnRampAggregator, + }), + ) + }, [disableForKorea, onClose, dispatch]) + const onPressReceive = useCallback(() => { + onClose() dispatch( openModal( cexTransferProviders.length > 0 @@ -51,7 +62,7 @@ export function FundWalletModal({ onClose }: { onClose: () => void }): JSX.Eleme }, ), ) - }, [cexTransferProviders, dispatch]) + }, [cexTransferProviders, dispatch, onClose]) const cards = useMemo( () => @@ -87,7 +98,7 @@ export function FundWalletModal({ onClose }: { onClose: () => void }): JSX.Eleme [BackgroundImageWrapperCallback, cexTransferProviders, onPressBuy, onPressReceive, t], ) return ( - + {cards.map((card) => ( void }): JSX.Eleme /> ))} - + ) } diff --git a/apps/mobile/src/components/home/introCards/IntroCard.tsx b/apps/mobile/src/components/home/introCards/IntroCard.tsx index a91a7753314..349006cb902 100644 --- a/apps/mobile/src/components/home/introCards/IntroCard.tsx +++ b/apps/mobile/src/components/home/introCards/IntroCard.tsx @@ -1,4 +1,13 @@ -import { Flex, GeneratedIcon, IconProps, Text, TouchableArea, ViewProps, useIsDarkMode } from 'ui/src' +import { + Flex, + GeneratedIcon, + IconProps, + Text, + TouchableArea, + ViewProps, + useIsDarkMode, + useShadowPropsShort, +} from 'ui/src' import { X } from 'ui/src/components/icons' import { useTranslation } from 'uniswap/src/i18n' @@ -31,10 +40,12 @@ export function IntroCard({ onClose, }: IntroCardProps): JSX.Element { const isDarkMode = useIsDarkMode() + const shadowProps = useShadowPropsShort() const { t } = useTranslation() return ( string onSwiped?: (card: IntroCardProps, index: number) => void } + +const MIN_CARD_HEIGHT = 110 + export function IntroCardStack({ cards, keyExtractor, onSwiped }: IntroCardStackProps): JSX.Element { return ( } onSwiped={onSwiped} /> diff --git a/apps/mobile/src/components/home/introCards/OnboardingIntroCardStack.tsx b/apps/mobile/src/components/home/introCards/OnboardingIntroCardStack.tsx index f9c9db173d1..b4d699f79ed 100644 --- a/apps/mobile/src/components/home/introCards/OnboardingIntroCardStack.tsx +++ b/apps/mobile/src/components/home/introCards/OnboardingIntroCardStack.tsx @@ -1,6 +1,7 @@ import { SharedEventName } from '@uniswap/analytics-events' import React, { useCallback, useMemo, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' +import { navigate } from 'src/app/navigation/rootNavigation' import { FundWalletModal } from 'src/components/home/introCards/FundWalletModal' import { CardType, IntroCardProps } from 'src/components/home/introCards/IntroCard' import { IntroCardStack } from 'src/components/home/introCards/IntroCardStack' @@ -13,7 +14,8 @@ import { ElementName, MobileEventName } from 'uniswap/src/features/telemetry/con import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { OnboardingCardLoggingName } from 'uniswap/src/features/telemetry/types' import { useTranslation } from 'uniswap/src/i18n' -import { MobileScreens } from 'uniswap/src/types/screens/mobile' +import { ImportType, OnboardingEntryPoint } from 'uniswap/src/types/onboarding' +import { MobileScreens, OnboardingScreens } from 'uniswap/src/types/screens/mobile' import { selectHasSkippedUnitagPrompt, selectHasViewedWelcomeWalletCard, @@ -31,6 +33,7 @@ export function OnboardingIntroCardStack(): JSX.Element { const { t } = useTranslation() const dispatch = useDispatch() const activeAccount = useActiveAccountWithThrow() + const hasBackups = activeAccount.backups && activeAccount.backups.length > 0 const welcomeCardTitle = t('onboarding.home.intro.welcome.title') const hasViewedWelcomeWalletCard = useSelector(selectHasViewedWelcomeWalletCard) @@ -88,13 +91,22 @@ export function OnboardingIntroCardStack(): JSX.Element { }) } - if (redesignRecoveryBackupEnabled) { + if (redesignRecoveryBackupEnabled && !hasBackups) { output.push({ loggingName: OnboardingCardLoggingName.RecoveryBackup, Icon: ShieldCheck, title: t('onboarding.home.intro.backup.title'), description: t('onboarding.home.intro.backup.description'), cardType: CardType.Required, + onPress: (): void => { + navigate(MobileScreens.OnboardingStack, { + screen: OnboardingScreens.Backup, + params: { + importType: ImportType.BackupOnly, + entryPoint: OnboardingEntryPoint.BackupCard, + }, + }) + }, }) } @@ -116,6 +128,7 @@ export function OnboardingIntroCardStack(): JSX.Element { }, [ handleUnitagClaim, handleUnitagDismiss, + hasBackups, hasViewedWelcomeWalletCard, redesignRecoveryBackupEnabled, shouldPromptUnitag, diff --git a/apps/mobile/src/components/mnemonic/HiddenMnemonicWordView.tsx b/apps/mobile/src/components/mnemonic/HiddenMnemonicWordView.tsx index 142df3b4087..da567fe002e 100644 --- a/apps/mobile/src/components/mnemonic/HiddenMnemonicWordView.tsx +++ b/apps/mobile/src/components/mnemonic/HiddenMnemonicWordView.tsx @@ -1,22 +1,56 @@ import React from 'react' -import { Flex } from 'ui/src' +import { useTranslation } from 'react-i18next' +import { Flex, Text, TouchableArea, useShadowPropsMedium } from 'ui/src' +import { EyeSlash } from 'ui/src/components/icons' const ROW_COUNT = 6 -export function HiddenMnemonicWordView(): JSX.Element { +type HiddenMnemonicWordViewProps = { + enableRevealButton?: boolean + onRevealPress?: () => void +} +export function HiddenMnemonicWordView({ + enableRevealButton = false, + onRevealPress, +}: HiddenMnemonicWordViewProps): JSX.Element { + const { t } = useTranslation() + const shadowProps = useShadowPropsMedium() + return ( - - - + + + + + + {enableRevealButton && ( + + onRevealPress?.()}> + + + + {t('common.button.reveal')} + + + + + )} ) } diff --git a/apps/mobile/src/components/mnemonic/MnemonicDisplay.tsx b/apps/mobile/src/components/mnemonic/MnemonicDisplay.tsx index e59084e0871..0416689e897 100644 --- a/apps/mobile/src/components/mnemonic/MnemonicDisplay.tsx +++ b/apps/mobile/src/components/mnemonic/MnemonicDisplay.tsx @@ -2,6 +2,7 @@ import React, { useState } from 'react' import { useTranslation } from 'react-i18next' import { NativeSyntheticEvent, StyleSheet, ViewProps, requireNativeComponent } from 'react-native' import { useNativeComponentKey } from 'src/app/hooks' +import { HiddenMnemonicWordView } from 'src/components/mnemonic/HiddenMnemonicWordView' import { Flex, HiddenFromScreenReaders, Text, flexStyles } from 'ui/src' import { GraduationCap } from 'ui/src/components/icons' import { spacing } from 'ui/src/theme' @@ -15,14 +16,25 @@ interface NativeMnemonicDisplayProps { copyText: string copiedText: string mnemonicId: string + onHeightMeasured: (event: NativeSyntheticEvent) => void } const NativeMnemonicDisplay = requireNativeComponent('MnemonicDisplay') -type MnemonicDisplayProps = ViewProps & Pick +type MnemonicDisplayProps = { + showMnemonic?: boolean + enableRevealButton?: boolean + onMnemonicShown?: () => void +} & ViewProps & + Pick -export function MnemonicDisplay(props: MnemonicDisplayProps): JSX.Element { +export function MnemonicDisplay({ + showMnemonic = true, + enableRevealButton = false, + onMnemonicShown, + ...nativeComponentProps +}: MnemonicDisplayProps): JSX.Element { const { t } = useTranslation() const [height, setHeight] = useState(0) // Android only (ensures that Jetpack Compose mounts the view again @@ -30,20 +42,34 @@ export function MnemonicDisplay(props: MnemonicDisplayProps): JSX.Element { // (see https://github.com/react-native-community/discussions-and-proposals/issues/446#issuecomment-2041254054) const { key } = useNativeComponentKey(isAndroid) + const [revealPressed, setRevealPressed] = useState(false) + const showMnemonicWithReveal = enableRevealButton ? revealPressed : showMnemonic + return ( - { - // Round to limit state updates (was called with nearly the same value multiple times) - setHeight(Math.round(e.nativeEvent.height)) - }} - {...props} - /> - + {showMnemonicWithReveal ? ( + { + // Round to limit state updates (was called with nearly the same value multiple times) + setHeight(Math.round(e.nativeEvent.height)) + }} + {...nativeComponentProps} + /> + ) : ( + setHeight(Math.round(e.nativeEvent.layout.height))}> + { + onMnemonicShown?.() + setRevealPressed(true) + }} + /> + + )} - {showSeedPhrase ? ( - - - - ) : ( - - - - )} + + + ) diff --git a/apps/mobile/src/features/CloudBackup/CloudBackupProcessingAnimation.tsx b/apps/mobile/src/features/CloudBackup/CloudBackupProcessingAnimation.tsx index 5915226806d..d0c7b4755f5 100644 --- a/apps/mobile/src/features/CloudBackup/CloudBackupProcessingAnimation.tsx +++ b/apps/mobile/src/features/CloudBackup/CloudBackupProcessingAnimation.tsx @@ -40,12 +40,11 @@ export function CloudBackupProcessingAnimation({ }: Props): JSX.Element { const { t } = useTranslation() const dispatch = useDispatch() - const { addBackupMethod, getImportedAccounts, getOnboardingAccount } = useOnboardingContext() - const onboardingAccount = getOnboardingAccount() - const importedAccounts = getImportedAccounts() + const { addBackupMethod, getOnboardingOrImportedAccount } = useOnboardingContext() + const onboardingContextAccount = getOnboardingOrImportedAccount() const activeAccount = useSignerAccountIfExists(accountAddress) - const account = activeAccount || onboardingAccount || importedAccounts?.[0] + const account = activeAccount || onboardingContextAccount if (!account) { throw Error('No account available for backup') diff --git a/apps/mobile/src/features/appRating/saga.ts b/apps/mobile/src/features/appRating/saga.ts index 2ca212fe676..20a0ea17e20 100644 --- a/apps/mobile/src/features/appRating/saga.ts +++ b/apps/mobile/src/features/appRating/saga.ts @@ -1,4 +1,3 @@ -import * as StoreReview from 'expo-store-review' import { Alert } from 'react-native' import { MobileState } from 'src/app/mobileReducer' import { APP_FEEDBACK_LINK } from 'src/constants/urls' @@ -6,12 +5,12 @@ import { hasConsecutiveRecentSwapsSelector } from 'src/features/appRating/select import { call, delay, put, select, takeLatest } from 'typed-redux-saga' import { MobileEventName } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' +import { finalizeTransaction } from 'uniswap/src/features/transactions/slice' +import { TransactionStatus, TransactionType } from 'uniswap/src/features/transactions/types/transactionDetails' import i18n from 'uniswap/src/i18n/i18n' import { openUri } from 'uniswap/src/utils/linking' import { logger } from 'utilities/src/logger/logger' import { ONE_DAY_MS, ONE_SECOND_MS } from 'utilities/src/time/time' -import { finalizeTransaction } from 'wallet/src/features/transactions/slice' -import { TransactionStatus, TransactionType } from 'wallet/src/features/transactions/types' import { selectActiveAccountAddress } from 'wallet/src/features/wallet/selectors' import { setAppRating } from 'wallet/src/features/wallet/slice' @@ -22,6 +21,17 @@ const MIN_FEEDBACK_REMINDER_MS = 180 * ONE_DAY_MS // small delay to help ux const SWAP_FINALIZED_PROMPT_DELAY_MS = 3 * ONE_SECOND_MS +// Wrap the StoreReview import in a function that catches the specific error +const getStoreReview = async () => { + try { + return await import('expo-store-review') + } catch (error) { + const message = error instanceof Error ? error.message : 'Store Review import error' + logger.warn('appRating/saga.ts', 'getStoreReview', message) + return + } +} + export function* appRatingWatcherSaga() { function* processFinalizedTx(action: ReturnType) { // count successful swaps @@ -36,6 +46,12 @@ export function* appRatingWatcherSaga() { function* maybeRequestAppRating() { try { + const StoreReview = yield* call(getStoreReview) + if (!StoreReview) { + logger.warn('appRating/saga.ts', 'maybeRequestAppRating', 'StoreReview not available') + return + } + const canRequestReview = yield* call(StoreReview.hasAction) if (!canRequestReview) { return @@ -174,10 +190,11 @@ async function openFeedbackRequestAlert() { /** Opens the native store review modal that will send the rating to the store. */ async function openNativeReviewModal() { try { - if (await StoreReview.hasAction()) { + const StoreReview = await getStoreReview() + if (StoreReview && (await StoreReview.hasAction())) { await StoreReview.requestReview() } } catch (e) { - logger.error(e, { tags: { file: 'appRating/saga', function: 'useAppRating' } }) + logger.error(e, { tags: { file: 'appRating/saga', function: 'openNativeReviewModal' } }) } } diff --git a/apps/mobile/src/features/appRating/selectors.test.ts b/apps/mobile/src/features/appRating/selectors.test.ts index 87dee0ef7ee..57404492e21 100644 --- a/apps/mobile/src/features/appRating/selectors.test.ts +++ b/apps/mobile/src/features/appRating/selectors.test.ts @@ -1,8 +1,12 @@ import { MobileState } from 'src/app/mobileReducer' import { hasConsecutiveRecentSwapsSelector } from 'src/features/appRating/selectors' +import { + TransactionDetails, + TransactionStatus, + TransactionType, +} from 'uniswap/src/features/transactions/types/transactionDetails' import { UniverseChainId } from 'uniswap/src/types/chains' import { ONE_HOUR_MS, ONE_MINUTE_MS } from 'utilities/src/time/time' -import { TransactionDetails, TransactionStatus, TransactionType } from 'wallet/src/features/transactions/types' import { signerMnemonicAccount } from 'wallet/src/test/fixtures' import { preloadedWalletReducerState } from 'wallet/src/test/fixtures/wallet/redux' diff --git a/apps/mobile/src/features/appRating/selectors.ts b/apps/mobile/src/features/appRating/selectors.ts index e6f0382de0f..cb8da6514ed 100644 --- a/apps/mobile/src/features/appRating/selectors.ts +++ b/apps/mobile/src/features/appRating/selectors.ts @@ -1,16 +1,20 @@ import { createSelector, Selector } from '@reduxjs/toolkit' import { MobileState } from 'src/app/mobileReducer' +import { TransactionsState } from 'uniswap/src/features/transactions/slice' +import { + TransactionDetails, + TransactionStatus, + TransactionType, +} from 'uniswap/src/features/transactions/types/transactionDetails' import { flattenObjectOfObjects } from 'utilities/src/primitives/objects' import { ONE_MINUTE_MS } from 'utilities/src/time/time' import { selectTransactions } from 'wallet/src/features/transactions/selectors' -import { TransactionStateMap } from 'wallet/src/features/transactions/slice' -import { TransactionDetails, TransactionStatus, TransactionType } from 'wallet/src/features/transactions/types' const NUM_CONSECUTIVE_SWAPS = 2 export const hasConsecutiveRecentSwapsSelector: Selector = createSelector( [selectTransactions, (state: MobileState): number => state.wallet.appRatingPromptedMs ?? 0], - (transactions: TransactionStateMap, appRatingPromptedMs): boolean => { + (transactions: TransactionsState, appRatingPromptedMs): boolean => { const swapTxs: Array = [] const txs = flattenObjectOfObjects(transactions) diff --git a/apps/mobile/src/features/authentication/LockScreenModal.tsx b/apps/mobile/src/features/authentication/LockScreenModal.tsx index e607ac27df9..9467c07c924 100644 --- a/apps/mobile/src/features/authentication/LockScreenModal.tsx +++ b/apps/mobile/src/features/authentication/LockScreenModal.tsx @@ -15,6 +15,8 @@ export function LockScreenModal(): JSX.Element | null { return null } + // We do not add explicit error boundary here as we can not hide or replace + // the lock screen on error, hence we fallback to the global error boundary return ( { diff --git a/apps/mobile/src/features/deepLinking/handleOnRampReturnLinkSaga.ts b/apps/mobile/src/features/deepLinking/handleOnRampReturnLinkSaga.ts index 19c0a67eeb1..698682535a0 100644 --- a/apps/mobile/src/features/deepLinking/handleOnRampReturnLinkSaga.ts +++ b/apps/mobile/src/features/deepLinking/handleOnRampReturnLinkSaga.ts @@ -1,8 +1,8 @@ import { navigate } from 'src/app/navigation/rootNavigation' import { HomeScreenTabIndex } from 'src/screens/HomeScreenTabIndex' import { call, put } from 'typed-redux-saga' +import { forceFetchFiatOnRampTransactions } from 'uniswap/src/features/transactions/slice' import { MobileScreens } from 'uniswap/src/types/screens/mobile' -import { forceFetchFiatOnRampTransactions } from 'wallet/src/features/transactions/slice' import { dismissInAppBrowser } from 'wallet/src/utils/linking' export function* handleOnRampReturnLink() { diff --git a/apps/mobile/src/features/deepLinking/handleSwapLinkSaga.test.ts b/apps/mobile/src/features/deepLinking/handleSwapLinkSaga.test.ts index 47719d2e6e1..fce137acd7e 100644 --- a/apps/mobile/src/features/deepLinking/handleSwapLinkSaga.test.ts +++ b/apps/mobile/src/features/deepLinking/handleSwapLinkSaga.test.ts @@ -5,8 +5,9 @@ import { openModal } from 'src/features/modals/modalSlice' import { DAI, UNI } from 'uniswap/src/constants/tokens' import { AssetType } from 'uniswap/src/entities/assets' import { ModalName } from 'uniswap/src/features/telemetry/constants' -import { CurrencyField, TransactionState } from 'uniswap/src/features/transactions/transactionState/types' +import { TransactionState } from 'uniswap/src/features/transactions/types/transactionState' import { UniverseChainId, WalletChainId } from 'uniswap/src/types/chains' +import { CurrencyField } from 'uniswap/src/types/currency' import { signerMnemonicAccount } from 'wallet/src/test/fixtures' const account = signerMnemonicAccount() diff --git a/apps/mobile/src/features/deepLinking/handleSwapLinkSaga.ts b/apps/mobile/src/features/deepLinking/handleSwapLinkSaga.ts index 9a0eae1b405..da59953a338 100644 --- a/apps/mobile/src/features/deepLinking/handleSwapLinkSaga.ts +++ b/apps/mobile/src/features/deepLinking/handleSwapLinkSaga.ts @@ -3,8 +3,9 @@ import { openModal } from 'src/features/modals/modalSlice' import { put } from 'typed-redux-saga' import { AssetType, CurrencyAsset } from 'uniswap/src/entities/assets' import { ModalName } from 'uniswap/src/features/telemetry/constants' -import { CurrencyField, TransactionState } from 'uniswap/src/features/transactions/transactionState/types' +import { TransactionState } from 'uniswap/src/features/transactions/types/transactionState' import { WALLET_SUPPORTED_CHAIN_IDS } from 'uniswap/src/types/chains' +import { CurrencyField } from 'uniswap/src/types/currency' import { getValidAddress } from 'uniswap/src/utils/addresses' import { currencyIdToAddress, currencyIdToChain } from 'uniswap/src/utils/currencyId' import { logger } from 'utilities/src/logger/logger' diff --git a/apps/mobile/src/features/externalProfile/ProfileHeader.tsx b/apps/mobile/src/features/externalProfile/ProfileHeader.tsx index 2566de362ce..b7ae6d1690e 100644 --- a/apps/mobile/src/features/externalProfile/ProfileHeader.tsx +++ b/apps/mobile/src/features/externalProfile/ProfileHeader.tsx @@ -26,14 +26,15 @@ import { ENS_LOGO } from 'ui/src/assets' import { SendAction, XTwitter } from 'ui/src/components/icons' import { AnimatedFlex } from 'ui/src/components/layout/AnimatedFlex' import { DEP_accentColors, iconSizes, imageSizes, validColor } from 'ui/src/theme' +import { useENSDescription, useENSName, useENSTwitterUsername } from 'uniswap/src/features/ens/api' +import { selectWatchedAddressSet } from 'uniswap/src/features/favorites/selectors' import { ModalName } from 'uniswap/src/features/telemetry/constants' -import { CurrencyField } from 'uniswap/src/features/transactions/transactionState/types' + import { TestID } from 'uniswap/src/test/fixtures/testIDs' +import { CurrencyField } from 'uniswap/src/types/currency' import { openUri } from 'uniswap/src/utils/linking' import { RecipientSelectSpeedBumps } from 'wallet/src/components/RecipientSearch/RecipientSelectSpeedBumps' import { AddressDisplay } from 'wallet/src/components/accounts/AddressDisplay' -import { useENSDescription, useENSName, useENSTwitterUsername } from 'wallet/src/features/ens/api' -import { selectWatchedAddressSet } from 'wallet/src/features/favorites/selectors' import { useAvatar, useDisplayName } from 'wallet/src/features/wallet/hooks' import { DisplayNameType } from 'wallet/src/features/wallet/types' diff --git a/apps/mobile/src/features/favorites/hooks.ts b/apps/mobile/src/features/favorites/hooks.ts index 0cd6f1080ed..81898b52df6 100644 --- a/apps/mobile/src/features/favorites/hooks.ts +++ b/apps/mobile/src/features/favorites/hooks.ts @@ -1,18 +1,18 @@ import { useCallback, useMemo } from 'react' import { useDispatch, useSelector } from 'react-redux' import { MobileState } from 'src/app/mobileReducer' -import { MobileEventName } from 'uniswap/src/features/telemetry/constants' -import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' -import { CurrencyId } from 'uniswap/src/types/currency' -import { currencyIdToAddress, currencyIdToChain } from 'uniswap/src/utils/currencyId' -import { makeSelectHasTokenFavorited, selectWatchedAddressSet } from 'wallet/src/features/favorites/selectors' +import { makeSelectHasTokenFavorited, selectWatchedAddressSet } from 'uniswap/src/features/favorites/selectors' import { addFavoriteToken, addWatchedAddress, removeFavoriteToken, removeWatchedAddress, -} from 'wallet/src/features/favorites/slice' -import { useCurrencyInfo } from 'wallet/src/features/tokens/useCurrencyInfo' +} from 'uniswap/src/features/favorites/slice' +import { MobileEventName } from 'uniswap/src/features/telemetry/constants' +import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' +import { useCurrencyInfo } from 'uniswap/src/features/tokens/useCurrencyInfo' +import { CurrencyId } from 'uniswap/src/types/currency' +import { currencyIdToAddress, currencyIdToChain } from 'uniswap/src/utils/currencyId' import { useDisplayName } from 'wallet/src/features/wallet/hooks' export function useToggleFavoriteCallback(id: CurrencyId, isFavoriteToken: boolean): () => void { diff --git a/apps/mobile/src/features/fiatOnRamp/ExchangeTransferModal.tsx b/apps/mobile/src/features/fiatOnRamp/ExchangeTransferModal.tsx index 5f49703c89c..def609eb850 100644 --- a/apps/mobile/src/features/fiatOnRamp/ExchangeTransferModal.tsx +++ b/apps/mobile/src/features/fiatOnRamp/ExchangeTransferModal.tsx @@ -2,7 +2,7 @@ import { useDispatch, useSelector } from 'react-redux' import { closeModal } from 'src/features/modals/modalSlice' import { selectModalState } from 'src/features/modals/selectModalState' import { ExchangeTransferConnecting } from 'src/screens/ExchangeTransferConnecting' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' import { ModalName } from 'uniswap/src/features/telemetry/constants' export function ExchangeTransferModal(): JSX.Element | null { @@ -15,7 +15,7 @@ export function ExchangeTransferModal(): JSX.Element | null { const serviceProvider = initialState?.serviceProvider return serviceProvider ? ( - - + ) : null } diff --git a/apps/mobile/src/features/fiatOnRamp/FiatOnRampAggregatorModal.tsx b/apps/mobile/src/features/fiatOnRamp/FiatOnRampAggregatorModal.tsx index 70e5b50fde5..ae5f13aaa4b 100644 --- a/apps/mobile/src/features/fiatOnRamp/FiatOnRampAggregatorModal.tsx +++ b/apps/mobile/src/features/fiatOnRamp/FiatOnRampAggregatorModal.tsx @@ -3,7 +3,7 @@ import { useDispatch } from 'react-redux' import { FiatOnRampStackNavigator } from 'src/app/navigation/navigation' import { closeModal } from 'src/features/modals/modalSlice' import { useSporeColors } from 'ui/src' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' import { ModalName } from 'uniswap/src/features/telemetry/constants' export function FiatOnRampAggregatorModal(): JSX.Element { @@ -15,16 +15,16 @@ export function FiatOnRampAggregatorModal(): JSX.Element { }, [dispatch]) return ( - - + ) } diff --git a/apps/mobile/src/features/fiatOnRamp/FiatOnRampContext.tsx b/apps/mobile/src/features/fiatOnRamp/FiatOnRampContext.tsx index e7566090183..071cf9972dc 100644 --- a/apps/mobile/src/features/fiatOnRamp/FiatOnRampContext.tsx +++ b/apps/mobile/src/features/fiatOnRamp/FiatOnRampContext.tsx @@ -9,9 +9,9 @@ import { selectModalState } from 'src/features/modals/selectModalState' import { getNativeAddress } from 'uniswap/src/constants/addresses' import { FORQuote, FiatCurrencyInfo, FiatOnRampCurrency } from 'uniswap/src/features/fiatOnRamp/types' import { ModalName } from 'uniswap/src/features/telemetry/constants' +import { useCurrencyInfo } from 'uniswap/src/features/tokens/useCurrencyInfo' import { UniverseChainId } from 'uniswap/src/types/chains' import { buildCurrencyId } from 'uniswap/src/utils/currencyId' -import { useCurrencyInfo } from 'wallet/src/features/tokens/useCurrencyInfo' interface FiatOnRampContextType { quotesSections?: SectionListData[] | undefined diff --git a/apps/mobile/src/features/fiatOnRamp/FiatOnRampCountryListModal.tsx b/apps/mobile/src/features/fiatOnRamp/FiatOnRampCountryListModal.tsx index 4e817a492b7..60401392436 100644 --- a/apps/mobile/src/features/fiatOnRamp/FiatOnRampCountryListModal.tsx +++ b/apps/mobile/src/features/fiatOnRamp/FiatOnRampCountryListModal.tsx @@ -10,7 +10,7 @@ import Check from 'ui/src/assets/icons/check.svg' import { AnimatedFlex } from 'ui/src/components/layout/AnimatedFlex' import { useDeviceDimensions } from 'ui/src/hooks/useDeviceDimensions' import { fonts, iconSizes, spacing } from 'ui/src/theme' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' import { useBottomSheetFocusHook } from 'uniswap/src/components/modals/hooks' import { useFiatOnRampAggregatorCountryListQuery } from 'uniswap/src/features/fiatOnRamp/api' import { FOR_MODAL_SNAP_POINTS } from 'uniswap/src/features/fiatOnRamp/constants' @@ -141,18 +141,18 @@ export function FiatOnRampCountryListModal({ const colors = useSporeColors() return ( - - + ) } diff --git a/apps/mobile/src/features/fiatOnRamp/FiatOnRampTokenSelector.tsx b/apps/mobile/src/features/fiatOnRamp/FiatOnRampTokenSelector.tsx index d287d3c02ac..b35ffe3e660 100644 --- a/apps/mobile/src/features/fiatOnRamp/FiatOnRampTokenSelector.tsx +++ b/apps/mobile/src/features/fiatOnRamp/FiatOnRampTokenSelector.tsx @@ -4,7 +4,7 @@ import { FadeIn, FadeOut } from 'react-native-reanimated' import { TokenFiatOnRampList } from 'src/components/TokenSelector/TokenFiatOnRampList' import { Flex, Text, useSporeColors } from 'ui/src' import { AnimatedFlex } from 'ui/src/components/layout/AnimatedFlex' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' import { FOR_MODAL_SNAP_POINTS } from 'uniswap/src/features/fiatOnRamp/constants' import { FiatOnRampCurrency } from 'uniswap/src/features/fiatOnRamp/types' import Trace from 'uniswap/src/features/telemetry/Trace' @@ -31,13 +31,13 @@ export function FiatOnRampTokenSelectorModal({ const colors = useSporeColors() return ( - - + ) } diff --git a/apps/mobile/src/features/import/GenericImportForm.test.tsx b/apps/mobile/src/features/import/GenericImportForm.test.tsx index 0d64d98f766..035edc4f916 100644 --- a/apps/mobile/src/features/import/GenericImportForm.test.tsx +++ b/apps/mobile/src/features/import/GenericImportForm.test.tsx @@ -1,8 +1,8 @@ import React from 'react' import { GenericImportForm } from 'src/features/import/GenericImportForm' import { render, screen } from 'src/test/test-utils' +import { noOpFunction } from 'utilities/src/test/utils' import { TamaguiProvider } from 'wallet/src/provider/tamagui-provider' -import { noOpFunction } from 'wallet/src/test/mocks' describe(GenericImportForm, () => { it('renders a placeholder when there is no value', async () => { diff --git a/apps/mobile/src/features/import/__snapshots__/GenericImportForm.test.tsx.snap b/apps/mobile/src/features/import/__snapshots__/GenericImportForm.test.tsx.snap index 442e733f3a5..7c7fb2177c1 100644 --- a/apps/mobile/src/features/import/__snapshots__/GenericImportForm.test.tsx.snap +++ b/apps/mobile/src/features/import/__snapshots__/GenericImportForm.test.tsx.snap @@ -216,8 +216,8 @@ exports[`GenericImportForm renders a placeholder when there is no value 1`] = ` { isOpen: boolean initialState?: T } - export interface ModalsState { [ModalName.AccountSwitcher]: AppModalState + [ModalName.BackupReminder]: AppModalState + [ModalName.KoreaCexTransferInfoModal]: AppModalState [ModalName.ExchangeTransferModal]: AppModalState<{ serviceProvider: FORServiceProvider }> diff --git a/apps/mobile/src/features/modals/modalSlice.ts b/apps/mobile/src/features/modals/modalSlice.ts index 19aa7f6464d..1a6d01bf58c 100644 --- a/apps/mobile/src/features/modals/modalSlice.ts +++ b/apps/mobile/src/features/modals/modalSlice.ts @@ -7,7 +7,7 @@ import { ScantasticModalState } from 'src/features/scantastic/ScantasticModalSta import { FiatOnRampModalState } from 'src/screens/FiatOnRampModalState' import { ReceiveCryptoModalState } from 'src/screens/ReceiveCryptoModalState' import { ModalName } from 'uniswap/src/features/telemetry/constants' -import { TransactionState } from 'uniswap/src/features/transactions/transactionState/types' +import { TransactionState } from 'uniswap/src/features/transactions/types/transactionState' import { MobileScreens } from 'uniswap/src/types/screens/mobile' import { getKeys } from 'utilities/src/primitives/objects' import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants' @@ -17,6 +17,11 @@ type AccountSwitcherModalParams = { initialState?: undefined } +type KoreaCexTransferInfoModalParams = { + name: typeof ModalName.KoreaCexTransferInfoModal + initialState?: undefined +} + type ExchangeTransferModalParams = { name: typeof ModalName.ExchangeTransferModal initialState?: ExchangeTransferModalState @@ -80,8 +85,15 @@ type ViewOnlyExplainerParams = { initialState?: undefined } +type BackupReminderParams = { + name: typeof ModalName.BackupReminder + initialState?: undefined +} + export type OpenModalParams = | AccountSwitcherModalParams + | BackupReminderParams + | KoreaCexTransferInfoModalParams | ExchangeTransferModalParams | ExperimentsModalParams | ExploreModalParams @@ -100,15 +112,24 @@ export type OpenModalParams = export type CloseModalParams = { name: keyof ModalsState } -export const initialModalsState: ModalsState = { - [ModalName.ExchangeTransferModal]: { - isOpen: false, - initialState: undefined, - }, - [ModalName.FiatOnRampAggregator]: { - isOpen: false, - initialState: undefined, - }, +const createInitialModalState = (overrides?: Partial): ModalsState => { + const defaultState = Object.values(ModalName).reduce((state, key) => { + return { + ...state, + [key]: { + isOpen: false, + initialState: undefined, + }, + } + }, {} as ModalsState) + + return { + ...defaultState, + ...overrides, + } +} + +export const initialModalsState: ModalsState = createInitialModalState({ [ModalName.ReceiveCryptoModal]: { isOpen: false, initialState: [], @@ -117,59 +138,7 @@ export const initialModalsState: ModalsState = { isOpen: false, initialState: ScannerModalState.ScanQr, }, - [ModalName.Scantastic]: { - isOpen: false, - initialState: undefined, - }, - [ModalName.Swap]: { - isOpen: false, - initialState: undefined, - }, - [ModalName.Send]: { - isOpen: false, - initialState: undefined, - }, - [ModalName.Experiments]: { - isOpen: false, - initialState: undefined, - }, - [ModalName.Explore]: { - isOpen: false, - initialState: undefined, - }, - [ModalName.AccountSwitcher]: { - isOpen: false, - initialState: undefined, - }, - [ModalName.RemoveWallet]: { - isOpen: false, - initialState: undefined, - }, - [ModalName.RestoreWallet]: { - isOpen: false, - initialState: undefined, - }, - [ModalName.LanguageSelector]: { - isOpen: false, - initialState: undefined, - }, - [ModalName.FiatCurrencySelector]: { - isOpen: false, - initialState: undefined, - }, - [ModalName.UnitagsIntro]: { - isOpen: false, - initialState: undefined, - }, - [ModalName.ViewOnlyExplainer]: { - isOpen: false, - initialState: undefined, - }, - [ModalName.QueuedOrderModal]: { - isOpen: false, - initialState: undefined, - }, -} +}) const slice = createSlice({ name: 'modals', diff --git a/apps/mobile/src/features/nfts/item/__snapshots__/CollectionPreviewCard.test.tsx.snap b/apps/mobile/src/features/nfts/item/__snapshots__/CollectionPreviewCard.test.tsx.snap index 40dcb125cab..35ed042ea69 100644 --- a/apps/mobile/src/features/nfts/item/__snapshots__/CollectionPreviewCard.test.tsx.snap +++ b/apps/mobile/src/features/nfts/item/__snapshots__/CollectionPreviewCard.test.tsx.snap @@ -177,14 +177,13 @@ exports[`renders collection preview card 1`] = ` > diff --git a/apps/mobile/src/features/onboarding/BackupSpeedBumpModal.tsx b/apps/mobile/src/features/onboarding/BackupSpeedBumpModal.tsx new file mode 100644 index 00000000000..89f099f91cf --- /dev/null +++ b/apps/mobile/src/features/onboarding/BackupSpeedBumpModal.tsx @@ -0,0 +1,118 @@ +import { useState } from 'react' +import { useTranslation } from 'react-i18next' +import { LockPreviewImage } from 'src/features/onboarding/LockPreviewImage' +import { Button, CheckBox, Flex, Text, useIsDarkMode, useShadowPropsShort } from 'ui/src' +import { CheckCircleFilled } from 'ui/src/components/icons' +import { Modal } from 'uniswap/src/components/modals/Modal' +import { ModalName } from 'uniswap/src/features/telemetry/constants' +import { BackupType } from 'wallet/src/features/wallet/accounts/types' + +const PREVIEW_BOX_HEIGHT = 122 + +type BackupSpeedBumpModalProps = { + backupType: BackupType + + onContinue: () => void + onClose: () => void +} +export function BackupSpeedBumpModal({ backupType, onContinue, onClose }: BackupSpeedBumpModalProps): JSX.Element { + const { t } = useTranslation() + const [checked, setChecked] = useState(false) + + let preview + let title + let description + + switch (backupType) { + case BackupType.Cloud: + preview = + title = t('onboarding.backup.speedBump.cloud.title') + description = t('onboarding.backup.speedBump.cloud.description') + break + case BackupType.Manual: + preview = + title = t('onboarding.backup.speedBump.manual.title') + description = t('onboarding.backup.speedBump.manual.description') + break + default: + break + } + + return ( + + + {preview} + + + + {title} + + + {description} + + + + setChecked(!checked)} + > + { + setChecked(!checked) + }} + /> + + {t('onboarding.backup.speedBump.disclaimer')} + + + + + + + + + + ) +} + +const BULLET_COUNT = 13 +const BULLET = '•' + +function CloudBackupPreview(): JSX.Element { + const isDarkMode = useIsDarkMode() + const shadowProps = useShadowPropsShort() + const bullets = new Array(BULLET_COUNT).fill(BULLET) + + return ( + + + + {bullets} + + + + + ) +} diff --git a/apps/mobile/src/features/onboarding/LockPreviewImage.tsx b/apps/mobile/src/features/onboarding/LockPreviewImage.tsx new file mode 100644 index 00000000000..41c8fdca78d --- /dev/null +++ b/apps/mobile/src/features/onboarding/LockPreviewImage.tsx @@ -0,0 +1,71 @@ +import { Flex, useShadowPropsShort } from 'ui/src' +import { Lock } from 'ui/src/components/icons' + +const BOX_ROW_COUNT = 4 +const BOX_COL_COUNT = 2 +const BOX_HEIGHT = 7 +const BOX_WIDTH = 77 +const BOXES_CONTAINER_HEIGHT = 136 +const BOXES_CONTAINER_WIDTH = 222 + +const DEFAULT_PREVIEW_HEIGHT = 122 + +export function LockPreviewImage({ height = DEFAULT_PREVIEW_HEIGHT }: { height?: number }): JSX.Element { + const shadowProps = useShadowPropsShort() + + const rows: number[][] = new Array(BOX_ROW_COUNT).fill(new Array(BOX_COL_COUNT).fill(0)) + + return ( + + + + {rows.map((cols, rowIndex) => ( + + {cols.map((_, colIndex) => ( + + ))} + + ))} + + + + + + + + + + ) +} diff --git a/apps/mobile/src/features/openai/AIAssistantScreen.tsx b/apps/mobile/src/features/openai/AIAssistantScreen.tsx index c1a34a0d0bb..67e379ffe7c 100644 --- a/apps/mobile/src/features/openai/AIAssistantScreen.tsx +++ b/apps/mobile/src/features/openai/AIAssistantScreen.tsx @@ -4,7 +4,7 @@ import { Message, OpenAIContext } from 'src/features/openai/OpenAIContext' import { Button, Flex, Input, ScrollView, SpinningLoader, Text } from 'ui/src' import { ArrowUpCircle, UniswapLogo } from 'ui/src/components/icons' import { fonts, spacing } from 'ui/src/theme' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' import { useBottomSheetSafeKeyboard } from 'uniswap/src/components/modals/useBottomSheetSafeKeyboard' import { AccountIcon } from 'wallet/src/components/accounts/AccountIcon' import { useActiveAccountAddress, useAvatar } from 'wallet/src/features/wallet/hooks' @@ -35,7 +35,7 @@ export function AIAssistantScreen(): JSX.Element { return ( <> {isOpen && ( - + 0 ? keyboardHeight - spacing.spacing20 : '$spacing12'}> - + )} ) diff --git a/apps/mobile/src/features/openai/OpenAIContext.tsx b/apps/mobile/src/features/openai/OpenAIContext.tsx index 57fc3363ca6..d18c60c11fd 100644 --- a/apps/mobile/src/features/openai/OpenAIContext.tsx +++ b/apps/mobile/src/features/openai/OpenAIContext.tsx @@ -22,13 +22,13 @@ import { ALL_GQL_CHAINS } from 'uniswap/src/features/dataApi/searchTokens' import { FeatureFlags } from 'uniswap/src/features/gating/flags' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' import { ModalName } from 'uniswap/src/features/telemetry/constants' +import { WarningAction, WarningLabel, WarningSeverity } from 'uniswap/src/features/transactions/WarningModal/types' import { UniverseChainId } from 'uniswap/src/types/chains' import { CurrencyField } from 'uniswap/src/types/currency' import { MobileScreens } from 'uniswap/src/types/screens/mobile' import { logger } from 'utilities/src/logger/logger' import { useWalletNavigation } from 'wallet/src/contexts/WalletNavigationContext' import { AppearanceSettingType, setSelectedAppearanceSettings } from 'wallet/src/features/appearance/slice' -import { WarningAction, WarningLabel, WarningSeverity } from 'wallet/src/features/transactions/WarningModal/types' import { BackupType } from 'wallet/src/features/wallet/accounts/types' import { useActiveAccountAddress, useSignerAccounts } from 'wallet/src/features/wallet/hooks' diff --git a/apps/mobile/src/features/scantastic/ScantasticModal.tsx b/apps/mobile/src/features/scantastic/ScantasticModal.tsx index 3a0631adc53..c99dc0688bf 100644 --- a/apps/mobile/src/features/scantastic/ScantasticModal.tsx +++ b/apps/mobile/src/features/scantastic/ScantasticModal.tsx @@ -8,7 +8,7 @@ import { getEncryptedMnemonic } from 'src/features/scantastic/ScantasticEncrypti import { Button, Flex, Text, TouchableArea, useSporeColors } from 'ui/src' import { AlertTriangle, Faceid, Laptop, LinkBrokenHorizontal, Wifi } from 'ui/src/components/icons' import { iconSizes } from 'ui/src/theme' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' import { uniswapUrls } from 'uniswap/src/constants/urls' import { ModalName } from 'uniswap/src/features/telemetry/constants' import { logger } from 'utilities/src/logger/logger' @@ -219,7 +219,7 @@ export function ScantasticModal(): JSX.Element | null { if (showIPWarning) { return ( - + @@ -234,13 +234,13 @@ export function ScantasticModal(): JSX.Element | null { {t('common.button.close')} - + ) } if (expired) { return ( - + @@ -253,13 +253,13 @@ export function ScantasticModal(): JSX.Element | null { {t('common.button.close')} - + ) } if (OTP) { return ( - + @@ -276,13 +276,13 @@ export function ScantasticModal(): JSX.Element | null { {expiryText} - + ) } if (error) { return ( - + @@ -291,20 +291,20 @@ export function ScantasticModal(): JSX.Element | null { {error} - + - + ) } const renderDeviceDetails = Boolean(device || browser) return ( - + @@ -354,7 +354,7 @@ export function ScantasticModal(): JSX.Element | null { {t('scantastic.confirmation.warning')} - + + ) +} diff --git a/apps/mobile/src/features/send/SendFormScreen.tsx b/apps/mobile/src/features/send/SendFormScreen.tsx new file mode 100644 index 00000000000..8c232d9d1d0 --- /dev/null +++ b/apps/mobile/src/features/send/SendFormScreen.tsx @@ -0,0 +1,190 @@ +import React, { Dispatch, SetStateAction, useCallback, useEffect, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { Keyboard, LayoutAnimation, TouchableWithoutFeedback } from 'react-native' +import Animated from 'react-native-reanimated' +import { useSelector } from 'react-redux' +import { RecipientSelect } from 'src/components/RecipientSelect/RecipientSelect' +import { SendFormButton } from 'src/features/send/SendFormButton' +import { SendHeader } from 'src/features/send/SendHeader' +import { SendTokenForm } from 'src/features/send/SendTokenForm' +import { SEND_CONTENT_RENDER_DELAY_MS } from 'src/features/send/constants' +import { Flex, useSporeColors } from 'ui/src' +import EyeIcon from 'ui/src/assets/icons/eye.svg' +import { iconSizes } from 'ui/src/theme' +import { TokenSelectorModal, TokenSelectorVariation } from 'uniswap/src/components/TokenSelector/TokenSelector' +import { + useCommonTokensOptions, + useFilterCallbacks, + usePopularTokensOptions, + usePortfolioTokenOptions, + useTokenSectionsForSearchResults, +} from 'uniswap/src/components/TokenSelector/hooks' +import { TokenSelectorFlow } from 'uniswap/src/components/TokenSelector/types' +import { Modal } from 'uniswap/src/components/modals/Modal' +import { TokenSearchResult } from 'uniswap/src/features/search/SearchResult' +import { selectSearchHistory } from 'uniswap/src/features/search/selectSearchHistory' +import { ModalName } from 'uniswap/src/features/telemetry/constants' +import { useTokenWarningDismissed } from 'uniswap/src/features/tokens/slice/hooks' +import { + TransactionModalFooterContainer, + TransactionModalInnerContainer, +} from 'uniswap/src/features/transactions/TransactionModal/TransactionModal' +import { useTransactionModalContext } from 'uniswap/src/features/transactions/TransactionModal/TransactionModalContext' +import { WarningSeverity } from 'uniswap/src/features/transactions/WarningModal/types' +import { CurrencyField } from 'uniswap/src/types/currency' +import { + useAddToSearchHistory, + useFavoriteTokensOptions, + useTokenSectionsForEmptySearch, +} from 'wallet/src/components/TokenSelector/hooks' +import { WarningModal } from 'wallet/src/components/modals/WarningModal/WarningModal' +import { useWalletNavigation } from 'wallet/src/contexts/WalletNavigationContext' +import { usePortfolioValueModifiers } from 'wallet/src/features/dataApi/balances' +import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext' +import { useSendContext } from 'wallet/src/features/transactions/contexts/SendContext' +import { useActiveAccountAddressWithThrow } from 'wallet/src/features/wallet/hooks' + +export function SendFormScreen(): JSX.Element { + const [hideContent, setHideContent] = useState(true) + useEffect(() => { + setTimeout(() => setHideContent(false), SEND_CONTENT_RENDER_DELAY_MS) + }, []) + + return +} + +function SendFormScreenContent({ hideContent }: { hideContent: boolean }): JSX.Element { + const { t } = useTranslation() + const colors = useSporeColors() + const { bottomSheetViewStyles } = useTransactionModalContext() + const { showRecipientSelector, recipient, derivedSendInfo, updateSendForm } = useSendContext() + const [showViewOnlyModal, setShowViewOnlyModal] = useState(false) + + const onSelectRecipient = useCallback( + (newRecipient: string) => { + updateSendForm({ recipient: newRecipient, showRecipientSelector: false }) + }, + [updateSendForm], + ) + + const onHideRecipientSelector = useCallback(() => { + updateSendForm({ showRecipientSelector: false }) + }, [updateSendForm]) + + // Renders recipient select within a bottom sheet, only used when a recipient already exists. If no recipient + // a full screen select view is rendered within `SendFlow` + const showRecipientSelectBottomSheet = recipient && showRecipientSelector + + return ( + <> + + {showRecipientSelectBottomSheet && ( + + + + + + )} + + {!hideContent && ( + <> + + + + )} + + + + + + ) +} + +export function SendFormContent({ + showViewOnlyModal, + setShowViewOnlyModal, +}: { + showViewOnlyModal: boolean + setShowViewOnlyModal: Dispatch> +}): JSX.Element { + const colors = useSporeColors() + const { t } = useTranslation() + const { formatNumberOrString, convertFiatAmountFormatted } = useLocalizationContext() + const { navigateToBuyOrReceiveWithEmptyWallet } = useWalletNavigation() + + const activeAccountAddress = useActiveAccountAddressWithThrow() + const valueModifiers = usePortfolioValueModifiers(activeAccountAddress) + const { registerSearch } = useAddToSearchHistory() + const searchHistory = useSelector(selectSearchHistory) + + const { selectingCurrencyField, onSelectCurrency, updateSendForm } = useSendContext() + + const onHideTokenSelector = useCallback(() => { + updateSendForm({ selectingCurrencyField: undefined }) + }, [updateSendForm]) + + return ( + <> + } + isOpen={showViewOnlyModal} + modalName={ModalName.SwapWarning} + severity={WarningSeverity.Low} + title={t('send.warning.viewOnly.title')} + onClose={(): void => setShowViewOnlyModal(false)} + onConfirm={(): void => setShowViewOnlyModal(false)} + /> + + + + + + + + + {!!selectingCurrencyField && ( + Keyboard.dismiss()} + onPressAnimation={() => LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)} + onSelectCurrency={onSelectCurrency} + /> + )} + + ) +} diff --git a/apps/mobile/src/features/transactions/transfer/TransferHeader.tsx b/apps/mobile/src/features/send/SendHeader.tsx similarity index 86% rename from apps/mobile/src/features/transactions/transfer/TransferHeader.tsx rename to apps/mobile/src/features/send/SendHeader.tsx index b4d60f7626a..2b3a40d4df4 100644 --- a/apps/mobile/src/features/transactions/transfer/TransferHeader.tsx +++ b/apps/mobile/src/features/send/SendHeader.tsx @@ -4,14 +4,14 @@ import { Flex, Text, TouchableArea, useSporeColors } from 'ui/src' import EyeIcon from 'ui/src/assets/icons/eye.svg' import { iconSizes } from 'ui/src/theme' import { AccountType } from 'uniswap/src/features/accounts/types' -import { TransferFlowProps } from 'wallet/src/features/transactions/types' import { useActiveAccountWithThrow } from 'wallet/src/features/wallet/hooks' -type HeaderContentProps = Pick & { +type HeaderContentProps = { + flowName: string setShowViewOnlyModal: Dispatch> } -export function TransferHeader({ flowName, setShowViewOnlyModal }: HeaderContentProps): JSX.Element { +export function SendHeader({ flowName, setShowViewOnlyModal }: HeaderContentProps): JSX.Element { const colors = useSporeColors() const account = useActiveAccountWithThrow() const { t } = useTranslation() @@ -24,7 +24,7 @@ export function TransferHeader({ flowName, setShowViewOnlyModal }: HeaderContent alignItems="center" justifyContent="space-between" mt="$spacing8" - pb="$spacing8" + pb="$spacing16" pl="$spacing12" pr="$spacing16" > diff --git a/apps/mobile/src/features/send/SendRecipientSelectFullScreen.tsx b/apps/mobile/src/features/send/SendRecipientSelectFullScreen.tsx new file mode 100644 index 00000000000..61d38bf37f1 --- /dev/null +++ b/apps/mobile/src/features/send/SendRecipientSelectFullScreen.tsx @@ -0,0 +1,46 @@ +import React, { useCallback, useEffect, useState } from 'react' +import { RecipientSelect } from 'src/components/RecipientSelect/RecipientSelect' +import { SEND_CONTENT_RENDER_DELAY_MS } from 'src/features/send/constants' +import { TransactionModalInnerContainer } from 'uniswap/src/features/transactions/TransactionModal/TransactionModal' +import { useTransactionModalContext } from 'uniswap/src/features/transactions/TransactionModal/TransactionModalContext' +import { useSendContext } from 'wallet/src/features/transactions/contexts/SendContext' + +// We add a short hardcoded delay to allow the sheet to animate quickly both on first render and when going back from Review -> Form. +export function SendRecipientSelectFullScreen(): JSX.Element { + const [hideContent, setHideContent] = useState(true) + useEffect(() => { + setTimeout(() => setHideContent(false), SEND_CONTENT_RENDER_DELAY_MS) + }, []) + + return +} + +function SendRecipientSelectFullScreenContent({ hideContent }: { hideContent: boolean }): JSX.Element { + const { bottomSheetViewStyles } = useTransactionModalContext() + const { showRecipientSelector, recipient, derivedSendInfo, updateSendForm } = useSendContext() + + const onSelectRecipient = useCallback( + (newRecipient: string) => { + updateSendForm({ recipient: newRecipient, showRecipientSelector: false }) + }, + [updateSendForm], + ) + + const onHideRecipientSelector = useCallback(() => { + updateSendForm({ showRecipientSelector: false }) + }, [updateSendForm]) + + return ( + + {!hideContent && ( + + )} + + ) +} diff --git a/apps/mobile/src/features/send/SendReviewScreen.tsx b/apps/mobile/src/features/send/SendReviewScreen.tsx new file mode 100644 index 00000000000..2715427a100 --- /dev/null +++ b/apps/mobile/src/features/send/SendReviewScreen.tsx @@ -0,0 +1,33 @@ +import React, { useEffect, useState } from 'react' +import { SEND_CONTENT_RENDER_DELAY_MS } from 'src/features/send/constants' +import { Flex } from 'ui/src/components/layout/Flex' +import { TransactionModalInnerContainer } from 'uniswap/src/features/transactions/TransactionModal/TransactionModal' +import { useTransactionModalContext } from 'uniswap/src/features/transactions/TransactionModal/TransactionModalContext' +import { SendReviewDetails } from 'wallet/src/features/transactions/send/SendReviewDetails' + +// We add a short hardcoded delay to allow the sheet to animate quickly both on first render and when going back from Review -> Form. +export function SendReviewScreen(): JSX.Element { + const [hideContent, setHideContent] = useState(true) + useEffect(() => { + setTimeout(() => setHideContent(false), SEND_CONTENT_RENDER_DELAY_MS) + }, []) + + return +} + +function SendReviewScreenContent({ hideContent }: { hideContent: boolean }): JSX.Element { + const { bottomSheetViewStyles, BiometricsIcon, onClose, authTrigger } = useTransactionModalContext() + + // Same logic we apply in `SwapReviewScreen` + // We forcefully hide the content via `hideContent` to allow the bottom sheet to animate faster while still allowing all API requests to trigger ASAP. + // The value of `height + mb` must be equal to the height of the fully rendered component to avoid the modal jumping on open. + if (hideContent) { + return + } + + return ( + + + + ) +} diff --git a/apps/mobile/src/features/send/SendTokenForm.tsx b/apps/mobile/src/features/send/SendTokenForm.tsx new file mode 100644 index 00000000000..656e532afe5 --- /dev/null +++ b/apps/mobile/src/features/send/SendTokenForm.tsx @@ -0,0 +1,410 @@ +/* eslint-disable complexity */ +import { useCallback, useRef, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { Keyboard, StyleSheet } from 'react-native' +import { Flex, Text, TouchableArea, useIsShortMobileDevice, useSporeColors } from 'ui/src' +import InfoCircleFilled from 'ui/src/assets/icons/info-circle-filled.svg' +import { AlertCircle } from 'ui/src/components/icons' +import { useDeviceDimensions } from 'ui/src/hooks/useDeviceDimensions' +import { iconSizes, spacing } from 'ui/src/theme' +import { TextInputProps } from 'uniswap/src/components/input/TextInput' +import { MAX_FIAT_INPUT_DECIMALS } from 'uniswap/src/constants/transactions' +import { ModalName } from 'uniswap/src/features/telemetry/constants' +import { useTransactionModalContext } from 'uniswap/src/features/transactions/TransactionModal/TransactionModalContext' +import { WarningSeverity } from 'uniswap/src/features/transactions/WarningModal/types' +import { useUSDCValue } from 'uniswap/src/features/transactions/swap/hooks/useUSDCPrice' +import { CurrencyField } from 'uniswap/src/types/currency' +import { truncateToMaxDecimals } from 'utilities/src/format/truncateToMaxDecimals' +import { RecipientInputPanel } from 'wallet/src/components/input/RecipientInputPanel' +import { WarningModal, getAlertColor } from 'wallet/src/components/modals/WarningModal/WarningModal' +import { NFTTransfer } from 'wallet/src/components/nfts/NFTTransfer' +import { useSendContext } from 'wallet/src/features/transactions/contexts/SendContext' +import { GasFeeRow } from 'wallet/src/features/transactions/send/GasFeeRow' +import { useShowSendNetworkNotification } from 'wallet/src/features/transactions/send/hooks/useShowSendNetworkNotification' +import { CurrencyInputPanel, CurrencyInputPanelRef } from 'wallet/src/features/transactions/swap/CurrencyInputPanel' +import { + DecimalPadCalculateSpace, + DecimalPadInput, + DecimalPadInputRef, +} from 'wallet/src/features/transactions/swap/DecimalPadInput' +import { SwapArrowButton } from 'wallet/src/features/transactions/swap/SwapArrowButton' +import { useUSDTokenUpdater } from 'wallet/src/features/transactions/swap/trade/hooks/useUSDTokenUpdater' +import { BlockedAddressWarning } from 'wallet/src/features/trm/BlockedAddressWarning' +import { useIsBlocked, useIsBlockedActiveAddress } from 'wallet/src/features/trm/hooks' + +const TRANSFER_DIRECTION_BUTTON_SIZE = iconSizes.icon20 +const TRANSFER_DIRECTION_BUTTON_INNER_PADDING = spacing.spacing12 +const TRANSFER_DIRECTION_BUTTON_BORDER_WIDTH = spacing.spacing4 + +export function SendTokenForm(): JSX.Element { + const { t } = useTranslation() + const colors = useSporeColors() + const isShortMobileDevice = useIsShortMobileDevice() + const { fullHeight } = useDeviceDimensions() + + const { walletNeedsRestore, openWalletRestoreModal } = useTransactionModalContext() + const { updateSendForm, derivedSendInfo, warnings, gasFee } = useSendContext() + + const [currencyFieldFocused, setCurrencyFieldFocused] = useState(true) + const [showWarningModal, setShowWarningModal] = useState(false) + + const { + currencyAmounts, + currencyBalances, + exactAmountToken, + exactAmountFiat, + recipient, + isFiatInput = false, + currencyInInfo, + nftIn, + } = derivedSendInfo + + const currencyIn = currencyInInfo?.currency + + const onFiatAmountUpdated = useCallback( + (amount: string): void => { + updateSendForm({ exactAmountFiat: amount }) + }, + [updateSendForm], + ) + + const onTokenAmountUpdated = useCallback( + (amount: string): void => { + updateSendForm({ exactAmountToken: amount }) + }, + [updateSendForm], + ) + + useShowSendNetworkNotification({ chainId: currencyIn?.chainId }) + + const inputCurrencyUSDValue = useUSDCValue(currencyAmounts[CurrencyField.INPUT]) + + const onShowTokenSelector = useCallback(() => { + updateSendForm({ selectingCurrencyField: CurrencyField.INPUT }) + }, [updateSendForm]) + + const onShowRecipientSelector = useCallback(() => { + updateSendForm({ showRecipientSelector: true }) + }, [updateSendForm]) + + const { isBlocked: isActiveBlocked } = useIsBlockedActiveAddress() + const { isBlocked: isRecipientBlocked } = useIsBlocked(recipient) + const isBlocked = isActiveBlocked || isRecipientBlocked + + const onRestorePress = (): void => { + if (!openWalletRestoreModal) { + throw new Error('Invalid call to `onRestorePress` with missing `openWalletRestoreModal`') + } + setCurrencyFieldFocused(false) + openWalletRestoreModal() + } + + const onTransferWarningClick = (): void => { + Keyboard.dismiss() + setShowWarningModal(true) + } + const transferWarning = warnings.warnings.find((warning) => warning.severity >= WarningSeverity.Low) + const transferWarningColor = getAlertColor(transferWarning?.severity) + const SendWarningIcon = transferWarning?.icon ?? AlertCircle + + const currencyInputPanelRef = useRef(null) + + const exactAmountTokenRef = useRef(exactAmountToken) + const exactAmountFiatRef = useRef(exactAmountFiat) + const exactValueRef = isFiatInput ? exactAmountFiatRef : exactAmountTokenRef + + const onSetExactAmount = useCallback( + (amount: string) => { + if (isFiatInput) { + exactAmountFiatRef.current = amount + updateSendForm({ exactAmountFiat: amount }) + } else { + exactAmountTokenRef.current = amount + updateSendForm({ exactAmountToken: amount }) + } + }, + [isFiatInput, updateSendForm], + ) + + // Decimal pad logic + const decimalPadRef = useRef(null) + const maxDecimals = isFiatInput ? MAX_FIAT_INPUT_DECIMALS : currencyIn?.decimals ?? 0 + const selectionRef = useRef() + + const onInputSelectionChange = useCallback( + (start: number, end: number) => { + selectionRef.current = { start, end } + decimalPadRef.current?.updateDisabledKeys() + }, + [selectionRef], + ) + + const resetSelection = useCallback( + ({ start, end }: { start: number; end?: number; currencyField?: CurrencyField }) => { + // Update refs first to have the latest selection state available in the DecimalPadInput + // component and properly update disabled keys of the decimal pad. + // We reset the native selection on the next tick because we need to wait for the native input to be updated. + // This is needed because of the combination of state (delayed update) + ref (instant update) to improve performance. + selectionRef.current = { start, end } + const inputFieldRef = currencyInputPanelRef.current?.textInputRef + + if (inputFieldRef) { + setTimeout(() => { + inputFieldRef?.current?.setNativeProps?.({ selection: { start, end } }) + }, 0) + } + }, + [], + ) + + const onSetMax = useCallback( + (amount: string) => { + exactAmountTokenRef.current = amount + updateSendForm({ exactAmountToken: amount, isFiatInput: false, focusOnCurrencyField: null }) + + // We want this update to happen on the next tick, after the input value is updated. + setTimeout(() => { + resetSelection({ + start: exactAmountTokenRef.current.length, + end: exactAmountTokenRef.current.length, + }) + decimalPadRef.current?.updateDisabledKeys() + }, 0) + }, + [resetSelection, updateSendForm], + ) + + const onToggleFiatInput = useCallback(() => { + const newIsFiatInput = !isFiatInput + + exactAmountFiatRef.current = exactAmountFiat + exactAmountTokenRef.current = exactAmountToken + + updateSendForm({ isFiatInput: newIsFiatInput }) + // We want this update to happen on the next tick, after the input value is updated. + setTimeout(() => { + const amount = newIsFiatInput ? exactAmountFiat : exactAmountToken + resetSelection({ + start: amount.length, + end: amount.length, + }) + }, 0) + }, [exactAmountFiat, exactAmountToken, isFiatInput, resetSelection, updateSendForm]) + + useUSDTokenUpdater({ + onFiatAmountUpdated, + onTokenAmountUpdated, + isFiatInput, + exactAmountToken, + exactAmountFiat, + currency: currencyIn ?? undefined, + }) + + const [decimalPadReady, setDecimalPadReady] = useState(false) + + const onDecimalPadReady = useCallback(() => setDecimalPadReady(true), []) + + const onDecimalPadTriggerInputShake = useCallback(() => { + currencyInputPanelRef.current?.triggerShakeAnimation() + }, []) + + const decimalPadSetValue = useCallback( + (value: string): void => { + // We disable the `DecimalPad` when the input reaches the max number of decimals, + // but we still need to truncate in case the user moves the cursor and adds a decimal separator in the middle of the input. + const truncatedValue = truncateToMaxDecimals({ + value, + maxDecimals, + }) + + console.log('truncatedValue in decimal set value', truncatedValue) + + if (isFiatInput) { + exactAmountFiatRef.current = truncatedValue + } else { + exactAmountTokenRef.current = truncatedValue + } + + updateSendForm({ + exactAmountFiat: isFiatInput ? truncatedValue : undefined, + exactAmountToken: !isFiatInput ? truncatedValue : undefined, + exactCurrencyField: CurrencyField.INPUT, + focusOnCurrencyField: CurrencyField.INPUT, + }) + }, + [isFiatInput, maxDecimals, updateSendForm], + ) + return ( + <> + {transferWarning?.title && ( + } + isOpen={showWarningModal} + modalName={ModalName.SendWarning} + severity={transferWarning.severity} + title={transferWarning.title} + onClose={(): void => setShowWarningModal(false)} + onConfirm={(): void => setShowWarningModal(false)} + /> + )} + + + {nftIn ? ( + + ) : ( + + setCurrencyFieldFocused(true)} + onSelectionChange={onInputSelectionChange} + onSetExactAmount={onSetExactAmount} + onSetMax={onSetMax} + onShowTokenSelector={onShowTokenSelector} + onToggleIsFiatMode={onToggleFiatInput} + /> + + )} + + + + + + + + + + + + {recipient && ( + + )} + {walletNeedsRestore && ( + + + + + {t('send.warning.restore')} + + + + )} + {isBlocked ? ( + + ) : null} + + + {gasFee && !transferWarning && currencyIn?.chainId && !isBlocked && ( + + )} + + {transferWarning && !isBlocked ? ( + + + + + {transferWarning.title} + + + + ) : null} + + + {!nftIn && ( + <> + + + + + + )} + + + ) +} diff --git a/apps/mobile/src/features/send/constants.ts b/apps/mobile/src/features/send/constants.ts new file mode 100644 index 00000000000..9b20b8e2139 --- /dev/null +++ b/apps/mobile/src/features/send/constants.ts @@ -0,0 +1 @@ +export const SEND_CONTENT_RENDER_DELAY_MS = 25 diff --git a/apps/mobile/src/features/telemetry/saga.ts b/apps/mobile/src/features/telemetry/saga.ts index ebffb15918d..de85c02b69b 100644 --- a/apps/mobile/src/features/telemetry/saga.ts +++ b/apps/mobile/src/features/telemetry/saga.ts @@ -1,12 +1,15 @@ +import ReactNativeIdfaAaid from '@sparkfabrik/react-native-idfa-aaid' // eslint-disable-next-line no-restricted-imports -import { OriginApplication } from '@uniswap/analytics' +import { ANONYMOUS_DEVICE_ID, OriginApplication } from '@uniswap/analytics' import DeviceInfo, { getUniqueId } from 'react-native-device-info' import { call, delay, fork, select } from 'typed-redux-saga' import { uniswapUrls } from 'uniswap/src/constants/urls' +import { MobileUserPropertyName } from 'uniswap/src/features/telemetry/user' +import { isAndroid } from 'utilities/src/platform' import { ApplicationTransport } from 'utilities/src/telemetry/analytics/ApplicationTransport' -import { selectAllowAnalytics } from 'wallet/src/features/telemetry/selectors' // eslint-disable-next-line no-restricted-imports import { analytics } from 'utilities/src/telemetry/analytics/analytics' +import { selectAllowAnalytics } from 'wallet/src/features/telemetry/selectors' import { watchTransactionEvents } from 'wallet/src/features/transactions/transactionWatcherSaga' export function* telemetrySaga() { @@ -24,5 +27,18 @@ export function* telemetrySaga() { undefined, async () => getUniqueId(), ) + if (isAndroid) { + // Only need GAID, not using IDFA + const advertisingInfoResponse = yield* call(ReactNativeIdfaAaid.getAdvertisingInfo) + const adTrackingAllowed = allowAnalytics && !advertisingInfoResponse.isAdTrackingLimited + if (adTrackingAllowed) { + yield* call( + analytics.setUserProperty, + MobileUserPropertyName.AdvertisingId, + adTrackingAllowed && advertisingInfoResponse.id ? advertisingInfoResponse.id : ANONYMOUS_DEVICE_ID, + ) + } + } + yield* fork(watchTransactionEvents) } diff --git a/apps/mobile/src/features/transactions/TransactionPending/StatusAnimation.tsx b/apps/mobile/src/features/transactions/TransactionPending/StatusAnimation.tsx deleted file mode 100644 index 2ceb3f23af6..00000000000 --- a/apps/mobile/src/features/transactions/TransactionPending/StatusAnimation.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import React, { useEffect, useRef } from 'react' -import Rive, { Alignment, Fit, RiveRef } from 'rive-react-native' -import { TransactionStatus } from 'wallet/src/features/transactions/types' - -const ANIMATION_WIDTH = 250 -const ANIMATION_HEIGHT = 250 -const stateMachineName = 'State Machine 1' - -export function StatusAnimation({ - status, - transactionType, -}: { - status?: TransactionStatus - transactionType: 'swap' | 'send' -}): JSX.Element { - const animationRef = useRef(null) - - useEffect(() => { - if (status === TransactionStatus.Success) { - animationRef.current?.setInputState(stateMachineName, 'isSuccess', true) - } else if (status === TransactionStatus.Failed) { - animationRef.current?.setInputState(stateMachineName, 'isFailure', true) - } - }, [status]) - - return ( - - ) -} diff --git a/apps/mobile/src/features/transactions/TransactionPending/TransactionPending.tsx b/apps/mobile/src/features/transactions/TransactionPending/TransactionPending.tsx deleted file mode 100644 index 4714c057f5e..00000000000 --- a/apps/mobile/src/features/transactions/TransactionPending/TransactionPending.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import React from 'react' -import { useTranslation } from 'react-i18next' -import { StatusAnimation } from 'src/features/transactions/TransactionPending/StatusAnimation' -import { Button, Flex, Text, TouchableArea } from 'ui/src' -import { AnimatedFlex } from 'ui/src/components/layout/AnimatedFlex' -import { TestID } from 'uniswap/src/test/fixtures/testIDs' -import { WalletChainId } from 'uniswap/src/types/chains' -import { TransactionDetails, TransactionStatus, isFinalizedTx } from 'wallet/src/features/transactions/types' -import { openTransactionLink } from 'wallet/src/utils/linking' - -type TransactionStatusProps = { - transaction: TransactionDetails | undefined - chainId: WalletChainId - title: string - description: string - onNext: () => void - onTryAgain: () => void - transactionType: 'swap' | 'send' -} - -export function TransactionPending({ - transaction, - title, - description, - onNext, - onTryAgain, - transactionType, -}: TransactionStatusProps): JSX.Element { - const { t } = useTranslation() - - const onPressViewTransaction = async (): Promise => { - if (transaction) { - await openTransactionLink(transaction?.hash, transaction.chainId) - } - } - - return ( - - - - - - - {title} - - {description} - - {transaction?.status === TransactionStatus.Failed ? ( - - - {t('common.button.tryAgain')} - - - ) : null} - - - - {transaction && isFinalizedTx(transaction) ? ( - - ) : null} - - - - ) -} diff --git a/apps/mobile/src/features/transactions/swap/hooks/useOnCloseSendModal.tsx b/apps/mobile/src/features/transactions/swap/hooks/useOnCloseSendModal.tsx deleted file mode 100644 index 26792643e47..00000000000 --- a/apps/mobile/src/features/transactions/swap/hooks/useOnCloseSendModal.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { useCallback } from 'react' -import { useDispatch } from 'react-redux' -import { closeModal } from 'src/features/modals/modalSlice' -import { ModalName } from 'uniswap/src/features/telemetry/constants' - -export function useOnCloseSendModal(): () => void { - const appDispatch = useDispatch() - - const onClose = useCallback((): void => { - appDispatch(closeModal({ name: ModalName.Send })) - }, [appDispatch]) - - return onClose -} diff --git a/apps/mobile/src/features/transactions/transfer/TransferFlow.tsx b/apps/mobile/src/features/transactions/transfer/TransferFlow.tsx deleted file mode 100644 index 34120bc7ae6..00000000000 --- a/apps/mobile/src/features/transactions/transfer/TransferFlow.tsx +++ /dev/null @@ -1,399 +0,0 @@ -import { providers } from 'ethers' -import { default as React, useCallback, useEffect, useMemo, useReducer, useState } from 'react' -import { useTranslation } from 'react-i18next' -import { Keyboard, LayoutAnimation, StyleSheet, TouchableWithoutFeedback } from 'react-native' -import Animated, { useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated' -import { useSelector } from 'react-redux' -import { useShouldShowNativeKeyboard } from 'src/app/hooks' -import { RecipientSelect } from 'src/components/RecipientSelect/RecipientSelect' -import { Screen } from 'src/components/layout/Screen' -import { useBiometricAppSettings, useBiometricPrompt } from 'src/features/biometrics/hooks' -import { TransferHeader } from 'src/features/transactions/transfer/TransferHeader' -import { TransferStatus } from 'src/features/transactions/transfer/TransferStatus' -import { useWalletRestore } from 'src/features/wallet/hooks' -import { Flex, useDeviceInsets, useSporeColors } from 'ui/src' -import EyeIcon from 'ui/src/assets/icons/eye.svg' -import { useDeviceDimensions } from 'ui/src/hooks/useDeviceDimensions' -import { iconSizes } from 'ui/src/theme' -import { TokenSelectorModal, TokenSelectorVariation } from 'uniswap/src/components/TokenSelector/TokenSelector' -import { - useCommonTokensOptions, - useFilterCallbacks, - usePopularTokensOptions, - usePortfolioTokenOptions, - useTokenSectionsForSearchResults, -} from 'uniswap/src/components/TokenSelector/hooks' -import { useBottomSheetContext } from 'uniswap/src/components/modals/BottomSheetContext' -import { HandleBar } from 'uniswap/src/components/modals/HandleBar' -import { TokenSearchResult } from 'uniswap/src/features/search/SearchResult' -import Trace from 'uniswap/src/features/telemetry/Trace' -import { ModalName, SectionName } from 'uniswap/src/features/telemetry/constants' -import { CurrencyField, TransactionState } from 'uniswap/src/features/transactions/transactionState/types' -import { TokenSelectorFlow } from 'uniswap/src/features/transactions/transfer/types' -import { currencyAddress } from 'uniswap/src/utils/currencyId' -import { - useAddToSearchHistory, - useFavoriteTokensOptions, - useTokenSectionsForEmptySearch, -} from 'wallet/src/components/TokenSelector/hooks' -import { WarningModal } from 'wallet/src/components/modals/WarningModal/WarningModal' -import { useWalletNavigation } from 'wallet/src/contexts/WalletNavigationContext' -import { usePortfolioValueModifiers } from 'wallet/src/features/dataApi/balances' -import { useTransactionGasFee } from 'wallet/src/features/gas/hooks' -import { GasFeeResult, GasSpeed } from 'wallet/src/features/gas/types' -import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext' -import { selectSearchHistory } from 'wallet/src/features/search/selectSearchHistory' -import { useTokenWarningDismissed } from 'wallet/src/features/tokens/safetyHooks' -import { WarningAction, WarningSeverity } from 'wallet/src/features/transactions/WarningModal/types' -import { useParsedSendWarnings } from 'wallet/src/features/transactions/hooks/useParsedTransactionWarnings' -import { useTokenSelectorActionHandlers } from 'wallet/src/features/transactions/hooks/useTokenSelectorActionHandlers' -import { useTransactionGasWarning } from 'wallet/src/features/transactions/hooks/useTransactionGasWarning' -import { useUSDCValue } from 'wallet/src/features/transactions/swap/trade/hooks/useUSDCPrice' -import { - INITIAL_TRANSACTION_STATE, - transactionStateReducer, -} from 'wallet/src/features/transactions/transactionState/transactionState' -import { TransferReview } from 'wallet/src/features/transactions/transfer/TransferReview' -import { TransferTokenForm } from 'wallet/src/features/transactions/transfer/TransferTokenForm' -import { useDerivedTransferInfo } from 'wallet/src/features/transactions/transfer/hooks/useDerivedTransferInfo' -import { useOnSelectRecipient } from 'wallet/src/features/transactions/transfer/hooks/useOnSelectRecipient' -import { useSetShowRecipientSelector } from 'wallet/src/features/transactions/transfer/hooks/useOnToggleShowRecipientSelector' -import { - useTransferERC20Callback, - useTransferNFTCallback, -} from 'wallet/src/features/transactions/transfer/hooks/useTransferCallback' -import { useTransferTransactionRequest } from 'wallet/src/features/transactions/transfer/hooks/useTransferTransactionRequest' -import { useTransferWarnings } from 'wallet/src/features/transactions/transfer/hooks/useTransferWarnings' -import { DerivedTransferInfo } from 'wallet/src/features/transactions/transfer/types' -import { TransactionStep, TransferFlowProps } from 'wallet/src/features/transactions/types' -import { useActiveAccountAddressWithThrow, useActiveAccountWithThrow } from 'wallet/src/features/wallet/hooks' - -interface TransferFormProps { - prefilledState?: TransactionState - onClose: () => void -} - -export function TransferFlow({ prefilledState, onClose }: TransferFormProps): JSX.Element { - const insets = useDeviceInsets() - const colors = useSporeColors() - const { t } = useTranslation() - const { fullWidth } = useDeviceDimensions() - const { isSheetReady } = useBottomSheetContext() - const { formatNumberOrString, convertFiatAmountFormatted } = useLocalizationContext() - const { navigateToBuyOrReceiveWithEmptyWallet } = useWalletNavigation() - const account = useActiveAccountWithThrow() - const address = account.address - const valueModifiers = usePortfolioValueModifiers(address) - const { registerSearch } = useAddToSearchHistory() - const searchHistory = useSelector(selectSearchHistory) - - const [state, dispatch] = useReducer(transactionStateReducer, prefilledState || INITIAL_TRANSACTION_STATE) - const derivedTransferInfo = useDerivedTransferInfo(state) - const [showViewOnlyModal, setShowViewOnlyModal] = useState(false) - const [step, setStep] = useState(TransactionStep.FORM) - - const { isFiatInput, exactAmountToken, exactAmountFiat } = derivedTransferInfo - const { showRecipientSelector } = state - - const activeAccountAddress = useActiveAccountAddressWithThrow() - - const onSelectRecipient = useOnSelectRecipient(dispatch) - const onSetShowRecipientSelector = useSetShowRecipientSelector(dispatch) - - const onHideRecipientSelector = useCallback(() => { - onSetShowRecipientSelector(false) - }, [onSetShowRecipientSelector]) - - const txRequest = useTransferTransactionRequest(derivedTransferInfo) - const warnings = useTransferWarnings(t, derivedTransferInfo) - const gasFee = useTransactionGasFee( - txRequest, - GasSpeed.Urgent, - // stop polling for gas once transaction is submitted - step === TransactionStep.SUBMITTED || warnings.some((warning) => warning.action === WarningAction.DisableReview), - ) - - const transferTxWithGasSettings = useMemo( - (): providers.TransactionRequest => ({ ...txRequest, ...gasFee.params }), - [gasFee.params, txRequest], - ) - - const gasWarning = useTransactionGasWarning({ - account, - derivedInfo: derivedTransferInfo, - gasFee: gasFee?.value, - }) - - const allWarnings = useMemo(() => { - return !gasWarning ? warnings : [...warnings, gasWarning] - }, [warnings, gasWarning]) - - const parsedSendWarnings = useParsedSendWarnings(allWarnings) - - const { onSelectCurrency, onHideTokenSelector } = useTokenSelectorActionHandlers(dispatch, TokenSelectorFlow.Transfer) - - // optimization for not rendering InnerContent initially, - // when modal is opened with recipient or token selector presented - const [renderInnerContentRouter, setRenderInnerContentRouter] = useState(!showRecipientSelector) - useEffect(() => { - setRenderInnerContentRouter(renderInnerContentRouter || !showRecipientSelector) - }, [renderInnerContentRouter, showRecipientSelector]) - - const onFormNext = useCallback(() => setStep(TransactionStep.REVIEW), [setStep]) - const onReviewNext = useCallback(() => setStep(TransactionStep.SUBMITTED), [setStep]) - const onReviewPrev = useCallback(() => setStep(TransactionStep.FORM), [setStep]) - const onRetrySubmit = useCallback(() => setStep(TransactionStep.FORM), [setStep]) - - const exactValue = isFiatInput ? exactAmountFiat : exactAmountToken - const recipient = state.recipient - - const isRecipientScreenOnLeft = useSharedValue(true) - const inputScreenOffsetX = useSharedValue(0) - - useEffect(() => { - if (!recipient) { - // If starting from the recipient selector screen, move the input to the right - inputScreenOffsetX.value = fullWidth - return - } - - if (!showRecipientSelector) { - // Transition input screen to the center if recipient selector is not shown - inputScreenOffsetX.value = withTiming(0, undefined, () => { - isRecipientScreenOnLeft.value = false - }) - } else { - // Transition input screen to the left if recipient selector is shown - // and recipient is already selected - inputScreenOffsetX.value = withTiming(-fullWidth) - } - }, [showRecipientSelector, recipient, fullWidth, inputScreenOffsetX, isRecipientScreenOnLeft]) - - const recipientScreenStyle = useAnimatedStyle(() => ({ - transform: [ - { - translateX: inputScreenOffsetX.value + (isRecipientScreenOnLeft.value ? -1 : 1) * fullWidth, - }, - ], - })) - - const inputScreenStyle = useAnimatedStyle(() => ({ - transform: [{ translateX: inputScreenOffsetX.value }], - })) - - return ( - <> - - - - - - - - - - {/* Padding bottom must have a similar size to the handlebar - height as 100% height doesn't include the handlebar height */} - - {step !== TransactionStep.SUBMITTED && ( - - )} - {renderInnerContentRouter && isSheetReady && ( - - )} - - - - {showViewOnlyModal && ( - } - modalName={ModalName.SwapWarning} - severity={WarningSeverity.Low} - title={t('send.warning.viewOnly.title')} - onClose={(): void => setShowViewOnlyModal(false)} - onConfirm={(): void => setShowViewOnlyModal(false)} - /> - )} - - - - {!!state.selectingCurrencyField && ( - Keyboard.dismiss()} - onPressAnimation={() => LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)} - onSelectCurrency={onSelectCurrency} - /> - )} - - ) -} - -type TransferInnerContentProps = { - step: number - setStep: (step: TransactionStep) => void - showingSelectorScreen: boolean - gasFee: GasFeeResult - derivedTransferInfo: DerivedTransferInfo - onFormNext: () => void - onReviewNext: () => void - onReviewPrev: () => void - onRetrySubmit: () => void - setShowViewOnlyModal: (show: boolean) => void -} & Pick - -function TransferInnerContent({ - showingSelectorScreen, - derivedTransferInfo, - onClose, - dispatch, - step, - gasFee, - txRequest, - warnings, - onFormNext, - onRetrySubmit, - onReviewNext, - onReviewPrev, - setShowViewOnlyModal, -}: TransferInnerContentProps): JSX.Element | null { - // TODO: move this up in the tree to mobile specific flow - const { walletNeedsRestore, openWalletRestoreModal } = useWalletRestore() - const { showNativeKeyboard, onDecimalPadLayout, isLayoutPending, onInputPanelLayout } = useShouldShowNativeKeyboard() - - const { currencyAmounts, recipient, currencyInInfo, nftIn, chainId, txId } = derivedTransferInfo - - // for transfer analytics - const currencyAmountUSD = useUSDCValue(currencyAmounts[CurrencyField.INPUT]) - - const transferERC20Callback = useTransferERC20Callback( - txId, - chainId, - recipient, - currencyInInfo ? currencyAddress(currencyInInfo.currency) : undefined, - currencyAmounts[CurrencyField.INPUT]?.quotient.toString(), - txRequest, - onReviewNext, - currencyAmountUSD, - ) - const transferNFTCallback = useTransferNFTCallback( - txId, - chainId, - recipient, - nftIn?.nftContract?.address, - nftIn?.tokenId, - txRequest, - onReviewNext, - ) - - const onTransfer = (): void => { - onFormNext() - nftIn ? transferNFTCallback?.() : transferERC20Callback?.() - } - - const { trigger: biometricAuthAndTransfer } = useBiometricPrompt(onTransfer) - const { requiredForTransactions: biometricRequired } = useBiometricAppSettings() - - const onReviewSubmit = async (): Promise => { - if (biometricRequired) { - await biometricAuthAndTransfer() - } else { - onTransfer() - } - } - - switch (step) { - case TransactionStep.SUBMITTED: - return ( - - - - ) - case TransactionStep.FORM: - return ( - - - - ) - case TransactionStep.REVIEW: - return ( - - - - ) - default: - return null - } -} - -const styles = StyleSheet.create({ - screen: { - height: '100%', - position: 'absolute', - width: '100%', - }, -}) diff --git a/apps/mobile/src/features/transactions/transfer/TransferStatus.tsx b/apps/mobile/src/features/transactions/transfer/TransferStatus.tsx deleted file mode 100644 index 6264957444b..00000000000 --- a/apps/mobile/src/features/transactions/transfer/TransferStatus.tsx +++ /dev/null @@ -1,120 +0,0 @@ -import React, { useCallback, useMemo } from 'react' -import { useTranslation } from 'react-i18next' -import { goBack } from 'src/app/navigation/rootNavigation' -import { TransactionPending } from 'src/features/transactions/TransactionPending/TransactionPending' -import { AppTFunction } from 'ui/src/i18n/types' -import { FiatCurrencyInfo } from 'uniswap/src/features/fiatOnRamp/types' -import { CurrencyField } from 'uniswap/src/features/transactions/transactionState/types' -import { NumberType } from 'utilities/src/format/types' -import { useAppFiatCurrencyInfo } from 'wallet/src/features/fiatCurrency/hooks' -import { LocalizationContextState, useLocalizationContext } from 'wallet/src/features/language/LocalizationContext' -import { useSelectTransaction } from 'wallet/src/features/transactions/hooks' -import { DerivedTransferInfo } from 'wallet/src/features/transactions/transfer/types' -import { TransactionDetails, TransactionStatus, TransactionType } from 'wallet/src/features/transactions/types' -import { useActiveAccountAddressWithThrow, useDisplayName } from 'wallet/src/features/wallet/hooks' - -type TransferStatusProps = { - derivedTransferInfo: DerivedTransferInfo - onNext: () => void - onTryAgain: () => void -} - -const getTextFromTransferStatus = ( - t: AppTFunction, - formatter: LocalizationContextState, - fiatCurrencyInfo: FiatCurrencyInfo, - derivedTransferInfo: DerivedTransferInfo, - recipient: string | undefined, - transactionDetails?: TransactionDetails, -): { - title: string - description: string -} => { - const { currencyInInfo, nftIn, currencyAmounts, isFiatInput, exactAmountFiat } = derivedTransferInfo - if ( - !transactionDetails || - transactionDetails.typeInfo.type !== TransactionType.Send || - !recipient || - (!currencyInInfo && !nftIn) - ) { - // TODO: [MOB-240] should never go into this state but should probably do some - // error display here as well as log to sentry or amplitude - return { - title: t('send.status.inProgress.title'), - description: t('send.status.inProgress.description'), - } - } - const status = transactionDetails.status - if (status === TransactionStatus.Success) { - const formattedFiatValue = formatter.addFiatSymbolToNumber({ - value: exactAmountFiat, - currencyCode: fiatCurrencyInfo.code, - currencySymbol: fiatCurrencyInfo.symbol, - }) - return { - title: t('send.status.success.title'), - description: t('send.status.success.description', { - currencyAmount: nftIn - ? '' - : formatter.formatCurrencyAmount({ - value: currencyAmounts[CurrencyField.INPUT], - type: NumberType.TokenTx, - }), - fiatValue: isFiatInput ? ` (${formattedFiatValue})` : '', - tokenName: nftIn?.name ?? ` ${currencyInInfo?.currency.symbol}` ?? ' tokens', - recipient, - }), - } - } - - if (status === TransactionStatus.Failed) { - return { - title: t('send.status.failed.title'), - description: t('send.status.fail.description'), - } - } - - // TODO: [MOB-241] handle TransactionStatus.Unknown state - return { - title: t('send.status.inProgress.title'), - description: t('send.status.inProgress.description'), - } -} - -export function TransferStatus({ derivedTransferInfo, onNext, onTryAgain }: TransferStatusProps): JSX.Element | null { - const { t } = useTranslation() - const formatter = useLocalizationContext() - const appFiatCurrencyInfo = useAppFiatCurrencyInfo() - const activeAddress = useActiveAccountAddressWithThrow() - - const { recipient, chainId, txId } = derivedTransferInfo - - const transaction = useSelectTransaction(activeAddress, chainId, txId) - - const displayName = useDisplayName(recipient, { includeUnitagSuffix: true }) - const recipientName = displayName?.name ?? recipient - const { title, description } = useMemo(() => { - return getTextFromTransferStatus(t, formatter, appFiatCurrencyInfo, derivedTransferInfo, recipientName, transaction) - }, [t, formatter, appFiatCurrencyInfo, derivedTransferInfo, recipientName, transaction]) - - const onClose = useCallback(() => { - onNext() - goBack() - }, [onNext]) - - if (!chainId) { - return null - } - - return ( - - ) -} diff --git a/apps/mobile/src/features/transactions/transfer/transferRewrite/TransferFlow.tsx b/apps/mobile/src/features/transactions/transfer/transferRewrite/TransferFlow.tsx deleted file mode 100644 index 23b043e9114..00000000000 --- a/apps/mobile/src/features/transactions/transfer/transferRewrite/TransferFlow.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import { Dispatch, ReactNode, SetStateAction, useEffect, useMemo, useState } from 'react' -import { useSelector } from 'react-redux' -import { selectModalState } from 'src/features/modals/selectModalState' -import { useOnCloseSendModal } from 'src/features/transactions/swap/hooks/useOnCloseSendModal' -import { TransferFormScreen } from 'src/features/transactions/transfer/transferRewrite/TransferFormScreen' -import { - TransferScreen, - TransferScreenContextProvider, - useTransferScreenContext, -} from 'src/features/transactions/transfer/transferRewrite/TransferScreenContext' -import { useWalletRestore } from 'src/features/wallet/hooks' -import Trace from 'uniswap/src/features/telemetry/Trace' -import { ModalName, SectionName } from 'uniswap/src/features/telemetry/constants' -import { TradeProtocolPreference } from 'uniswap/src/features/transactions/transactionState/types' -import { SwapFormContextProvider, SwapFormState } from 'wallet/src/features/transactions/contexts/SwapFormContext' -import { TransactionModal } from 'wallet/src/features/transactions/swap/TransactionModal' -import { getFocusOnCurrencyFieldFromInitialState } from 'wallet/src/features/transactions/swap/hooks/useSwapPrefilledState' -import { useActiveAccountWithThrow } from 'wallet/src/features/wallet/hooks' - -/** - * @todo: The screens within this flow are not implemented. - * MOB-555 https://linear.app/uniswap/issue/MOB-555/implement-updated-send-flow - */ -export function TransferFlow(): JSX.Element { - // We need this additional `screen` state outside of the `SwapScreenContext` because the `TransferContextProvider` needs to be inside the `BottomSheetModal`'s `Container`. - const [screen, setScreen] = useState(TransferScreen.TransferForm) - const fullscreen = screen === TransferScreen.TransferForm - const onClose = useOnCloseSendModal() - - const account = useActiveAccountWithThrow() - const { walletNeedsRestore, openWalletRestoreModal } = useWalletRestore() - - return ( - - - - - - ) -} - -function CurrentScreen({ - screen, - setScreen, -}: { - screen: TransferScreen - setScreen: Dispatch> -}): JSX.Element { - const { screen: contextScreen, screenRef: contextScreenRef } = useTransferScreenContext() - - useEffect(() => { - setScreen(contextScreen) - }, [contextScreen, contextScreenRef, setScreen]) - - switch (screen) { - case TransferScreen.TransferForm: - return ( - - - - ) - default: - throw new Error(`Unknown screen: ${screen}`) - } -} - -function TransferFormScreenDelayedRender(): JSX.Element { - const [hideContent, setHideContent] = useState(true) - useEffect(() => { - setTimeout(() => setHideContent(false), 25) - }, []) - return -} - -function TransferContextsContainer({ children }: { children?: ReactNode }): JSX.Element { - const { initialState } = useSelector(selectModalState(ModalName.Send)) - - const prefilledState = useMemo( - (): SwapFormState | undefined => - initialState - ? { - customSlippageTolerance: initialState.customSlippageTolerance, - exactAmountFiat: initialState.exactAmountFiat, - exactAmountToken: initialState.exactAmountToken, - exactCurrencyField: initialState.exactCurrencyField, - focusOnCurrencyField: getFocusOnCurrencyFieldFromInitialState(initialState), - input: initialState.input ?? undefined, - output: initialState.output ?? undefined, - selectingCurrencyField: initialState.selectingCurrencyField, - txId: initialState.txId, - isFiatMode: false, - isSubmitting: false, - tradeProtocolPreference: TradeProtocolPreference.Default, - } - : undefined, - [initialState], - ) - - return ( - - {children} - - ) -} diff --git a/apps/mobile/src/features/transactions/transfer/transferRewrite/TransferFormScreen.tsx b/apps/mobile/src/features/transactions/transfer/transferRewrite/TransferFormScreen.tsx deleted file mode 100644 index 17e9456e859..00000000000 --- a/apps/mobile/src/features/transactions/transfer/transferRewrite/TransferFormScreen.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import React from 'react' -import { Text } from 'ui/src' -import { useSwapFormContext } from 'wallet/src/features/transactions/contexts/SwapFormContext' -import { useTransactionModalContext } from 'wallet/src/features/transactions/contexts/TransactionModalContext' -import { TransactionModalInnerContainer } from 'wallet/src/features/transactions/swap/TransactionModal' - -export function TransferFormScreen({ hideContent }: { hideContent: boolean }): JSX.Element { - const { bottomSheetViewStyles } = useTransactionModalContext() - const { selectingCurrencyField } = useSwapFormContext() - - return ( - - {!hideContent && !!selectingCurrencyField && } - - TODO: transfer form content - - - ) -} - -function TokenSelector(): JSX.Element | null { - // TODO: implement. See `wallet/.../SwapTokenSelector.tsx` for reference. - return null -} diff --git a/apps/mobile/src/features/transactions/transfer/transferRewrite/TransferScreenContext.tsx b/apps/mobile/src/features/transactions/transfer/transferRewrite/TransferScreenContext.tsx deleted file mode 100644 index fbe41b0778f..00000000000 --- a/apps/mobile/src/features/transactions/transfer/transferRewrite/TransferScreenContext.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { createContext, ReactNode, useCallback, useContext, useMemo, useRef, useState } from 'react' - -export enum TransferScreen { - TransferForm, - TransferReview, -} - -type TransferScreenContextState = { - screen: TransferScreen - screenRef: React.MutableRefObject - setScreen: (screen: TransferScreen) => void -} - -export const TransferScreenContext = createContext(undefined) - -// TODO: re-use the same context built in extension, and move that to shared folder. -export function TransferScreenContextProvider({ children }: { children: ReactNode }): JSX.Element { - const screenRef = useRef(TransferScreen.TransferForm) - const [screen, setScreen] = useState(TransferScreen.TransferForm) - - const wrappedSetScreen = useCallback((_screen: TransferScreen) => { - screenRef.current = _screen - setScreen(_screen) - }, []) - - const state = useMemo( - (): TransferScreenContextState => ({ - screen, - screenRef, - setScreen: wrappedSetScreen, - }), - [screen, wrappedSetScreen], - ) - - return {children} -} - -export const useTransferScreenContext = (): TransferScreenContextState => { - const transferContext = useContext(TransferScreenContext) - - if (transferContext === undefined) { - throw new Error('`useTransferScreenContext ` must be used inside of `TransferScreenContextProvider`') - } - - return transferContext -} diff --git a/apps/mobile/src/features/tweaks/selectors.ts b/apps/mobile/src/features/tweaks/selectors.ts index 1d506e7c010..2c12bce4574 100644 --- a/apps/mobile/src/features/tweaks/selectors.ts +++ b/apps/mobile/src/features/tweaks/selectors.ts @@ -1,5 +1,5 @@ import { TweaksState } from 'src/features/tweaks/slice' -import { CustomEndpoint } from 'wallet/src/data/links' +import { CustomEndpoint } from 'uniswap/src/data/links' export const selectCustomEndpoint = (state: { tweaks: TweaksState }): CustomEndpoint | undefined => state.tweaks.customEndpoint diff --git a/apps/mobile/src/features/tweaks/slice.ts b/apps/mobile/src/features/tweaks/slice.ts index 1e6a0c63ff9..b46e23a8da1 100644 --- a/apps/mobile/src/features/tweaks/slice.ts +++ b/apps/mobile/src/features/tweaks/slice.ts @@ -1,5 +1,5 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit' -import { CustomEndpoint } from 'wallet/src/data/links' +import { CustomEndpoint } from 'uniswap/src/data/links' export interface TweaksState { customEndpoint?: CustomEndpoint diff --git a/apps/mobile/src/features/unitags/ChooseProfilePictureScreen.tsx b/apps/mobile/src/features/unitags/ChooseProfilePictureScreen.tsx index 8a82b0a6aa8..2e07b057d69 100644 --- a/apps/mobile/src/features/unitags/ChooseProfilePictureScreen.tsx +++ b/apps/mobile/src/features/unitags/ChooseProfilePictureScreen.tsx @@ -11,12 +11,14 @@ import { UnitagName } from 'src/features/unitags/UnitagName' import { Button, Flex, Text, useIsDarkMode, useSporeColors } from 'ui/src' import { Pen } from 'ui/src/components/icons' import { fonts, iconSizes, imageSizes, spacing } from 'ui/src/theme' +import { useENSName } from 'uniswap/src/features/ens/api' +import { Experiments, OnboardingRedesignRecoveryBackupProperties } from 'uniswap/src/features/gating/experiments' +import { getExperimentValue } from 'uniswap/src/features/gating/hooks' import { UnitagClaimSource } from 'uniswap/src/features/unitags/types' import { TestID } from 'uniswap/src/test/fixtures/testIDs' import { UniverseChainId } from 'uniswap/src/types/chains' import { ImportType, OnboardingEntryPoint } from 'uniswap/src/types/onboarding' import { MobileScreens, OnboardingScreens, UnitagScreens } from 'uniswap/src/types/screens/mobile' -import { useENSName } from 'wallet/src/features/ens/api' import { useOnboardingContext } from 'wallet/src/features/onboarding/OnboardingContext' import { useClaimUnitag } from 'wallet/src/features/unitags/hooks' @@ -68,10 +70,16 @@ export function ChooseProfilePictureScreen({ const onPressContinue = async (): Promise => { if (entryPoint === OnboardingScreens.Landing) { + const onboardingExperimentEnabled = getExperimentValue( + Experiments.OnboardingRedesignRecoveryBackup, + OnboardingRedesignRecoveryBackupProperties.Enabled, + false, + ) + addUnitagClaim({ address, username: unitag, avatarUri: imageUri }) // Handle case navigating from onboarding navigate(MobileScreens.OnboardingStack, { - screen: OnboardingScreens.WelcomeWallet, + screen: onboardingExperimentEnabled ? OnboardingScreens.Notifications : OnboardingScreens.WelcomeWallet, params: { importType: ImportType.CreateNew, entryPoint: OnboardingEntryPoint.FreshInstallOrReplace, diff --git a/apps/mobile/src/features/unitags/ClaimUnitagScreen.tsx b/apps/mobile/src/features/unitags/ClaimUnitagScreen.tsx index 427cdf2c74e..aae88ed39ec 100644 --- a/apps/mobile/src/features/unitags/ClaimUnitagScreen.tsx +++ b/apps/mobile/src/features/unitags/ClaimUnitagScreen.tsx @@ -18,6 +18,8 @@ import { TextInput } from 'uniswap/src/components/input/TextInput' import { Pill } from 'uniswap/src/components/pill/Pill' import { LearnMoreLink } from 'uniswap/src/components/text/LearnMoreLink' import { uniswapUrls } from 'uniswap/src/constants/urls' +import { Experiments, OnboardingRedesignRecoveryBackupProperties } from 'uniswap/src/features/gating/experiments' +import { getExperimentValue } from 'uniswap/src/features/gating/hooks' import Trace from 'uniswap/src/features/telemetry/Trace' import { ElementName, ModalName, UnitagEventName } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' @@ -145,10 +147,16 @@ export function ClaimUnitagScreen({ navigation, route }: Props): JSX.Element { } const onPressMaybeLater = (): void => { + const onboardingExperimentEnabled = getExperimentValue( + Experiments.OnboardingRedesignRecoveryBackup, + OnboardingRedesignRecoveryBackupProperties.Enabled, + false, + ) + sendAnalyticsEvent(UnitagEventName.UnitagOnboardingActionTaken, { action: 'later' }) // Navigate to next screen if in onboarding navigate(MobileScreens.OnboardingStack, { - screen: OnboardingScreens.WelcomeWallet, + screen: onboardingExperimentEnabled ? OnboardingScreens.Notifications : OnboardingScreens.WelcomeWallet, params: { importType: ImportType.CreateNew, entryPoint: OnboardingEntryPoint.FreshInstallOrReplace, @@ -377,18 +385,23 @@ export function ClaimUnitagScreen({ navigation, route }: Props): JSX.Element { )} - {showInfoModal && setShowInfoModal(false)} />} - {showClaimPeriodInfoModal && ( - setShowClaimPeriodInfoModal(false)} /> - )} + setShowInfoModal(false)} /> + + setShowClaimPeriodInfoModal(false)} + /> ) } const InfoModal = ({ + isOpen, unitagAddress, onClose, }: { + isOpen: boolean unitagAddress: string | undefined onClose: () => void }): JSX.Element => { @@ -436,6 +449,7 @@ const InfoModal = ({ } + isOpen={isOpen} modalName={ModalName.TooltipContent} title={t('unitags.onboarding.info.title')} onClose={onClose} @@ -443,7 +457,15 @@ const InfoModal = ({ ) } -const ClaimPeriodInfoModal = ({ onClose, username }: { onClose: () => void; username: string }): JSX.Element => { +const ClaimPeriodInfoModal = ({ + isOpen, + onClose, + username, +}: { + isOpen: boolean + onClose: () => void + username: string +}): JSX.Element => { const colors = useSporeColors() const { t } = useTranslation() @@ -453,6 +475,7 @@ const ClaimPeriodInfoModal = ({ onClose, username }: { onClose: () => void; user caption={t('unitags.onboarding.claimPeriod.description', { username })} closeText={t('common.button.close')} icon={} + isOpen={isOpen} modalName={ModalName.ENSClaimPeriod} title={t('unitags.onboarding.claimPeriod.title')} onClose={onClose} diff --git a/apps/mobile/src/features/unitags/EditUnitagProfileScreen.tsx b/apps/mobile/src/features/unitags/EditUnitagProfileScreen.tsx index 7adbf15502a..81737097a16 100644 --- a/apps/mobile/src/features/unitags/EditUnitagProfileScreen.tsx +++ b/apps/mobile/src/features/unitags/EditUnitagProfileScreen.tsx @@ -18,6 +18,7 @@ import { Pen, TripleDots } from 'ui/src/components/icons' import { borderRadii, fonts, iconSizes, imageSizes, spacing } from 'ui/src/theme' import { useExtractedColors } from 'ui/src/utils/colors' import { TextInput } from 'uniswap/src/components/input/TextInput' +import { useENS } from 'uniswap/src/features/ens/useENS' import { UnitagEventName } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { useUnitagUpdater } from 'uniswap/src/features/unitags/context' @@ -30,7 +31,6 @@ import { logger } from 'utilities/src/logger/logger' import { isIOS } from 'utilities/src/platform' import { normalizeTwitterUsername } from 'utilities/src/primitives/string' import { DisplayNameText } from 'wallet/src/components/accounts/DisplayNameText' -import { useENS } from 'wallet/src/features/ens/useENS' import { pushNotification } from 'wallet/src/features/notifications/slice' import { AppNotificationType } from 'wallet/src/features/notifications/types' import { updateUnitagMetadata } from 'wallet/src/features/unitags/api' diff --git a/apps/mobile/src/features/walletConnect/signWcRequestSaga.ts b/apps/mobile/src/features/walletConnect/signWcRequestSaga.ts index c008cd87b51..81fe10840cb 100644 --- a/apps/mobile/src/features/walletConnect/signWcRequestSaga.ts +++ b/apps/mobile/src/features/walletConnect/signWcRequestSaga.ts @@ -3,13 +3,13 @@ import { wcWeb3Wallet } from 'src/features/walletConnect/saga' import { TransactionRequest, UwuLinkErc20Request } from 'src/features/walletConnect/walletConnectSlice' import { call, put } from 'typed-redux-saga' import { AssetType } from 'uniswap/src/entities/assets' +import { TransactionOriginType, TransactionType } from 'uniswap/src/features/transactions/types/transactionDetails' import { UniverseChainId, WalletChainId } from 'uniswap/src/types/chains' import { DappInfo, EthMethod, EthSignMethod, UwULinkMethod, WalletConnectEvent } from 'uniswap/src/types/walletConnect' import { logger } from 'utilities/src/logger/logger' import { pushNotification } from 'wallet/src/features/notifications/slice' import { AppNotificationType } from 'wallet/src/features/notifications/types' import { SendTransactionParams, sendTransaction } from 'wallet/src/features/transactions/sendTransactionSaga' -import { TransactionType } from 'wallet/src/features/transactions/types' import { Account } from 'wallet/src/features/wallet/accounts/types' import { getSignerManager } from 'wallet/src/features/wallet/context' import { signMessage, signTypedDataMessage } from 'wallet/src/features/wallet/signing/signing' @@ -69,6 +69,7 @@ export function* signWcRequest(params: SignMessageParams | SignTransactionParams tokenAddress: params.request.tokenAddress, currencyAmountRaw: params.request.amount, }, + transactionOriginType: TransactionOriginType.External, } const { transactionResponse } = yield* call(sendTransaction, txParams) signature = transactionResponse.hash @@ -83,6 +84,7 @@ export function* signWcRequest(params: SignMessageParams | SignTransactionParams type: TransactionType.WCConfirm, dapp: params.dapp, }, + transactionOriginType: TransactionOriginType.External, } const { transactionResponse } = yield* call(sendTransaction, txParams) signature = transactionResponse.hash diff --git a/apps/mobile/src/screens/DevScreen.tsx b/apps/mobile/src/screens/DevScreen.tsx index c8a0966090a..369e5eca45f 100644 --- a/apps/mobile/src/screens/DevScreen.tsx +++ b/apps/mobile/src/screens/DevScreen.tsx @@ -6,6 +6,7 @@ import { BackButton } from 'src/components/buttons/BackButton' import { Screen } from 'src/components/layout/Screen' import { Flex, Text, TouchableArea, useDeviceInsets } from 'ui/src' import { spacing } from 'ui/src/theme' +import { resetDismissedWarnings } from 'uniswap/src/features/tokens/slice/slice' import { MobileScreens } from 'uniswap/src/types/screens/mobile' import { logger } from 'utilities/src/logger/logger' import { UniconSampleSheet } from 'wallet/src/components/DevelopmentOnly/UniconSampleSheet' @@ -13,7 +14,6 @@ import { Switch } from 'wallet/src/components/buttons/Switch' import { pushNotification } from 'wallet/src/features/notifications/slice' import { AppNotificationType } from 'wallet/src/features/notifications/types' import { createOnboardingAccount } from 'wallet/src/features/onboarding/createOnboardingAccount' -import { resetDismissedWarnings } from 'wallet/src/features/tokens/tokensSlice' import { createAccountsActions } from 'wallet/src/features/wallet/create/createAccountsSaga' import { useActiveAccount } from 'wallet/src/features/wallet/hooks' import { selectSortedSignerMnemonicAccounts } from 'wallet/src/features/wallet/selectors' diff --git a/apps/mobile/src/screens/ExchangeTransferConnecting.tsx b/apps/mobile/src/screens/ExchangeTransferConnecting.tsx index 6609a96a5f9..47f0dac904f 100644 --- a/apps/mobile/src/screens/ExchangeTransferConnecting.tsx +++ b/apps/mobile/src/screens/ExchangeTransferConnecting.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useState } from 'react' +import { useCallback, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { useDispatch } from 'react-redux' import { Screen } from 'src/components/layout/Screen' @@ -19,7 +19,6 @@ import { useFiatOnRampTransactionCreator } from 'wallet/src/features/fiatOnRamp/ import { ImageUri } from 'wallet/src/features/images/ImageUri' import { pushNotification } from 'wallet/src/features/notifications/slice' import { AppNotificationType } from 'wallet/src/features/notifications/types' -import { FiatPurchaseTransactionInfo } from 'wallet/src/features/transactions/types' import { useActiveAccountAddressWithThrow } from 'wallet/src/features/wallet/hooks' // Design decision @@ -37,16 +36,10 @@ export function ExchangeTransferConnecting({ const activeAccountAddress = useActiveAccountAddressWithThrow() const [timeoutElapsed, setTimeoutElapsed] = useState(false) - const initialTypeInfo = useMemo>( - () => ({ serviceProviderLogo: serviceProvider.logos, serviceProvider: serviceProvider.serviceProvider }), - [serviceProvider], - ) - const { externalTransactionId, dispatchAddTransaction } = useFiatOnRampTransactionCreator( activeAccountAddress, UniverseChainId.Mainnet, serviceProvider.serviceProvider, - initialTypeInfo, ) const onError = useCallback((): void => { diff --git a/apps/mobile/src/screens/ExploreScreen.tsx b/apps/mobile/src/screens/ExploreScreen.tsx index 1c4cda83734..f6810d097a0 100644 --- a/apps/mobile/src/screens/ExploreScreen.tsx +++ b/apps/mobile/src/screens/ExploreScreen.tsx @@ -29,7 +29,7 @@ export function ExploreScreen(): JSX.Element { const { isSheetReady } = useBottomSheetContext() // The ExploreStack is not directly accessible from outside - // (e.g., navigating from Home to NFTItem within ExploreStack), due to its mount within BottomSheetModal. + // (e.g., navigating from Home to NFTItem within ExploreStack), due to its mount within Modal. // To bypass this limitation, we use an initialState to define a specific screen within ExploreStack. useEffect(() => { if (modalInitialState) { diff --git a/apps/mobile/src/screens/FiatOnRampConnecting.tsx b/apps/mobile/src/screens/FiatOnRampConnecting.tsx index 80f0fd9cc55..7778b396a1f 100644 --- a/apps/mobile/src/screens/FiatOnRampConnecting.tsx +++ b/apps/mobile/src/screens/FiatOnRampConnecting.tsx @@ -1,6 +1,6 @@ import { NativeStackScreenProps } from '@react-navigation/native-stack' import { skipToken } from '@reduxjs/toolkit/query/react' -import React, { useCallback, useEffect, useMemo, useState } from 'react' +import React, { useCallback, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { useDispatch } from 'react-redux' import { FiatOnRampStackParamList } from 'src/app/navigation/types' @@ -16,6 +16,7 @@ import { ServiceProviderLogoStyles } from 'uniswap/src/features/fiatOnRamp/const import { getOptionalServiceProviderLogo } from 'uniswap/src/features/fiatOnRamp/utils' import { FiatOnRampEventName, ModalName } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' +import { forceFetchFiatOnRampTransactions } from 'uniswap/src/features/transactions/slice' import { UniverseChainId } from 'uniswap/src/types/chains' import { FiatOnRampScreens } from 'uniswap/src/types/screens/mobile' import { openUri } from 'uniswap/src/utils/linking' @@ -26,8 +27,6 @@ import { ImageUri } from 'wallet/src/features/images/ImageUri' import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext' import { pushNotification } from 'wallet/src/features/notifications/slice' import { AppNotificationType } from 'wallet/src/features/notifications/types' -import { forceFetchFiatOnRampTransactions } from 'wallet/src/features/transactions/slice' -import { FiatPurchaseTransactionInfo } from 'wallet/src/features/transactions/types' import { useActiveAccountAddressWithThrow } from 'wallet/src/features/wallet/hooks' // Design decision @@ -46,19 +45,10 @@ export function FiatOnRampConnectingScreen({ navigation }: Props): JSX.Element | useFiatOnRampContext() const serviceProvider = selectedQuote?.serviceProviderDetails - const initialTypeInfo = useMemo>( - () => ({ - serviceProviderLogo: serviceProvider?.logos, - serviceProvider: serviceProvider?.serviceProvider, - }), - [serviceProvider], - ) - const { externalTransactionId, dispatchAddTransaction } = useFiatOnRampTransactionCreator( activeAccountAddress, quoteCurrency.currencyInfo?.currency.chainId ?? UniverseChainId.Mainnet, serviceProvider?.serviceProvider, - initialTypeInfo, ) const onError = useCallback((): void => { diff --git a/apps/mobile/src/screens/FiatOnRampScreen.tsx b/apps/mobile/src/screens/FiatOnRampScreen.tsx index 9c9e7088635..46d006e44da 100644 --- a/apps/mobile/src/screens/FiatOnRampScreen.tsx +++ b/apps/mobile/src/screens/FiatOnRampScreen.tsx @@ -16,6 +16,7 @@ import { Flex, Text, isWeb, useIsDarkMode, useIsShortMobileDevice } from 'ui/src import { AnimatedFlex } from 'ui/src/components/layout/AnimatedFlex' import { useBottomSheetContext } from 'uniswap/src/components/modals/BottomSheetContext' import { HandleBar } from 'uniswap/src/components/modals/HandleBar' +import { MAX_FIAT_INPUT_DECIMALS } from 'uniswap/src/constants/transactions' import { FiatOnRampCountryPicker } from 'uniswap/src/features/fiatOnRamp/FiatOnRampCountryPicker' import { useFiatOnRampAggregatorGetCountryQuery } from 'uniswap/src/features/fiatOnRamp/api' import { @@ -49,7 +50,6 @@ import { type Props = NativeStackScreenProps -const MAX_FIAT_INPUT_DECIMALS = 2 const ON_SELECTION_CHANGE_WAIT_TIME_MS = 500 function selectInitialQuote(quotes: FORQuote[] | undefined): { diff --git a/apps/mobile/src/screens/HomeScreen.tsx b/apps/mobile/src/screens/HomeScreen.tsx index 9d1c11906c0..3d307d6bf49 100644 --- a/apps/mobile/src/screens/HomeScreen.tsx +++ b/apps/mobile/src/screens/HomeScreen.tsx @@ -49,6 +49,7 @@ import { useWalletRestore } from 'src/features/wallet/hooks' import { removePendingSession } from 'src/features/walletConnect/walletConnectSlice' import { HomeScreenTabIndex } from 'src/screens/HomeScreenTabIndex' import { hideSplashScreen } from 'src/utils/splashScreen' +import { useOpenBackupReminderModal } from 'src/utils/useOpenBackupReminderModal' import { Flex, Text, TouchableArea, useDeviceInsets, useHapticFeedback, useMedia, useSporeColors } from 'ui/src' import ReceiveIcon from 'ui/src/assets/icons/arrow-down-circle.svg' import BuyIcon from 'ui/src/assets/icons/buy.svg' @@ -112,7 +113,6 @@ export function HomeScreen(props?: AppStackScreenProp): JSX. const { hapticFeedback } = useHapticFeedback() const hasSkippedUnitagPrompt = useSelector(selectHasSkippedUnitagPrompt) - const showFeedTab = useFeatureFlag(FeatureFlags.FeedTab) const portfolioValueModifiers = usePortfolioValueModifiers(activeAccount.address) ?? [] @@ -144,7 +144,10 @@ export function HomeScreen(props?: AppStackScreenProp): JSX. // Report balances at most every 24 hours, checking every 15 seconds when app is open useLastBalancesReporter() - const [tabIndex, setTabIndex] = useState(props?.route?.params?.tab ?? HomeScreenTabIndex.Tokens) + const [routeTabIndex, setRouteTabIndex] = useState(props?.route?.params?.tab ?? HomeScreenTabIndex.Tokens) + // Ensures that tabIndex has the proper value between the empty state and non-empty state + const tabIndex = showOnboardingRedesign ? 0 : routeTabIndex + // Necessary to declare these as direct dependencies due to race condition with initializing react-i18next and useMemo const tokensTitle = t('home.tokens.title') const nftsTitle = t('home.nfts.title') @@ -181,7 +184,7 @@ export function HomeScreen(props?: AppStackScreenProp): JSX. if (newTabIndex === undefined) { return } - setTabIndex(newTabIndex) + setRouteTabIndex(newTabIndex) }, [props?.route.params?.tab], ) @@ -297,11 +300,11 @@ export function HomeScreen(props?: AppStackScreenProp): JSX. if (showOnboardingRedesign) { exploreTabScrollRef.current?.scrollToOffset({ offset: 0, animated: true }) } else if (currentTabIndex.value === HomeScreenTabIndex.NFTs && isNftTabsAtTop.value) { - setTabIndex(HomeScreenTabIndex.Tokens) + setRouteTabIndex(HomeScreenTabIndex.Tokens) } else if (currentTabIndex.value === HomeScreenTabIndex.NFTs) { nftsTabScrollRef.current?.scrollToOffset({ offset: 0, animated: true }) } else if (currentTabIndex.value === HomeScreenTabIndex.Activity && isActivityTabAtTop.value) { - setTabIndex(HomeScreenTabIndex.NFTs) + setRouteTabIndex(HomeScreenTabIndex.NFTs) } else if (currentTabIndex.value === HomeScreenTabIndex.Activity) { activityTabScrollRef.current?.scrollToOffset({ offset: 0, animated: true }) } else { @@ -341,9 +344,21 @@ export function HomeScreen(props?: AppStackScreenProp): JSX. const { sync } = useScrollSync(currentTabIndex, scrollPairs, headerConfig) + // Shows an info modal instead of FOR flow if country is listed behind this flag + const disableForKorea = useFeatureFlag(FeatureFlags.DisableFiatOnRampKorea) + const cexTransferProviders = useCexTransferProviders() - const onPressBuy = useCallback(() => dispatch(openModal({ name: ModalName.FiatOnRampAggregator })), [dispatch]) + const onPressBuy = useCallback( + () => + dispatch( + openModal({ + name: disableForKorea ? ModalName.KoreaCexTransferInfoModal : ModalName.FiatOnRampAggregator, + }), + ), + [dispatch, disableForKorea], + ) + const onPressScan = useCallback(() => { // in case we received a pending session from a previous scan after closing modal dispatch(removePendingSession()) @@ -408,8 +423,10 @@ export function HomeScreen(props?: AppStackScreenProp): JSX. const { canClaimUnitag } = useCanActiveAddressClaimUnitag() - const shouldPromptUnitag = - activeAccount.type === AccountType.SignerMnemonic && !hasSkippedUnitagPrompt && canClaimUnitag + // This hooks handles the logic for when to open the BackupReminderModal + useOpenBackupReminderModal(activeAccount) + + const shouldPromptUnitag = isSignerAccount && !hasSkippedUnitagPrompt && canClaimUnitag const viewOnlyLabel = t('home.warning.viewOnly') const promoBanner = useMemo(() => { @@ -727,7 +744,7 @@ export function HomeScreen(props?: AppStackScreenProp): JSX. renderScene={renderTab} renderTabBar={renderTabBar} screenName={MobileScreens.Home} - onIndexChange={setTabIndex} + onIndexChange={setRouteTabIndex} /> diff --git a/apps/mobile/src/screens/Import/OnDeviceRecoveryScreen.tsx b/apps/mobile/src/screens/Import/OnDeviceRecoveryScreen.tsx index 15eeb0572fa..88f72003bb7 100644 --- a/apps/mobile/src/screens/Import/OnDeviceRecoveryScreen.tsx +++ b/apps/mobile/src/screens/Import/OnDeviceRecoveryScreen.tsx @@ -1,4 +1,5 @@ import { NativeStackScreenProps } from '@react-navigation/native-stack' +import { ReactNavigationPerformanceView } from '@shopify/react-native-performance-navigation' import { SharedEventName } from '@uniswap/analytics-events' import dayjs from 'dayjs' import React, { useCallback, useEffect, useState } from 'react' @@ -22,6 +23,7 @@ import { useDynamicConfigValue } from 'uniswap/src/features/gating/hooks' import Trace from 'uniswap/src/features/telemetry/Trace' import { ElementName, ModalName } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' +import { WarningSeverity } from 'uniswap/src/features/transactions/WarningModal/types' import { TestID } from 'uniswap/src/test/fixtures/testIDs' import { ImportType, OnboardingEntryPoint } from 'uniswap/src/types/onboarding' import { OnboardingScreens } from 'uniswap/src/types/screens/mobile' @@ -29,7 +31,6 @@ import { logger } from 'utilities/src/logger/logger' import { useTimeout } from 'utilities/src/time/timing' import { WarningModal } from 'wallet/src/components/modals/WarningModal/WarningModal' import { useOnboardingContext } from 'wallet/src/features/onboarding/OnboardingContext' -import { WarningSeverity } from 'wallet/src/features/transactions/WarningModal/types' import { Keyring } from 'wallet/src/features/wallet/Keyring/Keyring' import { SignerMnemonicAccount } from 'wallet/src/features/wallet/accounts/types' @@ -175,84 +176,89 @@ export function OnDeviceRecoveryScreen({ const showAllWallets = !screenLoading && !hasAnySignificantWallets return ( - - - - - - {t('onboarding.import.onDeviceRecovery.title')} - - {t('onboarding.import.onDeviceRecovery.subtitle')} - - - - - {mnemonicIds.map((mnemonicId) => ( - { - setSelectedMnemonicId(mnemonicId) - setSelectedRecoveryWalletInfos(recoveryAddressesInfos) - setShowConfirmationModal(true) - - sendAnalyticsEvent(SharedEventName.ELEMENT_CLICKED, { - element: ElementName.OnDeviceRecoveryWallet, - }) - }} - onPressViewRecoveryPhrase={() => { - navigation.navigate(OnboardingScreens.OnDeviceRecoveryViewSeedPhrase, { - mnemonicId, - importType: ImportType.OnDeviceRecovery, - entryPoint: OnboardingEntryPoint.FreshInstallOrReplace, - }) - }} - /> - ))} - {screenLoading - ? Array(LOADING_COUNT) - .fill(0) - .map((_, index) => ( - - - - )) - : null} + + + + + + + {t('onboarding.import.onDeviceRecovery.title')} + + {t('onboarding.import.onDeviceRecovery.subtitle')} + - + + + {mnemonicIds.map((mnemonicId) => ( + { + setSelectedMnemonicId(mnemonicId) + setSelectedRecoveryWalletInfos(recoveryAddressesInfos) + setShowConfirmationModal(true) - - - - {t('onboarding.import.onDeviceRecovery.other_options.label')} - - - - - {t('onboarding.import.onDeviceRecovery.other_options')} - - - + sendAnalyticsEvent(SharedEventName.ELEMENT_CLICKED, { + element: ElementName.OnDeviceRecoveryWallet, + }) + }} + onPressViewRecoveryPhrase={() => { + navigation.navigate(OnboardingScreens.OnDeviceRecoveryViewSeedPhrase, { + mnemonicId, + importType: ImportType.OnDeviceRecovery, + entryPoint: OnboardingEntryPoint.FreshInstallOrReplace, + }) + }} + /> + ))} + {screenLoading + ? Array(LOADING_COUNT) + .fill(0) + .map((_, index) => ( + + + + )) + : null} + + + + + + + {t('onboarding.import.onDeviceRecovery.other_options.label')} + + + + + {t('onboarding.import.onDeviceRecovery.other_options')} + + + + - - {showConfirmationModal && ( } + isOpen={showConfirmationModal} modalName={ModalName.OnDeviceRecoveryConfirmation} severity={WarningSeverity.None} title={t('onboarding.import.onDeviceRecovery.warning.title')} onClose={onPressClose} onConfirm={onPressConfirm} /> - )} - - + + + ) } diff --git a/apps/mobile/src/screens/Import/RestoreCloudBackupPasswordScreen.tsx b/apps/mobile/src/screens/Import/RestoreCloudBackupPasswordScreen.tsx index f97b80cae14..ad7a767df4f 100644 --- a/apps/mobile/src/screens/Import/RestoreCloudBackupPasswordScreen.tsx +++ b/apps/mobile/src/screens/Import/RestoreCloudBackupPasswordScreen.tsx @@ -111,7 +111,7 @@ export function RestoreCloudBackupPasswordScreen({ navigation, route: { params } async function checkCorrectPassword(): Promise { try { await restoreMnemonicFromCloudStorage(params.mnemonicId, enteredPassword) - await generateImportedAccounts(params.mnemonicId, BackupType.Cloud) + await generateImportedAccounts({ mnemonicId: params.mnemonicId, backupType: BackupType.Cloud }) dispatch(resetPasswordAttempts()) // restore flow is handled in saga after `restoreMnemonicComplete` is dispatched diff --git a/apps/mobile/src/screens/Import/SeedPhraseInputScreen.android.mock.tsx b/apps/mobile/src/screens/Import/SeedPhraseInputScreen.android.mock.tsx index 916d45ae561..e084588f9a6 100644 --- a/apps/mobile/src/screens/Import/SeedPhraseInputScreen.android.mock.tsx +++ b/apps/mobile/src/screens/Import/SeedPhraseInputScreen.android.mock.tsx @@ -31,7 +31,7 @@ type Props = NativeStackScreenProps { const { error, invalidWord } = validateMnemonic(value) diff --git a/apps/mobile/src/screens/Import/SeedPhraseInputScreen.tsx b/apps/mobile/src/screens/Import/SeedPhraseInputScreen.tsx index 39aa86e3acf..f816cf0f6a9 100644 --- a/apps/mobile/src/screens/Import/SeedPhraseInputScreen.tsx +++ b/apps/mobile/src/screens/Import/SeedPhraseInputScreen.tsx @@ -54,7 +54,7 @@ export function SeedPhraseInputScreen({ navigation, route: { params } }: Props): const handleNext = useCallback( async (storedMnemonicId: string) => { - await generateImportedAccounts(storedMnemonicId, BackupType.Manual) + await generateImportedAccounts({ mnemonicId: storedMnemonicId, backupType: BackupType.Manual }) // restore flow is handled in saga after `restoreMnemonicComplete` is dispatched if (!isRestoringMnemonic) { diff --git a/apps/mobile/src/screens/Import/SelectWalletScreen.tsx b/apps/mobile/src/screens/Import/SelectWalletScreen.tsx index fe723ac93e3..4bec9a11227 100644 --- a/apps/mobile/src/screens/Import/SelectWalletScreen.tsx +++ b/apps/mobile/src/screens/Import/SelectWalletScreen.tsx @@ -19,9 +19,16 @@ type Props = NativeStackScreenProps ({ useOnboardingContext: jest.fn().mockReturnValue({ - getOnboardingAccountAddress: jest.fn().mockReturnValue('mockedAccountAddress'), - getImportedAccountsAddresses: jest.fn(), + getOnboardingOrImportedAccount: jest.fn().mockReturnValue({ address: 'mockedAccountAddress' }), hasBackup: jest.fn(), }), + useCreateImportedAccountsFromMnemonicIfNone: jest.fn(), })) const navigationProp = {} as CompositeNavigationProp< diff --git a/apps/mobile/src/screens/Onboarding/BackupScreen.tsx b/apps/mobile/src/screens/Onboarding/BackupScreen.tsx index aa6ae6cb545..5f7c5feed3e 100644 --- a/apps/mobile/src/screens/Onboarding/BackupScreen.tsx +++ b/apps/mobile/src/screens/Onboarding/BackupScreen.tsx @@ -17,13 +17,14 @@ import { iconSizes } from 'ui/src/theme' import Trace from 'uniswap/src/features/telemetry/Trace' import { ElementName } from 'uniswap/src/features/telemetry/constants' import { TestID } from 'uniswap/src/test/fixtures/testIDs' -import { ImportType } from 'uniswap/src/types/onboarding' +import { ImportType, OnboardingEntryPoint } from 'uniswap/src/types/onboarding' import { MobileScreens, OnboardingScreens } from 'uniswap/src/types/screens/mobile' import { getCloudProviderName } from 'uniswap/src/utils/cloud-backup/getCloudProviderName' import { isAndroid } from 'utilities/src/platform' import { useAsyncData } from 'utilities/src/react/hooks' import { useOnboardingContext } from 'wallet/src/features/onboarding/OnboardingContext' import { BackupType } from 'wallet/src/features/wallet/accounts/types' +import { useActiveAccount } from 'wallet/src/features/wallet/hooks' import { openSettings } from 'wallet/src/utils/linking' type Props = CompositeScreenProps< @@ -39,15 +40,14 @@ export function BackupScreen({ navigation, route: { params } }: Props): JSX.Elem const { data: cloudStorageAvailable } = useAsyncData(isCloudStorageAvailable) - const { getImportedAccountsAddresses, getOnboardingAccountAddress, hasBackup } = useOnboardingContext() - const onboardingAccountAddress = getOnboardingAccountAddress() - const importedAccountsAddresses = getImportedAccountsAddresses() + const { getOnboardingOrImportedAccount, hasBackup } = useOnboardingContext() + const onboardingContextAccount = getOnboardingOrImportedAccount() + const activeAccount = useActiveAccount() + const address = onboardingContextAccount?.address || activeAccount?.address - const address = onboardingAccountAddress || importedAccountsAddresses?.[0] - - if (!address) { - throw Error('No account available to backup') - } + const isCreatingNew = params?.importType === ImportType.CreateNew + const screenTitle = isCreatingNew ? t('onboarding.backup.title.new') : t('onboarding.backup.title.existing') + const fromBackupCard = params.entryPoint === OnboardingEntryPoint.BackupCard const renderHeaderLeft = useCallback( () => ( @@ -70,12 +70,20 @@ export function BackupScreen({ navigation, route: { params } }: Props): JSX.Elem } }) + if (!address) { + throw Error('No account available to backup') + } + const onPressNext = (): void => { - navigation.navigate({ - name: OnboardingScreens.Notifications, - params, - merge: true, - }) + if (fromBackupCard) { + navigation.navigate(MobileScreens.Home) + } else { + navigation.navigate({ + name: OnboardingScreens.Notifications, + params, + merge: true, + }) + } } const onPressEducationButton = (): void => { @@ -113,7 +121,7 @@ export function BackupScreen({ navigation, route: { params } }: Props): JSX.Elem } const onPressManualBackup = (): void => { - navigate({ name: OnboardingScreens.BackupManual, params, merge: true }) + navigate({ name: OnboardingScreens.BackupManual, params: { ...params, address }, merge: true }) } const showSkipOption = @@ -122,8 +130,6 @@ export function BackupScreen({ navigation, route: { params } }: Props): JSX.Elem const hasCloudBackup = hasBackup(address, BackupType.Cloud) const hasManualBackup = hasBackup(address, BackupType.Manual) - const isCreatingNew = params?.importType === ImportType.CreateNew - const screenTitle = isCreatingNew ? t('onboarding.backup.title.new') : t('onboarding.backup.title.existing') const options = [] options.push( , ) - if (isCreatingNew) { + if (isCreatingNew || fromBackupCard) { options.push( export function CloudBackupPasswordConfirmScreen({ navigation, route: { params } }: Props): JSX.Element { const { t } = useTranslation() + const { password } = params + const [showSpeedBumpModal, setShowSpeedBumpModal] = useState(false) + + const onboardingExperimentEnabled = useExperimentValue( + Experiments.OnboardingRedesignRecoveryBackup, + OnboardingRedesignRecoveryBackupProperties.Enabled, + false, + ) + const navigateToNextScreen = useCallback((): void => { navigation.navigate({ name: OnboardingScreens.BackupCloudProcessing, @@ -24,19 +37,30 @@ export function CloudBackupPasswordConfirmScreen({ navigation, route: { params } return ( - + setShowSpeedBumpModal(true) : undefined} + /> } subtitle={t('onboarding.cloud.confirm.description')} title={t('onboarding.cloud.confirm.title')} > + + {onboardingExperimentEnabled && showSpeedBumpModal && ( + setShowSpeedBumpModal(false)} + onContinue={navigateToNextScreen} + /> + )} ) diff --git a/apps/mobile/src/screens/Onboarding/CloudBackupProcessingScreen.tsx b/apps/mobile/src/screens/Onboarding/CloudBackupProcessingScreen.tsx index 7ddb5b10060..786025458e8 100644 --- a/apps/mobile/src/screens/Onboarding/CloudBackupProcessingScreen.tsx +++ b/apps/mobile/src/screens/Onboarding/CloudBackupProcessingScreen.tsx @@ -1,9 +1,11 @@ import { NativeStackScreenProps } from '@react-navigation/native-stack' import React from 'react' +import { navigate } from 'src/app/navigation/rootNavigation' import { OnboardingStackParamList } from 'src/app/navigation/types' import { Screen } from 'src/components/layout/Screen' import { CloudBackupProcessingAnimation } from 'src/features/CloudBackup/CloudBackupProcessingAnimation' -import { OnboardingScreens } from 'uniswap/src/types/screens/mobile' +import { OnboardingEntryPoint } from 'uniswap/src/types/onboarding' +import { MobileScreens, OnboardingScreens } from 'uniswap/src/types/screens/mobile' type Props = NativeStackScreenProps @@ -15,11 +17,15 @@ export function CloudBackupProcessingScreen({ }, }: Props): JSX.Element | null { const onBackupComplete = (): void => { - navigation.navigate({ - name: OnboardingScreens.Notifications, - params: { importType, entryPoint }, - merge: true, - }) + if (entryPoint === OnboardingEntryPoint.BackupCard) { + navigate(MobileScreens.Home) + } else { + navigation.navigate({ + name: OnboardingScreens.Notifications, + params: { importType, entryPoint }, + merge: true, + }) + } } const onErrorPress = (): void => { diff --git a/apps/mobile/src/screens/Onboarding/LandingScreen.tsx b/apps/mobile/src/screens/Onboarding/LandingScreen.tsx index 7687e70783b..ebaa3edfc94 100644 --- a/apps/mobile/src/screens/Onboarding/LandingScreen.tsx +++ b/apps/mobile/src/screens/Onboarding/LandingScreen.tsx @@ -1,4 +1,5 @@ import { NativeStackScreenProps } from '@react-navigation/native-stack' +import { ReactNavigationPerformanceView } from '@shopify/react-native-performance-navigation' import React, { useCallback, useEffect } from 'react' import { useTranslation } from 'react-i18next' import { useAnimatedStyle, useSharedValue, withDelay, withTiming } from 'react-native-reanimated' @@ -66,62 +67,68 @@ export function LandingScreen({ navigation }: Props): JSX.Element { useTimeout(hideSplashScreen, 1) return ( - - - - - - - - - + + + + + + + + + + + + + {t('onboarding.landing.button.create')} + + + + + => { + if (isDevEnv()) { + await hapticFeedback.selection() + dispatch(openModal({ name: ModalName.Experiments })) + } + }} + onPress={onPressImportWallet} > - - {t('onboarding.landing.button.create')} + + {t('onboarding.landing.button.add')} + + + - - - => { - if (isDevEnv()) { - await hapticFeedback.selection() - dispatch(openModal({ name: ModalName.Experiments })) - } - }} - onPress={onPressImportWallet} - > - - {t('onboarding.landing.button.add')} - - - - - - - - - + + + + ) } diff --git a/apps/mobile/src/screens/Onboarding/ManualBackupScreen.tsx b/apps/mobile/src/screens/Onboarding/ManualBackupScreen.tsx index 80127099f7c..4e677641ab1 100644 --- a/apps/mobile/src/screens/Onboarding/ManualBackupScreen.tsx +++ b/apps/mobile/src/screens/Onboarding/ManualBackupScreen.tsx @@ -3,23 +3,31 @@ import { SharedEventName } from '@uniswap/analytics-events' import { addScreenshotListener } from 'expo-screen-capture' import React, { useEffect, useReducer, useState } from 'react' import { useTranslation } from 'react-i18next' +import { useDispatch } from 'react-redux' +import { navigate } from 'src/app/navigation/rootNavigation' import { OnboardingStackParamList } from 'src/app/navigation/types' -import { HiddenMnemonicWordView } from 'src/components/mnemonic/HiddenMnemonicWordView' import { MnemonicConfirmation } from 'src/components/mnemonic/MnemonicConfirmation' import { MnemonicDisplay } from 'src/components/mnemonic/MnemonicDisplay' import { useLockScreenOnBlur } from 'src/features/authentication/lockScreenContext' +import { BackupSpeedBumpModal } from 'src/features/onboarding/BackupSpeedBumpModal' import { OnboardingScreen } from 'src/features/onboarding/OnboardingScreen' import { Button, Flex, Text, useMedia, useSporeColors } from 'ui/src' import LockIcon from 'ui/src/assets/icons/lock.svg' +import { EyeSlash, FileListLock, Key, Pen } from 'ui/src/components/icons' import { iconSizes } from 'ui/src/theme' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' +import { Experiments, OnboardingRedesignRecoveryBackupProperties } from 'uniswap/src/features/gating/experiments' +import { useExperimentValue } from 'uniswap/src/features/gating/hooks' import { ModalName } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { TestID } from 'uniswap/src/test/fixtures/testIDs' -import { ManualPageViewScreen, OnboardingScreens } from 'uniswap/src/types/screens/mobile' +import { OnboardingEntryPoint } from 'uniswap/src/types/onboarding' +import { ManualPageViewScreen, MobileScreens, OnboardingScreens } from 'uniswap/src/types/screens/mobile' import { WarningModal } from 'wallet/src/components/modals/WarningModal/WarningModal' import { useOnboardingContext } from 'wallet/src/features/onboarding/OnboardingContext' +import { EditAccountAction, editAccountActions } from 'wallet/src/features/wallet/accounts/editAccountSaga' import { BackupType } from 'wallet/src/features/wallet/accounts/types' +import { useSignerAccountIfExists } from 'wallet/src/features/wallet/hooks' type Props = NativeStackScreenProps @@ -31,29 +39,53 @@ enum View { export function ManualBackupScreen({ navigation, route: { params } }: Props): JSX.Element | null { const { t } = useTranslation() const media = useMedia() - const { getOnboardingAccount, addBackupMethod } = useOnboardingContext() - const onboardingAccount = getOnboardingAccount() + const dispatch = useDispatch() + + const { getOnboardingOrImportedAccount, addBackupMethod } = useOnboardingContext() + const onboardingContextAccount = getOnboardingOrImportedAccount() + const activeAccount = useSignerAccountIfExists(params.address) + + const onboardingExperimentEnabled = useExperimentValue( + Experiments.OnboardingRedesignRecoveryBackup, + OnboardingRedesignRecoveryBackupProperties.Enabled, + false, + ) + + const account = activeAccount || onboardingContextAccount useLockScreenOnBlur() - if (!onboardingAccount) { - throw Error('pendingAccount needs to be defined on ManualBackupScreen') + if (!account) { + throw Error('No account available for manual backup') } - const mnemonicId = onboardingAccount.mnemonicId + const mnemonicId = account.mnemonicId const [showScreenShotWarningModal, setShowScreenShotWarningModal] = useState(false) + const [showSpeedBumpModal, setShowSpeedBumpModal] = useState(false) + const [view, nextView] = useReducer((curView: View) => curView + 1, View.SeedPhrase) - const [continueButtonEnabled, setContinueButtonEnabled] = useState(false) - const [continueButtonPressed, setContinueButtonPressed] = useState(false) + const [confirmContinueButtonEnabled, setConfirmContinueButtonEnabled] = useState(false) + const [confirmContinueButtonPressed, setConfirmContinueButtonPressed] = useState(false) + const [displayContinueButtonEnabled, setDisplayContinueButtonEnabled] = useState(!onboardingExperimentEnabled) // warning modal on seed phrase view const [seedWarningAcknowledged, setSeedWarningAcknowledged] = useState(false) const onValidationSuccessful = (): void => { - setContinueButtonPressed(true) - addBackupMethod(BackupType.Manual) + setConfirmContinueButtonPressed(true) + if (activeAccount) { + dispatch( + editAccountActions.trigger({ + type: EditAccountAction.AddBackupMethod, + address: activeAccount.address, + backupMethod: BackupType.Manual, + }), + ) + } else { + addBackupMethod(BackupType.Manual) + } } useEffect(() => { @@ -66,10 +98,14 @@ export function ManualBackupScreen({ navigation, route: { params } }: Props): JS }, [view]) useEffect(() => { - if (continueButtonPressed && onboardingAccount?.backups?.includes(BackupType.Manual)) { - navigation.replace(OnboardingScreens.Notifications, params) + if (confirmContinueButtonPressed && account?.backups?.includes(BackupType.Manual)) { + if (params.entryPoint === OnboardingEntryPoint.BackupCard) { + navigate(MobileScreens.Home) + } else { + navigation.replace(OnboardingScreens.Notifications, params) + } } - }, [continueButtonPressed, navigation, params, onboardingAccount?.backups]) + }, [confirmContinueButtonPressed, navigation, params, account?.backups]) // Manually log as page views as these screens are not captured in navigation events useEffect(() => { @@ -93,26 +129,37 @@ export function ManualBackupScreen({ navigation, route: { params } }: Props): JS subtitle={t('onboarding.recoveryPhrase.view.subtitle')} title={t('onboarding.recoveryPhrase.view.title')} > - {showScreenShotWarningModal && ( - setShowScreenShotWarningModal(false)} - /> - )} + setShowScreenShotWarningModal(false)} + /> - {seedWarningAcknowledged ? : } + { + setDisplayContinueButtonEnabled(true) + }} + /> - - {!seedWarningAcknowledged && setSeedWarningAcknowledged(true)} />} + {!seedWarningAcknowledged && + (onboardingExperimentEnabled ? ( + setSeedWarningAcknowledged(true)} /> + ) : ( + setSeedWarningAcknowledged(true)} /> + ))} ) case View.SeedPhraseConfirm: @@ -125,17 +172,29 @@ export function ManualBackupScreen({ navigation, route: { params } }: Props): JS } title={media.short ? undefined : t('onboarding.recoveryPhrase.confirm.title')} > - + setContinueButtonEnabled(true)} + onConfirmComplete={(): void => setConfirmContinueButtonEnabled(true)} /> - + + {showSpeedBumpModal && ( + setShowSpeedBumpModal(false)} + onContinue={onValidationSuccessful} + /> + )} ) } @@ -147,8 +206,8 @@ const SeedWarningModal = ({ onPress }: { onPress: () => void }): JSX.Element => const colors = useSporeColors() const { t } = useTranslation() return ( - void }): JSX.Element => {t('onboarding.recoveryPhrase.warning.final.button')} - + + ) +} + +type ManualBackWarningModalProps = { + onBack: () => void + onContinue: () => void +} +function ManualBackWarningModal({ onBack, onContinue }: ManualBackWarningModalProps): JSX.Element { + const { t } = useTranslation() + + const rows = [ + { Icon: Key, text: t('onboarding.backup.manual.displayWarning.note.access') }, + { Icon: Pen, text: t('onboarding.backup.manual.displayWarning.note.storage') }, + { Icon: EyeSlash, text: t('onboarding.backup.manual.displayWarning.note.secure') }, + ] + + return ( + + + + + + + + + + + {t('onboarding.backup.manual.displayWarning.title')} + + + {t('onboarding.backup.manual.displayWarning.description')} + + + + + {rows.map((row, index) => ( + + + + + + {row.text} + + + ))} + + + + + + + + ) } diff --git a/apps/mobile/src/screens/Onboarding/SecuritySetupScreen.tsx b/apps/mobile/src/screens/Onboarding/SecuritySetupScreen.tsx index 81a87080258..b264ec34eed 100644 --- a/apps/mobile/src/screens/Onboarding/SecuritySetupScreen.tsx +++ b/apps/mobile/src/screens/Onboarding/SecuritySetupScreen.tsx @@ -95,9 +95,12 @@ export function SecuritySetupScreen({ route: { params } }: Props): JSX.Element { return ( <> - {showWarningModal && ( - - )} + {isLoadingAccount && ( diff --git a/apps/mobile/src/screens/Onboarding/WelcomeWalletScreen.tsx b/apps/mobile/src/screens/Onboarding/WelcomeWalletScreen.tsx index f5e43968bdf..6478597d4de 100644 --- a/apps/mobile/src/screens/Onboarding/WelcomeWalletScreen.tsx +++ b/apps/mobile/src/screens/Onboarding/WelcomeWalletScreen.tsx @@ -9,6 +9,7 @@ import { useAddBackButton } from 'src/utils/useAddBackButton' import { Button, Flex, Loader, Text, useMedia, useSporeColors } from 'ui/src' import LockIcon from 'ui/src/assets/icons/lock.svg' import { fonts, iconSizes, opacify } from 'ui/src/theme' +import { useENSAvatar } from 'uniswap/src/features/ens/api' import Trace from 'uniswap/src/features/telemetry/Trace' import { ElementName } from 'uniswap/src/features/telemetry/constants' import { TestID } from 'uniswap/src/test/fixtures/testIDs' @@ -17,7 +18,6 @@ import { NumberType } from 'utilities/src/format/types' import { AccountIcon } from 'wallet/src/components/accounts/AccountIcon' import { DisplayNameText } from 'wallet/src/components/accounts/DisplayNameText' import { Arrow } from 'wallet/src/components/icons/Arrow' -import { useENSAvatar } from 'wallet/src/features/ens/api' import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext' import { useCreateOnboardingAccountIfNone, @@ -82,6 +82,7 @@ export function WelcomeWalletScreen({ navigation, route: { params } }: Props): J )} @@ -134,6 +134,6 @@ export function ReceiveCryptoModal(): JSX.Element { - + ) } diff --git a/apps/mobile/src/screens/SettingsBiometricAuthScreen.tsx b/apps/mobile/src/screens/SettingsBiometricAuthScreen.tsx index 436e62d703a..54a96c801f4 100644 --- a/apps/mobile/src/screens/SettingsBiometricAuthScreen.tsx +++ b/apps/mobile/src/screens/SettingsBiometricAuthScreen.tsx @@ -186,25 +186,24 @@ export function SettingsBiometricAuthScreen(): JSX.Element { return ( <> - {showUnsafeWarningModal && ( - => { - await trigger({ - params: { - biometricAppSettingType: unsafeWarningModalType, - // flip the bit - newValue: !(unsafeWarningModalType === BiometricSettingType.RequiredForAppAccess - ? requiredForAppAccess - : requiredForTransactions), - }, - }) - setShowUnsafeWarningModal(false) - setUnsafeWarningModalType(null) - }} - /> - )} + => { + await trigger({ + params: { + biometricAppSettingType: unsafeWarningModalType, + // flip the bit + newValue: !(unsafeWarningModalType === BiometricSettingType.RequiredForAppAccess + ? requiredForAppAccess + : requiredForTransactions), + }, + }) + setShowUnsafeWarningModal(false) + setUnsafeWarningModalType(null) + }} + /> {isAndroid ? t('settings.setting.biometrics.title') : biometricsMethod} diff --git a/apps/mobile/src/screens/SettingsCloudBackupPasswordCreateScreen.tsx b/apps/mobile/src/screens/SettingsCloudBackupPasswordCreateScreen.tsx index 2ef62bbafa4..55b64d6c051 100644 --- a/apps/mobile/src/screens/SettingsCloudBackupPasswordCreateScreen.tsx +++ b/apps/mobile/src/screens/SettingsCloudBackupPasswordCreateScreen.tsx @@ -7,7 +7,7 @@ import { SafeKeyboardScreen } from 'src/components/layout/SafeKeyboardScreen' import { CloudBackupPassword } from 'src/features/CloudBackup/CloudBackupForm' import { Button, Flex, Text, useSporeColors } from 'ui/src' import { OSDynamicCloudIcon } from 'ui/src/components/icons' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' import { ModalName } from 'uniswap/src/features/telemetry/constants' import { TestID } from 'uniswap/src/test/fixtures/testIDs' import { MobileScreens } from 'uniswap/src/types/screens/mobile' @@ -65,7 +65,7 @@ export function SettingsCloudBackupPasswordCreateScreen({ {showCloudBackupInfoModal && ( - + @@ -91,7 +91,7 @@ export function SettingsCloudBackupPasswordCreateScreen({ - + )} diff --git a/apps/mobile/src/screens/SettingsCloudBackupStatus.tsx b/apps/mobile/src/screens/SettingsCloudBackupStatus.tsx index 370d0f35b84..84edc626b49 100644 --- a/apps/mobile/src/screens/SettingsCloudBackupStatus.tsx +++ b/apps/mobile/src/screens/SettingsCloudBackupStatus.tsx @@ -131,34 +131,33 @@ export function SettingsCloudBackupStatus({ - {showBackupDeleteWarning && ( - { - setShowBackupDeleteWarning(false) - }} - onConfirm={onConfirmDeleteBackup} - > - {associatedAccounts.length > 1 && ( + { + setShowBackupDeleteWarning(false) + }} + onConfirm={onConfirmDeleteBackup} + > + {associatedAccounts.length > 1 && ( + + + {t('settings.setting.backup.delete.confirm.message')} + - - {t('settings.setting.backup.delete.confirm.message')} - - - {associatedAccounts.map((account) => ( - - ))} - + {associatedAccounts.map((account) => ( + + ))} - )} - - )} + + )} + ) } diff --git a/apps/mobile/src/screens/SettingsFiatCurrencyModal.tsx b/apps/mobile/src/screens/SettingsFiatCurrencyModal.tsx index 8128ff32dad..00fbf9d8567 100644 --- a/apps/mobile/src/screens/SettingsFiatCurrencyModal.tsx +++ b/apps/mobile/src/screens/SettingsFiatCurrencyModal.tsx @@ -1,12 +1,12 @@ +import { BottomSheetFlatList } from '@gorhom/bottom-sheet' import React, { useCallback } from 'react' import { useTranslation } from 'react-i18next' import { useDispatch } from 'react-redux' -import { Action } from 'redux' -import { VirtualizedList } from 'src/components/layout/VirtualizedList' import { closeModal } from 'src/features/modals/modalSlice' import { Flex, Text, TouchableArea, useSporeColors } from 'ui/src' import { Check } from 'ui/src/components/icons' -import { BottomSheetModal } from 'uniswap/src/components/modals/BottomSheetModal' +import { Modal } from 'uniswap/src/components/modals/Modal' +import { useBottomSheetFocusHook } from 'uniswap/src/components/modals/hooks' import { ModalName } from 'uniswap/src/features/telemetry/constants' import { FiatCurrency, ORDERED_CURRENCIES } from 'wallet/src/features/fiatCurrency/constants' import { useAppFiatCurrency, useFiatCurrencyInfo } from 'wallet/src/features/fiatCurrency/hooks' @@ -15,36 +15,40 @@ import { setCurrentFiatCurrency } from 'wallet/src/features/fiatCurrency/slice' export function SettingsFiatCurrencyModal(): JSX.Element { const dispatch = useDispatch() const { t } = useTranslation() + const selectedCurrency = useAppFiatCurrency() + + // render + const renderItem = useCallback( + ({ item: currency }: { item: FiatCurrency }) => ( + { + dispatch(closeModal({ name: ModalName.FiatCurrencySelector })) + }} + /> + ), + [dispatch, selectedCurrency], + ) return ( - dispatch(closeModal({ name: ModalName.FiatCurrencySelector }))} + onClose={() => { + dispatch(closeModal({ name: ModalName.FiatCurrencySelector })) + }} > {t('settings.setting.currency.title')} - - { - dispatch(closeModal({ name: ModalName.FiatCurrencySelector })) - }} - /> - - - ) -} - -function FiatCurrencySelection({ onClose }: { onClose: () => void }): JSX.Element { - const selectedCurrency = useAppFiatCurrency() - - return ( - - {ORDERED_CURRENCIES.map((currency) => ( - - ))} - + item} + renderItem={renderItem} + /> + ) } diff --git a/apps/mobile/src/screens/SettingsScreen.tsx b/apps/mobile/src/screens/SettingsScreen.tsx index 8eb2bb5af50..c0576c368b5 100644 --- a/apps/mobile/src/screens/SettingsScreen.tsx +++ b/apps/mobile/src/screens/SettingsScreen.tsx @@ -40,6 +40,8 @@ import { } from 'ui/src/components/icons' import { iconSizes, spacing } from 'ui/src/theme' import { uniswapUrls } from 'uniswap/src/constants/urls' +import { useHideSmallBalancesSetting, useHideSpamTokensSetting } from 'uniswap/src/features/settings/hooks' +import { setHideSmallBalances, setHideSpamTokens } from 'uniswap/src/features/settings/slice' import { ModalName } from 'uniswap/src/features/telemetry/constants' import { ImportType, OnboardingEntryPoint } from 'uniswap/src/types/onboarding' import { MobileScreens, OnboardingScreens } from 'uniswap/src/types/screens/mobile' @@ -51,12 +53,7 @@ import { selectHapticsEnabled, setHapticsUserSettingEnabled } from 'wallet/src/f import { useAppFiatCurrencyInfo } from 'wallet/src/features/fiatCurrency/hooks' import { useCurrentLanguageInfo } from 'wallet/src/features/language/hooks' import { BackupType } from 'wallet/src/features/wallet/accounts/types' -import { - useHideSmallBalancesSetting, - useHideSpamTokensSetting, - useSignerAccounts, -} from 'wallet/src/features/wallet/hooks' -import { setHideSmallBalances, setHideSpamTokens } from 'wallet/src/features/wallet/slice' +import { useSignerAccounts } from 'wallet/src/features/wallet/hooks' export function SettingsScreen(): JSX.Element { const navigation = useNavigation() diff --git a/apps/mobile/src/screens/SettingsWallet.tsx b/apps/mobile/src/screens/SettingsWallet.tsx index 71033ff2c12..c0be1b1710e 100644 --- a/apps/mobile/src/screens/SettingsWallet.tsx +++ b/apps/mobile/src/screens/SettingsWallet.tsx @@ -32,6 +32,7 @@ import GlobalIcon from 'ui/src/assets/icons/global.svg' import TextEditIcon from 'ui/src/assets/icons/textEdit.svg' import { iconSizes, spacing } from 'ui/src/theme' import { AccountType } from 'uniswap/src/features/accounts/types' +import { useENS } from 'uniswap/src/features/ens/useENS' import { MobileEventName, ModalName } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { useUnitagByAddress } from 'uniswap/src/features/unitags/hooks' @@ -40,7 +41,6 @@ import { UniverseChainId } from 'uniswap/src/types/chains' import { MobileScreens, UnitagScreens } from 'uniswap/src/types/screens/mobile' import { AddressDisplay } from 'wallet/src/components/accounts/AddressDisplay' import { Switch } from 'wallet/src/components/buttons/Switch' -import { useENS } from 'wallet/src/features/ens/useENS' import { EditAccountAction, editAccountActions } from 'wallet/src/features/wallet/accounts/editAccountSaga' import { useAccounts, useSelectAccountNotificationSetting } from 'wallet/src/features/wallet/hooks' diff --git a/apps/mobile/src/screens/TokenDetailsScreen.tsx b/apps/mobile/src/screens/TokenDetailsScreen.tsx index 75fbedc5e93..7c27a3751a1 100644 --- a/apps/mobile/src/screens/TokenDetailsScreen.tsx +++ b/apps/mobile/src/screens/TokenDetailsScreen.tsx @@ -37,12 +37,15 @@ import { import { fromGraphQLChain } from 'uniswap/src/features/chains/utils' import { PortfolioBalance } from 'uniswap/src/features/dataApi/types' import { currencyIdToContractInput } from 'uniswap/src/features/dataApi/utils' +import { useOnChainNativeCurrencyBalance } from 'uniswap/src/features/portfolio/api' import Trace from 'uniswap/src/features/telemetry/Trace' import { ModalName } from 'uniswap/src/features/telemetry/constants' import TokenWarningModal from 'uniswap/src/features/tokens/TokenWarningModal' -import { CurrencyField } from 'uniswap/src/features/transactions/transactionState/types' +import { useTokenWarningDismissed } from 'uniswap/src/features/tokens/slice/hooks' + import { TestID } from 'uniswap/src/test/fixtures/testIDs' import { UniverseChainId } from 'uniswap/src/types/chains' +import { CurrencyField } from 'uniswap/src/types/currency' import { MobileScreens } from 'uniswap/src/types/screens/mobile' import { buildCurrencyId, @@ -57,9 +60,7 @@ import { useIsSupportedFiatOnRampCurrency } from 'wallet/src/features/fiatOnRamp import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext' import { Language } from 'wallet/src/features/language/constants' import { useCurrentLanguage } from 'wallet/src/features/language/hooks' -import { useOnChainNativeCurrencyBalance } from 'wallet/src/features/portfolio/api' import { useTokenContextMenu } from 'wallet/src/features/portfolio/useTokenContextMenu' -import { useTokenWarningDismissed } from 'wallet/src/features/tokens/safetyHooks' import { useActiveAccountAddressWithThrow } from 'wallet/src/features/wallet/hooks' function HeaderTitleElement({ diff --git a/apps/mobile/src/utils/useOpenBackupReminderModal.ts b/apps/mobile/src/utils/useOpenBackupReminderModal.ts new file mode 100644 index 00000000000..32927293231 --- /dev/null +++ b/apps/mobile/src/utils/useOpenBackupReminderModal.ts @@ -0,0 +1,49 @@ +import { useEffect } from 'react' +import { useDispatch, useSelector } from 'react-redux' +import { openModal } from 'src/features/modals/modalSlice' +import { selectModalState } from 'src/features/modals/selectModalState' +import { AccountType } from 'uniswap/src/features/accounts/types' +import { Experiments, OnboardingRedesignRecoveryBackupProperties } from 'uniswap/src/features/gating/experiments' +import { getExperimentValue } from 'uniswap/src/features/gating/hooks' +import { ModalName } from 'uniswap/src/features/telemetry/constants' +import { ONE_SECOND_MS } from 'utilities/src/time/time' +import { selectBackupReminderLastSeenTs } from 'wallet/src/features/behaviorHistory/selectors' +import { useSelectAddressTransactions } from 'wallet/src/features/transactions/selectors' +import { Account } from 'wallet/src/features/wallet/accounts/types' + +export function useOpenBackupReminderModal(activeAccount: Account): void { + const dispatch = useDispatch() + const txns = useSelectAddressTransactions(activeAccount.address) + const { isOpen: isBackupReminderModalOpen } = useSelector(selectModalState(ModalName.BackupReminder)) + const backupReminderLastSeenTs = useSelector(selectBackupReminderLastSeenTs) + + const isSignerAccount = activeAccount.type === AccountType.SignerMnemonic + const shouldOpenBackupReminderModal = + !isBackupReminderModalOpen && isSignerAccount && !!txns && !activeAccount.backups + + useEffect(() => { + const onboardingBackupExperimentEnabled = getExperimentValue( + Experiments.OnboardingRedesignRecoveryBackup, + OnboardingRedesignRecoveryBackupProperties.Enabled, + false, + ) + const backupReminderOpenDelaySec = getExperimentValue( + Experiments.OnboardingRedesignRecoveryBackup, + OnboardingRedesignRecoveryBackupProperties.BackupReminderDelaySecs, + 0, // Defaulting to 0 seconds delay + (x): x is number => typeof x === 'number', + ) + + if (shouldOpenBackupReminderModal && onboardingBackupExperimentEnabled && backupReminderLastSeenTs === undefined) { + // Get the min addedTime from the transactions (i.e. the user's first transaction) + const minAddedTime = Math.min(...txns.map((txn) => txn.addedTime)) + const delayMs = backupReminderOpenDelaySec * ONE_SECOND_MS + const remainingTimeMs = Math.max(minAddedTime + delayMs - Date.now(), 0) + const timeoutId = setTimeout(() => { + dispatch(openModal({ name: ModalName.BackupReminder })) + }, remainingTimeMs) + + return () => clearTimeout(timeoutId) + } + }, [dispatch, shouldOpenBackupReminderModal, backupReminderLastSeenTs, txns]) +} diff --git a/apps/web/.depcheckrc b/apps/web/.depcheckrc index c58a83ff836..51d548ce02b 100644 --- a/apps/web/.depcheckrc +++ b/apps/web/.depcheckrc @@ -1,72 +1,73 @@ ignores: [ # Dependencies that depcheck thinks are unused but are actually used - "@web3-react/eip1193", - "@web3-react/empty", - "@swc/core", - "@swc/jest", - "@swc/plugin-styled-components", - "@typechain/ethers-v5", - "@vanilla-extract/jest-transform", - "buffer", - "swc-loader", - "postinstall-postinstall", - "process", - "madge", + '@web3-react/eip1193', + '@web3-react/empty', + '@swc/core', + '@swc/jest', + '@swc/plugin-styled-components', + '@typechain/ethers-v5', + '@vanilla-extract/jest-transform', + 'buffer', + 'swc-loader', + 'postinstall-postinstall', + 'process', + 'madge', # Dependencies that depcheck thinks are missing but are actually present or never used ## package.json scripts - "esbuild-register", + 'esbuild-register', ## GraphQL - "@graphql-codegen/*", + '@graphql-codegen/*', ## React Scripts and subpackages used from within it - "case-sensitive-paths-webpack-plugin", - "react-dev-utils", - "workbox-expiration", - "workbox-strategies", + 'case-sensitive-paths-webpack-plugin', + 'react-dev-utils', + 'workbox-expiration', + 'workbox-strategies', ## Packages used in github actions - "start-server-and-test", + 'start-server-and-test', ## Polyfills - "resize-observer-polyfill", + 'resize-observer-polyfill', ## Linting and Babel - "@babel/preset-env", - "eslint-plugin-import", - "terser-webpack-plugin", + '@babel/preset-env', + 'eslint-plugin-import', + 'terser-webpack-plugin', ## Testing - "@types/testing-library__cypress", + '@types/testing-library__cypress', ## i18n - "dotenv-cli", - "@crowdin/cli", + 'dotenv-cli', + '@crowdin/cli', ## sub-packages - "@ethersproject/*", - "@walletconnect/ethereum-provider", - "@testing-library/dom", + '@ethersproject/*', + '@walletconnect/ethereum-provider', + '@testing-library/dom', ## Internal packages / workspaces - "utilities", - "ui", + 'utilities', + 'ui', ## Top level local file paths - "abis", - "analytics", - "assets", - "components", - "connection", - "constants", - "dev", - "featureFlags", - "hooks", - "lib", - "locales", - "nft", - "pages", - "polyfills", - "rpc", - "shared-cloud", - "state", - "test-utils", - "theme", - "tracing", - "types", - "utils", - "i18n", - "tamagui.config", - "setupRive", - "sideEffects" + 'abis', + 'analytics', + 'assets', + 'components', + 'connection', + 'constants', + 'dev', + 'featureFlags', + 'hooks', + 'lib', + 'locales', + 'nft', + 'pages', + 'polyfills', + 'rpc', + 'shared-cloud', + 'state', + 'test-utils', + 'theme', + 'tracing', + 'types', + 'utils', + 'i18n', + 'tamagui.config', + 'setupRive', + 'sideEffects', + 'global.css', ] diff --git a/apps/web/cypress/e2e/token-details.test.ts b/apps/web/cypress/e2e/token-details.test.ts index c38376bd76a..56fb019280a 100644 --- a/apps/web/cypress/e2e/token-details.test.ts +++ b/apps/web/cypress/e2e/token-details.test.ts @@ -27,7 +27,7 @@ describe('Token details', () => { cy.get('h1').should('have.length', 1) // Price chart should be filled in - cy.get('[data-cy="chart-header"]').should('include.text', '$') + cy.get('#chart-header').should('include.text', '$') cy.get('[data-cy="tdp-Price-chart-container"]').should('exist') // Stats should have: TVL, FDV, market cap, 24H volume @@ -142,7 +142,7 @@ describe('Token details', () => { it('should show a L2 token even if the user is connected to a different network', () => { cy.visit('/explore/tokens') cy.get(getTestSelector('tokens-network-filter-selected')).click() - cy.get(getTestSelector('tokens-network-filter-option-arbitrum')).click() + cy.get(getTestSelector('tokens-network-filter-option-arbitrum')).first().click() cy.get(getTestSelector('tokens-network-filter-selected')).invoke('attr', 'alt').should('eq', `Arbitrum logo`) cy.get(getTestSelector(`token-table-row-${ARB.address.toLowerCase()}`)).click() cy.get(`#swap-currency-output .token-symbol-container`).should('contain.text', 'ARB') diff --git a/apps/web/functions/explore/pools/__snapshots__/pool.test.ts.snap b/apps/web/functions/explore/pools/__snapshots__/pool.test.ts.snap index 90d4a2a0e06..94e5dd79ff6 100644 --- a/apps/web/functions/explore/pools/__snapshots__/pool.test.ts.snap +++ b/apps/web/functions/explore/pools/__snapshots__/pool.test.ts.snap @@ -18,17 +18,10 @@ exports[`should inject metadata for valid pools 1`] = ` + - - - - - @@ -126,7 +119,7 @@ exports[`should inject metadata for valid pools 1`] = ` } } - + @@ -156,17 +149,10 @@ exports[`should inject metadata for valid pools 2`] = ` + - - - - - @@ -264,7 +250,7 @@ exports[`should inject metadata for valid pools 2`] = ` } } - + @@ -294,17 +280,10 @@ exports[`should inject metadata for valid pools 3`] = ` + - - - - - @@ -402,7 +381,7 @@ exports[`should inject metadata for valid pools 3`] = ` } } - + diff --git a/apps/web/functions/explore/tokens/__snapshots__/token.test.ts.snap b/apps/web/functions/explore/tokens/__snapshots__/token.test.ts.snap index c95e8357366..0c4f27c6161 100644 --- a/apps/web/functions/explore/tokens/__snapshots__/token.test.ts.snap +++ b/apps/web/functions/explore/tokens/__snapshots__/token.test.ts.snap @@ -18,22 +18,11 @@ exports[`should inject metadata for valid tokens 1`] = ` + - - - - - - @@ -160,22 +149,11 @@ exports[`should inject metadata for valid tokens 2`] = ` + - - - - - - @@ -302,22 +280,11 @@ exports[`should inject metadata for valid tokens 3`] = ` + - - - - - - @@ -444,22 +411,11 @@ exports[`should inject metadata for valid tokens 4`] = ` + - - - - - - diff --git a/apps/web/functions/nfts/asset/__snapshots__/nft.test.ts.snap b/apps/web/functions/nfts/asset/__snapshots__/nft.test.ts.snap index b0ebab009d8..ed8caec1f3c 100644 --- a/apps/web/functions/nfts/asset/__snapshots__/nft.test.ts.snap +++ b/apps/web/functions/nfts/asset/__snapshots__/nft.test.ts.snap @@ -18,17 +18,10 @@ exports[`should inject metadata for valid assets: Azuki 1`] = ` + - - - - - @@ -126,7 +119,7 @@ exports[`should inject metadata for valid assets: Azuki 1`] = ` } } - + @@ -156,17 +149,10 @@ exports[`should inject metadata for valid assets: Bored Ape Yacht Club 1`] = ` + - - - - - @@ -264,7 +250,7 @@ exports[`should inject metadata for valid assets: Bored Ape Yacht Club 1`] = ` } } - + @@ -294,17 +280,10 @@ exports[`should inject metadata for valid assets: CryptoPunk 1`] = ` + - - - - - @@ -402,7 +381,7 @@ exports[`should inject metadata for valid assets: CryptoPunk 1`] = ` } } - + diff --git a/apps/web/functions/nfts/collection/__snapshots__/collection.test.ts.snap b/apps/web/functions/nfts/collection/__snapshots__/collection.test.ts.snap index b9b0a77ca83..29dd84d52ad 100644 --- a/apps/web/functions/nfts/collection/__snapshots__/collection.test.ts.snap +++ b/apps/web/functions/nfts/collection/__snapshots__/collection.test.ts.snap @@ -18,17 +18,10 @@ exports[`should inject metadata for collections 1`] = ` + - - - - - @@ -126,7 +119,7 @@ exports[`should inject metadata for collections 1`] = ` } } - + @@ -156,17 +149,10 @@ exports[`should inject metadata for collections 2`] = ` + - - - - - @@ -264,7 +250,7 @@ exports[`should inject metadata for collections 2`] = ` } } - + @@ -294,17 +280,10 @@ exports[`should inject metadata for collections 3`] = ` + - - - - - @@ -402,7 +381,7 @@ exports[`should inject metadata for collections 3`] = ` } } - + diff --git a/apps/web/package.json b/apps/web/package.json index a5984c725ee..40bf07a7619 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -20,6 +20,7 @@ "typecheck:cloud": "tsc -p functions/tsconfig.json", "typecheck:cypress": "tsc -p cypress/tsconfig.json", "test": "craco test --watchAll=false", + "test:watch": "craco test", "test:bundle": "node -r esbuild-register ./src/test-utils/bundle-size-test.ts", "snapshots": "craco test -u", "test:cloud": "yarn jest functions --config=functions/jest.config.json", @@ -175,10 +176,10 @@ "@sentry/core": "7.80.0", "@sentry/react": "7.80.0", "@sentry/types": "7.80.0", - "@tamagui/core": "1.108.2", - "@tamagui/portal": "1.108.2", - "@tamagui/react-native-svg": "1.108.2", - "@tanstack/react-query": "5.28.14", + "@tamagui/core": "1.108.4", + "@tamagui/portal": "1.108.4", + "@tamagui/react-native-svg": "1.108.4", + "@tanstack/react-query": "5.51.16", "@tanstack/react-table": "8.10.7", "@types/poisson-disk-sampling": "2.2.4", "@types/react-scroll-sync": "0.8.7", @@ -194,7 +195,7 @@ "@uniswap/sdk-core": "5.3.0", "@uniswap/smart-order-router": "3.17.3", "@uniswap/token-lists": "1.0.0-beta.33", - "@uniswap/uniswapx-sdk": "2.0.4-alpha.1", + "@uniswap/uniswapx-sdk": "^2.1.0-beta.8", "@uniswap/universal-router-sdk": "2.2.0", "@uniswap/v2-core": "1.0.1", "@uniswap/v2-periphery": "1.1.0-beta.0", @@ -267,6 +268,7 @@ "redux-persist": "6.0.0", "statsig-react": "1.32.0", "styled-components": "5.3.11", + "tamagui": "1.108.4", "tiny-invariant": "1.3.1", "ui": "workspace:^", "uniswap": "workspace:^", @@ -275,7 +277,7 @@ "uuid": "9.0.0", "video-extensions": "1.2.0", "viem": "2.x", - "wagmi": "2.8.4", + "wagmi": "2.9.3", "wcag-contrast": "3.0.0", "web-vitals": "2.1.4", "xml2js": "0.6.2", diff --git a/apps/web/public/csp.json b/apps/web/public/csp.json index a6c42c61cd3..b449b9600e2 100644 --- a/apps/web/public/csp.json +++ b/apps/web/public/csp.json @@ -56,10 +56,10 @@ "https://cdn.center.app/", "https://celo-org.github.io", "https://cloudflare-eth.com", - "https://cloudflare-ipfs.com", "https://ethereum-optimism.github.io/", "https://forno.celo.org/", "https://gateway.ipfs.io/", + "https://hardbin.com/", "https://i.seadn.io/", "https://images-country.meld.io", "https://invalid.rpki.cloudflare.com/", @@ -84,6 +84,7 @@ "https://rpc.mevblocker.io/", "https://rpc.scroll.io/", "https://rpc.sepolia.org/", + "https://rpc.zora.energy/", "https://sockjs-us3.pusher.com/", "https://sparrow.cloudflare.com/", "https://statsigapi.net", diff --git a/apps/web/public/index.html b/apps/web/public/index.html index 306ebf05863..20974fe5784 100644 --- a/apps/web/public/index.html +++ b/apps/web/public/index.html @@ -15,6 +15,7 @@ + <% if (!process.env.REACT_APP_SKIP_CSP) { %> diff --git a/apps/web/public/nfts-sitemap.xml b/apps/web/public/nfts-sitemap.xml index 5d053264215..53f8c25b9a4 100644 --- a/apps/web/public/nfts-sitemap.xml +++ b/apps/web/public/nfts-sitemap.xml @@ -2,647 +2,697 @@ https://app.uniswap.org/nfts/collection/0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x60e4d786628fea6478f785a6d7e704777c86a7c6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xed5af388653567af2f388e6224dc7c4b3241c544 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x34d85c9cdeb23fa97cb08333b511ac86e1c4e258 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x99a9b7c1116f9ceeb1652de04d5969cce509b069 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x49cf6f5d44e70224e2e23fdcdd2c053f30ada28b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xb7f7f6c52f2e2fdb1963eab30438024864c313f6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x23581767a106ae21c074b2276d25e5c3e136a68b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x8a90cab2b38dba80c64b7734e58ee1db38b8992e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xba30e5f9bb24caa003e9f2f0497ad287fdf95623 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xbd3531da5cf5857e7cfaa92426877b022e612cf8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x7bd29408f11d2bfc23c34f18275bbf23bb716bc7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x306b1ea3ecdf94ab739f1910bbda052ed4a9f949 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x1a92f7381b9f03921564a437210bb9396471050c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x5cc5b05a8a13e3fbdb0bb9fccd98d38e50f90c38 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x5af0d9827e0c53e4799bb226655a1de152a425a5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x3bf2922f4520a8ba0c2efc3d2a1539678dad5e9d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xe785e82358879f061bc3dcac6f0444462d4b5330 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x76be3b62873462d2142405439777e971754e8e77 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xfd43af6d3fe1b916c026f6ac35b3ede068d1ca01 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x1cb1a5e65610aeff2551a50f76a87a7d3fb649c6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xff9c1b15b16263c61d017ee9f65c50e4ae0113d7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x6339e5e072086621540d0362c4e3cea0d643e114 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xb932a70a57673d89f4acffbe830e8ed7f75fb9e0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x79fcdef22feed20eddacbb2587640e45491b757f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xa3aee8bce55beea1951ef834b99f3ac60d1abeeb - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x769272677fab02575e84945f03eca517acc544cc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x4db1f25d3d98600140dfc18deb7515be5bd293af - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x34eebee6942d8def3c125458d1a86e0a897fd6f9 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x59468516a8259058bad1ca5f8f4bff190d30e066 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x394e3d3044fc89fcdd966d3cb35ac0b32b0cda91 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x60bb1e2aa1c9acafb4d34f71585d7e959f387769 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x28472a58a490c5e09a238847f66a68a47cc76f0f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x341a1c534248966c4b6afad165b98daed4b964ef - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x82c7a8f707110f5fbb16184a5933e9f78a34c6ab - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xccc441ac31f02cd96c153db6fd5fe0a2f4e6a68d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x764aeebcf425d56800ef2c84f2578689415a2daa - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x160c404b2b49cbc3240055ceaee026df1e8497a0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xd2f668a8461d6761115daf8aeb3cdf5f40c532c6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x39ee2c7b3cb80254225884ca001f57118c8f21b6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xd774557b647330c91bf44cfeab205095f7e6c367 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x1792a96e5668ad7c167ab804a100ce42395ce54d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xf87e31492faf9a91b02ee0deaad50d51d56d5d4d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x04afa589e2b933f9463c5639f412b183ec062505 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xe75512aa3bec8f00434bbd6ad8b0a3fbff100ad6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x348fc118bcc65a92dc033a951af153d14d945312 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x892848074ddea461a15f337250da3ce55580ca85 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x5946aeaab44e65eb370ffaa6a7ef2218cff9b47d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x282bdd42f4eb70e7a9d9f40c8fea0825b7f68c5d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x4b15a9c28034dc83db40cd810001427d3bd7163d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x7ea3cca10668b8346aec0bf1844a49e995527c8b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xb852c6b5892256c264cc2c888ea462189154d8d7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x9378368ba6b85c1fba5b131b530f5f5bedf21a18 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x2acab3dea77832c09420663b0e1cb386031ba17b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x0c2e57efddba8c768147d1fdf9176a0a6ebd5d83 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x08d7c0242953446436f34b4c78fe9da38c73668d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x8943c7bac1914c9a7aba750bf2b6b09fd21037e0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x364c828ee171616a39897688a831c2499ad972ec - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x7f36182dee28c45de6072a34d29855bae76dbe2f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xf61f24c2d93bf2de187546b14425bf631f28d6dc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x797a48c46be32aafcedcfd3d8992493d8a1f256b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x123b30e25973fecd8354dd5f41cc45a3065ef88c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x6632a9d63e142f17a668064d41a21193b49b41a0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xf4ee95274741437636e748ddac70818b4ed7d043 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x57a204aa1042f6e66dd7730813f4024114d74f37 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xd1258db6ac08eb0e625b75b371c023da478e94a9 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x75e95ba5997eb235f40ecf8347cdb11f18ff640b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xd532b88607b1877fe20c181cba2550e3bbd6b31c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xa1d4657e0e6507d5a94d06da93e94dc7c8c44b51 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xedb61f74b0d09b2558f1eeb79b247c1f363ae452 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x7d8820fa92eb1584636f4f5b8515b5476b75171a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x231d3559aa848bf10366fb9868590f01d34bf240 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xad9fd7cb4fc7a0fbce08d64068f60cbde22ed34c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x0e9d6552b85be180d941f1ca73ae3e318d2d4f1f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xb716600ed99b4710152582a124c697a7fe78adbf - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xaadc2d4261199ce24a4b0a57370c4fcf43bb60aa - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x4e1f41613c9084fdb9e34e11fae9412427480e56 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x79986af15539de2db9a5086382daeda917a9cf0c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xc99c679c50033bbc5321eb88752e89a93e9e83c5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xc36cf0cfcb5d905b8b513860db0cfe63f6cf9f5c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x9c8ff314c9bc7f6e59a9d9225fb22946427edc03 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x3110ef5f612208724ca51f5761a69081809f03b7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x036721e5a769cc48b3189efbb9cce4471e8a48b1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x524cab2ec69124574082676e6f654a18df49a048 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x7ab2352b1d2e185560494d5e577f9d3c238b78c5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x32973908faee0bf825a343000fe412ebe56f802a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x7daec605e9e2a1717326eedfd660601e2753a057 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xc1caf0c19a8ac28c41fe59ba6c754e4b9bd54de9 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x33fd426905f149f8376e227d0c9d3340aad17af1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x466cfcd0525189b573e794f554b8a751279213ac - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x6be69b2a9b153737887cfcdca7781ed1511c7e36 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x80336ad7a747236ef41f47ed2c7641828a480baa - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x9401518f4ebba857baa879d9f76e1cc8b31ed197 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x4b61413d4392c806e6d0ff5ee91e6073c21d6430 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xc3f733ca98e0dad0386979eb96fb1722a1a05e69 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x09233d553058c2f42ba751c87816a8e9fae7ef10 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x960b7a6bcd451c9968473f7bbfd9be826efd549a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x36d30b3b85255473d27dd0f7fd8f35e36a9d6f06 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x698fbaaca64944376e2cdc4cad86eaa91362cf54 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x497a9a79e82e6fc0ff10a16f6f75e6fcd5ae65a8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x41a322b28d0ff354040e2cbc676f0320d8c8850d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xa9c0a07a7cb84ad1f2ffab06de3e55aab7d523e8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x942bc2d3e7a589fe5bd4a5c6ef9727dfd82f5c8a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x8821bee2ba0df28761afff119d66390d594cd280 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x8c6def540b83471664edc6d5cf75883986932674 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x8d9710f0e193d3f95c0723eaaf1a81030dc9116d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x86825dfca7a6224cfbd2da48e85df2fc3aa7c4b1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x629a673a8242c2ac4b7b8c5d8735fbeac21a6205 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x9a534628b4062e123ce7ee2222ec20b86e16ca8f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xc2c747e0f7004f9e8817db2ca4997657a7746928 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x73da73ef3a6982109c4d5bdb0db9dd3e3783f313 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xc92ceddfb8dd984a89fb494c376f9a48b999aafc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x3248e8ba90facc4fdd3814518c14f8cc4d980e4b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x67d9417c9c3c250f61a83c7e8658dac487b56b09 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xb6a37b5d14d502c3ab0ae6f3a0e058bc9517786e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x86c10d10eca1fca9daf87a279abccabe0063f247 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x4b3406a41399c7fd2ba65cbc93697ad9e7ea61e5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xb0640e8b5f24bedc63c33d371923d68fde020303 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xd3d9ddd0cf0a5f0bfb8f7fceae075df687eaebab - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xa5c0bd78d1667c13bfb403e2a3336871396713c5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x4d7d2e237d64d1484660b55c0a4cc092fa5e6716 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xfcb1315c4273954f74cb16d5b663dbf479eec62e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x66d1db16101502ed0ca428842c619ca7b62c8fef - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x128675d4fddbc4a0d3f8aa777d8ee0fb8b427c2f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x19b86299c21505cdf59ce63740b240a9c822b5e4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xacf63e56fd08970b43401492a02f6f38b6635c91 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0x0bebad1ff25c623dff9605dad4a8f782d5da37df - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.7 https://app.uniswap.org/nfts/collection/0xdceaf1652a131f32a821468dc03a92df0edd86ea - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z + 0.7 + + + https://app.uniswap.org/nfts/collection/0x273f7f8e6489682df756151f5525576e322d51a3 + 2024-08-16T22:35:51.074Z + 0.7 + + + https://app.uniswap.org/nfts/collection/0x77372a4cc66063575b05b44481f059be356964a4 + 2024-08-16T22:35:51.074Z + 0.7 + + + https://app.uniswap.org/nfts/collection/0xf5b0a3efb8e8e4c201e2a935f110eaaf3ffecb8d + 2024-08-16T22:35:51.074Z + 0.7 + + + https://app.uniswap.org/nfts/collection/0x22c36bfdcef207f9c0cc941936eff94d4246d14a + 2024-08-16T22:35:51.074Z + 0.7 + + + https://app.uniswap.org/nfts/collection/0x59325733eb952a92e069c87f0a6168b29e80627f + 2024-08-16T22:35:51.074Z + 0.7 + + + https://app.uniswap.org/nfts/collection/0x0e3a2a1f2146d86a604adc220b4967a898d7fe07 + 2024-08-16T22:35:51.074Z + 0.7 + + + https://app.uniswap.org/nfts/collection/0x3af2a97414d1101e2107a70e7f33955da1346305 + 2024-08-16T22:35:51.074Z + 0.7 + + + https://app.uniswap.org/nfts/collection/0x5ab21ec0bfa0b29545230395e3adaca7d552c948 + 2024-08-23T19:37:24.067Z + 0.7 + + + https://app.uniswap.org/nfts/collection/0x617913dd43dbdf4236b85ec7bdf9adfd7e35b340 + 2024-08-23T19:37:24.067Z + 0.7 + + + https://app.uniswap.org/nfts/collection/0x3fe1a4c1481c8351e91b64d5c398b159de07cbc5 + 2024-08-16T22:35:51.074Z 0.7 \ No newline at end of file diff --git a/apps/web/public/pools-sitemap.xml b/apps/web/public/pools-sitemap.xml index 0903b0778ae..a4349ccaf6c 100644 --- a/apps/web/public/pools-sitemap.xml +++ b/apps/web/public/pools-sitemap.xml @@ -2,4357 +2,6032 @@ https://app.uniswap.org/explore/pools/ethereum/0xcbcdf9626bc03e24f779434178a73a0b4bad62ed - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x4e68ccd3e89f51c3074ca5072bbac773960dfa36 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x4585fe77225b41b697c938b018e2ac67ac5a20c0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xc63b0708e2f7e69cb8a1df0e1389a98c35a76d52 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x99ac8ca7087fa4a2a1fb6357269965a2014abc35 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x11b815efb8f581194ae79006d24e0d814b7697f6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xa6cc3c2531fdaa6ae1a3ca84c2855806728693e8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x5777d92f208679db4b9778590fa3cab3ac9e2168 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x1d42064fc4beb5f8aaf85f4617ae8b3b5b8bd801 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xc2e9f25be6257c210d7adf0d4cd6e3e881ba25f8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x11950d141ecb863f01007add7d1a342041227b58 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xc5c134a1f112efa96003f8559dba6fac0ba77692 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x109830a1aaad605bbf02a9dfa7b0b92ec2fb7daa - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x1df4c6e36d61416813b42fe32724ef11e363eddc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x12d6867fa648d269835cf69b49f125147754b54d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x3416cf6c708da44db2624d63ea0aaef7113527c6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xe8c6c9227491c0a8156a0106a0204d881bb7e531 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x04708077eca6bb527a5bbbd6358ffb043a9c1c14 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x9db9e0e53058c89e5b94e29621a205198648425b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xf239009a101b6b930a527deaab6961b6e7dec8a6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xfe0df74636bc25c7f2400f22fe7dae32d39443d2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xf4c5e0f4590b6679b3030d29a84857f226087fef - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x5764a6f2212d502bc5970f9f129ffcd61e5d7563 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xa3f558aebaecaf0e11ca4b2199cc5ed341edfd74 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x99132b53ab44694eeb372e87bced3929e4ab8456 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x6c6bc977e13df9b0de53b251522280bb72383700 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x9d96880952b4c80a55099b9c258250f2cc5813ec - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x3afdc5e6dfc0b0a507a8e023c9dce2cafc310316 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x290a6a7460b308ee3f19023d2d00de604bcf5b42 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xac4b3dacb91461209ae9d41ec517c2b9cb1b7daf - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x60594a405d53811d3bc4766596efd80fd545a270 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x331399c614ca67dee86733e5a2fba40dbb16827c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x4b5ab61593a2401b1075b90c04cbcdd3f87ce011 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x844eb5c280f38c7462316aad3f338ef9bda62668 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xe936f0073549ad8b1fa53583600d629ba9375161 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x2f62f2b4c5fcd7570a709dec05d68ea19c82a9ec - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x381fe4eb128db1621647ca00965da3f9e09f4fac - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x97e7d56a0408570ba1a7852de36350f7713906ec - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xcd423f3ab39a11ff1d9208b7d37df56e902c932b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xe15e6583425700993bd08f51bf6e7b73cd5da91b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x69d91b94f0aaf8e8a2586909fa77a5c2c89818d5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xe42318ea3b998e8355a3da364eb9d48ec725eb45 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xad9ef19e289dcbc9ab27b83d2df53cdeff60f02d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x3b685307c8611afb2a9e83ebc8743dc20480716e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x7bea39867e4169dbe237d55c8242a8f2fcdcc387 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x7b1e5d984a43ee732de195628d20d05cfabc3cc7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x7858e59e0c01ea06df3af3d20ac7b0003275d4bf - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xae2a25cbdb19d0dc0dddd1d2f6b08a6e48c4a9a9 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x21b8065d10f73ee2e260e5b47d3344d3ced7596e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x0d4a11d5eeaac28ec3f61d100daf4d40471f1852 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x517f9dd285e75b599234f7221227339478d0fcc8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xa43fe16908251ee70ef74718545e4fe6c5ccec9f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x0af81cd5d9c124b4859d65697a4cd10ee223746a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xca7c2771d248dcbe09eabe0ce57a62e18da178c0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x09d1d767edf8fa23a64c51fa559e0688e526812f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x7b73644935b8e68019ac6356c40661e1bc315860 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x180efc1349a69390ade25667487a826164c9c6e4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x9c4fe5ffd9a9fc5678cfbd93aa2d4fd684b67c4c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xa478c2975ab1ea89e8196811f51a7b7ade33eb11 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xbb2b8038a1640196fbe3e38816f3e67cba72d940 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x9ec9367b8c4dd45ec8e7b800b1f719251053ad60 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xc91ef786fbf6d62858262c82c63de45085dea659 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x197d7010147df7b99e9025c724f13723b29313f8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x25647e01bd0967c1b9599fa3521939871d1d0888 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x2f0b1417aa42ebf0b4ca1154212847f6094d708d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x6ada49aeccf6e556bb7a35ef0119cc8ca795294a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x2a6c340bcbb0a79d3deecd3bc5cbc2605ea9259f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xda2d09fbbf8ee4b5051a0e9b562c5fcb4b393b18 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x48d20b3e529fb3dd7d91293f80638df582ab2daa - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x4028daac072e492d34a3afdbef0ba7e35d8b55c4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xc2eab7d33d3cb97692ecb231a5d0e4a649cb539d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xc5be99a02c6857f9eac67bbce58df5572498f40c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xe4b8583ccb95b25737c016ac88e539d0605949e8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x8dbee21e8586ee356130074aaa789c33159921ca - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x43de4318b6eb91a7cf37975dbb574396a7b5b5c6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x9ff68f61ca5eb0c6606dc517a9d44001e564bb66 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xa29fe6ef9592b5d408cca961d0fb9b1faf497d6d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x1b1137dd16faa651e38a9dfb5d9ffff7767fdf62 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x470e8de2ebaef52014a47cb5e6af86884947f08c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x8fb8e9921922d2ffb529a95d28a0d06d275d7a59 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xd3d2e2692501a5c9ca623199d38826e513033a17 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x97e1fcb93ae7267dbafad23f7b9afaa08264cfd8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xa5e9c917b4b821e4e0a5bbefce078ab6540d6b5e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x2cc846fff0b08fb3bffad71f53a60b4b6e6d6482 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x959873fb4fc11825fba83c80c4c632db1e936e15 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xa7480aafa8ad2af3ce24ac6853f960ae6ac7f0c4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xc7e6b676bfc73ae40bcc4577f22aab1682c691c6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x570febdf89c07f256c75686caca215289bb11cfc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x343fd171caf4f0287ae6b87d75a8964dc44516ab - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xcaa004418eb42cdf00cb057b7c9e28f0ffd840a5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xe3d3551bb608e7665472180a20280630d9e938aa - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xb6b0c651c37ec4ca81c0a128420e02001a57fac2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x4e34da137f0b317c633838458e0c923a5e088752 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xfe9e7931e55c514c33d489c88582fa36e84bd8e3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x5281e311734869c64ca60ef047fd87759397efe6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x149148acc3b06b8cc73af3a10e84189243a35925 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x8ef79d6c328c25da633559c20c75f638a4863462 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x14af1804dbbf7d621ecc2901eef292a24a0260ea - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x80a9ae39310abf666a87c743d6ebbd0e8c42158e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc31e54c7a869b9fcbecc14363cf510d1c41fa443 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x2f5e87c9312fa29aed5c179e456625d79015299c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc6962004f452be9203591991d15f6b388e09e8d0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc6f780497a95e246eb9449f5e4770916dcd6396a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x641c00a822e8b671738d32a431a4fb6074e5c79d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x92c63d0e701caae670c9415d91c474f686298f00 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x1aeedd3727a6431b8f070c0afaa81cc74f273882 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xcda53b1f66614552f834ceef361a8d12a0b8dad8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x35218a1cbac5bbc3e57fd9bd38219d37571b3537 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x17c14d2c404d167802b16c450d3c99f88f2c4f4d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x468b88941e7cc0b88c1869d68ab6b570bcef62ff - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xdbaeb7f0dfe3a0aafd798ccecb5b22e708f7852c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x149e36e72726e0bcea5c59d40df2c43f60f5a22d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xbaaf1fc002e31cb12b99e4119e5e350911ec575b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xa67f72f21bd9f91db2da2d260590da5e6c437009 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x92fd143a8fa0c84e016c2765648b9733b0aa519e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x7cf803e8d82a50504180f417b8bc7a493c0a0503 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x81c48d31365e6b526f6bbadc5c9aafd822134863 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x446bf9748b4ea044dd759d9b9311c70491df8f29 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc82819f72a9e77e2c0c3a69b3196478f44303cf4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x50c7390dfdd3756139e6efb5a461c2eb7331ceb4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x1dfc1054e0e2a10e33c9ca21aad5aa8a1cce91e3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc91b7b39bbb2c733f0e7459348fd0c80259c8471 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x59d72ddb29da32847a4665d08ffc8464a7185fae - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x09ba302a3f5ad2bf8853266e271b005a5b3716fe - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xa77d77c9773c35e910acc2e30cefe52b54a58414 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x8da66e470403b3d3eee66c67e2c61fda6e248ad1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x2f020e708811c054f146eebcc4d5a215fd4eec26 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x7e7fb3cceca5f2ac952edf221fd2a9f62e411980 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x68c685fd52a56f04665b491d491355a624540e85 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xa8328bf492ba1b77ad6381b3f7567d942b000baf - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc0cf0f380ddb44dbcaf19a86d094c8bba3efa04a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xa169d1ab5c948555954d38700a6cdaa7a4e0c3a0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x1862200e8e7ce1c0827b792d0f9546156f44f892 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x05bbaaa020ff6bea107a9a1e06d2feb7bfd79ed2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xd02a4969dc12bb889754361f8bcf3385ac1b2077 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc24f7d8e51a64dc1238880bd00bb961d54cbeb29 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x7c06736e41236fecd681dd3353aa77ecd19ea565 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc473e2aee3441bf9240be85eb122abb059a3b57c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x14353445c8329df76e6f15e9ead18fa2d45a8bb6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x2039f8c9cd32ba9cd2ea7e575d5b1abea93f7527 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xd3e11119d2680c963f1cdcffece0c4ade823fb58 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x8e295789c9465487074a65b1ae9ce0351172393f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x97bca422ec0ee4851f2110ea743c1cd0a14835a1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xbe3ad6a5669dc0b8b12febc03608860c31e2eef6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x56ebd63a756b94d3de9cea194896b4920b64fb01 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xe2ddd33585b441b9245085588169f35108f85a6e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x84436a2af97f37018db116ae8e1b691666db3d00 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x21b8065d10f73ee2e260e5b47d3344d3ced7596e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x0d4a11d5eeaac28ec3f61d100daf4d40471f1852 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x517f9dd285e75b599234f7221227339478d0fcc8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xa43fe16908251ee70ef74718545e4fe6c5ccec9f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x0af81cd5d9c124b4859d65697a4cd10ee223746a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xca7c2771d248dcbe09eabe0ce57a62e18da178c0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x09d1d767edf8fa23a64c51fa559e0688e526812f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x7b73644935b8e68019ac6356c40661e1bc315860 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x180efc1349a69390ade25667487a826164c9c6e4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x9c4fe5ffd9a9fc5678cfbd93aa2d4fd684b67c4c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xa478c2975ab1ea89e8196811f51a7b7ade33eb11 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xbb2b8038a1640196fbe3e38816f3e67cba72d940 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x9ec9367b8c4dd45ec8e7b800b1f719251053ad60 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc91ef786fbf6d62858262c82c63de45085dea659 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x197d7010147df7b99e9025c724f13723b29313f8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x25647e01bd0967c1b9599fa3521939871d1d0888 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x2f0b1417aa42ebf0b4ca1154212847f6094d708d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x6ada49aeccf6e556bb7a35ef0119cc8ca795294a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x2a6c340bcbb0a79d3deecd3bc5cbc2605ea9259f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xda2d09fbbf8ee4b5051a0e9b562c5fcb4b393b18 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x48d20b3e529fb3dd7d91293f80638df582ab2daa - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x4028daac072e492d34a3afdbef0ba7e35d8b55c4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc2eab7d33d3cb97692ecb231a5d0e4a649cb539d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc5be99a02c6857f9eac67bbce58df5572498f40c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xe4b8583ccb95b25737c016ac88e539d0605949e8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x8dbee21e8586ee356130074aaa789c33159921ca - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x43de4318b6eb91a7cf37975dbb574396a7b5b5c6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x9ff68f61ca5eb0c6606dc517a9d44001e564bb66 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xa29fe6ef9592b5d408cca961d0fb9b1faf497d6d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x1b1137dd16faa651e38a9dfb5d9ffff7767fdf62 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x470e8de2ebaef52014a47cb5e6af86884947f08c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x8fb8e9921922d2ffb529a95d28a0d06d275d7a59 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xd3d2e2692501a5c9ca623199d38826e513033a17 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x97e1fcb93ae7267dbafad23f7b9afaa08264cfd8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xa5e9c917b4b821e4e0a5bbefce078ab6540d6b5e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x2cc846fff0b08fb3bffad71f53a60b4b6e6d6482 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x959873fb4fc11825fba83c80c4c632db1e936e15 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xa7480aafa8ad2af3ce24ac6853f960ae6ac7f0c4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc7e6b676bfc73ae40bcc4577f22aab1682c691c6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x570febdf89c07f256c75686caca215289bb11cfc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x343fd171caf4f0287ae6b87d75a8964dc44516ab - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xcaa004418eb42cdf00cb057b7c9e28f0ffd840a5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xe3d3551bb608e7665472180a20280630d9e938aa - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xb6b0c651c37ec4ca81c0a128420e02001a57fac2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x4e34da137f0b317c633838458e0c923a5e088752 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xfe9e7931e55c514c33d489c88582fa36e84bd8e3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x5281e311734869c64ca60ef047fd87759397efe6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x149148acc3b06b8cc73af3a10e84189243a35925 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x8ef79d6c328c25da633559c20c75f638a4863462 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x68f5c0a2de713a54991e01858fd27a3832401849 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x4533bad2dc588f0fadf8d2e72386d4cd6a19b519 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x85149247691df622eaf1a8bd0cafd40bc45154a9 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x0392b358ce4547601befa962680bede836606ae2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x1c3140ab59d6caf9fa7459c6f83d4b52ba881d36 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xd1f1bad4c9e6c44dec1e9bf3b94902205c5cd6c3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x03af20bdaaffb4cc0a521796a223f7d85e2aac31 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x73b14a78a0d396c521f954532d43fd5ffe385216 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xac85eaf55e9c60ed40a683de7e549d23fdfbeb33 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x04f6c85a1b00f6d9b75f91fd23835974cc07e65c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x730691cdac3cbd4d41fc5eb9d8abbb0cea795b94 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x535541f1aa08416e69dc4d610131099fa2ae7222 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xfc1f3296458f9b2a27a0b91dd7681c4020e09d05 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x85c31ffa3706d1cce9d525a00f1c7d4a2911754c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xd52533a3309b393afebe3176620e8ccfb6159f8a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xff7fbdf7832ae524deda39ca402e03d92adff7a5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xb589969d38ce76d3d7aa319de7133bc9755fd840 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xf334f6104a179207ddacfb41fa3567feea8595c2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x1fb3cf6e48f1e7b10213e7b6d87d4c073c7fdb7b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xd4344ea0c5ade7e22b9b275f0bde7a145dec5a23 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x5b42a63d6741416ce9a7b9f4f16d8c9231ccddd4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x252cbdff917169775be2b552ec9f6781af95e7f6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x2ab22ac86b25bd448a4d9dc041bd2384655299c4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xc858a329bf053be78d6239c4a4343b8fbd21472b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xa73c628eaf6e283e26a7b1f8001cf186aa4c0e8e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xb533c12fb4e7b53b5524eab9b47d93ff6c7a456f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x2ae3d6096d8215ac2acddf30c60caa984ea5debe - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x19ea026886cbb7a900ecb2458636d72b5cae223b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x6f32061f59a21086c334d0d45f804089ce374aaf - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xfaf037caafa9620bfaebc04c298bf4a104963613 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xadb35413ec50e0afe41039eac8b930d313e94fa4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xe9e3893921de87b1194a8108f9d70c24bde71c27 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xf1f199342687a7d78bcc16fce79fa2665ef870e1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xf44acaa38be5e965c5ddf374e7a2ba270e580684 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x36e42931a765022790b797963e42c5522d6b585a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x5adba6c5589c50791dd65131df29677595c7efa7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x3249e3e3e4133ee18e65347daf586610cc265f54 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xca1b837c87c6563910c2befa48834fa2a8c3d72d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x6ef7b14bcd8d989cef8f8ec8ba4bf371b2ac95fd - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x37ffd11972128fd624337ebceb167c8c0a5115ff - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xe62bd99a9501ca33d98913105fc2bec5bae6e5dd - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xb2ac2e5a3684411254d58b1c5a542212b782114d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xb0efaf46a1de55c54f333f93b1f0641e73bc16d0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xd0fa3b5264ccde31e8b094b86bca4a1e97d3c603 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xad4c666fc170b468b19988959eb931a3676f0e9f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x790fde1fd6d2568050061a88c375d5c2e06b140b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xaefc1edaede6adadcdf3bb344577d45a80b19582 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xa8a5356ee5d02fe33d72355e4f698782f8f199e8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x55bc964fe3b0c8cc2d4c63d65f1be7aef9bb1a3c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x95d9d28606ee55de7667f0f176ebfc3215cfd9c0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x21b8065d10f73ee2e260e5b47d3344d3ced7596e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x0d4a11d5eeaac28ec3f61d100daf4d40471f1852 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x517f9dd285e75b599234f7221227339478d0fcc8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xa43fe16908251ee70ef74718545e4fe6c5ccec9f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x0af81cd5d9c124b4859d65697a4cd10ee223746a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xca7c2771d248dcbe09eabe0ce57a62e18da178c0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x09d1d767edf8fa23a64c51fa559e0688e526812f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x7b73644935b8e68019ac6356c40661e1bc315860 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x180efc1349a69390ade25667487a826164c9c6e4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x9c4fe5ffd9a9fc5678cfbd93aa2d4fd684b67c4c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xa478c2975ab1ea89e8196811f51a7b7ade33eb11 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xbb2b8038a1640196fbe3e38816f3e67cba72d940 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x9ec9367b8c4dd45ec8e7b800b1f719251053ad60 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xc91ef786fbf6d62858262c82c63de45085dea659 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x197d7010147df7b99e9025c724f13723b29313f8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x25647e01bd0967c1b9599fa3521939871d1d0888 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x2f0b1417aa42ebf0b4ca1154212847f6094d708d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x6ada49aeccf6e556bb7a35ef0119cc8ca795294a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x2a6c340bcbb0a79d3deecd3bc5cbc2605ea9259f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xda2d09fbbf8ee4b5051a0e9b562c5fcb4b393b18 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x48d20b3e529fb3dd7d91293f80638df582ab2daa - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x4028daac072e492d34a3afdbef0ba7e35d8b55c4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xc2eab7d33d3cb97692ecb231a5d0e4a649cb539d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xc5be99a02c6857f9eac67bbce58df5572498f40c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xe4b8583ccb95b25737c016ac88e539d0605949e8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x8dbee21e8586ee356130074aaa789c33159921ca - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x43de4318b6eb91a7cf37975dbb574396a7b5b5c6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x9ff68f61ca5eb0c6606dc517a9d44001e564bb66 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xa29fe6ef9592b5d408cca961d0fb9b1faf497d6d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x1b1137dd16faa651e38a9dfb5d9ffff7767fdf62 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x470e8de2ebaef52014a47cb5e6af86884947f08c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x8fb8e9921922d2ffb529a95d28a0d06d275d7a59 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xd3d2e2692501a5c9ca623199d38826e513033a17 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x97e1fcb93ae7267dbafad23f7b9afaa08264cfd8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xa5e9c917b4b821e4e0a5bbefce078ab6540d6b5e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x2cc846fff0b08fb3bffad71f53a60b4b6e6d6482 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x959873fb4fc11825fba83c80c4c632db1e936e15 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xa7480aafa8ad2af3ce24ac6853f960ae6ac7f0c4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xc7e6b676bfc73ae40bcc4577f22aab1682c691c6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x570febdf89c07f256c75686caca215289bb11cfc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x343fd171caf4f0287ae6b87d75a8964dc44516ab - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xcaa004418eb42cdf00cb057b7c9e28f0ffd840a5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xe3d3551bb608e7665472180a20280630d9e938aa - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xb6b0c651c37ec4ca81c0a128420e02001a57fac2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x4e34da137f0b317c633838458e0c923a5e088752 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xfe9e7931e55c514c33d489c88582fa36e84bd8e3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x5281e311734869c64ca60ef047fd87759397efe6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x149148acc3b06b8cc73af3a10e84189243a35925 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x8ef79d6c328c25da633559c20c75f638a4863462 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x45dda9cb7c25131df268515131f647d726f50608 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x50eaedb835021e4a108b7290636d62e9765cc6d7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x167384319b41f7094e62f7506409eb38079abff8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa374094527e1673a86de625aa59517c5de346d32 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x86f1d8390222a3691c28938ec7404a1661e618e0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xeda1094f59a4781456734e5d258b95e6be20b983 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x847b64f9d3a95e977d157866447a5c0a5dfa0ee5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x94ab9e4553ffb839431e37cc79ba8905f45bfbea - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x0e44ceb592acfc5d3f09d996302eb4c499ff8c10 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x1e5bd2ab4c308396c06c182e1b7e7ba8b2935b83 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x9b08288c3be4f62bbf8d1c20ac9c5e6f9467d8b7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xb6e57ed85c4c9dbfef2a68711e9d6f36c56e0fcb - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x3e31ab7f37c048fc6574189135d108df80f0ea26 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xd36ec33c8bed5a9f7b6630855f1533455b98a418 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xdac8a8e6dbf8c690ec6815e0ff03491b2770255d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xfe343675878100b344802a6763fd373fdeed07a4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x0a28c2f5e0e8463e047c203f00f649812ae67e4f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x88f3c15523544835ff6c738ddb30995339ad57d6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x98b9162161164de1ed182a0dfa08f5fbf0f733ca - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xeef1a9507b3d505f0062f2be9453981255b503c8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xc4c06c9a239f94fc0a1d3e04d23c159ebe8316f1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x849ec65748107aedc518dbc42961f358ea1361a7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x2db87c4831b2fec2e35591221455834193b50d1b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa4d8c89f0c20efbe54cba9e7e7a7e509056228d9 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x642f28a89fa9d0fa30e664f71804bfdd7341d21f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x2aceda63b5e958c45bd27d916ba701bc1dc08f7a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x781067ef296e5c4a4203f81c593274824b7c185d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x4ccd010148379ea531d6c587cfdd60180196f9b1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xd866fac7db79994d08c0ca2221fee08935595b4b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x941061770214613ba0ca3db9a700c39587bb89b6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa9077cdb3d13f45b8b9d87c43e11bce0e73d8631 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa01f64fa1b923dd9c5c7618b39a6ba8098a88863 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa830ff28bb7a46570a7e43dc24a35a663b9cfc2e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x8837a61644d523cbe5216dde226f8f85e3aa9be3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xca5d44977d6de1846530eb434167b208752fba7d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x4d05f2a005e6f36633778416764e82d1d12e7fbb - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x41e64a5bc929fa8e6a9c8d7e3b81a13b21ff3045 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x3ea34cfc9322273311f7843826a2581c4a00fd39 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x785061ed819414dc4269d2a5d5974069c0daea96 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x3f5228d0e7d75467366be7de2c31d0d098ba2c23 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x2e3f22e9a1c2470b2e293351f48c99e1fd788f32 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x2a08c38c7e1fa969325e2b64047abb085dec3756 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xe6c36eed27c2e8ecb9a233bf12da06c9730b5955 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xefa98fdf168f372e5e9e9b910fcdfd65856f3986 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x76fa081e510f43ac8335efdb4db88c9ff1894413 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xc6832ef0af793336aa44a936e54b992bff47e7cd - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x865f456479a21e2b3d866561d7171a3d0a7b112d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xbd934a7778771a7e2d9bf80596002a214d8c9304 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x9ab9f658104467604b5afa9a3e1df62f35f7b208 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x6e430d59ba145c59b73a6db674fe3d53c1f31cae - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x21b8065d10f73ee2e260e5b47d3344d3ced7596e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x0d4a11d5eeaac28ec3f61d100daf4d40471f1852 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x517f9dd285e75b599234f7221227339478d0fcc8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa43fe16908251ee70ef74718545e4fe6c5ccec9f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x0af81cd5d9c124b4859d65697a4cd10ee223746a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xca7c2771d248dcbe09eabe0ce57a62e18da178c0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x09d1d767edf8fa23a64c51fa559e0688e526812f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x7b73644935b8e68019ac6356c40661e1bc315860 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x180efc1349a69390ade25667487a826164c9c6e4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x9c4fe5ffd9a9fc5678cfbd93aa2d4fd684b67c4c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa478c2975ab1ea89e8196811f51a7b7ade33eb11 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xbb2b8038a1640196fbe3e38816f3e67cba72d940 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x9ec9367b8c4dd45ec8e7b800b1f719251053ad60 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xc91ef786fbf6d62858262c82c63de45085dea659 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x197d7010147df7b99e9025c724f13723b29313f8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x25647e01bd0967c1b9599fa3521939871d1d0888 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x2f0b1417aa42ebf0b4ca1154212847f6094d708d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x6ada49aeccf6e556bb7a35ef0119cc8ca795294a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x2a6c340bcbb0a79d3deecd3bc5cbc2605ea9259f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xda2d09fbbf8ee4b5051a0e9b562c5fcb4b393b18 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x48d20b3e529fb3dd7d91293f80638df582ab2daa - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x4028daac072e492d34a3afdbef0ba7e35d8b55c4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xc2eab7d33d3cb97692ecb231a5d0e4a649cb539d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xc5be99a02c6857f9eac67bbce58df5572498f40c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xe4b8583ccb95b25737c016ac88e539d0605949e8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x8dbee21e8586ee356130074aaa789c33159921ca - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x43de4318b6eb91a7cf37975dbb574396a7b5b5c6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x9ff68f61ca5eb0c6606dc517a9d44001e564bb66 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa29fe6ef9592b5d408cca961d0fb9b1faf497d6d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x1b1137dd16faa651e38a9dfb5d9ffff7767fdf62 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x470e8de2ebaef52014a47cb5e6af86884947f08c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x8fb8e9921922d2ffb529a95d28a0d06d275d7a59 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xd3d2e2692501a5c9ca623199d38826e513033a17 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x97e1fcb93ae7267dbafad23f7b9afaa08264cfd8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa5e9c917b4b821e4e0a5bbefce078ab6540d6b5e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x2cc846fff0b08fb3bffad71f53a60b4b6e6d6482 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x959873fb4fc11825fba83c80c4c632db1e936e15 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa7480aafa8ad2af3ce24ac6853f960ae6ac7f0c4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xc7e6b676bfc73ae40bcc4577f22aab1682c691c6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x570febdf89c07f256c75686caca215289bb11cfc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x343fd171caf4f0287ae6b87d75a8964dc44516ab - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xcaa004418eb42cdf00cb057b7c9e28f0ffd840a5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xe3d3551bb608e7665472180a20280630d9e938aa - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xb6b0c651c37ec4ca81c0a128420e02001a57fac2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x4e34da137f0b317c633838458e0c923a5e088752 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xfe9e7931e55c514c33d489c88582fa36e84bd8e3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x5281e311734869c64ca60ef047fd87759397efe6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x149148acc3b06b8cc73af3a10e84189243a35925 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x8ef79d6c328c25da633559c20c75f638a4863462 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x9e37cb775a047ae99fc5a24dded834127c4180cd - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x48413707b70355597404018e7c603b261fcadf3f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xade9bcd4b968ee26bed102dd43a55f6a8c2416df - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xda679706ff21114ac9fac5198bff24543f357a16 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xba3f945812a83471d709bce9c3ca699a19fb46f7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xc9034c3e7f58003e6ae0c8438e7c8f4598d5acaa - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x4c36388be6f416a29c8d8eee81c771ce6be14b18 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xa1b2457c0b627f97f6cc892946a382451e979014 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x4b0aaf3ebb163dd45f663b38b6d93f6093ebc2d3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xae2ce200bdb67c472030b31f602f0756c9aeb61c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x3bc5180d5439b500f381f9a46f15dd6608101671 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x5122e02898ece3bc62df8c1efdb29a9e914244d3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x24e1cbd6fed006ceed9af0dce688acc7951d57a9 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x2556230ac694093d4d3b7b965a2f2d77d4c403a4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xdaca082c2c7d052a96fa83ea9d3a7b6839e39586 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xa555149210075702a734968f338d5e1cbd509354 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x10648ba41b8565907cfa1496765fa4d95390aa0d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x00bcec1526dae1e170a53017b8775a93b7810d7c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x20e068d76f9e90b90604500b84c7e19dcb923e7e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x6b93950a9b589bc32b82a5df4e5148f98a7fae27 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xd9caa6dbe6791fcb7fc9fb59d1a6b3dd8c1c2339 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x62e81e93136ac42a1ada48d4098f5f9e703e7455 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x84206d33845c9d811438b6fe4e7a0c634748dc50 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xd0b53d9277642d899df5c87a3966a349a798f224 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xcfa7c4bb565915f1c4f9475e2a0536d31efad776 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xa7de21f28ca460b45373b217cd4eb111c3faeff8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xb64dff20dd5c47e6dbb56ead80d23568006dec1e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xad4e969f4193878e5cc89cefb57faf6c7c0048da - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xdf5eb97e3e23ca7f5a5fd2264680377c211310ba - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xf16baaae8eb7b37f4280e72924479f69e7a61f32 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xe745a591970e0fa981204cf525e170a2b9e4fb93 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x64b74c66b9ba60ca668b781289767ae7298f37ae - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x17e1ebd791e7253a5e606fd94c5b66c14d873136 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x46715bd57b9ec01deadb35fe096fb44acda79414 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x3447accd4b8e735329d1065244aad2ed630f0122 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x2feb7f3ffc243f7de94d5ea5975533d301584e07 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x0d5959a52e7004b601f0be70618d01ac3cdce976 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x2170ca774e48a3f51559917ada6f9d7ae8f7bfea - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x62a76dfa8951aefcff787e790782db3633ebf422 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x8073679e0b3b2d1d665777cf1b2b5b1c2d3d2d0c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x143f1a6f3fb32e6ab3f22d3cc6b417b5c2197599 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x82ad659c2f152aad59bb37cbc5e7663a2de0c607 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xa4efe9e8e2a2d5a2ac46805f233b8e49d0e11955 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xfcc89a1f250d76de198767d33e1ca9138a7fb54b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x2faa2b42b782d578a160f61bb7cd763a17476730 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xdd44c0e83c2570062d1e6fdd440b4724862e8f31 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xe3930a14641786e123e7bbe842d701fa1cbfe2df - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x6d03360ce4764e862ed81660c1f76cc2711b14b6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xc055f66f228105072315247785c00299d0ce27e8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xcae1d141ab11cef0a415cf0440025e1e5e962e06 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x21b8065d10f73ee2e260e5b47d3344d3ced7596e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x0d4a11d5eeaac28ec3f61d100daf4d40471f1852 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x517f9dd285e75b599234f7221227339478d0fcc8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xa43fe16908251ee70ef74718545e4fe6c5ccec9f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x0af81cd5d9c124b4859d65697a4cd10ee223746a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xca7c2771d248dcbe09eabe0ce57a62e18da178c0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x09d1d767edf8fa23a64c51fa559e0688e526812f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x7b73644935b8e68019ac6356c40661e1bc315860 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x180efc1349a69390ade25667487a826164c9c6e4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x9c4fe5ffd9a9fc5678cfbd93aa2d4fd684b67c4c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xa478c2975ab1ea89e8196811f51a7b7ade33eb11 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xbb2b8038a1640196fbe3e38816f3e67cba72d940 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x9ec9367b8c4dd45ec8e7b800b1f719251053ad60 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xc91ef786fbf6d62858262c82c63de45085dea659 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x197d7010147df7b99e9025c724f13723b29313f8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x25647e01bd0967c1b9599fa3521939871d1d0888 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x2f0b1417aa42ebf0b4ca1154212847f6094d708d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x6ada49aeccf6e556bb7a35ef0119cc8ca795294a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x2a6c340bcbb0a79d3deecd3bc5cbc2605ea9259f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xda2d09fbbf8ee4b5051a0e9b562c5fcb4b393b18 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x48d20b3e529fb3dd7d91293f80638df582ab2daa - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x4028daac072e492d34a3afdbef0ba7e35d8b55c4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xc2eab7d33d3cb97692ecb231a5d0e4a649cb539d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xc5be99a02c6857f9eac67bbce58df5572498f40c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xe4b8583ccb95b25737c016ac88e539d0605949e8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x8dbee21e8586ee356130074aaa789c33159921ca - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x43de4318b6eb91a7cf37975dbb574396a7b5b5c6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x9ff68f61ca5eb0c6606dc517a9d44001e564bb66 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xa29fe6ef9592b5d408cca961d0fb9b1faf497d6d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x1b1137dd16faa651e38a9dfb5d9ffff7767fdf62 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x470e8de2ebaef52014a47cb5e6af86884947f08c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x8fb8e9921922d2ffb529a95d28a0d06d275d7a59 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xd3d2e2692501a5c9ca623199d38826e513033a17 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x97e1fcb93ae7267dbafad23f7b9afaa08264cfd8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xa5e9c917b4b821e4e0a5bbefce078ab6540d6b5e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x2cc846fff0b08fb3bffad71f53a60b4b6e6d6482 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x959873fb4fc11825fba83c80c4c632db1e936e15 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xa7480aafa8ad2af3ce24ac6853f960ae6ac7f0c4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xc7e6b676bfc73ae40bcc4577f22aab1682c691c6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x570febdf89c07f256c75686caca215289bb11cfc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x343fd171caf4f0287ae6b87d75a8964dc44516ab - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xcaa004418eb42cdf00cb057b7c9e28f0ffd840a5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xe3d3551bb608e7665472180a20280630d9e938aa - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xb6b0c651c37ec4ca81c0a128420e02001a57fac2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x4e34da137f0b317c633838458e0c923a5e088752 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xfe9e7931e55c514c33d489c88582fa36e84bd8e3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x5281e311734869c64ca60ef047fd87759397efe6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x149148acc3b06b8cc73af3a10e84189243a35925 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x8ef79d6c328c25da633559c20c75f638a4863462 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x0f338ec12d3f7c3d77a4b9fcc1f95f3fb6ad0ea6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x4eaa90264d6a3567228dcb5cfc242200da586437 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x6fe9e9de56356f7edbfcbb29fab7cd69471a4869 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xf420603317a0996a3fce1b1a80993eaef6f7ae1a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x47a90a2d92a8367a91efa1906bfc8c1e05bf10c4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x41bf5eeae051fbd2e97b76b5f8f0fdcc1a1e526b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x28df0835942396b7a1b7ae1cd068728e6ddbbafd - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xa3f3664a52f01b42557524bd14556e379daf5669 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x1fd22fa7274bafebdfb1881321709f1219744829 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xe39cfc1a2e51a09ecbd060a24ee4eef5a97697bb - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x06396509195eb9e07c38a016694dc9ff535b128a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x5a1c486edefda2f09d3b349fadc38524f1743826 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x5bf1cf153c102a79d9e18b7fb7c79ba57fa70d0c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x2c3c320d49019d4f9a92352e947c7e5acfe47d68 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x4141325bac36affe9db165e854982230a14e6d48 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x17507bef4c3abc1bc715be723ee1baf571256e05 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x8149b92ea743cc382aada523b68b8834733b9015 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xc98f01bf2141e1140ef8f8cad99d4b021d10718f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x7f9d307973cdabe42769d9712df8ee1cc1a28d10 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x5c87da28a45e5089b762dcbbd86f743d14c54317 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x2cd97604ef77bbcb1fa0cff47545dff8ec7def08 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x7862d9b4be2156b15d54f41ee4ede2d5b0b455e4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x554548b404213c7efcdbab933f52edfe3c581834 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x63008c5ea4e47f5421e0e1428b1c5043a507d0d0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x0350ca994791c4b07a5b02b08aaf9d6fc8ab510e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x32776ed4d96ed069a2d812773f0ad8ad9ef83cf8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x84f3ca9b7a1579ff74059bd0e8929424d3fa330e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x5289a8dbf7029ee0b0498a84777ed3941d9acfec - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xb2bc284ab4c953b7f7a06d59c0ceb2de26405f22 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x508acf810857fefa86281499068ad5d19ebce325 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xccdfcd1aac447d5b29980f64b831c532a6a33726 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x4fb87838a29b37598099ef5aa6b3fbeeef987c50 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x515e94dc736b9d8b7d28ecf1cece0aba3d75da97 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xfd6e5b7c30538dff2752058e425ad01a56b831cc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xcb99fe720124129520f7a09ca3cbef78d58ed934 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xd2f21358c1549be193537b2a4c5dc7f0228ae011 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x93094ed1c907e4bca7eb041cb659da94f7e1b58e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xd37e6ecb991d1a0e7610c89666817665713362a7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x73234630bd159384c8d43f145407312d64614f43 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xad1ddf00c4ae50573e4dc98e6c5ee93baa04a0c4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xa765593c821f7df9ad81119509a37961e7ffa6c5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x9b501a7ad3087d603ceb34424b7b2a6c348ad0b7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xafebb7cfa1a15fcac4121b609b456cbce3137c20 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x0adaf134ae0c4583b3a38fc3168a83e33162651e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xf9878a5dd55edc120fde01893ea713a4f032229c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x84e47c7f2fe86f6b5efbe14fee46b8bb871b2e05 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xf3e5bec78654049990965f666b0612e116b94fb2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x33e59edd3214e97cb68450c6d3d6c167de072aba - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x2ca76c7e466e560e0cb11a91269bb953e41254bc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xbb124e35ab9e85f8d59ba83500e559dc052b9368 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x21b8065d10f73ee2e260e5b47d3344d3ced7596e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x0d4a11d5eeaac28ec3f61d100daf4d40471f1852 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x517f9dd285e75b599234f7221227339478d0fcc8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xa43fe16908251ee70ef74718545e4fe6c5ccec9f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x0af81cd5d9c124b4859d65697a4cd10ee223746a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xca7c2771d248dcbe09eabe0ce57a62e18da178c0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x09d1d767edf8fa23a64c51fa559e0688e526812f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x7b73644935b8e68019ac6356c40661e1bc315860 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x180efc1349a69390ade25667487a826164c9c6e4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x9c4fe5ffd9a9fc5678cfbd93aa2d4fd684b67c4c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xa478c2975ab1ea89e8196811f51a7b7ade33eb11 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xbb2b8038a1640196fbe3e38816f3e67cba72d940 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x9ec9367b8c4dd45ec8e7b800b1f719251053ad60 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xc91ef786fbf6d62858262c82c63de45085dea659 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x197d7010147df7b99e9025c724f13723b29313f8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x25647e01bd0967c1b9599fa3521939871d1d0888 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x2f0b1417aa42ebf0b4ca1154212847f6094d708d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x6ada49aeccf6e556bb7a35ef0119cc8ca795294a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x2a6c340bcbb0a79d3deecd3bc5cbc2605ea9259f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xda2d09fbbf8ee4b5051a0e9b562c5fcb4b393b18 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x48d20b3e529fb3dd7d91293f80638df582ab2daa - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x4028daac072e492d34a3afdbef0ba7e35d8b55c4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xc2eab7d33d3cb97692ecb231a5d0e4a649cb539d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xc5be99a02c6857f9eac67bbce58df5572498f40c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xe4b8583ccb95b25737c016ac88e539d0605949e8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x8dbee21e8586ee356130074aaa789c33159921ca - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x43de4318b6eb91a7cf37975dbb574396a7b5b5c6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x9ff68f61ca5eb0c6606dc517a9d44001e564bb66 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xa29fe6ef9592b5d408cca961d0fb9b1faf497d6d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x1b1137dd16faa651e38a9dfb5d9ffff7767fdf62 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x470e8de2ebaef52014a47cb5e6af86884947f08c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x8fb8e9921922d2ffb529a95d28a0d06d275d7a59 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xd3d2e2692501a5c9ca623199d38826e513033a17 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x97e1fcb93ae7267dbafad23f7b9afaa08264cfd8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xa5e9c917b4b821e4e0a5bbefce078ab6540d6b5e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x2cc846fff0b08fb3bffad71f53a60b4b6e6d6482 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x959873fb4fc11825fba83c80c4c632db1e936e15 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xa7480aafa8ad2af3ce24ac6853f960ae6ac7f0c4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xc7e6b676bfc73ae40bcc4577f22aab1682c691c6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x570febdf89c07f256c75686caca215289bb11cfc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x343fd171caf4f0287ae6b87d75a8964dc44516ab - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xcaa004418eb42cdf00cb057b7c9e28f0ffd840a5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xe3d3551bb608e7665472180a20280630d9e938aa - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xb6b0c651c37ec4ca81c0a128420e02001a57fac2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x4e34da137f0b317c633838458e0c923a5e088752 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xfe9e7931e55c514c33d489c88582fa36e84bd8e3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x5281e311734869c64ca60ef047fd87759397efe6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x149148acc3b06b8cc73af3a10e84189243a35925 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x8ef79d6c328c25da633559c20c75f638a4863462 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xd88d5f9e6c10e6febc9296a454f6c2589b1e8fae - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xb90fe7da36ac89448e6dfd7f2bb1e90a66659977 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xbd6313d0796984c578cae6bc5b5e23b27c5540c5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x1f18cd7d1c7ba0dbe3d9abe0d3ec84ce1ad10066 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x7da99753ff017f1b7afb2c8c0542718dc9f15f21 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x079e7a44f42e9cd2442c3b9536244be634e8f888 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x1c8dafd358d308b880f71edb5170b010b106ca60 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xbd0f6f34baa3c1329448a69bab90111a20756f01 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x3420720e561f3082f1e514a4545f0f2e0c955a5d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xea3fb6e3313a2a90757e4ca3d6749efd0107b0b6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xf130f72f8190f662522774c3367e6e8814f5e219 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x4a46c053bd5c10a959aea258228217b9d3405f3d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xb83258bf5940c98abf54f26c5a02710bd6b83b2c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x6a209c5329f0a225fa1890d4177823c096016f34 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xdb24905b1b080f65dedb0ad978aad5c76363d3c6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xddff2cdad11898b901a661e32e9fa010780263a0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x72dd8fe09b5b493012e5816068dfc6fb26a2a9e6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x54fc722a66abfb6500a36d8b7b2646129d0e836a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x53b612b32233c80ec439a64325a29766ce95be7f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xe5edcbe72d1bc223097a1bed1fe6c0e404b4290c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xb928c37b8bd9754d321dc3d3c6ef374d332fe761 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x2d70cbabf4d8e61d5317b62cbe912935fd94e0fe - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x953e2937f0515c43ca7995e80c84aedcbbb9385e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x84394d80830ae963b599ded7d9149b90059f182f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xa1777e082fa1746eb78dd9c1fbb515419cf6e538 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x112466c8b6e5abe42c78c47eb1b9d40baa3f943c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x9491d57c5687ab75726423b55ac2d87d1cda2c3f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x978799f1845c00c9a4d9fd2629b9ce18df66e488 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xdc55d1fd1c04e005051a40bd59c5f95623257bc5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x34757893070b0fc5de37aaf2844255ff90f7f1e0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x7faf167615419228f3f7d71d52d840dab154913c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xa4d7b6a50dd4c55334ca6f175dbc6561f269d264 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x0ed413cefde954d8e5c54d981d7d182b587e98e3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x524375d0c6a04439128428f400b00eae81a2e9e4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x4b7a4530d56ff55a4dce089d917ede812e543307 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x84bb5b9bf1b6782c87cfa3e396f2f571c8e49646 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x723292eea7e1576ae482a5c317934054c0199e24 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x9b42940e8184d866aac6595a91f8d8952a59d3b9 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x37622453c614f625d288151101ffe48fd222ced1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x4a94130b9e8eb0a0959c2c0f1ee9583213773fd9 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x51514b3dc24afc1db95586242b99f0063bea17c5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xc130254e9196d48bbd9f91240390a6e8203132e9 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x60ac25da2ada3be14a2a8c04e45b072bed965966 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x4e392a3883a84225260ff857318517eb50e5d128 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xca0aa06385a42242fe9523cd7015f6d01cd8f6b2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x3e448c17043ce1481bbe53c0fd19481bad8b98a6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x81060e6bf2a683f208b8799a33c7c09830cabed1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x463fe9f646b61ccfb43a022bf947075411cd71c7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x21b8065d10f73ee2e260e5b47d3344d3ced7596e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x0d4a11d5eeaac28ec3f61d100daf4d40471f1852 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x517f9dd285e75b599234f7221227339478d0fcc8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xa43fe16908251ee70ef74718545e4fe6c5ccec9f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x0af81cd5d9c124b4859d65697a4cd10ee223746a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xca7c2771d248dcbe09eabe0ce57a62e18da178c0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x09d1d767edf8fa23a64c51fa559e0688e526812f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x7b73644935b8e68019ac6356c40661e1bc315860 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x180efc1349a69390ade25667487a826164c9c6e4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x9c4fe5ffd9a9fc5678cfbd93aa2d4fd684b67c4c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xa478c2975ab1ea89e8196811f51a7b7ade33eb11 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xbb2b8038a1640196fbe3e38816f3e67cba72d940 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x9ec9367b8c4dd45ec8e7b800b1f719251053ad60 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xc91ef786fbf6d62858262c82c63de45085dea659 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x197d7010147df7b99e9025c724f13723b29313f8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x25647e01bd0967c1b9599fa3521939871d1d0888 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x2f0b1417aa42ebf0b4ca1154212847f6094d708d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x6ada49aeccf6e556bb7a35ef0119cc8ca795294a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x2a6c340bcbb0a79d3deecd3bc5cbc2605ea9259f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xda2d09fbbf8ee4b5051a0e9b562c5fcb4b393b18 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x48d20b3e529fb3dd7d91293f80638df582ab2daa - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x4028daac072e492d34a3afdbef0ba7e35d8b55c4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xc2eab7d33d3cb97692ecb231a5d0e4a649cb539d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xc5be99a02c6857f9eac67bbce58df5572498f40c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xe4b8583ccb95b25737c016ac88e539d0605949e8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x8dbee21e8586ee356130074aaa789c33159921ca - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x43de4318b6eb91a7cf37975dbb574396a7b5b5c6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x9ff68f61ca5eb0c6606dc517a9d44001e564bb66 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xa29fe6ef9592b5d408cca961d0fb9b1faf497d6d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x1b1137dd16faa651e38a9dfb5d9ffff7767fdf62 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x470e8de2ebaef52014a47cb5e6af86884947f08c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x8fb8e9921922d2ffb529a95d28a0d06d275d7a59 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xd3d2e2692501a5c9ca623199d38826e513033a17 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x97e1fcb93ae7267dbafad23f7b9afaa08264cfd8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xa5e9c917b4b821e4e0a5bbefce078ab6540d6b5e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x2cc846fff0b08fb3bffad71f53a60b4b6e6d6482 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x959873fb4fc11825fba83c80c4c632db1e936e15 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xa7480aafa8ad2af3ce24ac6853f960ae6ac7f0c4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xc7e6b676bfc73ae40bcc4577f22aab1682c691c6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x570febdf89c07f256c75686caca215289bb11cfc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x343fd171caf4f0287ae6b87d75a8964dc44516ab - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xcaa004418eb42cdf00cb057b7c9e28f0ffd840a5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xe3d3551bb608e7665472180a20280630d9e938aa - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xb6b0c651c37ec4ca81c0a128420e02001a57fac2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x4e34da137f0b317c633838458e0c923a5e088752 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xfe9e7931e55c514c33d489c88582fa36e84bd8e3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x5281e311734869c64ca60ef047fd87759397efe6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x149148acc3b06b8cc73af3a10e84189243a35925 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x8ef79d6c328c25da633559c20c75f638a4863462 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x0f23d49bc92ec52ff591d091b3e16c937034496e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x0f23d49bc92ec52ff591d091b3e16c937034496e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xbf16ef186e715668aa29cef57e2fd7f9d48adfe6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x0f23d49bc92ec52ff591d091b3e16c937034496e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x5645dcb64c059aa11212707fbf4e7f984440a8cf - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x0f23d49bc92ec52ff591d091b3e16c937034496e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x3ad4913fa896391c9822a81d8d869cc0d783bdd7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x0f23d49bc92ec52ff591d091b3e16c937034496e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x0f23d49bc92ec52ff591d091b3e16c937034496e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x0f23d49bc92ec52ff591d091b3e16c937034496e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x7a415b19932c0105c82fdb6b720bb01b0cc2cae3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x9b3423373e6e786c9ac367120533abe4ee398373 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x4a25dbdf9629b1782c3e2c7de3bdce41f1c7f801 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xbe80225f09645f172b079394312220637c440a63 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x059615ebf32c946aaab3d44491f78e4f8e97e1d3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x435664008f38b0650fbc1c9fc971d0a3bc2f1e47 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x4b62fa30fea125e43780dc425c2be5acb4ba743b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xc3db44adc1fcdfd5671f555236eae49f4a8eea18 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xddd23787a6b80a794d952f5fb036d0b31a8e6aff - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xa86aca6d7c393c06dcdc30473ea3d1b05c358dff - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x1ffec7119e315b15852557f654ae0052f76e6ae1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x0f027d40c80d8f70f77d3884776531f80b21d20e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x69c66beafb06674db41b22cfc50c34a93b8d82a2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xeedff72a683058f8ff531e8c98575f920430fdc5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x811cfb75567a252bea23474e2ccd1286927bfe0a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x2caccf71bdf8fff97c06a46eca29b611b1a74b5e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xf07a84f0732dfe8eea0d3961bcd8f62c761ff508 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x8c1c499b1796d7f3c2521ac37186b52de024e58c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xe5cf22ee4988d54141b77050967e1052bd9c7f7a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x7f580f8a02b759c350e6b8340e7c2d4b8162b6a9 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x48b0ab72c2591849e678e7d6f272b75ef9b863f7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x74d0ae8b8e1fca6039707564704a25ad2ee036b0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x5969efdde3cf5c0d9a88ae51e47d721096a97203 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xe32efff8f8b5fdc53803405aa3f623f03f8a8767 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xe8629b6a488f366d27dad801d1b5b445199e2ada - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x066b28f0c160935cf285f75ed600967bf8417035 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xddd23787a6b80a794d952f5fb036d0b31a8e6aff - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xa86aca6d7c393c06dcdc30473ea3d1b05c358dff - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x1ffec7119e315b15852557f654ae0052f76e6ae1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x0f027d40c80d8f70f77d3884776531f80b21d20e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x69c66beafb06674db41b22cfc50c34a93b8d82a2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xeedff72a683058f8ff531e8c98575f920430fdc5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x811cfb75567a252bea23474e2ccd1286927bfe0a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x2caccf71bdf8fff97c06a46eca29b611b1a74b5e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xf07a84f0732dfe8eea0d3961bcd8f62c761ff508 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x8c1c499b1796d7f3c2521ac37186b52de024e58c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x146b020399769339509c98b7b353d19130c150ec - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xd28f71e383e93c570d3edfe82ebbceb35ec6c412 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xadab76dd2dca7ae080a796f0ce86170e482afb4a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x0fb07e6d6e1f52c839608e1436d2ea810cf07257 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xddd23787a6b80a794d952f5fb036d0b31a8e6aff - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xa86aca6d7c393c06dcdc30473ea3d1b05c358dff - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x1ffec7119e315b15852557f654ae0052f76e6ae1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x0f027d40c80d8f70f77d3884776531f80b21d20e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x69c66beafb06674db41b22cfc50c34a93b8d82a2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xeedff72a683058f8ff531e8c98575f920430fdc5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x811cfb75567a252bea23474e2ccd1286927bfe0a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x2caccf71bdf8fff97c06a46eca29b611b1a74b5e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xf07a84f0732dfe8eea0d3961bcd8f62c761ff508 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x8c1c499b1796d7f3c2521ac37186b52de024e58c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x95d2483d2a0fff034004f91c53d649623d993896 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x19c5505638383337d2972ce68b493ad78e315147 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xc143161ed3ed8049bb63d8da42907c08a10e2269 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xc3286373599dd5af2a17a572ebb7561f05f88bec - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xbb98b3d2b18aef63a3178023a920971cf5f29be4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x647fb01a63de9a551b39c7915693b25e6bcec502 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa90c1c009dc8292bd04ced30f9b53a5ff7a806a0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xddd23787a6b80a794d952f5fb036d0b31a8e6aff - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa86aca6d7c393c06dcdc30473ea3d1b05c358dff - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x1ffec7119e315b15852557f654ae0052f76e6ae1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x0f027d40c80d8f70f77d3884776531f80b21d20e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x69c66beafb06674db41b22cfc50c34a93b8d82a2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xeedff72a683058f8ff531e8c98575f920430fdc5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x811cfb75567a252bea23474e2ccd1286927bfe0a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x2caccf71bdf8fff97c06a46eca29b611b1a74b5e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xf07a84f0732dfe8eea0d3961bcd8f62c761ff508 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x8c1c499b1796d7f3c2521ac37186b52de024e58c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xfb765ff72a14735550f1d798a5efd1311f2ddee7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x3537f2a5f99f08f59eb1417073db1fadbebf0c74 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xde8ed0277ee0e84c25756a73ffa7374e4aeadf46 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xd8f3a72d2b2220a5067abe8c38aea57dc2d69a5e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x7ec18abf80e865c6799069df91073335935c4185 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x14b1911dd6b451c2771661ae8cd70637d726c356 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x9ae8084c21752971d867597c07f2673765d949a1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xcfaf75a3d292c3535ea3acdb16ed2ee58c2bb091 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x8055e6de251e414e8393b20adab096afb3cf8399 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xffec10fe1355c2d8df4f62affcdeffdb04f06569 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xc16454420f100b2e771d8bc4c5b6200068129a34 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x046f405e4ae1d0e786eda4959adadbd417d13ad8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xeccb34691c06c1c9c31ceb2228b22cbd242b5879 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xe22a2dfaaaaec8a7b2b7acb4909eaaa5c5bd6e64 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xe2dda0911e227e73d9fd94745b851c8bc6504610 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x0f082a7870908f8cebbb2cd27a42a9225c19f898 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x69d667281778db0c3bc8177efea3a91ee95c3068 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x30d61bb28a6789f9f49d8c7fb198d63b6aba4b61 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x090f3fd9110621df127c3f9be5c6f58c02f2d5eb - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xd56f086e7b796b313d49f2bc926fac4bdd2a2b0b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x7eb847a214192aab8fa1b503f4d4c9ddd2a08db6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x81b3bc0ef974c16d71b8614adb8c22ccc045da01 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xc9b44ca4159dbaf5722a3dc8618e9d4b5f39d5b2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xbeef35a63fc62a3334630d9d3b4db27093d95317 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x3d5d143381916280ff91407febeb52f2b60f33cf - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x68c9325cc268df8b9ed4a06429587f28471b5f84 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xa00cc1fb7ac185222294777c6b23a13c013f07ce - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x77021e63bcbd3c5296b0cdd8a3c3770fb0ea8fa2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xcc28456d4ff980cee3457ca809a257e52cd9cdb0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xec0b7e8e44c9d60efd67a89dba1d4a6e02a7a4a0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x0c8fed5dd65542ca5f0add1acab14c2e470c9110 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xd56da2b74ba826f19015e6b7dd9dae1903e85da1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x5482c2b11951bbb92b87858242e17abde802b398 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xd95bae63641d822dc591bd4aca7a64e53eac76f9 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x06959273e9a65433de71f5a452d529544e07ddd0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x24bf2ee2e09477082d1ddf2f0603baa460b3f5f3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x56d8f846415e08c5e663d89505e79f522d33f947 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x548e923281f372d28a40287d3a2d30dce482fc66 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x9d744d3d905897608d24c1b8c1c7db0d30c36cd4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xddd23787a6b80a794d952f5fb036d0b31a8e6aff - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xa86aca6d7c393c06dcdc30473ea3d1b05c358dff - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x1ffec7119e315b15852557f654ae0052f76e6ae1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x0f027d40c80d8f70f77d3884776531f80b21d20e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x69c66beafb06674db41b22cfc50c34a93b8d82a2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xeedff72a683058f8ff531e8c98575f920430fdc5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x811cfb75567a252bea23474e2ccd1286927bfe0a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x2caccf71bdf8fff97c06a46eca29b611b1a74b5e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0xf07a84f0732dfe8eea0d3961bcd8f62c761ff508 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/base/0x8c1c499b1796d7f3c2521ac37186b52de024e58c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xab46d39cb398fb3649ecba781180016fef75f50b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x25048028ad87484b7fce99bc4e22dcb6c3307470 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xdb2177fee5b0ebdc7b8038cb70f3964bb6d14143 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x42d749f736051d8933b118324cded52d1f92bec1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xb1a1b707b143b911c36e1a0f4f901c5017791aca - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x3319a81a316abd4c086f7048904e31ff86648b38 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x4a978a2d4fb7393063babfb0cee741b8bcd4dd4b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xea403e36fb592fdfdc342c38e94284ddbb0d2105 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xe3fb01794d6912f0773171e32e723471ee8df061 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x916d7f23ccbb1d10118dcfc6ad5a10b6446ff73e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xddd23787a6b80a794d952f5fb036d0b31a8e6aff - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xa86aca6d7c393c06dcdc30473ea3d1b05c358dff - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x1ffec7119e315b15852557f654ae0052f76e6ae1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x0f027d40c80d8f70f77d3884776531f80b21d20e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x69c66beafb06674db41b22cfc50c34a93b8d82a2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xeedff72a683058f8ff531e8c98575f920430fdc5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x811cfb75567a252bea23474e2ccd1286927bfe0a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x2caccf71bdf8fff97c06a46eca29b611b1a74b5e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xf07a84f0732dfe8eea0d3961bcd8f62c761ff508 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x8c1c499b1796d7f3c2521ac37186b52de024e58c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x6cde5f5a192fbf3fd84df983aa6dc30dbd9f8fac - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xd80d28850bebe6208433c298334392bc940b4fc7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x7f7c4335ccac291ddedcef4429a626c442b627ed - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x628cb3a5a206956423d158009612813b64b19dab - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x116361f4f45e310347b43cd098fdfa459760ea7f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x5dc631ad6c26bea1a59fbf2c2680cf3df43d249f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x1a810e0b6c2dd5629afa2f0c898b9512c6f78846 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xac1cb6d3d419da9ead0b53e62d6fb4bb53473523 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x0115d04a88990889471a88e85817aac9e961c07b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xd3409b7f3f54bb097433d0f4cd31c48ac33e569b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x493bfc1adb2e60805693197f23132350ffd2a04e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xcf4f103759770c21f945413781ca787620316988 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xb135ebde27d366b0d62e579bae4118cb991b820e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xecbc2f008c20729b9239317408367377c5473812 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x96e0c440d3377c2dfe4f2a82add0b045e46cbe64 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x6f5304c22ac77e228e8af4732ac6677c46e09030 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xcb037f27eb3952222810966e28e0ceb650c65cd9 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xddd23787a6b80a794d952f5fb036d0b31a8e6aff - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xa86aca6d7c393c06dcdc30473ea3d1b05c358dff - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x1ffec7119e315b15852557f654ae0052f76e6ae1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x0f027d40c80d8f70f77d3884776531f80b21d20e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x69c66beafb06674db41b22cfc50c34a93b8d82a2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xeedff72a683058f8ff531e8c98575f920430fdc5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x811cfb75567a252bea23474e2ccd1286927bfe0a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x2caccf71bdf8fff97c06a46eca29b611b1a74b5e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0xf07a84f0732dfe8eea0d3961bcd8f62c761ff508 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/pools/celo/0x8c1c499b1796d7f3c2521ac37186b52de024e58c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x7baece5d47f1bc5e1953fbe0e9931d54dab6d810 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x83abecf7204d5afc1bea5df734f085f2535a9976 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x4eefe02fce5b53ca33c7717bbd8ad3c9cb0609f1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xaf996125e98b5804c00ffdb4f7ff386307c99a00 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x7924a818013f39cf800f5589ff1f1f0def54f31f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0xb2eb5849e2606f99fc492e9add0103c667f806d3 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x53c6ca2597711ca7a73b6921faf4031eedf71339 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x4eefe02fce5b53ca33c7717bbd8ad3c9cb0609f1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0xaf996125e98b5804c00ffdb4f7ff386307c99a00 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x7924a818013f39cf800f5589ff1f1f0def54f31f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0xd35937ecd47b04a1474f8569f457fc5ac395921a + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0x4eefe02fce5b53ca33c7717bbd8ad3c9cb0609f1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0xaf996125e98b5804c00ffdb4f7ff386307c99a00 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0x7924a818013f39cf800f5589ff1f1f0def54f31f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x6b75f2189f0e11c52e814e09e280eb1a9a8a094a + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xb372b5abdb7c2ab8ad9e614be9835a42d0009153 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xf369277650ad6654f25412ea8bfbd5942733babc + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x4eefe02fce5b53ca33c7717bbd8ad3c9cb0609f1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xaf996125e98b5804c00ffdb4f7ff386307c99a00 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x7924a818013f39cf800f5589ff1f1f0def54f31f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x4898cf312fbff8814cab80a8d7f6ee5ad0dc73fb + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x5e78afc6c804d4382bede3a0712d210e657e9b4f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x86b211ca7915a0c8d4659dd98242d9e801d88ab4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xb637f7c82fd774c280e23cebc725e7cd807c66d0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xd249c43faabc58d6dd4b0a4de598b5a956c5d8d7 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x1fbae785ce68b79f7ed4f7b27c3af3ef0e0bc3d4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x3c1376fb8487da57d4ffb263d9d01b578c7b586b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x7b24bed19856f4bb1d4c0421cfb328026cd936bd + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x7cf887a863d81e6a483ee947dee05cb51914923c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x588c8cf031809486f015908864ee8699b44017e4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x3987d38a4ff8520a8ef6bcc6f98d6da8bcd69b89 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x4eefe02fce5b53ca33c7717bbd8ad3c9cb0609f1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xaf996125e98b5804c00ffdb4f7ff386307c99a00 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x7924a818013f39cf800f5589ff1f1f0def54f31f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0xde67d05242b18af00b28678db34feec883cc9cd6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x4eefe02fce5b53ca33c7717bbd8ad3c9cb0609f1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0xaf996125e98b5804c00ffdb4f7ff386307c99a00 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x7924a818013f39cf800f5589ff1f1f0def54f31f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x4a5a8b0108f446df7c1c8a459fcfb54e844b7343 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0xf6ba006abf768ab2d1b5bba2d22d9f13eb1269d4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x4eefe02fce5b53ca33c7717bbd8ad3c9cb0609f1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0xaf996125e98b5804c00ffdb4f7ff386307c99a00 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x7924a818013f39cf800f5589ff1f1f0def54f31f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x92c2fc5f306405eab0ff0958f6d85d7f8892cf4d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xcbe856765eeec3fdc505ddebf9dc612da995e593 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x92c2fc5f306405eab0ff0958f6d85d7f8892cf4d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0xcbe856765eeec3fdc505ddebf9dc612da995e593 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0xc1738d90e2e26c35784a0d3e3d8a9f795074bca4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0x92c2fc5f306405eab0ff0958f6d85d7f8892cf4d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0xcbe856765eeec3fdc505ddebf9dc612da995e593 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xda908c0bf14ad0b61ea5ebe671ac59b2ce091cbf + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x254aa3a898071d6a2da0db11da73b02b4646078f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x92c2fc5f306405eab0ff0958f6d85d7f8892cf4d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xcbe856765eeec3fdc505ddebf9dc612da995e593 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x41824081f2e7beb83048bf52465ddd7c8e471da2 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xa0c2ce1723b3939f47ad01a293292f2f75dc629d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xc42442f6402b68626e791a447d87b35cb1c6236e + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x84537db6f6aaa2afdb71f325d14b9f5f7825bef1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x13933689ed2c6c66e83aed64336df14896efb7e2 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x92c2fc5f306405eab0ff0958f6d85d7f8892cf4d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xcbe856765eeec3fdc505ddebf9dc612da995e593 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x039df62583ddc1c5fda75db152b87113d863b6d6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x92c2fc5f306405eab0ff0958f6d85d7f8892cf4d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0xcbe856765eeec3fdc505ddebf9dc612da995e593 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x92c2fc5f306405eab0ff0958f6d85d7f8892cf4d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0xcbe856765eeec3fdc505ddebf9dc612da995e593 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xc39e83fe4e412a885c0577c08eb53bdb6548004a + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xdbac78be00503d10ae0074e5e5873a61fc56647c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xc1cd3d0913f4633b43fcddbcd7342bc9b71c676f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x6c4c7f46d9d4ef6bc5c9e155f011ad19fc4ef321 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xb2c86ff752f18499b70e8f642b3421405d50d6e9 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x16588709ca8f7b84829b43cc1c5cb7e84a321b16 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xd0a4c8a1a14530c7c9efdad0ba37e8cf4204d230 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xf92f2e3fca01491baba0975264362cc38b1cab7b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x3e6e23198679419cd73bb6376518dcc5168c8260 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x531b6a4b3f962208ea8ed5268c642c84bb29be0b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x553e9c493678d8606d6a5ba284643db2110df823 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xe3170d65018882a336743a9c396c52ea4b9c5563 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x1385fc1fe0418ea0b4fcf7adc61fc7535ab7f80d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x5cd0ad98ba6288ed7819246a1ebc0386c32c314b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xe945683b3462d2603a18bdfbb19261c6a4f03ad1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xa1bf0e900fb272089c9fd299ea14bfccb1d1c2c0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xe46935ae80e05cdebd4a4008b6ccaa36d2845370 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x3041cbd36888becc7bbcbc0045e3b1f144466f5f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x0ad1e922e764df5ab6d636f5d21ecc2e41e827f0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0xe945683b3462d2603a18bdfbb19261c6a4f03ad1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0xa1bf0e900fb272089c9fd299ea14bfccb1d1c2c0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0xe46935ae80e05cdebd4a4008b6ccaa36d2845370 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x3041cbd36888becc7bbcbc0045e3b1f144466f5f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0x6b3a3d6ed64faf933a7a4b1bd44b2efba47614ac + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0x4ce4a1a593ea9f2e6b2c05016a00a2d300c9ffd8 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0x0843e0f56b9e7fdc4fb95fabba22a01ef4088f41 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0x8323d063b1d12acce4742f1e3ed9bc46d71f4222 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0xe945683b3462d2603a18bdfbb19261c6a4f03ad1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0xa1bf0e900fb272089c9fd299ea14bfccb1d1c2c0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0xe46935ae80e05cdebd4a4008b6ccaa36d2845370 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0x3041cbd36888becc7bbcbc0045e3b1f144466f5f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xe30e4dfdbb10949c27501922f845e20cfa579f09 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x7e02ae3f794ebade542c92973eb1c46d7e2e935d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xfa22d298e3b0bc1752e5ef2849cec1149d596674 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x8066ee17156e4184d69277e26fa8cbca3a845edf + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x418de8e0ab58abfe916a47821a055c59b9502deb + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xfb9caae5a5c0ab91f68542124c05d1efbb97d151 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xb68606a75b117906e06caa0755896ad2b3dd0272 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x6e33c0f5e16b45114679eac217e0c0138cefcd2e + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xd64fb39a5681908ad488b487d65f5d8479cb235c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xe945683b3462d2603a18bdfbb19261c6a4f03ad1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xa1bf0e900fb272089c9fd299ea14bfccb1d1c2c0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xe46935ae80e05cdebd4a4008b6ccaa36d2845370 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x3041cbd36888becc7bbcbc0045e3b1f144466f5f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x0217fc17c642d29b890bcf888e21be2378493e01 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x099d23a43da5a8a9282266dbefeaaef958150300 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xd92e0767473d1e3ff11ac036f2b1db90ad0ae55f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xe945683b3462d2603a18bdfbb19261c6a4f03ad1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xa1bf0e900fb272089c9fd299ea14bfccb1d1c2c0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xe46935ae80e05cdebd4a4008b6ccaa36d2845370 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x3041cbd36888becc7bbcbc0045e3b1f144466f5f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x40c547e7fd88f60d94788953b83d9342d8d133c6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x397433498c7befde4b4049b98a7ff081a2c17387 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0xf9be03505869d719ba194757943575ed2af001f2 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x18c40bb9281a07627ff25cea45b7511f68fd0076 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x270d89e983d9821a418bf193684736414fab78c5 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0xb125aa15ad943d96e813e4a06d0c34716f897e26 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x813c0decbb1097fff46d0ed6a39fb5f6a83043f4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x9a7ac628ba9f330341486380af729c8975388959 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0xf2c9339945bff71dd0bffd3c142164112cd05dc6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x12a4619c0bd9710732fbc458e9baa73df6c3d35f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x96530dac7817f186390b64ba63d13becd079b28d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x18fc1e95adb68b556212ebbad777f3fbb644db98 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0xabbeb324b090550ca6d15ec71019915813f54f90 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x86d708404d0db1d97843e66d4ed6b86d11be705b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0xbfbba3de6a260c8374f8299c38898312c2d6e9a6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0xe945683b3462d2603a18bdfbb19261c6a4f03ad1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0xa1bf0e900fb272089c9fd299ea14bfccb1d1c2c0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0xe46935ae80e05cdebd4a4008b6ccaa36d2845370 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x3041cbd36888becc7bbcbc0045e3b1f144466f5f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0xe945683b3462d2603a18bdfbb19261c6a4f03ad1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0xa1bf0e900fb272089c9fd299ea14bfccb1d1c2c0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0xe46935ae80e05cdebd4a4008b6ccaa36d2845370 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x3041cbd36888becc7bbcbc0045e3b1f144466f5f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xd31d41dffa3589bb0c0183e46a1eed983a5e5978 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x391e8501b626c623d39474afca6f9e46c2686649 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xd0fc8ba7e267f2bc56044a7715a489d851dc6d78 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x4fd47e5102dfbf95541f64ed6fe13d4ed26d2546 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0xe9033c0011f35547fa90d3f8a6ad4b666a590759 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0x0c3561d3b72e17378d99684414aa8669daeb8bd0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x14653ce9f406ba7f35a7ffa43c81fa7ecd99c788 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x3204e9734a56a4d7c6f4f5822e14182d9d1a43c4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x43faefd4c0c25e969ac211cd97a4a51e52c729b7 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xa652ab3be697c7a01fbdce4d73f8e8acd990251c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x29962083891241aad61ad97bae46d032c9c0c55c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x26bf3601b77be9c31b13b22ebca02914db9c7468 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x0d2edd335982f56662d772b93d86901eb9bd2ff9 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xbaed273edd493930711fe88690ebd1f30f7f55ab + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x16033643947bf4d8a1ae37b055edf57cb183106a + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0xf59abf32c1e8c5d2c6e3faa2131533bbcd466194 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x0312187403bf72b8d2d80729894d6ac3300bd63f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x416fdbc4fb8d4d1f48d0d3778c59dfa5352e9b15 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x90908e414d3525e33733d320798b5681508255ea + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x5918aca9ae924e6eaaa3d293bb92bdec9ab79338 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x8270e64d22cf13e92c641c4006408c7d7e3ff341 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x16503510c58da73486950b72a12ead3d1d8355dd + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x90908e414d3525e33733d320798b5681508255ea + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0x7505159f644ddc5eae21c119e328d0d5bee574b0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0xe870bfe4aacb6e234b645e535d26c53790d50e78 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0x2e2d190ad4e0d7be9569baebd4d33298379b0502 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0x90908e414d3525e33733d320798b5681508255ea + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xb834093d7e46f7644be45e77281394d31003e866 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xb5a1fd804342cfb679bd8ada75718bc3ec43097e + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x90908e414d3525e33733d320798b5681508255ea + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x9e71e2b14d7e6d30811628ab0965f28e4e2edbce + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xa011da4a0c9261ecf4694bf73a74d113aa261133 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x7ab922c1bfdf7df977c7531c5782074d866f3adc + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xe2d2050430e341a8f3988e2726e44d9370f8cd3a + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xed66ba3ea44425805a085b1ca80d00467b055b38 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x40dade19adc198125ec237a2c48b3408568b2f81 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x166bc40da621d3cb978e24334f844b84ddef25f8 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x76bf0abd20f1e0155ce40a62615a90a709a6c3d8 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x90908e414d3525e33733d320798b5681508255ea + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x6948d6c8532c6b0006cb67c6fb9c399792c8ac91 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x90908e414d3525e33733d320798b5681508255ea + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x4e40cf4a7d8724e5adc2b791bbf9451d1e260b93 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x90908e414d3525e33733d320798b5681508255ea + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xc0067d751fb1172dbab1fa003efe214ee8f419b6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xc3d7aa944105d3fafe07fc1822102449c916a8d0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0xd6b4cce96ddf8aab2e5750983af9a901f17fbc36 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x4cef551255ec96d89fec975446301b5c4e164c59 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0xc0067d751fb1172dbab1fa003efe214ee8f419b6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0xc3d7aa944105d3fafe07fc1822102449c916a8d0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0xdd0c6bae8ad5998c358b823df15a2a4181da1b80 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0xc0067d751fb1172dbab1fa003efe214ee8f419b6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0xc3d7aa944105d3fafe07fc1822102449c916a8d0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xc0067d751fb1172dbab1fa003efe214ee8f419b6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xc3d7aa944105d3fafe07fc1822102449c916a8d0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x5e6ff2fa4ca244b6b33c7286d368120822eacc11 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x98efd62b4bfbde6393b18b063c506ce5a77f4810 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x3c5096df639262db0a6cd0172f08709d4161094b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xae31f0e673fc5f33cfc0e9abb426d8051404a7c5 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xc0067d751fb1172dbab1fa003efe214ee8f419b6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xc3d7aa944105d3fafe07fc1822102449c916a8d0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0xc0067d751fb1172dbab1fa003efe214ee8f419b6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0xc3d7aa944105d3fafe07fc1822102449c916a8d0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0xd10456ce05b9af05c8eede0f93ea8aa80a0daa2f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x065c22a16f6531706681fabbc8df135fe6eb1c2e + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x8ab8d851c6b31d8a4d42fd7d3e47b20861b025f2 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0xc0067d751fb1172dbab1fa003efe214ee8f419b6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0xc3d7aa944105d3fafe07fc1822102449c916a8d0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x2982d3295a0e1a99e6e88ece0e93ffdfc5c761ae + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xc593fe9193b745447e86b45ea0bf62565ee030cc + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x88051b0eea095007d3bef21ab287be961f3d8598 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xaf21b0ec0197e63a5c6cc30c8e947eb8165c6212 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x9c84f58bb51fabd18698efe95f5bab4f33e96e8f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0xb31273fd2dfc05e6fd91a3b8a2a681aeb0fbcf48 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0xaf7b48ae2f4773fd44f9208cca3db5ae7bfa7e37 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0xc2125a452115ff5a300cc2a6ffae99637f6e329d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0xb08a8794a5d3ccca3725d92964696858d3201909 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0xaf21b0ec0197e63a5c6cc30c8e947eb8165c6212 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x9c84f58bb51fabd18698efe95f5bab4f33e96e8f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0xae99efe6b04bbe5b8b4ad567946fb84b35681abb + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0xaf21b0ec0197e63a5c6cc30c8e947eb8165c6212 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0x9c84f58bb51fabd18698efe95f5bab4f33e96e8f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xaf21b0ec0197e63a5c6cc30c8e947eb8165c6212 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x9c84f58bb51fabd18698efe95f5bab4f33e96e8f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x6696710b8e3dc0d844c8b9244767962a4a61ad97 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xcde77ef185a8f886d03b109573cc1dcdcf3cf1f8 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xaf21b0ec0197e63a5c6cc30c8e947eb8165c6212 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x9c84f58bb51fabd18698efe95f5bab4f33e96e8f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x35f5387decce5a234da1a32ca3c9e338a48bcf37 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x4178dd7eb2eb983ba7f7e41648cf91db6be20190 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0xaf21b0ec0197e63a5c6cc30c8e947eb8165c6212 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x9c84f58bb51fabd18698efe95f5bab4f33e96e8f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0xb6c8f9490314394cfc6edacb8717bfdc1eb8dab5 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x1625fe58cdb3726e5841fb2bb367dde9aaa009b3 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0xb1ed164c736909ba7ddbc1feb7ced4eaad854a87 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x95faa9a91cd6c1c018e4b1a6fc4c89d4f1695e5d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0xa143ccf73c25eec6f38bd1b741043ebea228b8e9 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x2e067e0eab7fd31c01473c0f56f3295afb82e461 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0xbc83c60e853398d263c1d88899cf5a8b408f9654 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0xaf21b0ec0197e63a5c6cc30c8e947eb8165c6212 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x9c84f58bb51fabd18698efe95f5bab4f33e96e8f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x202a6012894ae5c288ea824cbc8a9bfb26a49b93 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x744159757cac173a7a3ecf5e97adb10d1a725377 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x127452f3f9cdc0389b0bf59ce6131aa3bd763598 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x5ced44f03ff443bbe14d8ea23bc24425fb89e3ed + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x5ced44f03ff443bbe14d8ea23bc24425fb89e3ed + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0x2264ba9dc0b257c69eeae7782e8ff608cc65d6a7 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0x5ced44f03ff443bbe14d8ea23bc24425fb89e3ed + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x00a59c2d0f0f4837028d47a391decbffc1e10608 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x5ced44f03ff443bbe14d8ea23bc24425fb89e3ed + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xad6e8f6a34087bddfb03815e2c10e4f7bfd4395b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xd5bb156cb73bfca62f68dc3dff7e5ec4e305b861 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xc0d8f259578c985947a050802fb4857261af0bf3 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x5ced44f03ff443bbe14d8ea23bc24425fb89e3ed + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x74f7a360eb36a46b675ea932ea07094a3ace441f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x626761cc5b9fafe4696bf8def4aa015576bb4bef + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x5ced44f03ff443bbe14d8ea23bc24425fb89e3ed + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0xc767c0b2e2e56c455fd29f9ee9b6e6f035c71ed4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x625cb959213d18a9853973c2220df7287f1e5b7d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x5ced44f03ff443bbe14d8ea23bc24425fb89e3ed + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x7138eae57e8a214f7297e5e67bb6e183df3572d5 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xc7bbec68d12a0d1830360f8ec58fa599ba1b0e9b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x840deeef2f115cf50da625f7368c24af6fe74410 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x69c7bd26512f52bf6f76fab834140d13dda673ca + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x69c7bd26512f52bf6f76fab834140d13dda673ca + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0x69c7bd26512f52bf6f76fab834140d13dda673ca + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xda71299ff6bdac31bdcafde52a41d460f17e3ad9 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xabebc245a9a47166ecd10933d43817c8ef6fb825 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x69c7bd26512f52bf6f76fab834140d13dda673ca + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x69c7bd26512f52bf6f76fab834140d13dda673ca + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0xb007dda6ca7a57785ce04981c30a1934995a197a + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x0de383928e4fcf0f90ad2d6a5ee18eb3b9d16a55 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x0a36df020fe3f132e6557899f272bf3d4591620e + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x69c7bd26512f52bf6f76fab834140d13dda673ca + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x69c7bd26512f52bf6f76fab834140d13dda673ca + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x8c9d230d45d6cfee39a6680fb7cb7e8de7ea8e71 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0xcb198a55e2a88841e855be4eacaad99422416b33 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x9b371948735f612be19195f5f6e5ebc03839cdaf + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0xb3709d0e16b618b15ee4bcf82d19b9e7d4100914 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0xe426e1305f5e6093864762bf9d2d8b44bc211c59 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x7b9a5bc920610f54881f2f6359007957de504862 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xfb82dd4d657033133eea6e5b7015042984c5825f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x92560c178ce069cc014138ed3c2f5221ba71f58a + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x6ef7d514d75b5a5a3c500dba1b161a81e842e7a4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0xac70bd92f89e6739b3a08db9b6081a923912f73d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x1ebcf8831b93450ea81b0619c5e05b98751c8322 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x470d0d72c975a7f328bd63808bfffd28194b3eb6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0xa961f0473da4864c5ed28e00fcc53a3aab056c1b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x6ef7d514d75b5a5a3c500dba1b161a81e842e7a4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0xa5b6d588ceb3aa1bf543d095038479188f884690 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0x6ef7d514d75b5a5a3c500dba1b161a81e842e7a4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x6ef7d514d75b5a5a3c500dba1b161a81e842e7a4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xb1419a7f9e8c6e434b1d05377e0dbc4154e3de78 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x6ef7d514d75b5a5a3c500dba1b161a81e842e7a4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x70c132a2ddeccf0d76cc9b64a749ffe375a79a21 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x6ef7d514d75b5a5a3c500dba1b161a81e842e7a4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x6ef7d514d75b5a5a3c500dba1b161a81e842e7a4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x1b942ce8bf08290f740b9e825c91e07fcd0bfe75 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x5016cd7b785a773f7f3a3ff4035a1e7a76543946 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xf6c4e4f339912541d3f8ed99dba64a1372af5e5b + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x4f122edcd91af8cda38c3a87158afa8687bab57c + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0xed3fe08bd12f24dad0f1a1e58610644debe374fb + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x5016cd7b785a773f7f3a3ff4035a1e7a76543946 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0xf6c4e4f339912541d3f8ed99dba64a1372af5e5b + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0x7bc815ca2c2115f896bb14b31b8196388c05e99b + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0x5016cd7b785a773f7f3a3ff4035a1e7a76543946 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0xf6c4e4f339912541d3f8ed99dba64a1372af5e5b + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xd29c2df656b2e4ae6b6817ccc2ebe932fc6a950b + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x1f6082db7c8f4b199e17090cd5c8831a1dad1997 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x5016cd7b785a773f7f3a3ff4035a1e7a76543946 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xf6c4e4f339912541d3f8ed99dba64a1372af5e5b + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xc64f886397988ff16d72123dbe3d46e5bf33ffac + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x0d2c430c6f7ef48ed34bf4aad0ec377e03cc53cf + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x5016cd7b785a773f7f3a3ff4035a1e7a76543946 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xf6c4e4f339912541d3f8ed99dba64a1372af5e5b + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x2b11a34f52e354ef197f0a2397008699b875ae7e + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x5016cd7b785a773f7f3a3ff4035a1e7a76543946 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0xf6c4e4f339912541d3f8ed99dba64a1372af5e5b + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0xde27bdec962a74a72fa1c5ef50bff6f3da083e05 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x7766bdc5ff15d3aceb4d37914963aebaccf3de15 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x5016cd7b785a773f7f3a3ff4035a1e7a76543946 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0xf6c4e4f339912541d3f8ed99dba64a1372af5e5b + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x67ab7dc903a10838a0de8861dfdff3287cf98e5c + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x88aaeed1fcfca2eda30749afa9ad45a75c80e292 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x2c8e9a1586ed822f79c0a241e1a4d48e839b3182 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x847165954680b989902e354f34d08b09afab3cd9 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x590269935821d760c54b32d31db66ba47d4e53b4 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x03d70bf9e6afbf8cac09ef0c45f9a00a841c2bed + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x8b238f615c1f312d22a65762bcf601a37f1eeec7 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x5280d5e63b416277d0f81fae54bb1e0444cabdaa + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xf4e43a4a17d2820c7cf724e46844943931a47894 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x5ab53ee1d50eef2c1dd3d5402789cd27bb52c1bb + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0xe6ff8b9a37b0fab776134636d9981aa778c4e718 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x44af8d03393e498eec5fcfc7936ebc381f02974d + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x4094915f7849b26e8d43dee1f7e3b7b477a0b5bb + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0xc3f5e0d4cdff86e85486cf6bd20cc0884df5f98e + 2024-08-23T19:37:24.067Z 0.8 \ No newline at end of file diff --git a/apps/web/public/tokens-sitemap.xml b/apps/web/public/tokens-sitemap.xml index e727529afef..57022745a3e 100644 --- a/apps/web/public/tokens-sitemap.xml +++ b/apps/web/public/tokens-sitemap.xml @@ -2,3182 +2,6187 @@ https://app.uniswap.org/explore/tokens/ethereum/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xdac17f958d2ee523a2206206994597c13d831ec7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x2260fac5e5542a773aa44fbcfedf7c193bc2c599 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x6982508145454ce325ddbe47a25d4ec3d2311933 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x6b175474e89094c44da98b954eedeac495271d0f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x6123b0049f904d730db3c36a31167d9d4121fa6b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x1f9840a85d5af5bf1d1762f925bdaddc4201f984 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xcf0c122c6b73ff809c693db761e7baebe62b6a2e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xfaba6f8e4a5e8ab82f62fe7c39859fa577269be3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x58cb30368ceb2d194740b144eab4c2da8a917dcb - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x4c9edd5852cd905f086c759e8383e09bff1e68b3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xaaee1a9723aadb7afa2810263653a34ba2c21c7a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x514910771af9ca656af840dff83e8264ecf986ca - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x5b7533812759b45c2b44c19e320ba2cd2681b542 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xae78736cd615f374d3085123a210448e74fc6393 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xb9f599ce614feb2e1bbe58f180f370d05b39344e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xd5f7838f5c461feff7fe49ea5ebaf7728bb0adfa - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xd31a59c85ae9d8edefec411d448f90841571b89c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x6a7eff1e2c355ad6eb91bebb5ded49257f3fed98 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x576e2bed8f7b46d34016198911cdf9886f78bea7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x1258d60b224c0c5cd888d37bbf31aa5fcfb7e870 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x62d0a8458ed7719fdaf978fe5929c6d342b0bfce - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x77e06c9eccf2e797fd462a92b6d7642ef85b0a44 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x24fcfc492c1393274b6bcd568ac9e225bec93584 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x27702a26126e0b3702af63ee09ac4d1a084ef628 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xd46ba6d942050d489dbd938a2c909a5d5039a161 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xbe9895146f7af43049ca1c1ae358b0541ea49704 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x72f713d11480dcf08b37e1898670e736688d218d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x0001a500a6b18995b03f44bb040a5ffc28e45cb0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x9e9fbde7c7a83c43913bddc8779158f1368f0413 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x5f98805a4e8be255a32880fdec7f6728c6568ba0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x2b591e99afe9f32eaa6214f7b7629768c40eeb39 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x1ae7e1d0ce06364ced9ad58225a1705b3e5db92b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x046eee2cc3188071c02bfc1745a6b17c656e3f3d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x84018071282d4b2996272659d9c01cb08dd7327f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x12970e6868f88f6557b76120662c1b3e50a646bf - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xaea46a60368a7bd060eec7df8cba43b7ef41ad85 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x6de037ef9ad2725eb40118bb1702ebb27e4aeb24 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xc01154b4ccb518232d6bbfc9b9e6c5068b766f82 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x5a98fcbea516cf06857215779fd812ca3bef1b32 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x102c776ddb30c754ded4fdcc77a19230a60d4e4f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x72e4f9f808c49a2a61de9c5896298920dc4eeea9 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x467719ad09025fcc6cf6f8311755809d45a5e5f3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xf19308f923582a6f7c465e5ce7a9dc1bec6665b1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x710287d1d39dcf62094a83ebb3e736e79400068a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xf951e335afb289353dc249e82926178eac7ded78 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xf017d3690346eb8234b85f74cee5e15821fee1f4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x8c282c35b5e1088bb208991c151182a782637699 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xeaa63125dd63f10874f99cdbbb18410e7fc79dd3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xde342a3e269056fc3305f9e315f4c40d917ba521 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x2dff88a56767223a5529ea5960da7a3f5f766406 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x626e8036deb333b408be468f951bdb42433cbf18 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xdd66781d0e9a08d4fbb5ec7bac80b691be27f21d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xb23d80f5fefcddaa212212f028021b41ded428cf - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xbaac2b4491727d78d2b78815144570b9f2fe8899 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xf8ebf4849f1fa4faf0dff2106a173d3a6cb2eb3a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xb90b2a35c65dbc466b04240097ca756ad2005295 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x1614f18fc94f47967a3fbe5ffcd46d4e7da3d787 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xf1df7305e4bab3885cab5b1e4dfc338452a67891 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x91fbb2503ac69702061f1ac6885759fc853e6eae - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xa9e8acf069c58aec8825542845fd754e41a9489a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x2c95d751da37a5c1d9c5a7fd465c1d50f3d96160 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xe453c3409f8ad2b1fe1ed08e189634d359705a5b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x89d584a1edb3a70b3b07963f9a3ea5399e38b136 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x4507cef57c46789ef8d1a19ea45f4216bae2b528 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xd1d2eb1b1e90b638588728b4130137d262c87cae - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xe92344b4edf545f3209094b192e46600a19e7c2d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x8a0a9b663693a22235b896f70a229c4a22597623 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x1bbe973bef3a977fc51cbed703e8ffdefe001fed - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xa41d2f8ee4f47d3b860a149765a7df8c3287b7f0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x761d38e5ddf6ccf6cf7c55759d5210750b5d60f3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xc18360217d8f7ab5e7c516566761ea12ce7f9d72 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xe28b3b32b6c345a34ff64674606124dd5aceca30 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x168e209d7b2f58f1f24b8ae7b7d35e662bbf11cc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xb131f4a55907b10d1f0a50d8ab8fa09ec342cd74 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x3472a5a71965499acd81997a54bba8d852c6e53d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x7dd9c5cba05e151c895fde1cf355c9a1d5da6429 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x19efa7d0fc88ffe461d1091f8cbe56dc2708a84f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x14fee680690900ba0cccfc76ad70fd1b95d10e16 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x3c3a81e81dc49a522a592e7622a7e711c06bf354 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xa1290d69c65a6fe4df752f95823fae25cb99e5a7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x92f419fb7a750aed295b0ddf536276bf5a40124f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x2c06ba9e7f0daccbc1f6a33ea67e85bb68fbee3a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x3d658390460295fb963f54dc0899cfb1c30776df - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x8e870d67f660d95d5be530380d0ec0bd388289e1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x853d955acef822db058eb8505911ed77f175b99e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x1294f4183763743c7c9519bec51773fb3acd78fd - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x4e15361fd6b4bb609fa63c81a2be19d873717870 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x695d38eb4e57e0f137e36df7c1f0f2635981246b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x40a7df3df8b56147b781353d379cb960120211d7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xaaef88cea01475125522e117bfe45cf32044e238 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x163f8c2467924be0ae7b5347228cabf260318753 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x30672ae2680c319ec1028b69670a4a786baa0f35 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xc944e90c64b2c07662a292be6244bdf05cda44a7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x15e6e0d4ebeac120f9a97e71faa6a0235b85ed12 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x7d225c4cc612e61d26523b099b0718d03152edef - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x82af49447d8a07e3bd95bd0d56f35241523fbab1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xaf88d065e77c8cc2239327c5edb3a432268e5831 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xff970a61a04b1ca14834a43f5de4533ebddb5cc8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x912ce59144191c1204e64559fe8253a0e49e6548 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x5979d7b546e38e414f7e9822514be443a4800529 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x35751007a407ca6feffe80b3cb397736d2cf4dbe - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xda10009cbd5d07dd0cecc66161fc93d7c9000da1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xeb466342c4d449bc9f53a865d5cb90586f405215 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xfc5a1a6eb076a2c7ad06ed22c90d7e710e35ad0a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x0c880f6761f1af8d9aa9c466984b80dab9a8c9e8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xf97f4df75117a78c1a5a0dbb814af92458539fb4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x9623063377ad1b27544c965ccd7342f7ea7e88c7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x539bde0d7dbd336b79148aa742883198bbf60342 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x3082cc23568ea640225c2467653db90e9250aaa0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x18c11fd286c5ec11c3b683caa813b77f5163a122 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x289ba1701c2f088cf0faf8b3705246331cb8a839 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x4cb9a7ae498cedcbb5eae9f25736ae7d428c9d66 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x00cbcf7b3d37844e44b888bc747bdd75fcf4e555 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xfa7f8980b0f1e64a2062791cc3b0871572f1f7f0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xd79bb960dc8a206806c3a428b31bca49934d18d7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x3096e7bfd0878cc65be71f8899bc4cfb57187ba3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x13ad51ed4f1b7e9dc168d8a00cb3f4ddd85efa60 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x4e352cf164e64adcbad318c3a1e222e9eba4ce42 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x11cdb42b0eb46d95f990bedd4695a6e3fa034978 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xba5ddd1f9d7f570dc94a51479a000e3bce967196 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xc8ccbd97b96834b976c995a67bf46e5754e2c48e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xd07d35368e04a839dee335e213302b21ef14bb4a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x323665443cef804a3b5206103304bd4872ea4253 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x83d6c8c06ac276465e4c92e7ac8c23740f435140 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x87aaffdf26c6885f6010219208d5b161ec7609c0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x1b8d516e2146d7a32aca0fcbf9482db85fd42c3a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xafccb724e3aec1657fc9514e3e53a0e71e80622d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x4425742f1ec8d98779690b5a3a6276db85ddc01a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xec70dcb4a1efa46b8f2d97c310c9c4790ba5ffa8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x3419875b4d3bca7f3fdda2db7a476a79fd31b4fe - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x3b60ff35d3f7f62d636b067dd0dc0dfdad670e4e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x58b9cb810a68a7f3e1e4f8cb45d1b9b3c79705e8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xfa5ed56a203466cbbc2430a43c66b9d8723528e7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x95146881b86b3ee99e63705ec87afe29fcc044d9 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x088cd8f5ef3652623c22d48b1605dcfe860cd704 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xbfd5206962267c7b4b4a8b3d76ac2e1b2a5c4d5e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x6daf586b7370b14163171544fca24abcc0862ac5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x9d2f299715d94d8a7e6f5eaa8e654e8c74a988a7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x580e933d90091b9ce380740e3a4a39c67eb85b4c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x655a6beebf2361a19549a99486ff65f709bd2646 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x9e64d3b9e8ec387a9a58ced80b71ed815f8d82b5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x2297aebd383787a160dd0d9f71508148769342e3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x6694340fc020c5e6b96567843da2df01b2ce1eb6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x772598e9e62155d7fdfe65fdf01eb5a53a8465be - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x431402e8b9de9aa016c743880e04e517074d8cec - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xd74f5255d557944cf7dd0e45ff521520002d5748 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x6fd58f5a2f3468e35feb098b5f59f04157002407 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x561877b6b3dd7651313794e5f2894b2f18be0766 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xf9ca0ec182a94f6231df9b14bd147ef7fb9fa17c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xd77b108d4f6cefaa0cae9506a934e825becca46e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xd56734d7f9979dd94fae3d67c7e928234e71cd4c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xf1264873436a0771e440e2b28072fafcc5eebd01 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x5575552988a3a80504bbaeb1311674fcfd40ad4b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x0341c0c0ec423328621788d4854119b97f44e391 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x764bfc309090e7f93edce53e5befa374cdcb7b8e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xaaa6c1e32c55a7bfa8066a6fae9b42650f262418 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x9e20461bc2c4c980f62f1b279d71734207a6a356 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x7fb7ede54259cb3d4e1eaf230c7e2b1ffc951e9a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x3a18dcc9745edcd1ef33ecb93b0b6eba5671e7ca - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x000000000026839b3f4181f2cf69336af6153b99 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x8b0e6f19ee57089f7649a455d89d7bc6314d04e8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x31c91d8fb96bff40955dd2dbc909b36e8b104dde - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x25d887ce7a35172c62febfd67a1856f20faebb00 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xd4d42f0b6def4ce0383636770ef773390d85c61a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xf8388c2b6edf00e2e27eef5200b1befb24ce141d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x619c82392cb6e41778b7d088860fea8447941f4c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x94025780a1ab58868d9b2dbbb775f44b32e8e6e5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xad4b9c1fbf4923061814dd9d5732eb703faa53d4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xd7a892f28dedc74e6b7b33f93be08abfc394a360 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x3269a3c00ab86c753856fd135d97b87facb0d848 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x4568ca00299819998501914690d6010ae48a59ba - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x21e60ee73f17ac0a411ae5d690f908c3ed66fe12 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xd3188e0df68559c0b63361f6160c57ad88b239d8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x2b41806cbf1ffb3d9e31a9ece6b738bf9d6f645f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xf19547f9ed24aa66b03c3a552d181ae334fbb8db - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x35e6a59f786d9266c7961ea28c7b768b33959cbb - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x59a729658e9245b0cf1f8cb9fb37945d2b06ea27 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xb56c29413af8778977093b9b4947efeea7136c36 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x43ab8f7d2a8dd4102ccea6b438f6d747b1b9f034 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x1d987200df3b744cfa9c14f713f5334cb4bc4d5d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x3404149e9ee6f17fb41db1ce593ee48fbdcd9506 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x080f6aed32fc474dd5717105dba5ea57268f46eb - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xb5a628803ee72d82098d4bcaf29a42e63531b441 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x1622bf67e6e5747b81866fe0b85178a93c7f86e3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x7dd747d63b094971e6638313a6a2685e80c7fb2e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xa2f9ecf83a48b86265ff5fd36cdbaaa1f349916c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x17a8541b82bf67e10b0874284b4ae66858cb1fd5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xbcd4d5ac29e06e4973a1ddcd782cd035d04bc0b7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x42069d11a2cc72388a2e06210921e839cfbd3280 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xbbea044f9e7c0520195e49ad1e561572e7e1b948 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xe85b662fe97e8562f4099d8a1d5a92d4b453bf30 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x3d9907f9a368ad0a51be60f7da3b97cf940982d8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x4e51ac49bc5e2d87e0ef713e9e5ab2d71ef4f336 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x4200000000000000000000000000000000000006 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x7f5c764cbc14f9669b88837ca1490cca17c31607 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x4200000000000000000000000000000000000042 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x0b2c639c533813f4aa9d7837caf62653d097ff85 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x1f32b1c2345538c0c6f582fcb022739c4a194ebb - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x68f180fcce6836688e9084f035309e29bf0a2095 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x94b008aa00579c1307b0ef2c499ad98a8ce58e58 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0xda10009cbd5d07dd0cecc66161fc93d7c9000da1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0xdc6ff44d5d932cbd77b52e5612ba0529dc6226f1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x8c6f28f2f1a3c87f0f938b96d27520d9751ec8d9 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x8700daec35af8ff88c16bdf0418774cb3d7599b4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x920cf626a271321c151d027030d5d08af699456b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x6c84a8f1c29108f47a79964b5fe888d4f4d0de40 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x9e1028f5f1d5ede59748ffcee5532509976840e0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0xeb466342c4d449bc9f53a865d5cb90586f405215 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x350a791bfc2c21f9ed5d10980dad2e2638ffa7f6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x17aabf6838a6303fc6e9c5a227dc1eb6d95c829a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0xf467c7d5a4a9c4687ffc7986ac6ad5a4c81e1404 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x76fb31fb4af56892a25e32cfc43de717950c9278 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0xc5b001dc33727f8f26880b184090d3e252470d45 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x9560e827af36c94d2ac33a39bce1fe78631088db - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x9bcef72be871e61ed4fbbc7630889bee758eb81d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x50c5725949a6f0c72e6c4a641f24049a917db0cb - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0xf98dcd95217e15e05d8638da4c91125e59590b07 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x4b03afc91295ed778320c2824bad5eb5a1d852dd - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0xc40f949f8a4e094d1b49a23ea9241d289b7b2819 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x323665443cef804a3b5206103304bd4872ea4253 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x50bce64397c75488465253c0a034b8097fea6578 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x296f55f8fb28e498b858d0bcda06d955b2cb3f97 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x2598c30330d5771ae9f983979209486ae26de875 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x0994206dfe8de6ec6920ff4d779b0d950605fb53 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0xc3248a1bd9d72fa3da6e6ba701e58cbf818354eb - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x6fd9d7ad17242c41f7131d257212c54a0e816691 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x14778860e937f509e651192a90589de711fb88a9 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0xdfa46478f9e5ea86d57387849598dbfb2e964b02 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x9b88d293b7a791e40d36a39765ffd5a1b9b5c349 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x3eb398fec5f7327c6b15099a9681d9568ded2e82 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x217d47011b23bb961eb6d93ca9945b7501a5bb11 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0xbfd5206962267c7b4b4a8b3d76ac2e1b2a5c4d5e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x1cef2d62af4cd26673c7416957cc4ec619a696a7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x9fd22a17b4a96da3f83797d122172c450381fb88 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0xaddb6a0412de1ba0f936dcaeb8aaa24578dcf3b2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x2791bca1f2de4661ed88a30c99a7a9449aa84174 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x7ceb23fd6bc0add59e62ac25578270cff1b9f619 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x3c499c542cef5e3811e1192ce70d8cc03d5c3359 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x1bfd67037b42cf73acf2047067bd4f2c47d9bfd6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xc2132d05d31c914a87c6611c10748aeb04b58e8f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x53e0bca35ec356bd5dddfebbd1fc0fd03fabad39 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x61299774020da444af134c82fa83e3810b309991 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xd6df932a45c0f255f85145f286ea0b292b21c90b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x2ad2934d5bfb7912304754479dd1f096d5c807da - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xc3c7d422809852031b44ab29eec9f1eff2a58756 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x8f3cf7ad23cd3cadbd9735aff958023239c6a063 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x750e4c4984a9e0f12978ea6742bc1c5d248f40ed - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x111111517e4929d3dcbdfa7cce55d30d4b6bc4d6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xd0258a3fd00f38aa8090dfee343f10a9d4d30d3f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x430ef9263e76dae63c84292c3409d61c598e9682 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xb33eaad8d922b1083446dc23f610c2567fb5180f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xdc3326e71d45186f113a2f448984ca0e8d201995 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x311434160d7537be358930def317afb606c0d737 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x0b3f868e0be5597d5db7feb59e1cadbb0fdda50a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xe3f2b1b2229c0333ad17d03f179b87500e7c5e01 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xac0f66379a6d7801d7726d5a943356a172549adb - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xf88332547c680f755481bf489d890426248bb275 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xe5417af564e4bfda1c483642db72007871397896 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xe261d618a959afffd53168cd07d12e37b26761db - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xe0b52e49357fd4daf2c15e02058dce6bc0057db4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xbbba073c31bf03b8acf7c28ef0738decf3695683 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xe238ecb42c424e877652ad82d8a939183a04c35f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x3b56a704c01d650147ade2b8cee594066b3f9421 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x5fe2b58c013d7601147dcdd68c143a77499f5531 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x172370d5cd63279efa6d502dab29171933a610af - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x53df32548214f51821cf1fe4368109ac5ddea1ff - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xff76c0b48363a7c7307868a81548d340049b0023 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x6f8a06447ff6fcf75d803135a7de15ce88c1d4ec - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x50b728d8d964fd00c2d0aad81718b71311fef68a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x3a58a54c066fdc0f2d55fc9c89f0415c92ebf3c4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x03b54a6e9a984069379fae1a4fc4dbae93b3bccd - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xd93f7e271cb87c23aaa73edc008a79646d1f9912 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x200c234721b5e549c3693ccc93cf191f90dc2af9 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x11cd37bb86f65419713f30673a480ea33c826872 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x8a16d4bf8a0a716017e8d2262c4ac32927797a2f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x9a71012b13ca4d3d0cdc72a177df3ef03b0e76a3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xa1c57f48f0deb89f569dfbe6e2b7f46d33606fd4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x190eb8a183d22a4bdf278c6791b152228857c033 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x2f6f07cdcf3588944bf4c42ac74ff24bf56e7590 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x235737dbb56e8517391473f7c964db31fa6ef280 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x0b220b82f3ea3b7f6d9a1d8ab58930c064a2b5bf - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x8bff1bd27e2789fe390acabc379c380a83b68e84 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xb58458c52b6511dc723d7d6f3be8c36d7383b4a8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x323665443cef804a3b5206103304bd4872ea4253 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x2760e46d9bb43dafcbecaad1f64b93207f9f0ed7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x18ec0a6e18e5bc3784fdd3a3634b31245ab704f6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x431d5dff03120afa4bdf332c61a6e1766ef37bdb - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x6f7c932e7684666c9fd1d44527765433e01ff61d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xeee3371b89fc43ea970e908536fcddd975135d8a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xe5b49820e5a1063f6f4ddf851327b5e8b2301048 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xaa3717090cddc9b227e49d0d84a28ac0a996e6ff - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x62a872d9977db171d9e213a5dc2b782e72ca0033 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x381caf412b45dac0f62fbeec89de306d3eabe384 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xe0bceef36f3a6efdd5eebfacd591423f8549b9d5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x23d29d30e35c5e8d321e1dc9a8a61bfd846d4c5c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x282d8efce846a88b159800bd4130ad77443fa1a1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x74dd45dd579cad749f9381d6227e7e02277c944b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x714db550b574b3e927af3d93e26127d15721d4c2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xfa68fb4628dff1028cfec22b4162fccd0d45efb6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xe631dabef60c37a37d70d3b4f812871df663226f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xdb725f82818de83e99f1dac22a9b5b51d3d04dd4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x3c59798620e5fec0ae6df1a19c6454094572ab92 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x0d0b8488222f7f83b23e365320a4021b12ead608 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xa380c0b01ad15c8cf6b46890bddab5f0868e87f3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x8a953cfe442c5e8855cc6c61b1293fa648bae472 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x45c32fa6df82ead1e2ef74d17b76547eddfaff89 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x11cd72f7a4b699c67f225ca8abb20bc9f8db90c7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x0c9c7712c83b3c70e7c5e11100d33d9401bdf9dd - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x77a6f2e9a9e44fd5d5c3f9be9e52831fc1c3c0a0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xbfc70507384047aa74c29cdc8c5cb88d0f7213ac - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xfcb54da3f4193435184f3f647467e12b50754575 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x9a6a40cdf21a0af417f1b815223fd92c85636c58 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xe111178a87a3bff0c8d18decba5798827539ae99 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x82617aa52dddf5ed9bb7b370ed777b3182a30fd1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x2ab0e9e4ee70fff1fb9d67031e44f6410170d00e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xa486c6bc102f409180ccb8a94ba045d39f8fc7cb - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xc4a206a306f0db88f98a3591419bc14832536862 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xf0059cc2b3e980065a906940fbce5f9db7ae40a7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x16eccfdbb4ee1a85a33f3a9b21175cd7ae753db4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x553d3d295e0f695b9228246232edf400ed3560b5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x14af1f2f02dccb1e43402339099a05a5e363b83c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x7bdf330f423ea880ff95fc41a280fd5ecfd3d09f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x8505b9d2254a7ae468c0e9dd10ccea3a837aef5c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xe2aa7db6da1dae97c5f5c6914d285fbfcc32a128 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xb7b31a6bc18e48888545ce79e83e06003be70930 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x1631244689ec1fecbdd22fb5916e920dfc9b8d30 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xf6372cdb9c1d3674e83842e3800f2a62ac9f3c66 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x692ac1e363ae34b6b489148152b12e2785a3d8d6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x0266f4f08d82372cf0fcbccc0ff74309089c74d1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x7fbc10850cae055b27039af31bd258430e714c62 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xa3fa99a148fa48d14ed51d610c367c61876997f1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x9dbfc1cbf7a1e711503a29b4b5f9130ebeccac96 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x236aa50979d5f3de3bd1eeb40e81137f22ab794b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xf86df9b91f002cfeb2aed0e6d05c4c4eaef7cf02 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x4200000000000000000000000000000000000006 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xd9aaec86b65d86f6a7b5b1b0c42ffa531710b6ca - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x6921b130d297cc43754afba22e5eac0fbf8db75b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x5babfc2f240bc5de90eb7e19d789412db1dec402 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x532f27101965dd16442e59d40670faf5ebb142e4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x833589fcd6edb6e08f4c7c32d4f71b54bda02913 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x4ed4e862860bed51a9570b96d89af5e1b0efefed - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xc1cba3fcea344f92d9239c08c0568f6f2f0ee452 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xac1bd2486aaf3b5c0fc3fd868558b082a531b2b4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x0d97f261b1e88845184f678e2d1e7a98d9fd38de - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x8129b94753f22ec4e62e2c4d099ffe6773969ebc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x3f14920c99beb920afa163031c4e47a3e03b3e4a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x940181a94a35a4569e4529a3cdfb74e38fd98631 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x3419875b4d3bca7f3fdda2db7a476a79fd31b4fe - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xa067436db77ab18b1a315095e4b816791609897c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xafb89a09d82fbde58f18ac6437b3fc81724e4df6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x489fe42c267fe0366b16b0c39e7aeef977e841ef - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x2ae3f1ec7f1f5012cfeab0185bfc7aa3cf0dec22 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xdc46c1e93b71ff9209a0f8076a9951569dc35855 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x91f45aa2bde7393e0af1cc674ffe75d746b93567 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x236aa50979d5f3de3bd1eeb40e81137f22ab794b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xf6e932ca12afa26665dc4dde7e27be02a7c02e50 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x524d524b4c9366be706d3a90dcf70076ca037ae3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x5b5dee44552546ecea05edea01dcd7be7aa6144a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x2598c30330d5771ae9f983979209486ae26de875 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xfa980ced6895ac314e7de34ef1bfae90a5add21b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x469fda1fb46fcb4befc0d8b994b516bd28c87003 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x4e496c0256fb9d4cc7ba2fdf931bc9cbb7731660 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x27d2decb4bfc9c76f0309b8e88dec3a601fe25a8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xbfd5206962267c7b4b4a8b3d76ac2e1b2a5c4d5e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x9e1028f5f1d5ede59748ffcee5532509976840e0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x3c3aa127e6ee3d2f2e432d0184dd36f2d2076b52 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xba5e6fa2f33f3955f0cef50c63dcc84861eab663 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x97c806e7665d3afd84a8fe1837921403d59f3dcc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x8ee73c484a26e0a5df2ee2a4960b789967dd0415 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x00e57ec29ef2ba7df07ad10573011647b2366f6d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x8f019931375454fe4ee353427eb94e2e0c9e0a8c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x93e6407554b2f02640ab806cd57bd83e848ec65d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x55d398326f99059ff775485246999027b3197955 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x2170ed0880ac9a755fd29b2688956bd959f933f8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xfdc66a08b0d0dc44c17bbd471b88f49f50cdd20f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x7130d2a12b9bcbfae4f2634d864a1ee1ce3ead9c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x1d2f0da169ceb9fc7b3144628db156f3f6c60dbe - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xe9e7cea3dedca5984780bafc599bd69add087d56 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xfa54ff1a158b5189ebba6ae130ced6bbd3aea76e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x570a5d26f7765ecb712c0924e4de545b89fd43df - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x47c454ca6be2f6def6f32b638c80f91c9c3c5949 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xad86d0e9764ba90ddd68747d64bffbd79879a238 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xf8a0bf9cf54bb92f17374d9e9a321e6a111a51bd - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xd691d9a68c887bdf34da8c36f63487333acfd103 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x1af3f329e8be154074d8769d1ffa4ee058b1dbc3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x1294f4183763743c7c9519bec51773fb3acd78fd - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xb04906e95ab5d797ada81508115611fee694c2b3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x111111111117dc0aa78b770fa6a738034120c302 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xcc42724c6683b7e57334c4e856f4c9965ed682bd - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x90c97f71e18723b0cf0dfa30ee176ab653e89f40 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x2b72867c32cf673f7b02d208b26889fed353b1f8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x031b41e504677879370e9dbcf937283a8691fa7f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x1ce0c2827e2ef14d5c4f29a091d735a204794041 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xcf3bb6ac0f6d987a5727e2d15e39c2d6061d5bec - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x8ff795a6f4d97e7887c79bea79aba5cc76444adf - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x2dff88a56767223a5529ea5960da7a3f5f766406 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x003d87d02a2a01e9e8a20f507c83e15dd83a33d1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x4b0f1812e5df2a09796481ff14017e6005508003 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xbf5140a22578168fd562dccf235e5d43a02ce9b1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xca1c644704febf4ab81f85daca488d1623c28e63 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x51e72dd1f2628295cc2ef931cb64fdbdc3a0c599 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xbbca42c60b5290f2c48871a596492f93ff0ddc82 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x555296de6a86e72752e5c5dc091fe49713aa145c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x0808bf94d57c905f1236212654268ef82e1e594e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x8457ca5040ad67fdebbcc8edce889a335bc0fbfb - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xcebef3df1f3c5bfd90fde603e71f31a53b11944d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x90ed8f1dc86388f14b64ba8fb4bbd23099f18240 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x9840652dc04fb9db2c43853633f0f62be6f00f98 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xba2ae424d960c26247dd6c32edc70b295c744c43 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x0782b6d8c4551b9760e74c0545a9bcd90bdc41e5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xbe2b6c5e31f292009f495ddbda88e28391c9815e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x8f0528ce5ef7b51152a59745befdd91d97091d2f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xffeecbf8d7267757c2dc3d13d730e97e15bfdf7f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x0eb3a705fc54725037cc9e008bdede697f62f335 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xf21768ccbc73ea5b6fd3c687208a7c2def2d966e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x0000028a2eb8346cd5c0267856ab7594b7a55308 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x76a797a59ba2c17726896976b7b3747bfd1d220f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xc79d1fd14f514cd713b5ca43d288a782ae53eab2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xad29abb318791d579433d831ed122afeaf29dcfe - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x3203c9e46ca618c8c1ce5dc67e7e9d75f5da2377 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xdb021b1b247fe2f1fa57e0a87c748cc1e321f07f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x7083609fce4d1d8dc0c979aab8c869ea2c873402 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xc5f0f7b66764f6ec8c8dff7ba683102295e16409 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xe29142e14e52bdfbb8108076f66f49661f10ec10 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xb0d502e938ed5f4df2e681fe6e419ff29631d62b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x6730f7a6bbb7b9c8e60843948f7feb4b6a17b7f7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x1613957159e9b0ac6c80e824f7eea748a32a0ae2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/celo/0x471ece3750da237f93b8e339c536989b8978a438 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/celo/0x765de816845861e75a25fca122bb6898b8b1282a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/celo/0x66803fb87abd4aac3cbb3fad7c3aa01f6f3fb207 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/celo/0xd8763cba276a3738e6de85b4b3bf5fded6d6ca73 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/celo/0x37f750b7cc259a2f741af45294f6a16572cf5cad - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/celo/0xd71ffd0940c920786ec4dbb5a12306669b5b81ef - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/celo/0xe8537a3d056da446677b9e9d6c5db704eaab4787 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/celo/0x4f604735c1cf31399c6e711d5962b2b3e0225ad3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/celo/0x02de4766c272abc10bc88c220d214a26960a7e92 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/celo/0xceba9300f2b948710d2653dd7b07f33a8b32118c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/celo/0xc16b81af351ba9e64c1a069e3ab18c244a1e3049 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x728f30fa2f100742c7949d1961804fa8e0b1387d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x41ea5d41eeacc2d5c4072260945118a13bb7ebce - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xf21661d0d1d76d3ecb8e1b9f1c923dbfffae4097 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xb0ecc6ac0073c063dcfc026ccdc9039cae2998e1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x00f932f0fe257456b32deda4758922e56a4f4b42 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xa4af354d466e8a68090dd9eb2cb7caf162f4c8c2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xba50933c268f567bdc86e1ac131be072c6b0b71a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xd29da236dd4aac627346e1bba06a619e8c22d7c5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x1bfce574deff725a3f483c334b790e25c8fa9779 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x9e18d5bab2fa94a6a95f509ecb38f8f68322abd3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xcd5fe23c85820f7b72d0926fc9b05b43e359b7ee - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xbf5495efe5db9ce00f80364c8b423567e58d2110 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x065b4e5dfd50ac12a81722fd0a0de81d78ddf7fb - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x57e114b691db790c35207b2e685d4a43181e6061 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x0b7f0e51cd1739d6c96982d55ad8fa634dd43a9c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xc56c7a0eaa804f854b536a5f3d5f49d2ec4b12b8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x594daad7d77592a2b97b725a7ad59d7e188b5bfa - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x8355dbe8b0e275abad27eb843f3eaf3fc855e525 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x2a961d752eaa791cbff05991e4613290aec0d9ac - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x38e68a37e401f7271568cecaac63c6b1e19130b4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x1131d427ecd794714ed00733ac0f851e904c8398 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x1495bc9e44af1f8bcb62278d2bec4540cf0c05ea - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x808507121b80c02388fad14726482e061b8da827 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x44971abf0251958492fee97da3e5c5ada88b9185 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x320623b8e4ff03373931769a31fc52a4e78b5d70 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x6e5970dbd6fc7eb1f29c6d2edf2bc4c36124c0c1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xd40c688da9df74e03566eaf0a7c754ed98fbb8cc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x8afe4055ebc86bd2afb3940c0095c9aca511d852 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x9ce84f6a69986a83d92c324df10bc8e64771030f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xbe4d9c8c638b5f0864017d7f6a04b66c42953847 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x68bbed6a47194eff1cf514b50ea91895597fc91e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x69420e3a3aa9e17dea102bb3a9b3b73dcddb9528 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x7420b4b9a0110cdc71fb720908340c03f9bc03ec - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x03aa6298f1370642642415edc0db8b957783e8d6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xd533a949740bb3306d119cc777fa900ba034cd52 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xf14dd7b286ce197019cba54b189d2b883e70f761 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xa35923162c49cf95e6bf26623385eb431ad920d3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x8cefbeb2172a9382753de431a493e21ba9694004 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x120a3879da835a5af037bb2d1456bebd6b54d4ba - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x69457a1c9ec492419344da01daf0df0e0369d5d0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xf6ce4be313ead51511215f1874c898239a331e37 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x73d7c860998ca3c01ce8c808f5577d94d545d1b4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xeff49b0f56a97c7fd3b51f0ecd2ce999a7861420 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x236501327e701692a281934230af0b6be8df3353 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x5026f006b85729a8b14553fae6af249ad16c9aab - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x66761fa41377003622aee3c7675fc7b5c1c2fac5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x9f9c8ec3534c3ce16f928381372bfbfbfb9f4d24 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xd8c978de79e12728e38aa952a6cb4166f891790f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x7122985656e38bdc0302db86685bb972b145bd3c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x582d872a1b094fc48f5de31d3b73f2d9be47def1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x504624040e0642921c2c266a9ac37cafbd8cda4e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xc548e90589b166e1364de744e6d35d8748996fe8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x4c11249814f11b9346808179cf06e71ac328c1b5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x423f4e6138e475d85cf7ea071ac92097ed631eea - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x8390a1da07e376ef7add4be859ba74fb83aa02d5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xf94e7d0710709388bce3161c32b4eea56d3f91cc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xaa95f26e30001251fb905d264aa7b00ee9df6c18 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x2416092f143378750bb29b79ed961ab195cceea5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x6c84a8f1c29108f47a79964b5fe888d4f4d0de40 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x71eeba415a523f5c952cc2f06361d5443545ad28 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x88a269df8fe7f53e590c561954c52fccc8ec0cfb - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x429fed88f10285e61b12bdf00848315fbdfcc341 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xb299751b088336e165da313c33e3195b8c6663a6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xf0a479c9c3378638ec603b8b6b0d75903902550b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xb59c8912c83157a955f9d715e556257f432c35d7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xba0dda8762c24da9487f5fa026a9b64b695a07ea - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xc24a365a870821eb83fd216c9596edd89479d8d7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xa586b3b80d7e3e8d439e25fbc16bc5bcee3e2c85 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xef04804e1e474d3f9b73184d7ef5d786f3fce930 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x2e9a6df78e42a30712c10a9dc4b1c8656f8f2879 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x13a7dedb7169a17be92b0e3c7c2315b46f4772b3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x1dd6b5f9281c6b4f043c02a83a46c2772024636c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xc5102fe9359fd9a28f877a67e36b0f050d81a3cc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xf525e73bdeb4ac1b0e741af3ed8a8cbb43ab0756 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xe4177c1400a8eee1799835dcde2489c6f0d5d616 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xed5740209fcf6974d6f3a5f11e295b5e468ac27c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xe10d4a4255d2d35c9e23e2c4790e073046fbaf5c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x10398abc267496e49106b07dd6be13364d10dc71 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x2218a117083f5b482b0bb821d27056ba9c04b1d3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x395ae52bb17aef68c2888d941736a71dc6d4e125 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x9a601c5bb360811d96a23689066af316a30c3027 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xbac3368b5110f3a3dda8b5a0f7b66edb37c47afe - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x1d3c629ca5c1d0ab3bdf74600e81b4145615df8e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xe9c21de62c5c5d0ceacce2762bf655afdceb7ab3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x658cda444ac43b0a7da13d638700931319b64014 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x3d2bd0e15829aa5c362a4144fdf4a1112fa29b5c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x3fb83a9a2c4408909c058b0bfe5b4823f54fafe2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x00e5646f60ac6fb446f621d146b6e1886f002905 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x12a4cebf81f8671faf1ab0acea4e3429e42869e7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x9ff62d1fc52a907b6dcba8077c2ddca6e6a9d3e1 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xc61f39418cd27820b5d4e9ba4a7197eefaeb8b05 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x15b7c0c907e4c6b9adaaaabc300c08991d6cea05 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x7f67639ffc8c93dd558d452b8920b28815638c44 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x276c9cbaa4bdf57d7109a41e67bd09699536fa3d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x041fdf3f472d2c8a7ecc458fc3b7f543e6c57ef7 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x3c281a39944a2319aa653d81cfd93ca10983d234 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x96419929d7949d6a801a6909c145c8eef6a40431 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xfea9dcdc9e23a9068bf557ad5b186675c61d33ea - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xdb6e0e5094a25a052ab6845a9f1e486b9a9b3dde - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xcde172dc5ffc46d228838446c57c1227e0b82049 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xff0c532fdb8cd566ae169c1cb157ff2bdc83e105 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x9a26f5433671751c3276a065f57e5a02d2817973 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x3636a7734b669ce352e97780df361ce1f809c58c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x50c5725949a6f0c72e6c4a641f24049a917db0cb - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xe3086852a4b125803c815a158249ae468a3254ca - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xbeb0fd48c2ba0f1aacad2814605f09e08a96b94e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xbc45647ea894030a4e9801ec03479739fa2485f0 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x768be13e1680b5ebe0024c42c896e3db59ec0149 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x928a6a9fc62b2c94baf2992a6fba4715f5bb0066 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xbf4db8b7a679f89ef38125d5f84dd1446af2ea3b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xed899bfdb28c8ad65307fa40f4acab113ae2e14c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x1b6a569dd61edce3c383f6d565e2f79ec3a12980 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x76734b57dfe834f102fb61e1ebf844adf8dd931e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x4621b7a9c75199271f773ebd9a499dbd165c3191 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xaf07d812d1dcec20bf741075bc18660738d226dd - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x7f12d13b34f5f4f0a9449c16bcd42f0da47af200 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x55a6f6cb50db03259f6ab17979a4891313be2f45 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x968d6a288d7b024d5012c0b25d67a889e4e3ec19 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x7a8a5012022bccbf3ea4b03cd2bb5583d915fb1a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xcde90558fc317c69580deeaf3efc509428df9080 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x0028e1e60167b48a938b785aa5292917e7eaca8b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x76e7447bafa3f0acafc9692629b1d1bc937ca15d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x15ac90165f8b45a80534228bdcb124a011f62fee - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x4045b33f339a3027af80013fb5451fdbb01a4492 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xddf98aad8180c3e368467782cd07ae2e3e8d36a5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x698dc45e4f10966f6d1d98e3bfd7071d8144c233 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x3c8665472ec5af30981b06b4e0143663ebedcc1e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x18a8bd1fe17a1bb9ffb39ecd83e9489cfd17a022 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xba0dda8762c24da9487f5fa026a9b64b695a07ea - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x13741c5df9ab03e7aa9fb3bf1f714551dd5a5f8a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xebff2db643cf955247339c8c6bcd8406308ca437 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xfadb26be94c1f959f900bf88cd396b3e803481d6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x52c2b317eb0bb61e650683d2f287f56c413e4cf6 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x38d513ec43dda20f323f26c7bef74c5cf80b6477 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x33ad778e6c76237d843c52d7cafc972bb7cf8729 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x290814ad0fbd2b935f34d7b40306102313d4c63e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x5e432eecd01c12ee7071ee9219c2477a347da192 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xbdf5bafee1291eec45ae3aadac89be8152d4e673 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xff62ddfa80e513114c3a0bf4d6ffff1c1d17aadf - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x8c81b4c816d66d36c4bf348bdec01dbcbc70e987 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x6b82297c6f1f9c3b1f501450d2ee7c37667ab70d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x42069babe14fb1802c5cb0f50bb9d2ad6fef55e2 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x72499bddb67f4ca150e1f522ca82c87bc9fb18c8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x0578d8a44db98b23bf096a382e016e29a5ce0ffe - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x8fe815417913a93ea99049fc0718ee1647a2a07c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x7d12aeb5d96d221071d176980d23c213d88d9998 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xb166e8b140d35d9d8226e40c09f757bac5a4d87d - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x8853f0c059c27527d33d02378e5e4f6d5afb574a - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xf3c052f2baab885c610a748eb01dfbb643ba835b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xcd1cffa8ebc66f1a2cf7675b48ba955ffcb82d8e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xde7a416ac821c77478340eebaa21b68297025ef3 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x2da56acb9ea78330f947bd57c54119debda7af71 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x8972ab69d499b5537a31576725f0af8f67203d38 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x88faea256f789f8dd50de54f9c807eef24f71b16 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x42069de48741db40aef864f8764432bbccbd0b69 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x9a27c6759a6de0f26ac41264f0856617dec6bc3f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xfaa4f3bcfc87d791e9305951275e0f62a98bcb10 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xfd9fa4f785331ce88b5af8994a047ba087c705d8 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x21eceaf3bf88ef0797e3927d855ca5bb569a47fc - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x7d9ce55d54ff3feddb611fc63ff63ec01f26d15f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x4229c271c19ca5f319fb67b4bc8a40761a6d6299 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x80f45eacf6537498ecc660e4e4a2d2f99e195cf4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x1a475d06d967aeb686c98de80d079d72097aeacf - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x4fb9b20dafe45d91ae287f2e07b2e79709308178 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xd3741ac9b3f280b0819191e4b30be4ecd990771e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x09579452bc3872727a5d105f342645792bb8a82b - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x8a24d7260cd02d3dfd8eefb66bc17ad4b17d494c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xd88611a629265c9af294ffdd2e7fa4546612273e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x9a86980d3625b4a6e69d8a4606d51cbc019e2002 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x1c7a460413dd4e964f96d8dfc56e7223ce88cd85 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x776aaef8d8760129a0398cf8674ee28cefc0eab9 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x28e29ec91db66733a94ee8e3b86a6199117baf99 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xb9898511bd2bad8bfc23eba641ef97a08f27e730 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x76baa16ff15d61d32e6b3576c3a8c83a25c2f180 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x2816a491dd0b7a88d84cbded842a618e59016888 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0xa7ea9d5d4d4c7cf7dbde5871e6d108603c6942a5 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/base/0x586e10db93630a4d2da6c6a34ba715305b556f04 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xf486ad071f3bee968384d2e39e2d8af0fcf6fd46 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x76d36d44dc4595e8d2eb3ad745f175eda134284f - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x1fa4a73a3f0133f0025378af00236f3abdee5d63 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xb3ed0a426155b79b898849803e3b36552f7ed507 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x0ef4a107b48163ab4b57fca36e1352151a587be4 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x62694d43ccb9b64e76e38385d15e325c7712a735 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xa2b726b1145a4773f68593cf171187d8ebe4d495 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xf275e1ac303a4c9d987a2c48b8e555a77fec3f1c - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x11a31b833d43853f8869c9eec17f60e3b4d2a753 - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z 0.8 https://app.uniswap.org/explore/tokens/celo/0x48065fbbe25f71c9282ddf5e1cd6d6a887483d5e - 2024-05-20T17:20:52.753Z + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xbadff0ef41d2a68f22de21eabca8a59aaf495cf0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x1fdd61ef9a5c31b9a2abc7d39c139c779e8412af + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x4ade2b180f65ed752b6f1296d0418ad21eb578c0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x0c5cb676e38d6973837b9496f6524835208145a2 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xb69753c06bb5c366be51e73bfc0cc2e3dc07e371 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x8143182a775c54578c8b7b3ef77982498866945d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x76e222b07c53d28b89b0bac18602810fc22b49a8 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x18aaa7115705e8be94bffebde57af9bfc265b998 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x7d8146cf21e8d7cbe46054e01588207b51198729 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xfe0c30065b384f05761f15d0cc899d4f9f9cc0eb + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x1ce270557c1f68cfb577b856766310bf8b47fd9c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x793a5d8b30aab326f83d20a9370c827fea8fdc51 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xff836a5821e69066c87e268bc51b849fab94240c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xf4d2888d29d722226fafa5d9b24f9164c092421e + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x8ed97a637a790be1feff5e888d43629dc05408f6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x31c8eacbffdd875c74b94b077895bd78cf1e64a3 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xc55126051b22ebb829d00368f4b12bde432de5da + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xe0f63a424a4439cbe457d80e4f4b51ad25b2c56c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x8881562783028f5c1bcb985d2283d5e170d88888 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x67466be17df832165f8c80a5a120ccc652bd7e69 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xd939212f16560447ed82ce46ca40a63db62419b5 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x88417754ff7062c10f4e3a4ab7e9f9d9cbda6023 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x5afe3855358e112b5647b952709e6165e1c1eeee + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x02e7f808990638e9e67e1f00313037ede2362361 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xd2bdaaf2b9cc6981fd273dcb7c04023bfbe0a7fe + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x112b08621e27e10773ec95d250604a041f36c582 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x32b053f2cba79f80ada5078cb6b305da92bde6e1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x5ac34c53a04b9aaa0bf047e7291fb4e8a48f2a18 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x26ebb8213fb8d66156f1af8908d43f7e3e367c1d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xe3b9cfb8ea8a4f1279fbc28d3e15b4d2d86f18a0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x8207c1ffc5b6804f6024322ccf34f29c3541ae26 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x255f1b39172f65dc6406b8bee8b08155c45fe1b6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x092baadb7def4c3981454dd9c0a0d7ff07bcfc86 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x53bcf6698c911b2a7409a740eacddb901fc2a2c6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x2ac2b254bc18cd4999f64773a966e4f4869c34ee + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x17fc002b466eec40dae837fc4be5c67993ddbd6f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xc8a4eea31e9b6b61c406df013dd4fec76f21e279 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x498bf2b1e120fed3ad3d42ea2165e9b73f99c1e5 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xe4dddfe67e7164b0fe14e218d80dc4c08edc01cb + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x7c8a1a80fdd00c9cccd6ebd573e9ecb49bfa2a59 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x1debd73e752beaf79865fd6446b0c970eae7732f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xaf5db6e1cc585ca312e8c8f7c499033590cf5c98 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/optimism/0x65559aa14915a70190438ef90104769e5e890a00 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/optimism/0x7fb688ccf682d58f86d7e38e03f9d22e7705448b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/optimism/0x73cb180bf0521828d8849bc8cf2b920918e23032 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/optimism/0x2e3d870790dc77a83dd1d18184acc7439a53f475 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/optimism/0xa00e3a3511aac35ca78530c85007afcd31753819 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/optimism/0x528cdc92eab044e1e39fe43b9514bfdab4412b98 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/optimism/0x4f604735c1cf31399c6e711d5962b2b3e0225ad3 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x1c954e8fe737f99f68fa1ccda3e51ebdb291948c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xf50d05a1402d0adafa880d36050736f9f6ee7dee + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xab0b2ddb9c7e440fac8e140a89c0dbcbf2d7bbff + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x8bc3ec2e7973e64be582a90b08cadd13457160fe + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x64060ab139feaae7f06ca4e63189d86adeb51691 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x5ec03c1f7fa7ff05ec476d19e34a22eddb48acdc + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x9627a3d6872be48410fcece9b1ddd344bf08c53e + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x1ed02954d60ba14e26c230eec40cbac55fa3aeea + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x8d3419b9a18651f3926a205ee0b1acea1e7192de + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xb56d0839998fd79efcd15c27cf966250aa58d6d3 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x81f91fe59ee415735d59bd5be5cca91a0ea4fa69 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x87c211144b1d9bdaa5a791b8099ea4123dc31d21 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xf4210f93bc68d63df3286c73eba08c6414f40c0d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xece7b98bd817ee5b1f2f536daf34d0b6af8bb542 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x4c96a67b0577358894407af7bc3158fc1dffbeb5 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x70737489dfdf1a29b7584d40500d3561bd4fe196 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x39353a32eceafe4979a8606512c046c3b6398cc4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x92fb1b7d9730b2f1bd4e2e91368c1eb6fdd2a009 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x174e33ef2effa0a4893d97dda5db4044cc7993a3 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xfdc944fb59201fb163596ee5e209ebc8fa4dcdc5 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x388e543a5a491e7b42e3fbcd127dd6812ea02d0d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x56a38e7216304108e841579041249feb236c887b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x1804e3db872eed4141e482ff74c56862f2791103 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x9de16c805a3227b9b92e39a446f9d56cf59fe640 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xb8d98a102b0079b69ffbc760c8d857a31653e56e + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x5d6812722c3693078e4a0dbe3e9affc27a0b2768 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x255f1b39172f65dc6406b8bee8b08155c45fe1b6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xc2fe011c3885277c7f0e7ffd45ff90cadc8ecd12 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xc1ffaef4e7d553bbaf13926e258a1a555a363a07 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x4e73420dcc85702ea134d91a262c8ffc0a72aa70 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xecaf81eb42cd30014eb44130b89bcd6d4ad98b92 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x4eae52907dba9c370e9ee99f0ce810602a4f2c63 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x25d887ce7a35172c62febfd67a1856f20faebb00 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x382ea807a61a418479318efd96f1efbc5c1f2c21 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x6468e79a80c0eab0f9a2b574c8d5bc374af59414 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x3106a0a076bedae847652f42ef07fd58589e001f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xd015422879a1308ba557510345e944b912b9ab73 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x5de8ab7e27f6e7a1fff3e5b337584aa43961beef + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xcf078da6e85389de507ceede0e3d217e457b9d49 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x1bbf25e71ec48b84d773809b4ba55b6f4be946fb + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x7039cd6d7966672f194e8139074c3d5c4e6dcf65 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x943af17c37207c9d7a27d12cb5055542a0b7afa8 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x6d68015171eaa7af9a5a0a103664cf1e506ff699 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x6942806d1b2d5886d95ce2f04314ece8eb825833 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x949d48eca67b17269629c7194f4b727d4ef9e5d6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x9361adf2b72f413d96f81ff40d794b47ce13b331 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x3bb1be077f3f96722ae92ec985ab37fd0a0c4c51 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xdbb7a34bf10169d6d2d0d02a6cbb436cf4381bfa + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x66bff695f3b16a824869a8018a3a6e3685241269 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x85d19fb57ca7da715695fcf347ca2169144523a7 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x069d89974f4edabde69450f9cf5cf7d8cbd2568d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x0fe13ffe64b28a172c58505e24c0c111d149bd47 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x111111111117dc0aa78b770fa6a738034120c302 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xdc7ac5d5d4a9c3b5d8f3183058a92776dc12f4f3 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x482702745260ffd69fc19943f70cffe2cacd70e9 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xc555d625828c4527d477e595ff1dd5801b4a600e + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x9eec1a4814323a7396c938bc86aec46b97f1bd82 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x87d73e916d7057945c9bcd8cdd94e42a6f47f776 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x067def80d66fb69c276e53b641f37ff7525162f6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xdd157bd06c1840fa886da18a138c983a7d74c1d7 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xe80772eaf6e2e18b651f160bc9158b2a5cafca65 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xb6093b61544572ab42a0e43af08abafd41bf25a6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x35ca1e5a9b1c09fa542fa18d1ba4d61c8edff852 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x83e60b9f7f4db5cdb0877659b1740e73c662c55b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x4d01397994aa636bdcc65c9e8024bc497498c3bb + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xc3abc47863524ced8daf3ef98d74dd881e131c38 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x4d15a3a2286d883af0aa1b3f21367843fac63e07 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xfb7f8a2c0526d01bfb00192781b7a7761841b16c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x3809dcdd5dde24b37abe64a5a339784c3323c44f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x85955046df4668e1dd369d2de9f3aeb98dd2a369 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x554cd6bdd03214b10aafa3e0d4d42de0c5d2937b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x4318cb63a2b8edf2de971e2f17f77097e499459d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xab9cb20a28f97e189ca0b666b8087803ad636b3c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x6a8ec2d9bfbdd20a7f5a4e89d640f7e7ceba4499 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x385eeac5cb85a38a9a07a70c73e0a3271cfb54a7 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x0169ec1f8f639b32eec6d923e24c2a2ff45b9dd6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xe161be4a74ab8fa8706a2d03e67c02318d0a0ad6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x4d58608eff50b691a3b76189af2a7a123df1e9ba + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x420b0fa3de2efcf2b2fd04152eb1df36a09717cd + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x1cd38856ee0fdfd65c757e530e3b1de3061008d3 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xfad8cb754230dbfd249db0e8eccb5142dd675a0d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xda761a290e01c69325d12d82ac402e5a73d62e81 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xafb5d4d474693e68df500c9c682e6a2841f9661a + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x0b3e328455c4059eeb9e3f84b5543f74e24e7e1b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xfc5462143a3178cf044e97c491f6bcb5e38f173e + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xed1978d01d4a8a9d6a43ac79403d5b8dfbed739b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xba71cb8ef2d59de7399745793657838829e0b147 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x10c1b6f768e13c624a4a23337f1a5ba5c9be0e4b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x1b1514c76c54ce8807d7fdedf85c664eee734ece + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x58cd93c4a91c3940109fa27d700f5013b18b5dc2 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xea6f7e7e0f46a9e0f4e2048eb129d879f609d632 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x30d19fb77c3ee5cfa97f73d72c6a1e509fa06aef + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0xe2dca969624795985f2f083bcd0b674337ba130a + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0xbb7d61d2511fd2e63f02178ca9b663458af9fc63 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x59f4f336bf3d0c49dbfba4a74ebd2a6ace40539a + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x62d0a8458ed7719fdaf978fe5929c6d342b0bfce + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xb8fda5aee55120247f16225feff266dfdb381d4c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xca530408c3e552b020a2300debc7bd18820fb42f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x3ffeea07a27fab7ad1df5297fa75e77a43cb5790 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xcfeb09c3c5f0f78ad72166d55f9e6e9a60e96eec + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x467bccd9d29f223bce8043b84e8c8b282827790f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x2077d81d0c5258230d5a195233941547cb5f0989 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xa0bbbe391b0d0957f1d013381b643041d2ca4022 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xd1b89856d82f978d049116eba8b7f9df2f342ff3 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x62f03b52c377fea3eb71d451a95ad86c818755d1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x3927fb89f34bbee63351a6340558eebf51a19fb8 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xacd2c239012d17beb128b0944d49015104113650 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x86b69f38bea3e02f68ff88534bc61ec60e772b19 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x6873c95307e13beb58fb8fcddf9a99667655c9e4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x18084fba666a33d37592fa2633fd49a74dd93a88 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x6e79b51959cf968d87826592f46f819f92466615 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x80ee5c641a8ffc607545219a3856562f56427fe9 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x0414d8c87b271266a5864329fb4932bbe19c0c49 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xf57e7e7c23978c3caec3c3548e3d615c346e79ff + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xb0ffa8000886e57f86dd5264b9582b2ad87b2b91 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x1c986661170c1834db49c3830130d4038eeeb866 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x9ed7e4b1bff939ad473da5e7a218c771d1569456 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x7f9a7db853ca816b9a138aee3380ef34c437dee0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x371c7ec6d8039ff7933a2aa28eb827ffe1f52f07 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xb1bc21f748ae2be95674876710bc6d78235480e0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xadf5dd3e51bf28ab4f07e684ecf5d00691818790 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/optimism/0x1eba7a6a72c894026cd654ac5cdcf83a46445b08 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x38022a157b95c52d43abcac9bd09f028a1079105 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xd2507e7b5794179380673870d88b22f94da6abe0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xc708d6f2153933daa50b2d0758955be0a93a8fec + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x0052074d3eb1429f39e5ea529b54a650c21f5aa4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x4e78011ce80ee02d2c3e649fb657e45898257815 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x7583feddbcefa813dc18259940f76a02710a8905 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xe78aee6ccb05471a69677fb74da80f5d251c042b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x04f177fcacf6fb4d2f95d41d7d3fee8e565ca1d0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xa6da8c8999c094432c77e7d318951d34019af24b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x6d3b8c76c5396642960243febf736c6be8b60562 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x7cf7132ede0ca592a236b6198a681bb7b42dd5ae + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x3afeae00a594fbf2e4049f924e3c6ac93296b6e8 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x0a93a7be7e7e426fc046e204c44d6b03a302b631 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xc9b6ef062fab19d3f1eabc36b1f2e852af1acd18 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x1754e5aadce9567a95f545b146a616ce34eead53 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xdb173587d459ddb1b9b0f2d6d88febef039304a2 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x10a7a84c91988138f8dbbc82a23b02c8639e2552 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x92af6f53febd6b4c6f5293840b6076a1b82c4bc2 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xeb9e49fb4c33d9f6aefb1b03f9133435e24c0ec6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x1b2c141479757b8643a519be4692904088d860b2 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x4d25e94291fe8dcfbfa572cbb2aaa7b755087c91 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x8e0e798966382e53bfb145d474254cbe065c17dc + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x4b6f82a4ed0b9e3767f53309b87819a78d041a7f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x004aa1586011f3454f487eac8d0d5c647d646c69 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x741777f6b6d8145041f73a0bddd35ae81f55a40f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0xc6c58f600917de512cd02d2b6ed595ab54b4c30f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x03aa6298f1370642642415edc0db8b957783e8d6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x3ee2200efb3400fabb9aacf31297cbdd1d435d47 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x0d8ce2a99bb6e3b7db580ed848240e4a0f9ae153 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0xa697e272a73744b343528c3bc4702f2565b2f422 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x301af3eff0c904dc5ddd06faa808f653474f7fcc + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x776f9987d9deed90eed791cbd824d971fd5ccf09 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0xf7de7e8a6bd59ed41a4b5fe50278b3b7f31384df + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x19e6bfc1a6e4b042fb20531244d47e252445df01 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x4338665cbb7b2485a8855a139b75d5e34ab0db94 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x2940566eb50f15129238f4dc599adc4f742d7d8e + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0xbb73bb2505ac4643d5c0a99c2a1f34b3dfd09d11 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x4ea98c1999575aaadfb38237dd015c5e773f75a2 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/celo/0x1d18d0386f51ab03e7e84e71bda1681eba865f1f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x57b96d4af698605563a4653d882635da59bf11af + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xd33526068d116ce69f19a9ee46f0bd304f21a51f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x2a5fa016ffb20c70e2ef36058c08547f344677aa + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xbe0ed4138121ecfc5c0e56b40517da27e6c5226b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x9fd9278f04f01c6a39a9d1c1cd79f7782c6ade08 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x054c9d4c6f4ea4e14391addd1812106c97d05690 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x7613c48e0cd50e42dd9bf0f6c235063145f6f8dc + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x614da3b37b6f66f7ce69b4bbbcf9a55ce6168707 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x069e4aa272d17d9625aa3b6f863c7ef6cfb96713 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x24da31e7bb182cb2cabfef1d88db19c2ae1f5572 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x7d4a23832fad83258b32ce4fd3109ceef4332af4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xb58e61c3098d85632df34eecfb899a1ed80921cb + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x67c4d14861f9c975d004cfb3ac305bee673e996e + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x69babe9811cc86dcfc3b8f9a14de6470dd18eda4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x32f0d04b48427a14fb3cbc73db869e691a9fec6f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x4cff49d0a19ed6ff845a9122fa912abcfb1f68a6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x51cb253744189f11241becb29bedd3f1b5384fdb + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xcf4c91ecafc43c9f382db723ba20b82efa852821 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x6968676661ac9851c38907bdfcc22d5dd77b564d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x0d438f3b5175bebc262bf23753c1e53d03432bde + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xb98d4c97425d9908e66e53a6fdf673acca0be986 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x68a47fe1cf42eba4a030a10cd4d6a1031ca3ca0a + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x8a370c951f34e295b2655b47bb0985dd08d8f718 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x525574c899a7c877a11865339e57376092168258 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xd9a442856c234a39a81a089c06451ebaa4306a72 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x1c43d05be7e5b54d506e3ddb6f0305e8a66cd04e + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xb766039cc6db368759c1e56b79affe831d0cc507 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x18c14c2d707b2212e17d1579789fc06010cfca23 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xe0ee18eacafddaeb38f8907c74347c44385578ab + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x56659245931cb6920e39c189d2a0e7dd0da2d57b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xb6a5ae40e79891e4deadad06c8a7ca47396df21c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x04565fe9aa3ae571ada8e1bebf8282c4e5247b2a + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xf8a99f2bf2ce5bb6ce4aafcf070d8723bc904aa2 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x3b9728bd65ca2c11a817ce39a6e91808cceef6fd + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x6797b6244fa75f2e78cdffc3a4eb169332b730cc + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xe2c86869216ac578bd62a4b8313770d9ee359a05 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x47b464edb8dc9bc67b5cd4c9310bb87b773845bd + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x28a730de97dc62a8c88363e0b1049056f1274a70 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xba5ede8d98ab88cea9f0d69918dde28dc23c2553 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x8319767a7b602f88e376368dca1b92d38869b9b4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x461ee40928677644b8195662ab91bcdaae6ef105 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x24569d33653c404f90af10a2b98d6e0030d3d267 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x22222bd682745cf032006394750739684e45a5f8 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x9124577428c5bd73ad7636cbc5014081384f29d6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xaa6cccdce193698d33deb9ffd4be74eaa74c4898 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xe095780ba2a64a4efa7a74830f0b71656f0b0ad4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xb59c8912c83157a955f9d715e556257f432c35d7 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x7771450ece9c61430953d2646f995e33a06c91f5 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xc48823ec67720a04a9dfd8c7d109b2c3d6622094 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x9ec02756a559700d8d9e79ece56809f7bcc5dc27 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x3593d125a4f7849a1b059e64f4517a86dd60c95d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xb0ffa8000886e57f86dd5264b9582b2ad87b2b91 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x6985884c4392d348587b19cb9eaaf157f13271cd + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xa045fe936e26e1e1e1fb27c1f2ae3643acde0171 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xbeef698bd78139829e540622d5863e723e8715f1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x426a688ee72811773eb64f5717a32981b56f10c1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x873259322be8e50d80a4b868d186cc5ab148543a + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x661c70333aa1850ccdbae82776bb436a0fcfeefb + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x0a2c375553e6965b42c135bb8b15a8914b08de0c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x6fba952443be1de22232c824eb8d976b426b3c38 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x1abaea1f7c830bd89acc67ec4af516284b1bc33c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xb62132e35a6c13ee1ee0f84dc5d40bad8d815206 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xb60fdf036f2ad584f79525b5da76c5c531283a1b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x5a3e6a77ba2f983ec0d371ea3b475f8bc0811ad5 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x55296f69f40ea6d20e478533c15a6b08b654e758 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x1a7e4e63778b4f12a199c062f3efdd288afcbce8 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x45804880de22913dafe09f4980848ece6ecbaf78 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xe5018913f2fdf33971864804ddb5fca25c539032 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x6985884c4392d348587b19cb9eaaf157f13271cd + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x2c650dab03a59332e2e0c0c4a7f726913e5028c1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x9aee3c99934c88832399d6c6e08ad802112ebeab + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x439c0cf1038f8002a4cad489b427e217ba4b42ad + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/optimism/0x6985884c4392d348587b19cb9eaaf157f13271cd + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x6985884c4392d348587b19cb9eaaf157f13271cd + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x6985884c4392d348587b19cb9eaaf157f13271cd + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xb79dd08ea68a908a97220c76d19a6aa9cbde4376 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x4b61e2f1bbdee6d746209a693156952936f1702c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x7480527815ccae421400da01e052b120cc4255e9 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x7466de7bb8b5e41ee572f4167de6be782a7fa75d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x298d411511a05dc1b559ed8f79c56bee06687b14 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x8e16d46cb2da01cdd49601ec73d7b0344969ae33 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x18dd5b087bca9920562aff7a0199b96b9230438b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x37f0c2915cecc7e977183b8543fc0864d03e064c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x37f24b26bcefbfac7f261b97f8036da98f81a299 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xacb5b33ce55ba7729e38b2b59677e71c0112f0d9 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x6985884c4392d348587b19cb9eaaf157f13271cd + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0xc71b5f631354be6853efe9c3ab6b9590f8302e81 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x7e744bbb1a49a44dfcc795014a4ba618e418fbbe + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x4e3fbd56cd56c3e72c1403e103b45db9da5b9d2b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x0c04ff41b11065eed8c9eda4d461ba6611591395 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x636bd98fc13908e475f56d8a38a6e03616ec5563 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x590246bfbf89b113d8ac36faeea12b7589f7fe5b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x80034f803afb1c6864e3ca481ef1362c54d094b9 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x73fbd93bfda83b111ddc092aa3a4ca77fd30d380 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xff33a6b3dc0127862eedd3978609404b22298a54 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xc770eefad204b5180df6a14ee197d99d808ee52d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xa0385e7283c83e2871e9af49eec0966088421ddd + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xb2617246d0c6c0087f18703d576831899ca94f01 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xba386a4ca26b85fd057ab1ef86e3dc7bdeb5ce70 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x9ebb0895bd9c7c9dfab0d8d877c66ba613ac98ea + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xd12a99dbc40036cec6f1b776dccd2d36f5953b94 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x8ab2ff0116a279a99950c66a12298962d152b83c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x420698cfdeddea6bc78d59bc17798113ad278f9d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xa8c8cfb141a3bb59fea1e2ea6b79b5ecbcd7b6ca + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xd8e8438cf7beed13cfabc82f300fb6573962c9e3 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xb1c9d42fa4ba691efe21656a7e6953d999b990c4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xdadeca1167fe47499e53eb50f261103630974905 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xa05245ade25cc1063ee50cf7c083b4524c1c4302 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x4fafad147c8cd0e52f83830484d164e960bdc6c3 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x4dd9077269dd08899f2a9e73507125962b5bc87f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x8931ee05ec111325c1700b68e5ef7b887e00661d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x26f1bb40ea88b46ceb21557dc0ffac7b7c0ad40f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x642e993fa91ffe9fb24d39a8eb0e0663145f8e92 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x0c41f1fc9022feb69af6dc666abfe73c9ffda7ce + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xf7ccb8a6e3400eb8eb0c47619134f7516e025215 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x2416092f143378750bb29b79ed961ab195cceea5 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xf0268c5f9aa95baf5c25d646aabb900ac12f0800 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x0c067fc190cde145b0c537765a78d4e19873a5cc + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xbe5614875952b1683cb0a2c20e6509be46d353a4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x87a0233a8cb4392ec3eb8fa467817fc0b6a326dd + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xdfbea88c4842d30c26669602888d746d30f9d60d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xb6fe221fe9eef5aba221c348ba20a1bf5e73624c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x80b3455e1db60b4cba46aba12e8b1e256dd64979 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x747747e47a48c669be384e0dfb248eee6ba04039 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/celo/0x50e85c754929840b58614f48e29c64bc78c58345 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x02f92800f57bcd74066f5709f1daa1a4302df875 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x967da4048cd07ab37855c090aaf366e4ce1b9f48 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x729031b3995538ddf6b6bce6e68d5d6fdeb3ccb5 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x6dea81c8171d0ba574754ef6f8b412f2ed88c54d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x97a9a15168c22b3c137e6381037e1499c8ad0978 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x5faa989af96af85384b8a938c2ede4a7378d9875 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x4691937a7508860f876c9c0a2a617e7d9e945d4b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xb50721bcf8d664c30412cfbc6cf7a15145234ad1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x037a54aab062628c9bbae1fdb1583c195585fe41 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xcb8b5cd20bdcaea9a010ac1f8d835824f5c87a04 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xdfb8be6f8c87f74295a87de951974362cedcfa30 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x354a6da3fcde098f8389cad84b0182725c6c91de + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x3f56e0c36d275367b8c502090edf38289b3dea0d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x6f9590958ce2beaf9c92a3a8fca6d1ddf310e052 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/optimism/0x3e5d9d8a63cc8a88748f229999cf59487e90721e + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/optimism/0xecc68d0451e20292406967fe7c04280e5238ac7d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xf1c1a3c2481a3a8a3f173a9ab5ade275292a6fa3 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xb5e0cfe1b4db501ac003b740665bf43192cc7853 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xffa188493c15dfaf2c206c97d8633377847b6a52 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xb5c064f955d8e7f38fe0460c556a72987494ee17 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x4f604735c1cf31399c6e711d5962b2b3e0225ad3 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xf0949dd87d2531d665010d6274f06a357669457a + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x14e5386f47466a463f85d151653e1736c0c50fc3 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xadac33f543267c4d59a8c299cf804c303bc3e4ac + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xcfa3ef56d303ae4faaba0592388f19d7c3399fb4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x67ce18961c3269ca03c2e5632f1938cc53e614a1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x48164ea5df090e80a0eaee1147e466ea28669221 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x3054e8f8fba3055a42e5f5228a2a4e2ab1326933 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x42069d11a2cc72388a2e06210921e839cfbd3280 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x74ff3cbf86f95fea386f79633d7bc4460d415f34 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x2d6a3893966dda77749cc7e4003ab15f5cfa3cc1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x51b75da3da2e413ea1b8ed3eb078dc712304761c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x8ad5b9007556749de59e088c88801a3aaa87134b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xbd97693278f1948c59f65f130fd87e7ff7c61d11 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x3992b27da26848c2b19cea6fd25ad5568b68ab98 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x34980c35353a8d7b1a1ba02e02e387a8383e004a + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0xdebd6e2da378784a69dc6ec99fe254223b312287 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/celo/0x456a3d042c0dbd3db53d5489e98dfb038553b0d0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/celo/0x9995cc8f20db5896943afc8ee0ba463259c931ed + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x30d20208d987713f46dfd34ef128bb16c404d10f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x19848077f45356b21164c412eff3d3e4ff6ebc31 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x53206bf5b6b8872c1bb0b3c533e06fde2f7e22e4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x07ddacf367f0d40bd68b4b80b4709a37bdc9f847 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xbdbe9f26918918bd3f43a0219d54e5fda9ce1bb3 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xb9d09bc374577dac1ab853de412a903408204ea8 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xe72b141df173b999ae7c1adcbf60cc9833ce56a8 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x214549b0317564de15770561221433fb3e8c995c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xc82e3db60a52cf7529253b4ec688f631aad9e7c2 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xf3dcbc6d72a4e1892f7917b7c43b74131df8480e + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x62e3b3c557c792c4a70765b3cdb5b56b1879f82d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x2598c30330d5771ae9f983979209486ae26de875 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xd4f4d0a10bcae123bb6655e8fe93a30d01eebd04 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xa0995d43901551601060447f9abf93ebc277cec2 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x40379a439d4f6795b6fc9aa5687db461677a2dba + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x433cde5a82b5e0658da3543b47a375dffd126eb6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x619c4bbbd65f836b78b36cbe781513861d57f39d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x1e0bb24ed6c806c01ef2f880a4b91adb90099ea7 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x0dd7913197bfb6d2b1f03f9772ced06298f1a644 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xfbb75a59193a3525a8825bebe7d4b56899e2f7e1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xc3de830ea07524a0761646a6a4e4be0e114a3c83 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x3792dbdd07e87413247df995e692806aa13d3299 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x527856315a4bcd2f428ea7fa05ea251f7e96a50a + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x292fcdd1b104de5a00250febba9bc6a5092a0076 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xd749b369d361396286f8cc28a99dd3425ac05619 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xfe3e6a25e6b192a42a44ecddcd13796471735acf + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xa1faa113cbe53436df28ff0aee54275c13b40975 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x8802269d1283cdb2a5a329649e5cb4cdcee91ab6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x0000bdaa645097ef80f9d475f341d0d107a45b3a + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x683a4ac99e65200921f556a19dadf4b0214b5938 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x36c7188d64c44301272db3293899507eabb8ed43 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x8a2279d4a90b6fe1c4b30fa660cc9f926797baa2 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xf418588522d5dd018b425e472991e52ebbeeeeee + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x6135177a17e02658df99a07a2841464deb5b8589 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xcf91b70017eabde82c9671e30e5502d312ea6eb2 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x45080a6531d671ddff20db42f93792a489685e32 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x790814cd782983fab4d7b92cf155187a865d9f18 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x9e6be44cc1236eef7e1f197418592d363bedcd5a + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xaa7a9ca87d3694b5755f213b5d04094b8d0f0a6f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x69ee720c120ec7c9c52a625c04414459b3185f23 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x408e41876cccdc0f92210600ef50372656052a38 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x5cf04716ba20127f1e2297addcf4b5035000c9eb + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x8290333cef9e6d528dd5618fb97a76f268f3edd4 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x1929761e87667283f087ea9ab8370c174681b4e9 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x888888848b652b3e3a0f34c96e00eec0f3a23f72 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xf944e35f95e819e752f3ccb5faf40957d311e8c5 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x1f70300bce8c2302780bd0a153ebb75b8ca7efcb + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x3de81ce90f5a27c5e6a5adb04b54aba488a6d14e + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xc87b37a581ec3257b734886d9d3a581f5a9d056c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x1a6b3a62391eccaaa992ade44cd4afe6bec8cff1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x65c936f008bc34fe819bce9fa5afd9dc2d49977f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x07d65c18cecba423298c0aeb5d2beded4dfd5736 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x51fc0f6660482ea73330e414efd7808811a57fa2 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xcbe94d75ec713b7ead84f55620dc3174beeb1cfe + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xd3144ff5f388d36c0a445686c08540296d8b209b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x433e39ce74aef8f409182541269e417ad9b56011 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xb1a03eda10342529bbf8eb700a06c60441fef25d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x6b9bb36519538e0c073894e964e90172e1c0b41f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x689644b86075ed61c647596862c7403e1c474dbf + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x9a6d24c02ec35ad970287ee8296d4d6552a31dbe + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x506beb7965fc7053059006c7ab4c62c02c2d989f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x31b28012f61fc3600e1c076bafc9fd997fb2da90 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xd7d919ea0c33a97ad6e7bd4f510498e2ec98cb78 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xef553b6914dbd17567393f7e55fbd773fff7d0cb + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xe642657e4f43e6dcf0bd73ef24008394574dee28 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xf8b1b47aa748f5c7b5d0e80c726a843913eb573a + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xd064c53f043d5aee2ac9503b13ee012bf2def1d0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xfc60aa1ffca50ce08b3cdec9626c0bb9e9b09bec + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x82c8f48ac694841360de84d649a0d48d239b61f8 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x7d89e05c0b93b24b5cb23a073e60d008fed1acf9 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x7546e0d4d947a15f914e33de6616ffed826f45ef + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x9a5350edf28c1f93bb36d6e94b5c425fde8e222d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0xaa076b62efc6f357882e07665157a271ab46a063 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x6a6aa13393b7d1100c00a57c76c39e8b6c835041 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x07040971246a73ebda9cf29ea1306bb47c7c4e76 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x6df0e641fc9847c0c6fde39be6253045440c14d3 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x2b640a99991dea2916205ecdc9f9c58f80017ed8 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x38e4adb44ef08f22f5b5b76a8f0c2d0dcbe7dca1 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x42069cc15f5befb510430d22ff1c9a1b3ae22cfe + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x40d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x89fd2d8fd8d937f55c89b7da3ceed44fa27e4a81 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x76bc677d444f1e9d57daf5187ee2b7dc852745ae + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xa0084063ea01d5f09e56ef3ff6232a9e18b0bacd + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x4abd5745f326932b1b673bfa592a20d7bb6bc455 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xe53ec727dbdeb9e2d5456c3be40cff031ab40a55 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xf43f21384d03b5cbbddd58d2de64071e4ce76ab0 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x33349b282065b0284d756f0577fb39c158f935e6 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x33c88d4cac6ac34f77020915a2a88cd0417dc069 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xdce765f021410b3266aa0053c93cb4535f1e12e0 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xb50a8e92cb9782c9b8f3c88e4ee8a1d0aa2221d7 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x0a84edf70f30325151631ce7a61307d1f4d619a3 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xc11158c5da9db1d553ed28f0c2ba1cbedd42cfcb + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/optimism/0xb0b195aefa3650a6908f15cdac7d92f8a5791b0b + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xdc4f4ed9872571d5ec8986a502a0d88f3a175f1e + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x9beec80e62aa257ced8b0edd8692f79ee8783777 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xf95e1c0a67492720ca22842122fe7fa63d5519e5 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xca8e8d244f0d219a6fc9e4793c635cea98d0399c + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x6a4f69da1e2fb2a9b11d1aad60d03163fe567732 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x0718f45bbf4781ce891e4e18182f025725f0fc95 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x132bbda4a40d4d6288be49b637ec2c113b5d7600 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x9aaae745cf2830fb8ddc6248b17436dc3a5e701c + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x24fcfc492c1393274b6bcd568ac9e225bec93584 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x21fd16cd0ef24a49d28429921e335bb0c1bfadb3 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xa469b7ee9ee773642b3e93e842e5d9b5baa10067 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x8c19f7854b27758ddffdcdc8908f22bf55e00736 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xf2ae0038696774d65e67892c9d301c5f2cbbda58 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x6bc40d4099f9057b23af309c08d935b890d7adc0 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xee2a03aa6dacf51c18679c516ad5283d8e7c2637 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x7f911119435d8ded9f018194b4b6661331379a3d + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x777be1c6075c20184c4fd76344b7b0b7c858fe6b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x812ba41e071c7b7fa4ebcfb62df5f45f6fa853ee + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x881d4c8618d68872fa404518b2460ea839a02a6a + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xba2ae4e0a9c6ecaf172015aa2cdd70a21f5a290b + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x1caf237d7a2d103e3e9b1855988c01ac10344600 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x7d4a7be025652995364e0e232063abd9e8d65e6e + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x620aa20875ec1144126ea47fb27ecfe6e10d0c56 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xfae103dc9cf190ed75350761e95403b7b8afa6c0 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xae7ab96520de3a18e5e111b5eaab095312d7fe84 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x04c154b66cb340f3ae24111cc767e0184ed00cc6 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x70e8de73ce538da2beed35d14187f6959a8eca96 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xfb7b4564402e5500db5bb6d63ae671302777c75a + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x6810e776880c02933d47db1b9fc05908e5386b96 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x11e969e9b3f89cb16d686a03cd8508c9fc0361af + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x8b5d1d8b3466ec21f8ee33ce63f319642c026142 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x3ed03e95dd894235090b3d4a49e0c3239edce59e + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xb3f13b0c61d65d67d7d6215d70c89533ee567a91 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xfea31d704deb0975da8e77bf13e04239e70d7c28 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/optimism/0x66e535e8d2ebf13f49f3d49e5c50395a97c137b1 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x9a06db14d639796b25a6cec6a1bf614fd98815ec + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x7fdd7419428955dbf36d4176af5a8f09ad29d1f3 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x8c9037d1ef5c6d1f6816278c7aaf5491d24cd527 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xa9f5031b54c44c3603b4300fde9b8f5cd18ad06f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x57f5fbd3de65dfc0bd3630f732969e5fb97e6d37 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x9ef1139e6b420cc929dd912a5a7adeced6f12e91 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x120edc8e391ba4c94cb98bb65d8856ae6ec1525f + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xd7ea82d19f1f59ff1ae95f1945ee6e6d86a25b96 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x2c9ab600d71967ff259c491ad51f517886740cbc + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0xf4c8e32eadec4bfe97e0f595add0f4450a863a11 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x8c49a510756224e887b3d99d00d959f2d86dda1c + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x7777cec341e7434126864195adef9b05dcc3489c + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x19af07b52e5faa0c2b1e11721c52aa23172fe2f5 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xb7109df1a93f8fe2b8162c6207c9b846c1c68090 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xbbc2ae13b23d715c30720f079fcd9b4a74093505 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x595832f8fc6bf59c85c527fec3740a1b7a361269 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x7316d973b0269863bbfed87302e11334e25ea565 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xa0b73e1ff0b80914ab6fe0444e65848c4c34450b + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x2be8e422cb4a5a7f217a8f1b0658952a79132f28 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x83e6f1e41cdd28eaceb20cb649155049fac3d5aa + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xbabe3ce7835665464228df00b03246115c30730a + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x2e6a60492fb5b58f5b5d08c7cafc75e740e6dc8e + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xc08e7e23c235073c6807c2efe7021304cb7c2815 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x955d5c14c8d4944da1ea7836bd44d54a8ec35ba1 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x3540abe4f288b280a0740ad5121aec337c404d15 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xfe8526a77a2c3590e5973ba81308b90bea21fbff + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xd807f7e2818db8eda0d28b5be74866338eaedb86 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x4186bfc76e2e237523cbc30fd220fe055156b41f + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xd5d3aa404d7562d09a848f96a8a8d5d65977bf90 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xa3f751662e282e83ec3cbc387d225ca56dd63d3a + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xd24157aa1097486dc9d7cf094a7e15026e566b5d + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xbed0b9240bdbcc8e33f66d2ca650a5ef60a5bab0 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x5d559ea7bb2dae4b694a079cb8328a2145fd32f6 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x97b959385dfdcaf252223838746beb232ac601aa + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x18e692c03de43972fe81058f322fa542ae1a5e2c + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x38029c62dfa30d9fd3cadf4c64e9b2ab21dbda17 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x4507cef57c46789ef8d1a19ea45f4216bae2b528 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/celo/0x73f93dcc49cb8a239e2032663e9475dd5ef29a08 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x9e523234d36973f9e38642886197d023c88e307e + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x5de758bba013e58dae2693aea3f0b12b31a3023d + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x1001271083c249bd771e1bb76c22d935809a61ee + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x9d39a5de30e57443bff2a8307a4256c8797a3497 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xf3768d6e78e65fc64b8f12ffc824452130bd5394 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xf2ec4a773ef90c58d98ea734c0ebdb538519b988 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x0f2d719407fdbeff09d87557abb7232601fd9f29 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x180000dda70eb7fb7f3e10e52e88ce88f46e3b3a + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xed89fc0f41d8be2c98b13b7e3cd3e876d73f1d30 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x17c50d62e6e8d20d2dc18e9ad79c43263d0720d9 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x3b50805453023a91a8bf641e279401a0b23fa6f9 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xfd03723a9a3abe0562451496a9a394d2c4bad4ab + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xfe67a4450907459c3e1fff623aa927dd4e28c67a + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xc5fb36dd2fb59d3b98deff88425a3f425ee469ed + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x6b021b3f68491974be6d4009fee61a4e3c708fd6 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x7ae9ab13fc8945323b778b3f8678145e80ec2efb + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xbc4c97fb9befaa8b41448e1dfcc5236da543217f + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/optimism/0x93919784c523f39cacaa98ee0a9d96c3f32b593e + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xd55fce7cdab84d84f2ef3f99816d765a2a94a509 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x32e0f9d26d1e33625742a52620cc76c1130efde6 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x9b700b043e9587dde9a0c29a9483e2f8fa450d54 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x0b1594b0e896bf165d925956e0df733b8443af6a + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x891502ba08132653151f822a3a430198f1844115 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xc702b80a1bebac118cab22ce6f2978ef59563b3f + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x1287a235474e0331c0975e373bdd066444d1bd35 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xab36452dbac151be02b16ca17d8919826072f64a + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xcc7ff230365bd730ee4b352cc2492cedac49383e + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0xa9b038285f43cd6fe9e16b4c80b4b9bccd3c161b + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x77be1ba1cd2d7a63bffc772d361168cc327dd8bc + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x00000000efe302beaa2b3e6e1b18d08d69a9012a + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xd101dcc414f310268c37eeb4cd376ccfa507f571 + 2024-08-16T22:35:51.074Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xd09eb9099fac55edcbf4965e0a866779ca365a0c + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x7b0df1cd724ec34ec9bc4bd19749b01afb490761 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x71297312753ea7a2570a5a3278ed70d9a75f4f44 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x9e32b13ce7f2e80a01932b42553652e053d6ed8e + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x6942040b6d25d6207e98f8e26c6101755d67ac89 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x3301ee63fb29f863f2333bd4466acb46cd8323e6 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xfefe157c9d0ae025213092ff9a5cb56ab492bab8 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x44108f0223a3c3028f5fe7aec7f9bb2e66bef82f + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x1121acc14c63f3c872bfca497d10926a6098aac5 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xf1376bcef0f78459c0ed0ba5ddce976f1ddf51f4 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xce722f60f35c37ab295adc4e6ba45bcc7ca89dd6 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x614577036f0a024dbc1c88ba616b394dd65d105a + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x93fa0b88c0c78e45980fa74cdd87469311b7b3e4 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xe22c452bd2ade15dfc8ad98286bc6bdf0c9219b7 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x00000000000451f49c692bfc24971cacea2db678 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x00000000702749f73e5210b08b0a3d440078f888 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x86f65121804d2cdbef79f9f072d4e0c2eebabc08 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x127e47aba094a9a87d084a3a93732909ff031419 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x52b492a33e447cdb854c7fc19f1e57e8bfa1777d + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x55027a5b06f4340cc4c82dcc74c90ca93dcb173e + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x32b133add6d99d085ff23f522662b546b70d54a1 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x2ad3d80c917ddbf08acc04277f379e00e4d75395 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xc73dc7ae7a4fa40517aafa941ae1ee436b91a12c + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x9f235d23354857efe6c541db92a9ef1877689bcb + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x0c90c756350fb803a7d5d9f9ee5ac29e77369973 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xac12f930318be4f9d37f602cbf89cd33e99aa9d4 + 2024-08-23T19:37:24.067Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x1c45366641014069114c78962bdc371f534bc81c + 2024-08-23T19:37:24.067Z 0.8 \ No newline at end of file diff --git a/apps/web/src/components/AccountDetails/AddressDisplay.tsx b/apps/web/src/components/AccountDetails/AddressDisplay.tsx index 82970fb6775..dd89a0ffe6f 100644 --- a/apps/web/src/components/AccountDetails/AddressDisplay.tsx +++ b/apps/web/src/components/AccountDetails/AddressDisplay.tsx @@ -2,7 +2,7 @@ import useENSName from 'hooks/useENSName' import styled from 'lib/styled-components' import { CopyHelper, EllipsisStyle } from 'theme/components' import { Flex } from 'ui/src' -import { Unitag } from 'ui/src/components/icons' +import { Unitag } from 'ui/src/components/icons/Unitag' import { useUnitagByAddress } from 'uniswap/src/features/unitags/hooks' import { shortenAddress } from 'utilities/src/addresses' diff --git a/apps/web/src/components/AccountDrawer/AuthenticatedHeader.tsx b/apps/web/src/components/AccountDrawer/AuthenticatedHeader.tsx index 7f2825df3a1..898acd45c1b 100644 --- a/apps/web/src/components/AccountDrawer/AuthenticatedHeader.tsx +++ b/apps/web/src/components/AccountDrawer/AuthenticatedHeader.tsx @@ -31,7 +31,7 @@ import { useCloseModal, useFiatOnrampAvailability, useOpenModal, useToggleModal import { ApplicationModal } from 'state/application/reducer' import { useUserHasAvailableClaim, useUserUnclaimedAmount } from 'state/claim/hooks' import { ThemedText } from 'theme/components' -import { ArrowDownCircleFilled } from 'ui/src/components/icons' +import { ArrowDownCircleFilled } from 'ui/src/components/icons/ArrowDownCircleFilled' import { FeatureFlags } from 'uniswap/src/features/gating/flags' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' import Trace from 'uniswap/src/features/telemetry/Trace' diff --git a/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/getCurrency.ts b/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/getCurrency.ts index 0e5fbe98754..4952e85fa88 100644 --- a/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/getCurrency.ts +++ b/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/getCurrency.ts @@ -5,9 +5,9 @@ import { NATIVE_CHAIN_ID, nativeOnChain } from 'constants/tokens' import { apolloClient } from 'graphql/data/apollo/client' import { gqlTokenToCurrencyInfo } from 'graphql/data/types' import { - SimpleTokenDocument, - SimpleTokenQuery, Token, + TokenDocument, + TokenQuery, } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { isSameAddress } from 'utilities/src/addresses' @@ -26,8 +26,8 @@ export async function getCurrency( if (commonBase) { return commonBase.currency } - const { data } = await apolloClient.query({ - query: SimpleTokenDocument, + const { data } = await apolloClient.query({ + query: TokenDocument, variables: { address: currencyId, chain: chainIdToBackendChain({ chainId }), diff --git a/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/index.tsx b/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/index.tsx index f1ddf89f468..c28115064ef 100644 --- a/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/index.tsx +++ b/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/index.tsx @@ -5,14 +5,14 @@ import { createGroups } from 'components/AccountDrawer/MiniPortfolio/Activity/ut import { OpenLimitOrdersButton } from 'components/AccountDrawer/MiniPortfolio/Limits/OpenLimitOrdersButton' import { PortfolioSkeleton, PortfolioTabWrapper } from 'components/AccountDrawer/MiniPortfolio/PortfolioRow' import { useAccountDrawer } from 'components/AccountDrawer/MiniPortfolio/hooks' -import { hideSpamAtom } from 'components/AccountDrawer/SpamToggle' import Column from 'components/Column' import { LoadingBubble } from 'components/Tokens/loading' -import { useAtomValue, useUpdateAtom } from 'jotai/utils' +import { useUpdateAtom } from 'jotai/utils' import styled from 'lib/styled-components' import { EmptyWalletModule } from 'nft/components/profile/view/EmptyWalletContent' import { useMemo } from 'react' import { ThemedText } from 'theme/components' +import { useHideSpamTokensSetting } from 'uniswap/src/features/settings/hooks' const ActivityGroupWrapper = styled(Column)` margin-top: 16px; @@ -30,7 +30,7 @@ export function ActivityTab({ account }: { account: string }) { const { activities, loading } = useAllActivities(account) - const hideSpam = useAtomValue(hideSpamAtom) + const hideSpam = useHideSpamTokensSetting() const activityGroups = useMemo(() => createGroups(activities, hideSpam), [activities, hideSpam]) if (activityGroups.length === 0) { diff --git a/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/parseRemote.tsx b/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/parseRemote.tsx index d45fba13588..a1cb3c7c3a9 100644 --- a/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/parseRemote.tsx +++ b/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/parseRemote.tsx @@ -542,7 +542,7 @@ function parseFiatOnRampTransaction(activity: TransactionActivity | FiatOnRampAc hash: activity.id, chainId, timestamp: activity.timestamp, - logos: [onRampTransfer.token.project?.logo?.url], + logos: [onRampTransfer.token.project?.logoUrl], currencies: [gqlToCurrency(onRampTransfer.token)], title: t('fiatOnRamp.purchasedOn', { serviceProvider: onRampTransfer.serviceProvider.name, @@ -572,7 +572,7 @@ function parseFiatOnRampTransaction(activity: TransactionActivity | FiatOnRampAc hash: activity.details.hash, chainId, timestamp: activity.timestamp, - logos: [onRampTransfer.token.project?.logo?.url], + logos: [onRampTransfer.token.project?.logoUrl], currencies: [gqlToCurrency(onRampTransfer.token)], title: t('fiatOnRamp.purchasedOn', { serviceProvider: onRampTransfer.serviceProvider.name, diff --git a/apps/web/src/components/AccountDrawer/MiniPortfolio/EmptyWallet.tsx b/apps/web/src/components/AccountDrawer/MiniPortfolio/EmptyWallet.tsx index 48c2856f54c..29339fd7c87 100644 --- a/apps/web/src/components/AccountDrawer/MiniPortfolio/EmptyWallet.tsx +++ b/apps/web/src/components/AccountDrawer/MiniPortfolio/EmptyWallet.tsx @@ -2,7 +2,8 @@ import styled from 'lib/styled-components' import { useCallback, useMemo } from 'react' import { Flex, Text, useIsDarkMode } from 'ui/src' import { CRYPTO_PURCHASE_BACKGROUND_DARK, CRYPTO_PURCHASE_BACKGROUND_LIGHT } from 'ui/src/assets' -import { ArrowDownCircle, Buy as BuyIcon } from 'ui/src/components/icons' +import { ArrowDownCircle } from 'ui/src/components/icons/ArrowDownCircle' +import { Buy as BuyIcon } from 'ui/src/components/icons/Buy' import { ActionCard, ActionCardItem } from 'uniswap/src/components/misc/ActionCard' import { ElementName } from 'uniswap/src/features/telemetry/constants' import { Trans, t } from 'uniswap/src/i18n' diff --git a/apps/web/src/components/AccountDrawer/MiniPortfolio/ExtensionDeeplinks.tsx b/apps/web/src/components/AccountDrawer/MiniPortfolio/ExtensionDeeplinks.tsx index 0aeaf222fb1..2528cc26fb1 100644 --- a/apps/web/src/components/AccountDrawer/MiniPortfolio/ExtensionDeeplinks.tsx +++ b/apps/web/src/components/AccountDrawer/MiniPortfolio/ExtensionDeeplinks.tsx @@ -10,7 +10,10 @@ import { useTheme } from 'lib/styled-components' import { useEffect, useState } from 'react' import { Button, Flex, Image, Text } from 'ui/src' import { UNISWAP_LOGO } from 'ui/src/assets' -import { ArrowRightToLine, RotatableChevron, TimePast } from 'ui/src/components/icons' +import { ArrowRightToLine } from 'ui/src/components/icons/ArrowRightToLine' +import { RotatableChevron } from 'ui/src/components/icons/RotatableChevron' +import { TimePast } from 'ui/src/components/icons/TimePast' + import { iconSizes } from 'ui/src/theme/iconSizes' import { t } from 'uniswap/src/i18n' diff --git a/apps/web/src/components/AccountDrawer/MiniPortfolio/Limits/__snapshots__/OpenLimitOrdersButton.test.tsx.snap b/apps/web/src/components/AccountDrawer/MiniPortfolio/Limits/__snapshots__/OpenLimitOrdersButton.test.tsx.snap index 6e8d7c1cc6e..d757da59075 100644 --- a/apps/web/src/components/AccountDrawer/MiniPortfolio/Limits/__snapshots__/OpenLimitOrdersButton.test.tsx.snap +++ b/apps/web/src/components/AccountDrawer/MiniPortfolio/Limits/__snapshots__/OpenLimitOrdersButton.test.tsx.snap @@ -121,7 +121,7 @@ exports[`OpenLimitOrdersButton should render if there are open limit orders 1`] class="c4" > 1 open limit diff --git a/apps/web/src/components/AccountDrawer/MiniPortfolio/PortfolioLogo.test.tsx b/apps/web/src/components/AccountDrawer/MiniPortfolio/PortfolioLogo.test.tsx index 08933d9bf7e..c794af9ed46 100644 --- a/apps/web/src/components/AccountDrawer/MiniPortfolio/PortfolioLogo.test.tsx +++ b/apps/web/src/components/AccountDrawer/MiniPortfolio/PortfolioLogo.test.tsx @@ -3,7 +3,6 @@ import 'test-utils/tokens/mocks' import { PortfolioLogo } from 'components/AccountDrawer/MiniPortfolio/PortfolioLogo' import { DAI, DAI_ARBITRUM_ONE, USDC_ARBITRUM, USDC_MAINNET } from 'constants/tokens' import { render } from 'test-utils/render' -import 'test-utils/tokens/mocks' import { UniverseChainId } from 'uniswap/src/types/chains' describe('PortfolioLogo', () => { diff --git a/apps/web/src/components/AccountDrawer/MiniPortfolio/Tokens/index.tsx b/apps/web/src/components/AccountDrawer/MiniPortfolio/Tokens/index.tsx index 025b8e38146..71c235fa466 100644 --- a/apps/web/src/components/AccountDrawer/MiniPortfolio/Tokens/index.tsx +++ b/apps/web/src/components/AccountDrawer/MiniPortfolio/Tokens/index.tsx @@ -6,20 +6,18 @@ import PortfolioRow, { PortfolioTabWrapper, } from 'components/AccountDrawer/MiniPortfolio/PortfolioRow' import { useAccountDrawer } from 'components/AccountDrawer/MiniPortfolio/hooks' -import { hideSmallBalancesAtom } from 'components/AccountDrawer/SmallBalanceToggle' -import { hideSpamAtom } from 'components/AccountDrawer/SpamToggle' import Row from 'components/Row' import { DeltaArrow } from 'components/Tokens/TokenDetails/Delta' import { useTokenBalancesQuery } from 'graphql/data/apollo/TokenBalancesProvider' import { PortfolioToken } from 'graphql/data/portfolios' import { getTokenDetailsURL, gqlToCurrency } from 'graphql/data/util' -import { useAtomValue } from 'jotai/utils' import styled from 'lib/styled-components' import { EmptyWalletModule } from 'nft/components/profile/view/EmptyWalletContent' import { useCallback, useMemo, useState } from 'react' import { useNavigate } from 'react-router-dom' import { EllipsisStyle, ThemedText } from 'theme/components' import { PortfolioTokenBalancePartsFragment } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' +import { useHideSmallBalancesSetting, useHideSpamTokensSetting } from 'uniswap/src/features/settings/hooks' import Trace from 'uniswap/src/features/telemetry/Trace' import { logger } from 'utilities/src/logger/logger' import { NumberType, useFormatter } from 'utils/formatNumbers' @@ -27,8 +25,8 @@ import { splitHiddenTokens } from 'utils/splitHiddenTokens' export default function Tokens() { const accountDrawer = useAccountDrawer() - const hideSmallBalances = useAtomValue(hideSmallBalancesAtom) - const hideSpam = useAtomValue(hideSpamAtom) + const hideSmallBalances = useHideSmallBalancesSetting() + const hideSpam = useHideSpamTokensSetting() const [showHiddenTokens, setShowHiddenTokens] = useState(false) const { data } = useTokenBalancesQuery({ cacheOnly: !accountDrawer.isOpen }) diff --git a/apps/web/src/components/AccountDrawer/MiniPortfolio/shared.tsx b/apps/web/src/components/AccountDrawer/MiniPortfolio/shared.tsx index 161a71452f9..688b2a4ee2c 100644 --- a/apps/web/src/components/AccountDrawer/MiniPortfolio/shared.tsx +++ b/apps/web/src/components/AccountDrawer/MiniPortfolio/shared.tsx @@ -33,7 +33,7 @@ export function TabButton({ text, icon, extraWarning, onClick, disabled, classNa {icon} - + {text} {extraWarning && {extraWarning}} diff --git a/apps/web/src/components/AccountDrawer/SettingsMenu.tsx b/apps/web/src/components/AccountDrawer/SettingsMenu.tsx index b33f07bc790..173bd3e50ef 100644 --- a/apps/web/src/components/AccountDrawer/SettingsMenu.tsx +++ b/apps/web/src/components/AccountDrawer/SettingsMenu.tsx @@ -1,6 +1,5 @@ import { AnalyticsToggle } from 'components/AccountDrawer/AnalyticsToggle' import { GitVersionRow } from 'components/AccountDrawer/GitVersionRow' -import { LanguageMenuItems } from 'components/AccountDrawer/LanguageMenu' import { SlideOutMenu } from 'components/AccountDrawer/SlideOutMenu' import { SmallBalanceToggle } from 'components/AccountDrawer/SmallBalanceToggle' import { SpamToggle } from 'components/AccountDrawer/SpamToggle' @@ -22,11 +21,6 @@ const Container = styled(Column)` justify-content: space-between; ` -const SectionTitle = styled(ThemedText.SubHeader)` - color: ${({ theme }) => theme.neutral2}; - padding-bottom: 24px; -` - const ToggleWrapper = styled.div<{ currencyConversionEnabled?: boolean }>` display: flex; flex-direction: column; @@ -90,12 +84,6 @@ export default function SettingsMenu({ - <> - - - - - ('hideSmallBalances', true) - export function SmallBalanceToggle() { - const [hideSmallBalances, updateHideSmallBalances] = useAtom(hideSmallBalancesAtom) + const hideSmallBalances = useHideSmallBalancesSetting() + const dispatch = useDispatch() + + const onToggle = () => { + dispatch(setHideSmallBalances(!hideSmallBalances)) + } - return ( - void updateHideSmallBalances((value) => !value)} - /> - ) + return } diff --git a/apps/web/src/components/AccountDrawer/SpamToggle.tsx b/apps/web/src/components/AccountDrawer/SpamToggle.tsx index e61ab9bd027..951d06e5c8a 100644 --- a/apps/web/src/components/AccountDrawer/SpamToggle.tsx +++ b/apps/web/src/components/AccountDrawer/SpamToggle.tsx @@ -1,18 +1,18 @@ import { SettingsToggle } from 'components/AccountDrawer/SettingsToggle' -import { useAtom } from 'jotai' -import { atomWithStorage } from 'jotai/utils' +import { useDispatch } from 'react-redux' +import { useHideSpamTokensSetting } from 'uniswap/src/features/settings/hooks' +import { setHideSpamTokens } from 'uniswap/src/features/settings/slice' import { Trans } from 'uniswap/src/i18n' -export const hideSpamAtom = atomWithStorage('hideSpamBalances', true) - export function SpamToggle() { - const [hideSpam, updateHideSpam] = useAtom(hideSpamAtom) + const hideSpamTokens = useHideSpamTokensSetting() + const dispatch = useDispatch() + + const onToggle = () => { + dispatch(setHideSpamTokens(!hideSpamTokens)) + } return ( - } - isActive={hideSpam} - toggle={() => void updateHideSpam((value) => !value)} - /> + } isActive={hideSpamTokens} toggle={onToggle} /> ) } diff --git a/apps/web/src/components/AccountDrawer/index.tsx b/apps/web/src/components/AccountDrawer/index.tsx index e75d43280b6..eb167b2726e 100644 --- a/apps/web/src/components/AccountDrawer/index.tsx +++ b/apps/web/src/components/AccountDrawer/index.tsx @@ -13,11 +13,11 @@ import styled, { css } from 'lib/styled-components' import { useEffect, useRef, useState } from 'react' import { ChevronsRight } from 'react-feather' import { useGesture } from 'react-use-gesture' -import { BREAKPOINTS } from 'theme' +import { BREAKPOINTS, NAV_HEIGHT } from 'theme' import { ClickableStyle } from 'theme/components' import { Z_INDEX } from 'theme/zIndex' import Trace from 'uniswap/src/features/telemetry/Trace' -import { isMobile } from 'utilities/src/platform' +import { isMobileWeb } from 'utilities/src/platform' const DRAWER_WIDTH_XL = '390px' export const DRAWER_WIDTH = '320px' @@ -99,9 +99,9 @@ const Container = styled.div<{ isUniExtensionAvailable?: boolean; $open?: boolea const ExtensionContainerStyles = css` height: auto; - max-height: calc(100% - ${({ theme }) => theme.navHeight + 16}px); + max-height: calc(100% - ${NAV_HEIGHT + 16}px); right: 12px; - top: ${({ theme }) => theme.navHeight}px; + top: ${NAV_HEIGHT}px; ${ScrollBarStyles} ` @@ -115,8 +115,8 @@ const AccountDrawerWrapper = styled.div<{ open: boolean; isUniExtensionAvailable z-index: ${Z_INDEX.modal}; position: absolute; margin-right: 0; - top: ${({ open, theme }) => (open ? `calc(-1 * (100% - ${theme.navHeight}px))` : 0)}; - height: calc(100% - ${({ theme }) => theme.navHeight}px); + top: ${({ open }) => (open ? `calc(-1 * (100% - ${NAV_HEIGHT}px))` : 0)}; + height: calc(100% - ${NAV_HEIGHT}px); width: 100%; max-width: 100%; @@ -288,7 +288,7 @@ function AccountDrawer() { ref={modalRef} data-testid="account-drawer" open={accountDrawer.isOpen} - {...(isMobile + {...(isMobileWeb ? { ...bind(), style: { transform: `translateY(${yPosition}px)` }, diff --git a/apps/web/src/components/AddressQRModal/index.tsx b/apps/web/src/components/AddressQRModal/index.tsx index b759241a33d..04b45da9df4 100644 --- a/apps/web/src/components/AddressQRModal/index.tsx +++ b/apps/web/src/components/AddressQRModal/index.tsx @@ -10,7 +10,7 @@ import { useCallback } from 'react' import { useModalIsOpen, useOpenModal, useToggleModal } from 'state/application/hooks' import { ApplicationModal } from 'state/application/reducer' import { ExternalLink, ThemedText } from 'theme/components' -import { AdaptiveWebModalSheet, Flex, QRCodeDisplay, Text, useSporeColors } from 'ui/src' +import { AdaptiveWebModal, Flex, QRCodeDisplay, Text, useSporeColors } from 'ui/src' import { NetworkLogos } from 'uniswap/src/components/network/NetworkLogos' import { useUnitagByAddress } from 'uniswap/src/features/unitags/hooks' import { Trans } from 'uniswap/src/i18n' @@ -39,7 +39,7 @@ export function AddressQRModal({ accountAddress }: { accountAddress: Address }) }, [toggleModal, openReceiveCryptoModal]) return ( - + @@ -86,6 +86,6 @@ export function AddressQRModal({ accountAddress }: { accountAddress: Address }) - + ) } diff --git a/apps/web/src/components/Charts/ChartHeader.tsx b/apps/web/src/components/Charts/ChartHeader.tsx index 138877d5c65..3a0740b84bf 100644 --- a/apps/web/src/components/Charts/ChartHeader.tsx +++ b/apps/web/src/components/Charts/ChartHeader.tsx @@ -1,80 +1,43 @@ import { useHeaderDateFormatter } from 'components/Charts/hooks' -import Column from 'components/Column' -import Row from 'components/Row' import { getProtocolColor, getProtocolName } from 'graphql/data/util' -import styled, { useTheme } from 'lib/styled-components' +import { useTheme } from 'lib/styled-components' import { UTCTimestamp } from 'lightweight-charts' import { ReactElement, ReactNode } from 'react' -import { EllipsisStyle } from 'theme/components' +import { EllipsisTamaguiStyle } from 'theme/components' import { ThemedText } from 'theme/components/text' -import { textFadeIn } from 'theme/styles' +import { Flex, Text } from 'ui/src' import { PriceSource } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { NumberType, useFormatter } from 'utils/formatNumbers' export type ChartHeaderProtocolInfo = { protocol: PriceSource; value?: number } -const ChartHeaderWrapper = styled(Row)` - ${textFadeIn}; - position: absolute; - width: 100%; - gap: 8px; - align-items: flex-start; -` -const ChartHeaderLeftDisplay = styled.div` - position: absolute; - display: flex; - flex-direction: column; - gap: 4px; - padding-bottom: 14px; - text-align: left; - pointer-events: none; - width: 70%; - - * { - ${EllipsisStyle} - } -` -const ProtocolLegendWrapper = styled(Column)` - position: absolute; - right: 0px; - padding: 4px 12px; - gap: 12px; - text-align: left; - pointer-events: none; -` -const ProtocolBlip = styled.div<{ color: string }>` - background-color: ${({ color }) => color}; - border-radius: 4px; - width: 12px; - height: 12px; -` - -const ProtocolText = styled(ThemedText.Caption)` - width: 80px; - text-align: right; - ${EllipsisStyle} -` - function ProtocolLegend({ protocolData }: { protocolData?: ChartHeaderProtocolInfo[] }) { const { formatFiatPrice } = useFormatter() const theme = useTheme() return ( - + {protocolData ?.map(({ value, protocol }) => { const display = value ? formatFiatPrice({ price: value, type: NumberType.ChartFiatValue }) : getProtocolName(protocol) return ( - - {display} - - + + + {display} + + + ) }) .reverse()} - + ) } @@ -93,7 +56,9 @@ function HeaderValueDisplay({ value, valueFormatterType = NumberType.ChartFiatVa } return ( - {formatFiatPrice({ price: value, type: valueFormatterType })} + + {formatFiatPrice({ price: value, type: valueFormatterType })} + ) } @@ -124,15 +89,15 @@ export function ChartHeader({ additionalFields, }: ChartHeaderProps) { return ( - - + + - + {additionalFields} - - + + - + ) } diff --git a/apps/web/src/components/Charts/ChartModel.tsx b/apps/web/src/components/Charts/ChartModel.tsx index accb5407539..058e1488eb9 100644 --- a/apps/web/src/components/Charts/ChartModel.tsx +++ b/apps/web/src/components/Charts/ChartModel.tsx @@ -1,13 +1,12 @@ import { refitChartContentAtom } from 'components/Charts/TimeSelector' import { SeriesDataItemType } from 'components/Charts/types' import { formatTickMarks } from 'components/Charts/utils' -import Row from 'components/Row' import { MissingDataBars } from 'components/Table/icons' import { useScreenSize } from 'hooks/screenSize' import { useActiveLocale } from 'hooks/useActiveLocale' import { useOnClickOutside } from 'hooks/useOnClickOutside' import { useUpdateAtom } from 'jotai/utils' -import styled, { DefaultTheme, useTheme } from 'lib/styled-components' +import { DefaultTheme, useTheme } from 'lib/styled-components' import { BarPrice, CrosshairMode, @@ -21,8 +20,7 @@ import { } from 'lightweight-charts' import { ReactElement, useEffect, useMemo, useRef, useState } from 'react' import { ThemedText } from 'theme/components' -import { textFadeIn } from 'theme/styles' -import { Z_INDEX } from 'theme/zIndex' +import { Flex, TamaguiElement, assertWebElement, styled } from 'ui/src' import { Trans } from 'uniswap/src/i18n' import { useFormatter } from 'utils/formatNumbers' import { v4 as uuidv4 } from 'uuid' @@ -219,13 +217,6 @@ export abstract class ChartModel { const isBetween = (num: number, lower: number, upper: number) => num > lower && num < upper -const ChartDiv = styled.div<{ height?: number }>` - ${({ height }) => height && `height: ${height}px`}; - width: 100%; - position: relative; - ${textFadeIn}; -` - /** Returns a div injected with a lightweight-chart, corresponding to the given Model and params */ export function Chart, TDataType extends SeriesDataItemType>({ Model, @@ -245,7 +236,7 @@ export function Chart, TDataType e const setRefitChartContent = useUpdateAtom(refitChartContentAtom) // Lightweight-charts injects a canvas into the page through the div referenced below // It is stored in state to cause a re-render upon div mount, avoiding delay in chart creation - const [chartDivElement, setChartDivElement] = useState(null) + const [chartDivElement, setChartDivElement] = useState(null) const [crosshairData, setCrosshairData] = useState(undefined) const format = useFormatter() const theme = useTheme() @@ -262,6 +253,7 @@ export function Chart, TDataType e // Creates the chart as soon as the chart div ref is defined useEffect(() => { if (chartDivElement && chartModelRef.current === undefined) { + assertWebElement(chartDivElement) chartModelRef.current = new Model(chartDivElement, modelParams) // Providers the time period selector with a handle to refit the chart setRefitChartContent(() => () => chartModelRef.current?.fitContent()) @@ -287,7 +279,10 @@ export function Chart, TDataType e useOnClickOutside({ current: chartDivElement } as React.RefObject, () => setCrosshairData(undefined)) return ( - , TDataType e )} {params.stale && } - + ) } -const ChartTooltip = styled.div` - display: flex; - flex-direction: column; - align-items: center; - position: absolute; - left: 0%; - top: 0; - z-index: ${Z_INDEX.tooltip}; - background: ${({ theme }) => theme.surface5}; - backdrop-filter: ${({ theme }) => theme.blur.light}; - border-radius: 8px; - border: 1px solid ${({ theme }) => theme.surface3}; - padding: 8px; -` - -const StaleBannerWrapper = styled(ChartTooltip)` - border-radius: 16px; - left: unset; - top: unset; - right: 12px; - bottom: 40px; - padding: 12px; - background: ${({ theme }) => theme.surface4}; -` +const ChartTooltip = styled(Flex, { + alignItems: 'center', + position: 'absolute', + left: 0, + top: 0, + zIndex: '$tooltip', + backgroundColor: '$surface5', + backdropFilter: 'blur(8px)', + borderRadius: '$rounded8', + borderColor: '$surface3', + borderStyle: 'solid', + borderWidth: 1, + p: '$spacing8', +}) + +const StaleBannerWrapper = styled(ChartTooltip, { + borderRadius: '$rounded16', + left: 'unset', + top: 'unset', + right: '$spacing12', + bottom: '$spacing40', + p: '$spacing12', + backgroundColor: '$surface4', +}) function StaleBanner() { const theme = useTheme() // TODO(WEB-3739): Update Chart UI to grayscale when data is stale return ( - + - + ) } diff --git a/apps/web/src/components/Charts/PriceChart/index.tsx b/apps/web/src/components/Charts/PriceChart/index.tsx index 586270f94bf..deb9d6067c8 100644 --- a/apps/web/src/components/Charts/PriceChart/index.tsx +++ b/apps/web/src/components/Charts/PriceChart/index.tsx @@ -6,9 +6,7 @@ import { } from 'components/Charts/PriceChart/RoundedCandlestickSeries/rounded-candles-series' import { getCandlestickPriceBounds } from 'components/Charts/PriceChart/utils' import { PriceChartType } from 'components/Charts/utils' -import { RowBetween } from 'components/Row' import { DeltaArrow, DeltaText, calculateDelta } from 'components/Tokens/TokenDetails/Delta' -import styled from 'lib/styled-components' import { AreaData, AreaSeriesPartialOptions, @@ -22,8 +20,8 @@ import { UTCTimestamp, } from 'lightweight-charts' import { useMemo } from 'react' -import { ThemedText } from 'theme/components' import { opacify } from 'theme/utils' +import { Flex, Text, styled } from 'ui/src' import { Trans } from 'uniswap/src/i18n' import { NumberType, useFormatter } from 'utils/formatNumbers' @@ -194,14 +192,6 @@ export class PriceChartModel extends ChartModel { } } -const DeltaContainer = styled.div` - font-size: 16px; - line-height: 24px; - display: flex; - align-items: center; - gap: 4px; -` - interface PriceChartDeltaProps { startingPrice: PriceChartData endingPrice: PriceChartData @@ -213,10 +203,10 @@ export function PriceChartDelta({ startingPrice, endingPrice, noColor }: PriceCh const { formatDelta } = useFormatter() return ( - + {formatDelta(delta)} - + ) } @@ -227,33 +217,34 @@ interface PriceChartProps { stale: boolean } -const TooltipText = styled(ThemedText.LabelSmall)` - color: ${({ theme }) => theme.neutral1}; - line-height: 20px; -` +const CandlestickTooltipRow = styled(Flex, { + row: true, + justifyContent: 'space-between', + gap: '$sm', +}) function CandlestickTooltip({ data }: { data: PriceChartData }) { const { formatFiatPrice } = useFormatter() return ( <> - - + +
{formatFiatPrice({ price: data.open })}
-
- + +
{formatFiatPrice({ price: data.high })}
-
- + +
{formatFiatPrice({ price: data.low })}
-
- + +
{formatFiatPrice({ price: data.close })}
-
-
+ + ) } diff --git a/apps/web/src/components/Charts/TimeSelector.tsx b/apps/web/src/components/Charts/TimeSelector.tsx index 4563ec74b7e..be4a7b8e647 100644 --- a/apps/web/src/components/Charts/TimeSelector.tsx +++ b/apps/web/src/components/Charts/TimeSelector.tsx @@ -1,54 +1,57 @@ import { DISPLAYS, ORDERED_TIMES } from 'components/Tokens/TokenTable/TimeSelector' -import { MEDIUM_MEDIA_BREAKPOINT } from 'components/Tokens/constants' import { TimePeriod } from 'graphql/data/util' import { atom } from 'jotai' import { useAtomValue } from 'jotai/utils' -import styled from 'lib/styled-components' +import { Flex, Text, styled } from 'ui/src' export const refitChartContentAtom = atom<(() => void) | undefined>(undefined) const DEFAULT_TIME_SELECTOR_OPTIONS = ORDERED_TIMES.map((time: TimePeriod) => ({ time, display: DISPLAYS[time] })) -const TimeOptionsWrapper = styled.div` - display: flex; - width: 100%; - justify-content: flex-end; -` +const TimeOptionsContainer = styled(Flex, { + justifyContent: 'flex-end', + mt: '$spacing4', + gap: '$gap4', + borderRadius: '$rounded16', + height: 40, + p: '$spacing4', + width: 'fit-content', + overflow: 'visible', + $md: { + width: '100%', + justifyContent: 'space-between', + borderWidth: 0, + }, +}) -const TimeOptionsContainer = styled.div` - display: flex; - justify-content: flex-end; - margin-top: 4px; - gap: 4px; - border-radius: 16px; - height: 40px; - padding: 4px; - width: fit-content; - - @media only screen and (max-width: ${MEDIUM_MEDIA_BREAKPOINT}) { - width: 100%; - justify-content: space-between; - border: none; - } -` -const TimeButton = styled.button<{ active: boolean }>` - flex: 1; - display: flex; - align-items: center; - justify-content: center; - background-color: ${({ theme, active }) => (active ? theme.surface3 : 'transparent')}; - font-weight: 535; - font-size: 14px; - padding: 6px 12px; - border-radius: 12px; - line-height: 16px; - border: none; - cursor: pointer; - color: ${({ theme, active }) => (active ? theme.neutral1 : theme.neutral2)}; - transition-duration: ${({ theme }) => theme.transition.duration.fast}; - :hover { - ${({ active, theme }) => !active && `opacity: ${theme.opacity.hover};`} - } -` +const TimeButton = styled(Flex, { + flexGrow: 1, + flexShrink: 1, + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + height: 24, + width: 24, + borderRadius: '$roundedFull', + cursor: 'pointer', + animation: 'fast', + borderWidth: 0, + variants: { + active: { + true: { + backgroundColor: '$surface3', + hoverStyle: { + opacity: 1, + }, + }, + false: { + backgroundColor: 'transparent', + hoverStyle: { + opacity: 0.6, + }, + }, + }, + } as const, +}) interface TimePeriodSelectorOption { time: TimePeriod // Value to be selected/stored, used as default display value @@ -69,24 +72,29 @@ export default function TimePeriodSelector({ const refitChartContent = useAtomValue(refitChartContentAtom) return ( - - - {options.map(({ time, display }) => ( - { - if (timePeriod === time) { - refitChartContent?.() - } else { - onChangeTimePeriod(time) - } - }} + + {options.map(({ time, display }) => ( + { + if (timePeriod === time) { + refitChartContent?.() + } else { + onChangeTimePeriod(time) + } + }} + > + {display} - - ))} - - + + + ))} + ) } diff --git a/apps/web/src/components/Common/index.tsx b/apps/web/src/components/Common/index.tsx index 150327fb54c..8bdecf84445 100644 --- a/apps/web/src/components/Common/index.tsx +++ b/apps/web/src/components/Common/index.tsx @@ -29,13 +29,7 @@ export const ScrollBarStyles = css<{ $isHorizontalScroll?: boolean }>` border-radius: 8px; } ` -export const HideScrollBarStyles = css` - ::-webkit-scrollbar { - display: none; - } - -ms-overflow-style: none; - scrollbar-width: none; -` + export const OpacityHoverState = css` &:hover { opacity: ${({ theme }) => theme.opacity.hover}; diff --git a/apps/web/src/components/ConnectedAccountBlocked/index.tsx b/apps/web/src/components/ConnectedAccountBlocked/index.tsx index 2486250850e..ed3f12aebf3 100644 --- a/apps/web/src/components/ConnectedAccountBlocked/index.tsx +++ b/apps/web/src/components/ConnectedAccountBlocked/index.tsx @@ -1,7 +1,7 @@ import Column from 'components/Column' import Modal from 'components/Modal' -import { BlockedIcon } from 'components/TokenSafety/TokenSafetyIcon' import styled, { useTheme } from 'lib/styled-components' +import { Slash } from 'react-feather' import { CopyHelper, ExternalLink, ThemedText } from 'theme/components' import { Text } from 'ui/src' import { Trans } from 'uniswap/src/i18n' @@ -22,7 +22,7 @@ export default function ConnectedAccountBlocked(props: ConnectedAccountBlockedPr return ( - + diff --git a/apps/web/src/components/CurrencyInputPanel/LimitPriceInputPanel/LimitPriceInputPanel.test.tsx b/apps/web/src/components/CurrencyInputPanel/LimitPriceInputPanel/LimitPriceInputPanel.test.tsx index 4d94d6cadcc..16d49d81a2e 100644 --- a/apps/web/src/components/CurrencyInputPanel/LimitPriceInputPanel/LimitPriceInputPanel.test.tsx +++ b/apps/web/src/components/CurrencyInputPanel/LimitPriceInputPanel/LimitPriceInputPanel.test.tsx @@ -1,3 +1,5 @@ +import 'test-utils/tokens/mocks' + import { LimitPriceInputPanel } from 'components/CurrencyInputPanel/LimitPriceInputPanel/LimitPriceInputPanel' import { DAI, USDC_MAINNET } from 'constants/tokens' import { LimitContext } from 'state/limit/LimitContext' diff --git a/apps/web/src/components/DropdownSelector/FilterButton.tsx b/apps/web/src/components/DropdownSelector/FilterButton.tsx index 7ebe269ba03..6e9731ac75b 100644 --- a/apps/web/src/components/DropdownSelector/FilterButton.tsx +++ b/apps/web/src/components/DropdownSelector/FilterButton.tsx @@ -1,25 +1,40 @@ -import styled from 'lib/styled-components' -const FilterButton = styled.button<{ active: boolean; highlight?: boolean }>` - height: 100%; - color: ${({ theme }) => theme.neutral1}; - background-color: ${({ theme }) => theme.surface1}; - margin: 0; - padding: 2px 6px 2px 14px; - border-radius: 12px; - font-size: 16px; - line-height: 24px; - font-weight: 535; - transition-duration: ${({ theme }) => theme.transition.duration.fast}; - border: 1px solid ${({ theme }) => theme.surface3}; - outline: ${({ theme, active, highlight }) => (active && highlight ? `1px solid ${theme.accent1}` : 'none')}; +import { styled, Text } from 'ui/src' + +const FilterButton = styled(Text, { + display: 'flex', + flexDirection: 'row', + height: '100%', + color: '$neutral1', + backgroundColor: '$surface1', + m: 0, + p: '$spacing2', + pr: 6, + pl: 14, + borderRadius: '$rounded12', + fontSize: '$medium', + lineHeight: 24, + fontWeight: '$book', + borderWidth: 1, + borderStyle: 'solid', + borderColor: '$surface3', + whiteSpace: 'nowrap', + hoverStyle: { + cursor: 'pointer', + backgroundColor: '$surface2', + }, + focusStyle: { + backgroundColor: '$surface2', + }, + variants: { + active: { + true: { + backgroundColor: '$surface2', + focusStyle: { + backgroundColor: '$surface2', + }, + }, + }, + } as const, +}) - :hover { - cursor: pointer; - background-color: ${({ theme, active }) => (active ? theme.accent2 : theme.surface2)}; - opacity: ${({ theme, active }) => (active ? theme.opacity.hover : 1)}; - } - :focus { - background-color: ${({ theme, active }) => (active ? theme.surface2 : 'none')}; - } -` export default FilterButton diff --git a/apps/web/src/components/DropdownSelector/index.tsx b/apps/web/src/components/DropdownSelector/index.tsx index 15cb805a870..4b872c9ec22 100644 --- a/apps/web/src/components/DropdownSelector/index.tsx +++ b/apps/web/src/components/DropdownSelector/index.tsx @@ -1,116 +1,89 @@ -import Column from 'components/Column' import FilterButton from 'components/DropdownSelector/FilterButton' import { MouseoverTooltip, TooltipSize } from 'components/Tooltip' import { useOnClickOutside } from 'hooks/useOnClickOutside' -import styled, { css } from 'lib/styled-components' -import React, { useRef } from 'react' -import { dropdownSlideDown } from 'theme/styles' -import { Z_INDEX } from 'theme/zIndex' +import { useRef } from 'react' +import { NAV_HEIGHT } from 'theme' +import { + AnimatePresence, + Flex, + FlexProps, + Text, + WebBottomSheet, + styled, + useMedia, + useScrollbarStyles, + useShadowPropsMedium, +} from 'ui/src' import { RotatableChevron } from 'ui/src/components/icons/RotatableChevron' +import { zIndices } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme/iconSizes' -export const InternalMenuItem = styled.div<{ disabled?: boolean }>` - display: flex; - flex: 1; - padding: 12px 8px; - gap: 12px; - color: ${({ theme }) => theme.neutral1}; - align-items: center; - justify-content: space-between; - text-decoration: none; - cursor: pointer; - border-radius: 8px; +export const InternalMenuItem = styled(Text, { + display: 'flex', + flex: 1, + alignItems: 'center', + justifyContent: 'space-between', + px: '$spacing8', + py: '$spacing12', + gap: '$gap12', + color: '$neutral1', + textDecorationLine: 'none', + cursor: 'pointer', + borderRadius: '$rounded8', + hoverStyle: { + backgroundColor: '$surface3', + }, + variants: { + disabled: { + true: { + opacity: 0.6, + cursor: 'default', + }, + }, + } as const, +}) - :hover { - background-color: ${({ theme }) => theme.surface3}; - } +const MenuFlyout = styled(Text, { + display: 'flex', + flexDirection: 'column', + minWidth: 150, + backgroundColor: '$surface1', + borderWidth: 0.5, + borderStyle: 'solid', + borderColor: '$surface3', + borderRadius: '$rounded12', + p: '$spacing8', + fontSize: 16, + position: 'absolute', + top: 'calc(100% + 12px)', + zIndex: zIndices.dropdown, + animation: 'fastHeavy', + overflow: 'scroll', + enterStyle: { opacity: 0, y: -20 }, + exitStyle: { opacity: 0, y: -20 }, +}) - ${({ disabled }) => - disabled && - css` - opacity: 60%; - pointer-events: none; - `} -` -const MenuFlyout = styled(Column)<{ menuFlyoutCss?: string }>` - min-width: 150px; - overflow: auto; - background-color: ${({ theme }) => theme.surface1}; - box-shadow: ${({ theme }) => theme.deprecated_deepShadow}; - border: 0.5px solid ${({ theme }) => theme.surface3}; - border-radius: 12px; - padding: 8px; - font-size: 16px; - position: absolute; - top: 48px; - z-index: ${Z_INDEX.dropdown}; - ${dropdownSlideDown} - - scrollbar-width: thin; - scrollbar-color: ${({ theme }) => `${theme.surface3} transparent`}; - - // safari and chrome scrollbar styling - ::-webkit-scrollbar { - background: transparent; - width: 8px; - } - - ::-webkit-scrollbar-thumb { - background: ${({ theme }) => theme.surface3}; - border-radius: 8px; - } - - @media screen and (max-width: ${({ theme }) => theme.breakpoint.xs}px) { - position: fixed; - top: unset; - bottom: 0; - left: 0; - width: 100vw; - padding: 12px 16px; - background: ${({ theme }) => theme.surface2}; - border: ${({ theme }) => `1px solid ${theme.surface3}`}; - border-radius: 12px 12px 0 0; - z-index: ${Z_INDEX.modal}; - animation: none; - } - - ${({ menuFlyoutCss }) => menuFlyoutCss} -` -const StyledMenu = styled.div` - display: flex; - justify-content: center; - align-items: center; - position: relative; - border: none; - text-align: left; - width: 100%; -` -const StyledMenuContent = styled.div` - display: flex; - justify-content: space-between; - gap: 8px; - align-items: center; - border: none; - font-weight: 535; - width: 100%; - vertical-align: middle; - white-space: nowrap; -` -const StyledFilterButton = styled(FilterButton)<{ buttonCss?: string }>` - ${({ buttonCss }) => buttonCss} -` +const StyledMenu = styled(Text, { + justifyContent: 'center', + alignItems: 'center', + position: 'relative', + borderWidth: '$none', + textAlign: 'left', + width: '100%', +}) interface DropdownSelectorProps { isOpen: boolean - toggleOpen: React.DispatchWithoutAction + toggleOpen: (open: boolean) => void menuLabel: JSX.Element internalMenuItems: JSX.Element dataTestId?: string optionsContainerTestId?: string tooltipText?: string hideChevron?: boolean - buttonCss?: any - menuFlyoutCss?: any + buttonStyle?: FlexProps + dropdownStyle?: FlexProps + adaptToSheet?: boolean } export function DropdownSelector({ @@ -122,41 +95,71 @@ export function DropdownSelector({ optionsContainerTestId, tooltipText, hideChevron, - buttonCss, - menuFlyoutCss, + buttonStyle, + dropdownStyle, + adaptToSheet = true, }: DropdownSelectorProps) { const node = useRef(null) - useOnClickOutside(node, isOpen ? toggleOpen : undefined) + useOnClickOutside(node, () => isOpen && toggleOpen(false)) + const scrollbarStyles = useScrollbarStyles() + const shadowProps = useShadowPropsMedium() + const media = useMedia() + const isSheet = adaptToSheet && media.sm return ( - - - - - {menuLabel} - {!hideChevron && ( - + <> +
+ + + toggleOpen(!isOpen)} + active={isOpen} + aria-label={dataTestId} + data-testid={dataTestId} + {...buttonStyle} + > + + {menuLabel} + {!hideChevron && ( + + )} + + + + + {isOpen && !isSheet && ( + + {internalMenuItems} + )} - - - - {isOpen && ( - - {internalMenuItems} - - )} - + + +
+ toggleOpen(false)} + {...dropdownStyle} + maxHeight={`calc(100dvh - ${NAV_HEIGHT}px)`} + > + {internalMenuItems} + + ) } diff --git a/apps/web/src/components/FeatureFlagModal/FeatureFlagModal.tsx b/apps/web/src/components/FeatureFlagModal/FeatureFlagModal.tsx index b492b280713..23e2995ad23 100644 --- a/apps/web/src/components/FeatureFlagModal/FeatureFlagModal.tsx +++ b/apps/web/src/components/FeatureFlagModal/FeatureFlagModal.tsx @@ -219,9 +219,10 @@ export default function FeatureFlagModal() { label="Enable EIP-6963: Multi Injected Provider Discovery" /> - + + @@ -258,6 +259,7 @@ export default function FeatureFlagModal() { + window.location.reload()}>Reload diff --git a/apps/web/src/components/FiatOnrampModal/index.tsx b/apps/web/src/components/FiatOnrampModal/index.tsx index cecb8829ae2..6a273e2c81a 100644 --- a/apps/web/src/components/FiatOnrampModal/index.tsx +++ b/apps/web/src/components/FiatOnrampModal/index.tsx @@ -11,7 +11,7 @@ import { useCloseModal, useModalIsOpen } from 'state/application/hooks' import { ApplicationModal } from 'state/application/reducer' import { CustomLightSpinner, ThemedText } from 'theme/components' import { useIsDarkMode } from 'theme/components/ThemeToggle' -import { AdaptiveWebModalSheet } from 'ui/src' +import { AdaptiveWebModal } from 'ui/src' import { Trans } from 'uniswap/src/i18n' import { logger } from 'utilities/src/logger/logger' @@ -148,7 +148,7 @@ export default function FiatOnrampModal() { }, [fetchSignedIframeUrl]) return ( - closeModal()}> + closeModal()}> {error ? ( <> @@ -177,6 +177,6 @@ export default function FiatOnrampModal() { - + ) } diff --git a/apps/web/src/components/InputStepCounter/InputStepCounter.tsx b/apps/web/src/components/InputStepCounter/InputStepCounter.tsx index 18ba783edc3..f59441b1a01 100644 --- a/apps/web/src/components/InputStepCounter/InputStepCounter.tsx +++ b/apps/web/src/components/InputStepCounter/InputStepCounter.tsx @@ -1,4 +1,3 @@ -import { styled as tamaguiStyled } from '@tamagui/core' import { FeeAmount } from '@uniswap/v3-sdk' import { ButtonGray } from 'components/Button' import { OutlineCard } from 'components/Card' @@ -8,7 +7,7 @@ import styled, { keyframes } from 'lib/styled-components' import { ReactNode, useCallback, useEffect, useState } from 'react' import { Minus, Plus } from 'react-feather' import { ThemedText } from 'theme/components' -import { Text } from 'ui/src' +import { Text, styled as tamaguiStyled } from 'ui/src' import { Trans } from 'uniswap/src/i18n' const pulse = (color: string) => keyframes` diff --git a/apps/web/src/components/Menu/index.tsx b/apps/web/src/components/Menu/index.tsx deleted file mode 100644 index 7aeba089143..00000000000 --- a/apps/web/src/components/Menu/index.tsx +++ /dev/null @@ -1,134 +0,0 @@ -import { ReactComponent as MenuIcon } from 'assets/images/menu.svg' -import { useOnClickOutside } from 'hooks/useOnClickOutside' -import styled, { css } from 'lib/styled-components' -import { FunctionComponent, PropsWithChildren, useRef } from 'react' -import { Link } from 'react-router-dom' -import { useModalIsOpen, useToggleModal } from 'state/application/hooks' -import { ApplicationModal } from 'state/application/reducer' -import { ExternalLink } from 'theme/components' - -export enum FlyoutAlignment { - LEFT = 'LEFT', - RIGHT = 'RIGHT', -} - -const StyledMenuIcon = styled(MenuIcon)` - path { - stroke: ${({ theme }) => theme.neutral1}; - } -` - -const StyledMenu = styled.div` - display: flex; - justify-content: center; - align-items: center; - position: relative; - border: none; - text-align: left; -` - -const MenuFlyout = styled.span<{ flyoutAlignment?: FlyoutAlignment }>` - min-width: 196px; - max-height: 350px; - overflow: auto; - background-color: ${({ theme }) => theme.surface1}; - box-shadow: - 0px 0px 1px rgba(0, 0, 0, 0.01), - 0px 4px 8px rgba(0, 0, 0, 0.04), - 0px 16px 24px rgba(0, 0, 0, 0.04), - 0px 24px 32px rgba(0, 0, 0, 0.01); - border: 1px solid ${({ theme }) => theme.surface3}; - border-radius: 12px; - padding: 0.5rem; - display: flex; - flex-direction: column; - font-size: 16px; - position: absolute; - top: 3rem; - z-index: 100; - - ${({ flyoutAlignment = FlyoutAlignment.RIGHT }) => - flyoutAlignment === FlyoutAlignment.RIGHT - ? css` - right: 0rem; - ` - : css` - left: 0rem; - `}; -` - -const MenuItem = styled(ExternalLink)` - display: flex; - flex: 1; - flex-direction: row; - align-items: center; - padding: 0.5rem 0.5rem; - justify-content: space-between; - color: ${({ theme }) => theme.neutral2}; - :hover { - color: ${({ theme }) => theme.neutral1}; - cursor: pointer; - text-decoration: none; - } -` - -const InternalMenuItem = styled(Link)` - flex: 1; - padding: 0.5rem 0.5rem; - color: ${({ theme }) => theme.neutral2}; - width: max-content; - text-decoration: none; - :hover { - color: ${({ theme }) => theme.neutral1}; - cursor: pointer; - text-decoration: none; - } - > svg { - margin-right: 8px; - } -` - -interface MenuProps { - modal: ApplicationModal - flyoutAlignment?: FlyoutAlignment - ToggleUI?: FunctionComponent> - menuItems: { - content: any - link: string - external: boolean - }[] -} - -const ExternalMenuItem = styled(MenuItem)` - width: max-content; - text-decoration: none; -` - -export const Menu = ({ modal, flyoutAlignment = FlyoutAlignment.RIGHT, ToggleUI, menuItems, ...rest }: MenuProps) => { - const node = useRef() - const open = useModalIsOpen(modal) - const toggle = useToggleModal(modal) - useOnClickOutside(node, open ? toggle : undefined) - const ToggleElement = ToggleUI || StyledMenuIcon - - return ( - - - {open && ( - - {menuItems.map(({ content, link, external }, i) => - external ? ( - - {content} - - ) : ( - - {content} - - ), - )} - - )} - - ) -} diff --git a/apps/web/src/components/Modal/index.tsx b/apps/web/src/components/Modal/index.tsx index 589584f9231..4a0f9722a9a 100644 --- a/apps/web/src/components/Modal/index.tsx +++ b/apps/web/src/components/Modal/index.tsx @@ -5,7 +5,7 @@ import React, { KeyboardEvent, useCallback, useRef } from 'react' import { animated, easings, useSpring, useTransition } from 'react-spring' import { useGesture } from 'react-use-gesture' import { Z_INDEX } from 'theme/zIndex' -import { isMobile } from 'utilities/src/platform' +import { isMobileWeb } from 'utilities/src/platform' export const MODAL_TRANSITION_DURATION = 200 @@ -165,7 +165,7 @@ export default function Modal({ item && ( `translateY(${(y as number) > 0 ? y : 0}px)`) }, @@ -182,7 +182,7 @@ export default function Modal({ $maxWidth={maxWidth} > {/* prevents the automatic focusing of inputs on mobile by the reach dialog */} - {!initialFocusRef && isMobile ?
: null} + {!initialFocusRef && isMobileWeb ?
: null} {children} ), diff --git a/apps/web/src/components/NavBar/ChainSelector/index.tsx b/apps/web/src/components/NavBar/ChainSelector/index.tsx index 8571f0be54d..a8741706561 100644 --- a/apps/web/src/components/NavBar/ChainSelector/index.tsx +++ b/apps/web/src/components/NavBar/ChainSelector/index.tsx @@ -97,6 +97,8 @@ export const ChainSelector = ({ isNavSelector, hideArrow }: ChainSelectorProps) } searchParams.delete('inputCurrency') searchParams.delete('outputCurrency') + searchParams.delete('value') + searchParams.delete('field') targetChainId && searchParams.set('chain', CHAIN_IDS_TO_NAMES[targetChainId]) setSearchParams(searchParams) diff --git a/apps/web/src/components/NavBar/CompanyMenu/DownloadAppCTA.tsx b/apps/web/src/components/NavBar/CompanyMenu/DownloadAppCTA.tsx index ac46b5f56c9..a849d388ca0 100644 --- a/apps/web/src/components/NavBar/CompanyMenu/DownloadAppCTA.tsx +++ b/apps/web/src/components/NavBar/CompanyMenu/DownloadAppCTA.tsx @@ -1,4 +1,3 @@ -import { useIsTouchDevice } from '@tamagui/core' import { InterfaceElementName } from '@uniswap/analytics-events' import { MobileAppLogo } from 'components/Icons/MobileAppLogo' import { NAV_BREAKPOINT, useIsMobileDrawer } from 'components/NavBar/ScreenSizes' @@ -8,7 +7,7 @@ import { Text } from 'rebass' import { useOpenModal } from 'state/application/hooks' import { ApplicationModal } from 'state/application/reducer' import { ThemedText } from 'theme/components' -import { Flex } from 'ui/src' +import { Flex, useIsTouchDevice } from 'ui/src' import { Trans } from 'uniswap/src/i18n/Trans' import { isWebAndroid, isWebIOS } from 'utilities/src/platform' import { APP_DOWNLOAD_LINKS, openDownloadApp } from 'utils/openDownloadApp' diff --git a/apps/web/src/components/NavBar/CompanyMenu/index.tsx b/apps/web/src/components/NavBar/CompanyMenu/index.tsx index 2829749077f..4b5e1ec5829 100644 --- a/apps/web/src/components/NavBar/CompanyMenu/index.tsx +++ b/apps/web/src/components/NavBar/CompanyMenu/index.tsx @@ -8,7 +8,7 @@ import styled from 'lib/styled-components' import { useCallback, useEffect, useRef, useState } from 'react' import { useLocation, useNavigate } from 'react-router-dom' import { Popover, Text, useIsTouchDevice } from 'ui/src' -import { Hamburger } from 'ui/src/components/icons' +import { Hamburger } from 'ui/src/components/icons/Hamburger' const ArrowDown = styled(ArrowChangeDown)<{ $isActive: boolean }>` height: 100%; diff --git a/apps/web/src/components/NavBar/MobileBottomBar/MobileBottomBar.tsx b/apps/web/src/components/NavBar/MobileBottomBar/MobileBottomBar.tsx index 06682f0c602..f4a01ea23b8 100644 --- a/apps/web/src/components/NavBar/MobileBottomBar/MobileBottomBar.tsx +++ b/apps/web/src/components/NavBar/MobileBottomBar/MobileBottomBar.tsx @@ -1,26 +1,35 @@ -import { NAV_BREAKPOINT } from 'components/NavBar/ScreenSizes' -import styled from 'lib/styled-components' import { Z_INDEX } from 'theme/zIndex' +import { Flex, styled } from 'ui/src' const MOBILE_BAR_MAX_HEIGHT = 100 // ensure that it's translated out of view on scroll -export const MobileBottomBar = styled.div<{ $hide: boolean }>` - z-index: ${Z_INDEX.dropdown}; - position: fixed; - display: flex; - bottom: 0; - right: 0; - left: 0; - justify-content: space-between; - gap: 8px; - width: 100%; - max-height: ${MOBILE_BAR_MAX_HEIGHT}px; - backdrop-filter: blur(4px); - mask: linear-gradient(to bottom, transparent, ${({ theme }) => theme.surface1} 15%); - padding: 12px 16px; - transition: bottom ${({ theme }) => theme.transition.duration.slow}; - ${({ $hide }) => $hide && `bottom: -${MOBILE_BAR_MAX_HEIGHT}px !important`}; - @media screen and (min-width: ${NAV_BREAKPOINT.showMobileBar}px) { - display: none; - } -` +export const MobileBottomBar = styled(Flex, { + zIndex: Z_INDEX.dropdown, + position: 'fixed' as any, + bottom: 0, + right: 0, + left: 0, + justifyContent: 'space-between', + gap: '$gap8', + width: '100%', + maxHeight: MOBILE_BAR_MAX_HEIGHT, + backdropFilter: 'blur(4px)', + mask: 'linear-gradient(to bottom, transparent, $surface1 15%)', + py: '$padding12', + px: '$padding16', + animation: 'lazy', + display: 'none', + $xl: { + display: 'block', + }, + variants: { + hide: { + true: { + bottom: `-${MOBILE_BAR_MAX_HEIGHT}px !important`, + }, + false: { + bottom: 0, + }, + }, + } as const, +}) diff --git a/apps/web/src/components/NavBar/MobileBottomBar/TDPActionTabs.tsx b/apps/web/src/components/NavBar/MobileBottomBar/TDPActionTabs.tsx index 0b2ad66deac..ef906a8c875 100644 --- a/apps/web/src/components/NavBar/MobileBottomBar/TDPActionTabs.tsx +++ b/apps/web/src/components/NavBar/MobileBottomBar/TDPActionTabs.tsx @@ -79,7 +79,7 @@ export function TDPActionTabs() { }, ] return ( - + {tabs.map((tab) => ( toActionLink(tab.href)} $color={tokenColor}> {tab.icon} diff --git a/apps/web/src/components/NavBar/NavDropdown/NavDropdown.tsx b/apps/web/src/components/NavBar/NavDropdown/NavDropdown.tsx index 4a847185032..144814e0ad2 100644 --- a/apps/web/src/components/NavBar/NavDropdown/NavDropdown.tsx +++ b/apps/web/src/components/NavBar/NavDropdown/NavDropdown.tsx @@ -1,32 +1,21 @@ -import { ScrollBarStyles } from 'components/Common' -import { NAV_BREAKPOINT, useIsMobileDrawer } from 'components/NavBar/ScreenSizes' -import styled from 'lib/styled-components' import { ReactNode, RefObject } from 'react' -import { Flex, Popover, RemoveScroll } from 'ui/src' +import { NAV_HEIGHT } from 'theme' +import { Flex, Popover, WebBottomSheet, styled, useScrollbarStyles, useShadowPropsMedium } from 'ui/src' -const NavDropdownContent = styled.div<{ $width?: number }>` - border-radius: 16px; - border: 1px solid ${({ theme }) => theme.surface3}; - background: ${({ theme }) => theme.surface1}; - ${({ theme }) => !theme.darkMode && `box-shadow: 3px 3px 10px ${theme.surface3}`}; - ${({ $width }) => $width && `width: ${$width}px;`} - max-height: calc(100dvh - ${({ theme }) => theme.navHeight}px); - overflow: auto; - ${ScrollBarStyles} - - @media screen and (max-width: ${NAV_BREAKPOINT.isMobileDrawer}px) { - width: 100%; - border-radius: 0; - border: none; - box-shadow: none; - overflowx: auto; - max-height: calc(100dvh - ${({ theme }) => theme.navHeight + 12}px); - ${ScrollBarStyles} - ::-webkit-scrollbar-track { - margin-top: 40px; - } - } -` +const NavDropdownContent = styled(Flex, { + borderRadius: '$rounded16', + borderWidth: 1, + borderStyle: 'solid', + borderColor: '$surface2', + backgroundColor: '$surface1', + maxHeight: `calc(100dvh - ${NAV_HEIGHT}px)`, + $sm: { + width: '100%', + borderRadius: '$none', + borderWidth: 0, + shadowColor: '$transparent', + }, +}) interface NavDropdownProps { children: ReactNode @@ -37,7 +26,8 @@ interface NavDropdownProps { } export function NavDropdown({ children, width, dropdownRef, isOpen, dataTestId }: NavDropdownProps) { - const isMobileDrawer = useIsMobileDrawer() + const shadowProps = useShadowPropsMedium() + const scrollbarStyles = useScrollbarStyles() return ( <> @@ -48,7 +38,7 @@ export function NavDropdown({ children, width, dropdownRef, isOpen, dataTestId } width={width} elevate animation={[ - 'quicker', + 'fast', { opacity: { overshootClamping: true, @@ -58,31 +48,22 @@ export function NavDropdown({ children, width, dropdownRef, isOpen, dataTestId } data-testid={dataTestId} > - + {children} - - - - - - - - - - - - - + + + + + ) diff --git a/apps/web/src/components/NavBar/PreferencesMenu/index.tsx b/apps/web/src/components/NavBar/PreferencesMenu/index.tsx index 1fdcc421b88..a19f8c70195 100644 --- a/apps/web/src/components/NavBar/PreferencesMenu/index.tsx +++ b/apps/web/src/components/NavBar/PreferencesMenu/index.tsx @@ -6,7 +6,7 @@ import { PreferenceSettings } from 'components/NavBar/PreferencesMenu/Preference import { PreferencesView } from 'components/NavBar/PreferencesMenu/shared' import { useCallback, useState } from 'react' import { AnimateTransition, Popover } from 'ui/src' -import { Global } from 'ui/src/components/icons' +import { Global } from 'ui/src/components/icons/Global' export function getSettingsViewIndex(view: PreferencesView) { if (view === PreferencesView.SETTINGS) { diff --git a/apps/web/src/components/NavBar/SearchBar/RecentlySearchedAssets.ts b/apps/web/src/components/NavBar/SearchBar/RecentlySearchedAssets.ts index 8a924564885..7a73bd8bfbe 100644 --- a/apps/web/src/components/NavBar/SearchBar/RecentlySearchedAssets.ts +++ b/apps/web/src/components/NavBar/SearchBar/RecentlySearchedAssets.ts @@ -27,7 +27,7 @@ function getNativeQueryAddress(chain: Chain) { return `NATIVE-${chain}` } -export const recentlySearchedAssetsAtom = atomWithStorage('recentlySearchedAssetsV2', []) +export const recentlySearchedAssetsAtom = atomWithStorage('recentlySearchedAssetsV3', []) // Used by TokenSelector export function useAddRecentlySearchedCurrency() { diff --git a/apps/web/src/components/NavBar/SearchBar/SearchBarDropdown.tsx b/apps/web/src/components/NavBar/SearchBar/SearchBarDropdown.tsx index d06b1162adc..4fda1e9e2df 100644 --- a/apps/web/src/components/NavBar/SearchBar/SearchBarDropdown.tsx +++ b/apps/web/src/components/NavBar/SearchBar/SearchBarDropdown.tsx @@ -1,6 +1,7 @@ import { InterfaceSectionName, NavBarSearchTypes } from '@uniswap/analytics-events' import Badge from 'components/Badge' import Column from 'components/Column' +import { ScrollBarStyles } from 'components/Common' import { ChainLogo } from 'components/Logo/ChainLogo' import { useRecentlySearchedAssets } from 'components/NavBar/SearchBar/RecentlySearchedAssets' import { SkeletonRow, SuggestionRow } from 'components/NavBar/SearchBar/SuggestionRow' @@ -21,18 +22,20 @@ import { Clock, TrendingUp } from 'react-feather' import { useLocation } from 'react-router-dom' import { ThemedText } from 'theme/components' import { Flex } from 'ui/src' +import { UNIVERSE_CHAIN_INFO } from 'uniswap/src/constants/chains' import { HistoryDuration, SafetyLevel } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { InterfaceSearchResultSelectionProperties } from 'uniswap/src/features/telemetry/types' import { Trans } from 'uniswap/src/i18n' -import { InterfaceChainId, UniverseChainId } from 'uniswap/src/types/chains' +import { InterfaceChainId } from 'uniswap/src/types/chains' import { useTrace } from 'utilities/src/telemetry/trace/TraceContext' const SearchBarDropdownContainer = styled(Column)<{ $loading: boolean }>` width: 100%; backdrop-filter: blur(60px); - overflow-y: scroll; + overflow-y: auto; transition: 125; opacity: ${({ $loading }) => ($loading ? '0.3' : '1')}; + ${ScrollBarStyles} ` const DropdownHeader = styled(Row)` color: ${({ theme }) => theme.neutral2}; @@ -358,10 +361,8 @@ function SearchBarDropdownContents({ } function ComingSoonText({ chainId }: { chainId: InterfaceChainId }) { - switch (chainId) { - case UniverseChainId.Avalanche: - return - default: - return null - } + const chainName = UNIVERSE_CHAIN_INFO[chainId]?.name + return BACKEND_NOT_YET_SUPPORTED_CHAIN_IDS.includes(chainId) ? ( + + ) : null } diff --git a/apps/web/src/components/NavBar/SearchBar/SuggestionRow.tsx b/apps/web/src/components/NavBar/SearchBar/SuggestionRow.tsx index cd170d4e8ad..be2cf4d89d4 100644 --- a/apps/web/src/components/NavBar/SearchBar/SuggestionRow.tsx +++ b/apps/web/src/components/NavBar/SearchBar/SuggestionRow.tsx @@ -16,7 +16,7 @@ import { useCallback, useEffect, useState } from 'react' import { Link, useNavigate } from 'react-router-dom' import { EllipsisStyle, ThemedText } from 'theme/components' import { Flex } from 'ui/src' -import { Verified } from 'ui/src/components/icons' +import { Verified } from 'ui/src/components/icons/Verified' import { TokenStandard } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { InterfaceSearchResultSelectionProperties } from 'uniswap/src/features/telemetry/types' @@ -120,7 +120,7 @@ export function SuggestionRow({ ...suggestion, address, chainId: supportedChainIdFromGQLChain(suggestion.chain) as UniverseChainId, - isNative: suggestion.address === NATIVE_CHAIN_ID, + isNative: address === NATIVE_CHAIN_ID, isToken: suggestion.standard === TokenStandard.Erc20, }) : searchGenieCollectionToTokenSearchResult(suggestion as GenieCollection) diff --git a/apps/web/src/components/NavBar/SearchBar/__snapshots__/SearchBarDropdown.test.tsx.snap b/apps/web/src/components/NavBar/SearchBar/__snapshots__/SearchBarDropdown.test.tsx.snap index 6856b9d4887..da67ed55370 100644 --- a/apps/web/src/components/NavBar/SearchBar/__snapshots__/SearchBarDropdown.test.tsx.snap +++ b/apps/web/src/components/NavBar/SearchBar/__snapshots__/SearchBarDropdown.test.tsx.snap @@ -159,10 +159,30 @@ exports[`disable nft on searchbar dropdown should not render popular nft collect width: 100%; -webkit-backdrop-filter: blur(60px); backdrop-filter: blur(60px); - overflow-y: scroll; + overflow-y: auto; -webkit-transition: 125; transition: 125; opacity: 1; + -webkit-scrollbar-width: thin; + -moz-scrollbar-width: thin; + -ms-scrollbar-width: thin; + scrollbar-width: thin; + -webkit-scrollbar-color: #22222212 transparent; + -moz-scrollbar-color: #22222212 transparent; + -ms-scrollbar-color: #22222212 transparent; + scrollbar-color: #22222212 transparent; + height: 100%; +} + +.c1::-webkit-scrollbar { + background: transparent; + width: 4px; + overflow-y: scroll; +} + +.c1::-webkit-scrollbar-thumb { + background: #22222212; + border-radius: 8px; } .c4 { @@ -518,10 +538,30 @@ exports[`disable nft on searchbar dropdown should render popular nft collections width: 100%; -webkit-backdrop-filter: blur(60px); backdrop-filter: blur(60px); - overflow-y: scroll; + overflow-y: auto; -webkit-transition: 125; transition: 125; opacity: 1; + -webkit-scrollbar-width: thin; + -moz-scrollbar-width: thin; + -ms-scrollbar-width: thin; + scrollbar-width: thin; + -webkit-scrollbar-color: #22222212 transparent; + -moz-scrollbar-color: #22222212 transparent; + -ms-scrollbar-color: #22222212 transparent; + scrollbar-color: #22222212 transparent; + height: 100%; +} + +.c1::-webkit-scrollbar { + background: transparent; + width: 4px; + overflow-y: scroll; +} + +.c1::-webkit-scrollbar-thumb { + background: #22222212; + border-radius: 8px; } .c4 { diff --git a/apps/web/src/components/NavBar/SearchBar/index.tsx b/apps/web/src/components/NavBar/SearchBar/index.tsx index 245e344717f..c4a986119dc 100644 --- a/apps/web/src/components/NavBar/SearchBar/index.tsx +++ b/apps/web/src/components/NavBar/SearchBar/index.tsx @@ -1,5 +1,5 @@ -// eslint-disable-next-line no-restricted-imports import { InterfaceElementName, InterfaceEventName, InterfaceSectionName } from '@uniswap/analytics-events' +import { ScrollBarStyles } from 'components/Common' import { NavIcon } from 'components/NavBar/NavIcon' import { NAV_BREAKPOINT } from 'components/NavBar/ScreenSizes' import { SearchBarDropdown } from 'components/NavBar/SearchBar/SearchBarDropdown' @@ -139,12 +139,13 @@ const SearchBarDropdownContainer = styled.div<{ $isOpen: boolean; $fullScreen: b border: 1px solid ${({ theme }) => theme.surface3}; border-radius: 20px; max-height: 100%; - overflow-y: scroll; + overflow-y: auto; ${({ $isOpen }) => $isOpen && OpenSearchDropdown} ${({ $fullScreen }) => $fullScreen && FullScreenSearchDropdown} @media screen and (max-width: ${NAV_BREAKPOINT.isMobileDrawer}px) { border: none; } + ${ScrollBarStyles} ` const CloseIcon = styled(X)` width: 25px; diff --git a/apps/web/src/components/NavBar/index.tsx b/apps/web/src/components/NavBar/index.tsx index 7c5239eafd9..58b89317788 100644 --- a/apps/web/src/components/NavBar/index.tsx +++ b/apps/web/src/components/NavBar/index.tsx @@ -18,7 +18,7 @@ import { useIsSwapPage } from 'hooks/useIsSwapPage' import styled, { css } from 'lib/styled-components' import { useProfilePageState } from 'nft/hooks' import { ProfilePageStateType } from 'nft/types' -import { BREAKPOINTS } from 'theme' +import { BREAKPOINTS, NAV_HEIGHT } from 'theme' import { Z_INDEX } from 'theme/zIndex' import { FeatureFlags } from 'uniswap/src/features/gating/flags' import { useFeatureFlagWithLoading } from 'uniswap/src/features/gating/hooks' @@ -26,7 +26,7 @@ import { useFeatureFlagWithLoading } from 'uniswap/src/features/gating/hooks' const Nav = styled.nav` padding: 0px 12px; width: 100%; - height: ${({ theme }) => theme.navHeight}px; + height: ${NAV_HEIGHT}px; z-index: ${Z_INDEX.sticky}; display: flex; align-items: center; diff --git a/apps/web/src/components/Pools/PoolDetails/ChartSection/index.tsx b/apps/web/src/components/Pools/PoolDetails/ChartSection/index.tsx index 501c9af6d93..c8bf28f018c 100644 --- a/apps/web/src/components/Pools/PoolDetails/ChartSection/index.tsx +++ b/apps/web/src/components/Pools/PoolDetails/ChartSection/index.tsx @@ -48,10 +48,6 @@ const ChartTypeSelectorContainer = styled.div` } ` -const StyledChart: typeof Chart = styled(Chart)` - height: ${PDP_CHART_HEIGHT_PX}px; -` - const PDPChartTypeSelector = ({ chartType, onChartTypeChange, @@ -275,7 +271,7 @@ function PriceChart({ const lastPrice = data[data.length - 1] return ( - + {(crosshairData) => { const displayValue = crosshairData ?? lastPrice const currencyBAmountRaw = Math.floor( @@ -303,7 +299,7 @@ function PriceChart({ /> ) }} - + ) } @@ -399,7 +395,8 @@ function LiquidityChart({ } return ( - }} - + ) } diff --git a/apps/web/src/components/Pools/PoolDetails/PoolDetailsHeader.test.tsx b/apps/web/src/components/Pools/PoolDetails/PoolDetailsHeader.test.tsx index ec2df9060ed..9f0cc3e19f3 100644 --- a/apps/web/src/components/Pools/PoolDetails/PoolDetailsHeader.test.tsx +++ b/apps/web/src/components/Pools/PoolDetails/PoolDetailsHeader.test.tsx @@ -1,3 +1,5 @@ +import 'test-utils/tokens/mocks' + import userEvent from '@testing-library/user-event' import { ChartType, PriceChartType } from 'components/Charts/utils' import { PoolsDetailsChartType } from 'components/Pools/PoolDetails/ChartSection' diff --git a/apps/web/src/components/Pools/PoolDetails/PoolDetailsHeader.tsx b/apps/web/src/components/Pools/PoolDetails/PoolDetailsHeader.tsx index fefa6b35700..824780c6e5b 100644 --- a/apps/web/src/components/Pools/PoolDetails/PoolDetailsHeader.tsx +++ b/apps/web/src/components/Pools/PoolDetails/PoolDetailsHeader.tsx @@ -10,7 +10,6 @@ import CurrencyLogo from 'components/Logo/CurrencyLogo' import { DetailBubble } from 'components/Pools/PoolDetails/shared' import Row from 'components/Row' import ShareButton from 'components/Tokens/TokenDetails/ShareButton' -import { StyledExternalLink } from 'components/Tokens/TokenDetails/TokenDetailsHeader' import { ActionButtonStyle, ActionMenuFlyoutStyle } from 'components/Tokens/TokenDetails/shared' import { LoadingBubble } from 'components/Tokens/loading' import { SupportedInterfaceChainId, chainIdToBackendChain } from 'constants/chains' @@ -18,12 +17,11 @@ import { BIPS_BASE } from 'constants/misc' import { NATIVE_CHAIN_ID } from 'constants/tokens' import { getTokenDetailsURL, gqlToCurrency } from 'graphql/data/util' import { useScreenSize } from 'hooks/screenSize' -import { useOnClickOutside } from 'hooks/useOnClickOutside' -import styled, { css, useTheme } from 'lib/styled-components' -import React, { useMemo, useReducer, useRef } from 'react' +import styled, { useTheme } from 'lib/styled-components' +import React, { useMemo, useState } from 'react' import { ChevronRight, ExternalLink as ExternalLinkIcon } from 'react-feather' import { Link } from 'react-router-dom' -import { ClickableStyle, EllipsisStyle, ThemedText } from 'theme/components' +import { ClickableStyle, EllipsisStyle, ExternalLink, ThemedText } from 'theme/components' import { textFadeIn } from 'theme/styles' import { ProtocolVersion, Token } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { Trans, t } from 'uniswap/src/i18n' @@ -32,6 +30,13 @@ import { shortenAddress } from 'utilities/src/addresses' import { useFormatter } from 'utils/formatNumbers' import { ExplorerDataType, getExplorerLink } from 'utils/getExplorerLink' +const StyledExternalLink = styled(ExternalLink)` + &:hover { + // Override hover behavior from ExternalLink + opacity: 1; + } +` + const HeaderContainer = styled.div` display: flex; justify-content: space-between; @@ -159,6 +164,7 @@ const ContractsDropdownRowContainer = styled(Row)` gap: 12px; padding: 10px 8px; border-radius: 8px; + ${EllipsisStyle} &:hover { background: ${({ theme }) => theme.surface3}; } @@ -215,12 +221,11 @@ const ContractsDropdownRow = ({ ) } -const ContractsModalContainer = css` - ${ActionMenuFlyoutStyle} - min-width: 235px; - border-radius: 16px; - ${EllipsisStyle} -` +const ContractsModalContainer = { + ...ActionMenuFlyoutStyle, + minWidth: 235, + borderRadius: '$rounded16', +} const PoolDetailsHeaderActions = ({ chainId, @@ -236,37 +241,33 @@ const PoolDetailsHeaderActions = ({ token1?: Token }) => { const theme = useTheme() - - const [contractsModalIsOpen, toggleContractsModal] = useReducer((s) => !s, false) - const contractsRef = useRef(null) - useOnClickOutside(contractsRef, contractsModalIsOpen ? toggleContractsModal : undefined) + const [contractsModalIsOpen, toggleContractsModal] = useState(false) return ( -
- - ) : ( - - ) - } - internalMenuItems={ - <> - - - - - } - tooltipText={t('pool.explorers')} - hideChevron - buttonCss={ActionButtonStyle} - menuFlyoutCss={ContractsModalContainer} - /> -
+ + ) : ( + + ) + } + internalMenuItems={ + <> + + + + + } + tooltipText={t('pool.explorers')} + hideChevron + buttonStyle={ActionButtonStyle} + dropdownStyle={ContractsModalContainer} + adaptToSheet={false} + />
) diff --git a/apps/web/src/components/Pools/PoolDetails/PoolDetailsStats.test.tsx b/apps/web/src/components/Pools/PoolDetails/PoolDetailsStats.test.tsx index 5ecda2b1425..3fad1107592 100644 --- a/apps/web/src/components/Pools/PoolDetails/PoolDetailsStats.test.tsx +++ b/apps/web/src/components/Pools/PoolDetails/PoolDetailsStats.test.tsx @@ -1,10 +1,11 @@ +import 'test-utils/tokens/mocks' + import { PoolDetailsStats } from 'components/Pools/PoolDetails/PoolDetailsStats' import { enableNetConnect } from 'nock' import store from 'state' import { addSerializedToken } from 'state/user/reducer' import { validPoolDataResponse } from 'test-utils/pools/fixtures' import { act, render, screen } from 'test-utils/render' -import 'test-utils/tokens/mocks' import { BREAKPOINTS } from 'theme' describe('PoolDetailsStats', () => { diff --git a/apps/web/src/components/Pools/PoolDetails/PoolDetailsStatsButtons.test.tsx b/apps/web/src/components/Pools/PoolDetails/PoolDetailsStatsButtons.test.tsx index 221154e3c81..fc280c11e13 100644 --- a/apps/web/src/components/Pools/PoolDetails/PoolDetailsStatsButtons.test.tsx +++ b/apps/web/src/components/Pools/PoolDetails/PoolDetailsStatsButtons.test.tsx @@ -10,7 +10,6 @@ import { USE_DISCONNECTED_ACCOUNT } from 'test-utils/constants' import { mocked } from 'test-utils/mocked' import { useMultiChainPositionsReturnValue, validBEPoolToken0, validBEPoolToken1 } from 'test-utils/pools/fixtures' import { act, render, screen } from 'test-utils/render' -import 'test-utils/tokens/mocks' import { UniverseChainId } from 'uniswap/src/types/chains' jest.mock('components/AccountDrawer/MiniPortfolio/Pools/useMultiChainPositions') @@ -66,6 +65,7 @@ describe('PoolDetailsStatsButton', () => { }) it('renders both buttons correctly', () => { + window.history.pushState({}, '', '/swap') const { asFragment } = render() expect(asFragment()).toMatchSnapshot() diff --git a/apps/web/src/components/Pools/PoolDetails/PoolDetailsTransactionsTable.tsx b/apps/web/src/components/Pools/PoolDetails/PoolDetailsTransactionsTable.tsx index 31de388c257..4a0b6cece91 100644 --- a/apps/web/src/components/Pools/PoolDetails/PoolDetailsTransactionsTable.tsx +++ b/apps/web/src/components/Pools/PoolDetails/PoolDetailsTransactionsTable.tsx @@ -14,7 +14,7 @@ import { import { OrderDirection, getSupportedGraphQlChain, supportedChainIdFromGQLChain } from 'graphql/data/util' import { useActiveLocalCurrency } from 'hooks/useActiveLocalCurrency' import styled from 'lib/styled-components' -import { useMemo, useReducer, useState } from 'react' +import { useMemo, useReducer, useRef, useState } from 'react' import { ExternalLink, ThemedText } from 'theme/components' import { ProtocolVersion, Token } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { Trans } from 'uniswap/src/i18n' @@ -72,6 +72,7 @@ export function PoolDetailsTransactionsTable({ const activeLocalCurrency = useActiveLocalCurrency() const { formatNumber, formatFiatPrice } = useFormatter() const [filterModalIsOpen, toggleFilterModal] = useReducer((s) => !s, false) + const filterAnchorRef = useRef(null) const [filter, setFilters] = useState([ PoolTableTransactionType.BUY, PoolTableTransactionType.SELL, @@ -97,7 +98,7 @@ export function PoolDetailsTransactionsTable({ - + @@ -150,13 +151,14 @@ export function PoolDetailsTransactionsTable({ id: 'swap-type', header: () => ( - toggleFilterModal()}> + toggleFilterModal()} ref={filterAnchorRef}> diff --git a/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsHeader.test.tsx.snap b/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsHeader.test.tsx.snap index 1a119efa0bf..01346ecfcff 100644 --- a/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsHeader.test.tsx.snap +++ b/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsHeader.test.tsx.snap @@ -331,7 +331,7 @@ exports[`PoolDetailsHeader renders header text correctly 1`] = ` gap: 8px; } -.c16 { +.c15 { display: inline-block; height: inherit; } @@ -391,115 +391,6 @@ exports[`PoolDetailsHeader renders header text correctly 1`] = ` left: 0; } -.c17 { - height: 100%; - color: #222222; - background-color: #FFFFFF; - margin: 0; - padding: 2px 6px 2px 14px; - border-radius: 12px; - font-size: 16px; - line-height: 24px; - font-weight: 535; - -webkit-transition-duration: 125ms; - transition-duration: 125ms; - border: 1px solid #22222212; - outline: none; -} - -.c17:hover { - cursor: pointer; - background-color: #F9F9F9; - opacity: 1; -} - -.c17:focus { - background-color: none; -} - -.c15 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - position: relative; - border: none; - text-align: left; - width: 100%; -} - -.c19 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between; - gap: 8px; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - border: none; - font-weight: 535; - width: 100%; - vertical-align: middle; - white-space: nowrap; -} - -.c18 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - padding: 8px 12px; - border-radius: 20px; - border: none; - background-color: #F9F9F9; - width: -webkit-max-content; - width: -moz-max-content; - width: max-content; - -webkit-text-decoration: none; - text-decoration: none; - cursor: pointer; - -webkit-transition-duration: 125ms; - transition-duration: 125ms; -} - -.c18:hover { - opacity: 0.6; -} - -.c18:active { - opacity: 0.4; -} - -.c18:hover { - background-color: #2222221f; -} - -.c18:focus { - background-color: #2222221f; -} - .c0 { display: -webkit-box; display: -webkit-flex; @@ -673,21 +564,25 @@ exports[`PoolDetailsHeader renders header text correctly 1`] = ` width="max-content" >
- -
+
-
-
+
+
- +
-
+
+
diff --git a/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsStatsButtons.test.tsx.snap b/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsStatsButtons.test.tsx.snap index 58e7bb29c59..ca43e2ff25d 100644 --- a/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsStatsButtons.test.tsx.snap +++ b/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsStatsButtons.test.tsx.snap @@ -1158,13 +1158,13 @@ exports[`PoolDetailsStatsButton renders both buttons correctly 1`] = `
- +

diff --git a/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsTransactionTable.test.tsx.snap b/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsTransactionTable.test.tsx.snap index 261641b42d7..291b5c39105 100644 --- a/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsTransactionTable.test.tsx.snap +++ b/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsTransactionTable.test.tsx.snap @@ -2,30 +2,13 @@ exports[`PoolDetailsTransactionsTable renders data filled state 1`] = ` - .c4 { + .c1 { box-sizing: border-box; margin: 0; min-width: 0; } -.c5 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c10 { +.c2 { width: 100%; display: -webkit-box; display: -webkit-flex; @@ -43,37 +26,7 @@ exports[`PoolDetailsTransactionsTable renders data filled state 1`] = ` gap: 4px; } -.c33 { - height: 16px; - width: 16px; -} - -.c33 path { - stroke: #FC72FF; - background: #7D7D7D; - fill: none; -} - -.c34 { - -webkit-animation: 2s fvtopB linear infinite; - animation: 2s fvtopB linear infinite; -} - -.c1 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c12 { +.c5 { color: #7D7D7D; -webkit-letter-spacing: -0.01em; -moz-letter-spacing: -0.01em; @@ -81,7 +34,7 @@ exports[`PoolDetailsTransactionsTable renders data filled state 1`] = ` letter-spacing: -0.01em; } -.c28 { +.c11 { color: #40B66B; -webkit-letter-spacing: -0.01em; -moz-letter-spacing: -0.01em; @@ -89,7 +42,7 @@ exports[`PoolDetailsTransactionsTable renders data filled state 1`] = ` letter-spacing: -0.01em; } -.c29 { +.c12 { color: #222222; -webkit-letter-spacing: -0.01em; -moz-letter-spacing: -0.01em; @@ -97,7 +50,7 @@ exports[`PoolDetailsTransactionsTable renders data filled state 1`] = ` letter-spacing: -0.01em; } -.c21 { +.c13 { -webkit-text-decoration: none; text-decoration: none; cursor: pointer; @@ -108,175 +61,20 @@ exports[`PoolDetailsTransactionsTable renders data filled state 1`] = ` font-weight: 500; } -.c21:hover { +.c13:hover { opacity: 0.6; } -.c21:active { +.c13:active { opacity: 0.4; } -.c25 { +.c8 { display: inline-block; height: inherit; } -.c2 { - max-width: px; - max-height: 600px; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - margin: 0px auto 24px auto; -} - .c3 { - width: 100%; - position: relative; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - background: #FFFFFF; -} - -.c19 { - width: 100%; - position: relative; - overflow-x: auto; - overscroll-behavior-x: none; - border-right: 1px solid #22222212; - border-bottom: 1px solid #22222212; - border-left: 1px solid #22222212; - border-bottom-right-radius: 20px; - border-bottom-left-radius: 20px; - -ms-overflow-style: none; - -webkit-scrollbar-width: none; - -moz-scrollbar-width: none; - -ms-scrollbar-width: none; - scrollbar-width: none; -} - -.c19::-webkit-scrollbar { - display: none; -} - -.c31 { - position: -webkit-sticky; - position: sticky; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - margin-top: -48px; - visibility: hidden; -} - -.c32 { - background: #FFEFFF; - border-radius: 8px; - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - padding: 8px; - color: #FC72FF; - font-size: 16px; - font-weight: 535; - gap: 8px; - height: 34px; - z-index: 990; -} - -.c6 { - padding: 0px 12px; - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - min-width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - min-height: 64px; -} - -.c7 { - border: 1px solid #22222212; - border-top-right-radius: 20px; - border-top-left-radius: 20px; - overflow: auto; - width: unset; - min-height: 52px; - background: #F9F9F9; - -ms-overflow-style: none; - -webkit-scrollbar-width: none; - -moz-scrollbar-width: none; - -ms-scrollbar-width: none; - scrollbar-width: none; - overscroll-behavior: none; -} - -.c7::-webkit-scrollbar { - display: none; -} - -.c8 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-flex: 1; - -webkit-flex-grow: 1; - -ms-flex-positive: 1; - flex-grow: 1; -} - -.c8:last-child { - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; -} - -.c8:first-child { - -webkit-box-flex: 0; - -webkit-flex-grow: 0; - -ms-flex-positive: 0; - flex-grow: 0; -} - -.c23 { - -webkit-text-decoration: none; - text-decoration: none; - -webkit-text-decoration: none; - text-decoration: none; - cursor: pointer; - -webkit-transition-duration: 125ms; - transition-duration: 125ms; - color: #222222; -} - -.c23:hover { - opacity: 0.6; -} - -.c23:active { - opacity: 0.4; -} - -.c11 { height: 16px; width: 16px; color: #222222; @@ -285,33 +83,7 @@ exports[`PoolDetailsTransactionsTable renders data filled state 1`] = ` transform: rotate(0deg); } -.c13 { - color: #222222; -} - -.c15 { - -webkit-text-decoration: none; - text-decoration: none; - cursor: pointer; - -webkit-transition-duration: 125ms; - transition-duration: 125ms; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - gap: 4px; -} - -.c15:hover { - opacity: 0.6; -} - -.c15:active { - opacity: 0.4; -} - -.c24 { +.c7 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -327,110 +99,22 @@ exports[`PoolDetailsTransactionsTable renders data filled state 1`] = ` width: 100%; } -.c27 { +.c10 { display: none; height: 16px; width: 16px; color: #7D7D7D; } -.c22:hover .c26 { +.c6:hover .c9 { display: block; } -.c9 { - min-width: 120px; - -webkit-flex: 0; - -ms-flex: 0; - flex: 0; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c14 { - min-width: 144px; - -webkit-flex: 0; - -ms-flex: 0; - flex: 0; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c17 { - min-width: 125px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c18 { - min-width: 100px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c16 { +.c4 { position: relative; } -.c30 { +.c14 { color: #7D7D7D; stroke: #7D7D7D; } @@ -439,12 +123,6 @@ exports[`PoolDetailsTransactionsTable renders data filled state 1`] = ` min-height: 256px; } -@media not all and (hover:none) { - .c20:hover { - background: #22222212; - } -} -
-
Time -
+
Type
@@ -544,48 +224,48 @@ exports[`PoolDetailsTransactionsTable renders data filled state 1`] = `
USD
Wallet
@@ -594,36 +274,38 @@ exports[`PoolDetailsTransactionsTable renders data filled state 1`] = `
@@ -758,30 +417,13 @@ exports[`PoolDetailsTransactionsTable renders data filled state 1`] = ` exports[`PoolDetailsTransactionsTable renders error state 1`] = ` - .c4 { + .c1 { box-sizing: border-box; margin: 0; min-width: 0; } -.c5 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c10 { +.c2 { width: 100%; display: -webkit-box; display: -webkit-flex; @@ -799,23 +441,7 @@ exports[`PoolDetailsTransactionsTable renders error state 1`] = ` gap: 4px; } -.c27 { - height: 16px; - width: 16px; -} - -.c27 path { - stroke: #FC72FF; - background: #7D7D7D; - fill: none; -} - -.c28 { - -webkit-animation: 2s fvtopB linear infinite; - animation: 2s fvtopB linear infinite; -} - -.c1 { +.c9 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -829,7 +455,7 @@ exports[`PoolDetailsTransactionsTable renders error state 1`] = ` justify-content: flex-start; } -.c12 { +.c5 { color: #7D7D7D; -webkit-letter-spacing: -0.01em; -moz-letter-spacing: -0.01em; @@ -837,7 +463,7 @@ exports[`PoolDetailsTransactionsTable renders error state 1`] = ` letter-spacing: -0.01em; } -.c24 { +.c10 { color: #222222; -webkit-letter-spacing: -0.01em; -moz-letter-spacing: -0.01em; @@ -845,7 +471,7 @@ exports[`PoolDetailsTransactionsTable renders error state 1`] = ` letter-spacing: -0.01em; } -.c23 { +.c8 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -875,179 +501,16 @@ exports[`PoolDetailsTransactionsTable renders error state 1`] = ` border-radius: 20px; } -.c2 { - max-width: px; - max-height: 600px; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - margin: 0px auto 24px auto; -} - .c3 { - width: 100%; - position: relative; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - background: #FFFFFF; -} - -.c21 { - width: 100%; - position: relative; - overflow-x: auto; - overscroll-behavior-x: none; - border-right: 1px solid #22222212; - border-bottom: 1px solid #22222212; - border-left: 1px solid #22222212; - border-bottom-right-radius: 20px; - border-bottom-left-radius: 20px; - -ms-overflow-style: none; - -webkit-scrollbar-width: none; - -moz-scrollbar-width: none; - -ms-scrollbar-width: none; - scrollbar-width: none; -} - -.c21::-webkit-scrollbar { - display: none; -} - -.c25 { - position: -webkit-sticky; - position: sticky; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - margin-top: -48px; - visibility: hidden; -} - -.c26 { - background: #FFEFFF; - border-radius: 8px; - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - padding: 8px; - color: #FC72FF; - font-size: 16px; - font-weight: 535; - gap: 8px; - height: 34px; - z-index: 990; -} - -.c6 { - padding: 0px 12px; - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - min-width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - min-height: 64px; -} - -.c7 { - border: 1px solid #22222212; - border-top-right-radius: 20px; - border-top-left-radius: 20px; - overflow: auto; - width: unset; - min-height: 52px; - background: #F9F9F9; - -ms-overflow-style: none; - -webkit-scrollbar-width: none; - -moz-scrollbar-width: none; - -ms-scrollbar-width: none; - scrollbar-width: none; - overscroll-behavior: none; - opacity: 0.4; -} - -.c7::-webkit-scrollbar { - display: none; -} - -.c8 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-flex: 1; - -webkit-flex-grow: 1; - -ms-flex-positive: 1; - flex-grow: 1; -} - -.c8:last-child { - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; -} - -.c8:first-child { - -webkit-box-flex: 0; - -webkit-flex-grow: 0; - -ms-flex-positive: 0; - flex-grow: 0; -} - -.c11 { - height: 16px; - width: 16px; - color: #222222; - -webkit-transform: rotate(0deg); - -ms-transform: rotate(0deg); - transform: rotate(0deg); -} - -.c13 { - color: #222222; -} - -.c15 { - -webkit-text-decoration: none; - text-decoration: none; - cursor: pointer; - -webkit-transition-duration: 125ms; - transition-duration: 125ms; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - gap: 4px; -} - -.c15:hover { - opacity: 0.6; -} - -.c15:active { - opacity: 0.4; + height: 16px; + width: 16px; + color: #222222; + -webkit-transform: rotate(0deg); + -ms-transform: rotate(0deg); + transform: rotate(0deg); } -.c18 { +.c6 { border-radius: 12px; border-radius: 12px; height: 24px; @@ -1062,100 +525,12 @@ exports[`PoolDetailsTransactionsTable renders error state 1`] = ` background-size: 400%; } -.c9 { - min-width: 120px; - -webkit-flex: 0; - -ms-flex: 0; - flex: 0; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c14 { - min-width: 144px; - -webkit-flex: 0; - -ms-flex: 0; - flex: 0; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c17 { - min-width: 125px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c20 { - min-width: 100px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c19 { +.c7 { width: 75%; height: 16px; } -.c16 { +.c4 { position: relative; } @@ -1163,12 +538,6 @@ exports[`PoolDetailsTransactionsTable renders error state 1`] = ` min-height: 256px; } -@media not all and (hover:none) { - .c22:hover { - background: #22222212; - } -} -
-
Time -
+
Type
@@ -1268,50 +639,50 @@ exports[`PoolDetailsTransactionsTable renders error state 1`] = `
USD
Wallet
@@ -1320,542 +691,542 @@ exports[`PoolDetailsTransactionsTable renders error state 1`] = `
@@ -1888,44 +1259,21 @@ exports[`PoolDetailsTransactionsTable renders error state 1`] = `
Error loading data
Data is unavailable at the moment; we’re working on a fix
-
-
- - - - Loading -
-
@@ -1937,30 +1285,13 @@ exports[`PoolDetailsTransactionsTable renders error state 1`] = ` exports[`PoolDetailsTransactionsTable renders loading state 1`] = ` - .c4 { + .c1 { box-sizing: border-box; margin: 0; min-width: 0; } -.c5 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c10 { +.c2 { width: 100%; display: -webkit-box; display: -webkit-flex; @@ -1978,37 +1309,7 @@ exports[`PoolDetailsTransactionsTable renders loading state 1`] = ` gap: 4px; } -.c25 { - height: 16px; - width: 16px; -} - -.c25 path { - stroke: #FC72FF; - background: #7D7D7D; - fill: none; -} - -.c26 { - -webkit-animation: 2s fvtopB linear infinite; - animation: 2s fvtopB linear infinite; -} - -.c1 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c12 { +.c5 { color: #7D7D7D; -webkit-letter-spacing: -0.01em; -moz-letter-spacing: -0.01em; @@ -2016,143 +1317,7 @@ exports[`PoolDetailsTransactionsTable renders loading state 1`] = ` letter-spacing: -0.01em; } -.c2 { - max-width: px; - max-height: 600px; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - margin: 0px auto 24px auto; -} - .c3 { - width: 100%; - position: relative; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - background: #FFFFFF; -} - -.c21 { - width: 100%; - position: relative; - overflow-x: auto; - overscroll-behavior-x: none; - border-right: 1px solid #22222212; - border-bottom: 1px solid #22222212; - border-left: 1px solid #22222212; - border-bottom-right-radius: 20px; - border-bottom-left-radius: 20px; - -ms-overflow-style: none; - -webkit-scrollbar-width: none; - -moz-scrollbar-width: none; - -ms-scrollbar-width: none; - scrollbar-width: none; -} - -.c21::-webkit-scrollbar { - display: none; -} - -.c23 { - position: -webkit-sticky; - position: sticky; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - margin-top: -48px; - visibility: hidden; -} - -.c24 { - background: #FFEFFF; - border-radius: 8px; - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - padding: 8px; - color: #FC72FF; - font-size: 16px; - font-weight: 535; - gap: 8px; - height: 34px; - z-index: 990; -} - -.c6 { - padding: 0px 12px; - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - min-width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - min-height: 64px; -} - -.c7 { - border: 1px solid #22222212; - border-top-right-radius: 20px; - border-top-left-radius: 20px; - overflow: auto; - width: unset; - min-height: 52px; - background: #F9F9F9; - -ms-overflow-style: none; - -webkit-scrollbar-width: none; - -moz-scrollbar-width: none; - -ms-scrollbar-width: none; - scrollbar-width: none; - overscroll-behavior: none; -} - -.c7::-webkit-scrollbar { - display: none; -} - -.c8 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-flex: 1; - -webkit-flex-grow: 1; - -ms-flex-positive: 1; - flex-grow: 1; -} - -.c8:last-child { - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; -} - -.c8:first-child { - -webkit-box-flex: 0; - -webkit-flex-grow: 0; - -ms-flex-positive: 0; - flex-grow: 0; -} - -.c11 { height: 16px; width: 16px; color: #222222; @@ -2161,33 +1326,7 @@ exports[`PoolDetailsTransactionsTable renders loading state 1`] = ` transform: rotate(0deg); } -.c13 { - color: #222222; -} - -.c15 { - -webkit-text-decoration: none; - text-decoration: none; - cursor: pointer; - -webkit-transition-duration: 125ms; - transition-duration: 125ms; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - gap: 4px; -} - -.c15:hover { - opacity: 0.6; -} - -.c15:active { - opacity: 0.4; -} - -.c18 { +.c6 { border-radius: 12px; border-radius: 12px; height: 24px; @@ -2202,100 +1341,12 @@ exports[`PoolDetailsTransactionsTable renders loading state 1`] = ` background-size: 400%; } -.c9 { - min-width: 120px; - -webkit-flex: 0; - -ms-flex: 0; - flex: 0; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c14 { - min-width: 144px; - -webkit-flex: 0; - -ms-flex: 0; - flex: 0; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c17 { - min-width: 125px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c20 { - min-width: 100px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c19 { +.c7 { width: 75%; height: 16px; } -.c16 { +.c4 { position: relative; } @@ -2303,12 +1354,6 @@ exports[`PoolDetailsTransactionsTable renders loading state 1`] = ` min-height: 256px; } -@media not all and (hover:none) { - .c22:hover { - background: #22222212; - } -} -
-
Time -
+
Type
@@ -2408,50 +1455,50 @@ exports[`PoolDetailsTransactionsTable renders loading state 1`] = `
USD
Wallet
@@ -2460,564 +1507,541 @@ exports[`PoolDetailsTransactionsTable renders loading state 1`] = `
-
-
- - - - Loading -
-
diff --git a/apps/web/src/components/Pools/PoolTable/PoolTable.test.tsx b/apps/web/src/components/Pools/PoolTable/PoolTable.test.tsx index fbc4e699b89..d6f3c5e8f51 100644 --- a/apps/web/src/components/Pools/PoolTable/PoolTable.test.tsx +++ b/apps/web/src/components/Pools/PoolTable/PoolTable.test.tsx @@ -1,3 +1,5 @@ +import 'test-utils/tokens/mocks' + import { ApolloError } from '@apollo/client' import { Percent } from '@uniswap/sdk-core' import { TopPoolTable } from 'components/Pools/PoolTable/PoolTable' diff --git a/apps/web/src/components/Pools/PoolTable/PoolTable.tsx b/apps/web/src/components/Pools/PoolTable/PoolTable.tsx index 96d42d084cc..515657e96b9 100644 --- a/apps/web/src/components/Pools/PoolTable/PoolTable.tsx +++ b/apps/web/src/components/Pools/PoolTable/PoolTable.tsx @@ -3,11 +3,10 @@ import { ColumnDef, createColumnHelper } from '@tanstack/react-table' import { InterfaceElementName } from '@uniswap/analytics-events' import { Percent } from '@uniswap/sdk-core' import { DoubleCurrencyAndChainLogo } from 'components/DoubleLogo' -import Row from 'components/Row' import { Table } from 'components/Table' import { Cell } from 'components/Table/Cell' import { ClickableHeaderRow, HeaderArrow, HeaderSortText } from 'components/Table/styled' -import { NameText } from 'components/Tokens/TokenTable' +import { EllipsisText } from 'components/Tokens/TokenTable' import { MAX_WIDTH_MEDIA_BREAKPOINT } from 'components/Tokens/constants' import { exploreSearchStringAtom } from 'components/Tokens/state' import { MouseoverTooltip } from 'components/Tooltip' @@ -18,9 +17,8 @@ import { PoolSortFields, TablePool, useTopPools } from 'graphql/data/pools/useTo import { OrderDirection, getSupportedGraphQlChain, gqlToCurrency, unwrapToken } from 'graphql/data/util' import { useAtom } from 'jotai' import { atomWithReset, useAtomValue, useResetAtom, useUpdateAtom } from 'jotai/utils' -import styled from 'lib/styled-components' import { ReactElement, ReactNode, useCallback, useEffect, useMemo } from 'react' -import { ThemedText } from 'theme/components' +import { Flex, Text, styled } from 'ui/src' import { ProtocolVersion, Token } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { Trans } from 'uniswap/src/i18n' import { InterfaceChainId } from 'uniswap/src/types/chains' @@ -34,16 +32,19 @@ const HEADER_DESCRIPTIONS: Record = { [PoolSortFields.OneDayApr]: , } -const TableWrapper = styled.div` - margin: 0 auto; - max-width: ${MAX_WIDTH_MEDIA_BREAKPOINT}; -` +const TableWrapper = styled(Flex, { + m: '0 auto', + maxWidth: MAX_WIDTH_MEDIA_BREAKPOINT, +}) -const Badge = styled(ThemedText.LabelMicro)` - padding: 2px 6px; - background: ${({ theme }) => theme.surface2}; - border-radius: 5px; -` +const Badge = styled(Text, { + py: 2, + px: 6, + backgroundColor: '$surface2', + borderRadius: '$rounded6', + variant: 'body4', + color: '$neutral2', +}) interface PoolTableValues { index: number @@ -81,14 +82,14 @@ function PoolDescription({ }) { const currencies = [gqlToCurrency(token0), gqlToCurrency(token1)] return ( - + - + {token0.symbol}/{token1.symbol} - + {protocolVersion === ProtocolVersion.V2 && {protocolVersion.toLowerCase()}} {feeTier / BIPS_BASE}% - + ) } @@ -131,9 +132,9 @@ function PoolTableHeader({ const handleSortCategory = useSetSortMethod(category) return ( - + {isCurrentSortMethod && } - {HEADER_TEXT[category]} + {HEADER_TEXT[category]} ) @@ -251,12 +252,16 @@ export function PoolsTable({ id: 'index', header: () => ( - # + + # + ), cell: (index) => ( - {index.getValue?.()} + + {index.getValue?.()} + ), }) @@ -266,13 +271,13 @@ export function PoolsTable({ id: 'poolDescription', header: () => ( - + - + ), cell: (poolDescription) => ( - + {poolDescription.getValue?.()} ), @@ -282,7 +287,7 @@ export function PoolsTable({ ? columnHelper.accessor((row) => row.txCount, { id: 'transactions', header: () => ( - + ), cell: (txCount) => ( - - + + {formatNumber({ input: txCount.getValue?.(), type: NumberType.NFTCollectionStats })} - + ), }) @@ -313,9 +318,9 @@ export function PoolsTable({ ), cell: (tvl) => ( - + {formatNumber({ input: tvl.getValue?.(), type: NumberType.FiatTokenStats })} - + ), }) @@ -334,9 +339,9 @@ export function PoolsTable({ ), cell: (volume24h) => ( - + {formatNumber({ input: volume24h.getValue?.(), type: NumberType.FiatTokenStats })} - + ), }) @@ -355,9 +360,9 @@ export function PoolsTable({ ), cell: (volumeWeek) => ( - + {formatNumber({ input: volumeWeek.getValue?.(), type: NumberType.FiatTokenStats })} - + ), }) @@ -376,7 +381,9 @@ export function PoolsTable({ ), cell: (oneDayApr) => ( - {formatPercent(oneDayApr.getValue?.())} + + {formatPercent(oneDayApr.getValue?.())} + ), }) diff --git a/apps/web/src/components/Pools/PoolTable/__snapshots__/PoolTable.test.tsx.snap b/apps/web/src/components/Pools/PoolTable/__snapshots__/PoolTable.test.tsx.snap index daf5cdb873a..9abd414e8a5 100644 --- a/apps/web/src/components/Pools/PoolTable/__snapshots__/PoolTable.test.tsx.snap +++ b/apps/web/src/components/Pools/PoolTable/__snapshots__/PoolTable.test.tsx.snap @@ -2,80 +2,7 @@ exports[`PoolTable renders data filled state 1`] = ` - .c30 { - height: 16px; - width: 16px; -} - -.c30 path { - stroke: #FC72FF; - background: #7D7D7D; - fill: none; -} - -.c31 { - -webkit-animation: 2s fvtopB linear infinite; - animation: 2s fvtopB linear infinite; -} - -.c4 { - box-sizing: border-box; - margin: 0; - min-width: 0; -} - -.c5 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c21 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 8px; -} - -.c10 { - color: #7D7D7D; - -webkit-letter-spacing: -0.01em; - -moz-letter-spacing: -0.01em; - -ms-letter-spacing: -0.01em; - letter-spacing: -0.01em; -} - -.c25 { - color: #222222; - -webkit-letter-spacing: -0.01em; - -moz-letter-spacing: -0.01em; - -ms-letter-spacing: -0.01em; - letter-spacing: -0.01em; -} - -.c23 { + .c4 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -86,230 +13,47 @@ exports[`PoolTable renders data filled state 1`] = ` left: 0; } -.c23 img { +.c4 img { width: 14px; height: 28px; object-fit: cover; } -.c23 img:first-child { +.c4 img:first-child { border-radius: 14px 0 0 14px; object-position: 0 0; } -.c23 img:last-child { +.c4 img:last-child { border-radius: 0 14px 14px 0; object-position: 100% 0; } -.c24 { +.c5 { width: 14px; height: 28px; border-radius: 50%; } -.c22 { +.c3 { position: relative; top: 0; left: 0; } -.c1 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c13 { +.c0 { display: inline-block; height: inherit; } .c2 { - max-width: 1200px; - max-height: px; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - margin: 0px auto 24px auto; -} - -.c3 { - width: 100%; - position: relative; - position: -webkit-sticky; - position: sticky; - position: -webkit-sticky; - top: 72px; - z-index: 990; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - background: #FFFFFF; -} - -.c3:before { - content: ''; - height: 12px; -} - -.c18 { - width: 100%; - position: relative; - overflow-x: auto; - overscroll-behavior-x: none; - border-right: 1px solid #22222212; - border-bottom: 1px solid #22222212; - border-left: 1px solid #22222212; - border-bottom-right-radius: 20px; - border-bottom-left-radius: 20px; - -ms-overflow-style: none; - -webkit-scrollbar-width: none; - -moz-scrollbar-width: none; - -ms-scrollbar-width: none; - scrollbar-width: none; -} - -.c18::-webkit-scrollbar { - display: none; -} - -.c28 { - position: -webkit-sticky; - position: sticky; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - margin-top: -48px; - visibility: hidden; -} - -.c29 { - background: #FFEFFF; - border-radius: 8px; - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - padding: 8px; - color: #FC72FF; - font-size: 16px; - font-weight: 535; - gap: 8px; - height: 34px; - z-index: 990; -} - -.c6 { - padding: 0px 12px; - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - min-width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - min-height: 64px; -} - -.c7 { - border: 1px solid #22222212; - border-top-right-radius: 20px; - border-top-left-radius: 20px; - overflow: auto; - width: unset; - min-height: 52px; - background: #F9F9F9; - -ms-overflow-style: none; - -webkit-scrollbar-width: none; - -moz-scrollbar-width: none; - -ms-scrollbar-width: none; - scrollbar-width: none; - overscroll-behavior: none; -} - -.c7::-webkit-scrollbar { - display: none; -} - -.c8 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-flex: 1; - -webkit-flex-grow: 1; - -ms-flex-positive: 1; - flex-grow: 1; -} - -.c8:last-child { - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; -} - -.c8:first-child { - -webkit-box-flex: 0; - -webkit-flex-grow: 0; - -ms-flex-positive: 0; - flex-grow: 0; -} - -.c19 { color: none; -webkit-text-decoration: none; text-decoration: none; cursor: pointer; } -.c14 { - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - cursor: pointer; - width: 100%; - gap: 4px; - -webkit-text-decoration: none; - text-decoration: none; - cursor: pointer; - -webkit-transition-duration: 125ms; - transition-duration: 125ms; -} - -.c14:hover { - opacity: 0.6; -} - -.c14:active { - opacity: 0.4; -} - -.c15 { +.c1 { height: 16px; width: 16px; color: #222222; @@ -318,121 +62,6 @@ exports[`PoolTable renders data filled state 1`] = ` transform: rotate(0deg); } -.c16 { - color: #222222; -} - -.c9 { - min-width: 44px; - -webkit-flex: 0; - -ms-flex: 0; - flex: 0; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c11 { - width: 240px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c12 { - min-width: 120px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c17 { - min-width: 100px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c26 { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.c0 { - margin: 0 auto; - max-width: 1200px; -} - -.c27 { - padding: 2px 6px; - background: #F9F9F9; - border-radius: 5px; -} - -@media not all and (hover:none) { - .c20:hover { - background: #22222212; - } -} -
+
-
# -
+
-
Pool -
+
-
Transactions -
+
-
TVL -
+
-
1 day volume -
+
-
7 day volume -
+
-
1 day APR -
+
@@ -624,160 +263,145 @@ exports[`PoolTable renders data filled state 1`] = `
-
-
- - - - Loading -
-
@@ -789,62 +413,23 @@ exports[`PoolTable renders data filled state 1`] = ` exports[`PoolTable renders error state 1`] = ` - .c26 { - height: 16px; - width: 16px; -} - -.c26 path { - stroke: #FC72FF; - background: #7D7D7D; - fill: none; -} - -.c27 { - -webkit-animation: 2s fvtopB linear infinite; - animation: 2s fvtopB linear infinite; -} - -.c4 { - box-sizing: border-box; - margin: 0; - min-width: 0; -} - -.c5 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c10 { - color: #7D7D7D; + .c6 { + color: #222222; -webkit-letter-spacing: -0.01em; -moz-letter-spacing: -0.01em; -ms-letter-spacing: -0.01em; letter-spacing: -0.01em; } -.c23 { - color: #222222; +.c7 { + color: #7D7D7D; -webkit-letter-spacing: -0.01em; -moz-letter-spacing: -0.01em; -ms-letter-spacing: -0.01em; letter-spacing: -0.01em; } -.c1 { +.c5 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -858,7 +443,7 @@ exports[`PoolTable renders error state 1`] = ` justify-content: flex-start; } -.c22 { +.c4 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -888,182 +473,12 @@ exports[`PoolTable renders error state 1`] = ` border-radius: 20px; } -.c13 { +.c0 { display: inline-block; height: inherit; } -.c2 { - max-width: 1200px; - max-height: px; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - margin: 0px auto 24px auto; -} - -.c3 { - width: 100%; - position: relative; - position: -webkit-sticky; - position: sticky; - position: -webkit-sticky; - top: 72px; - z-index: 990; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - background: #FFFFFF; -} - -.c3:before { - content: ''; - height: 12px; -} - -.c18 { - width: 100%; - position: relative; - overflow-x: auto; - overscroll-behavior-x: none; - border-right: 1px solid #22222212; - border-bottom: 1px solid #22222212; - border-left: 1px solid #22222212; - border-bottom-right-radius: 20px; - border-bottom-left-radius: 20px; - -ms-overflow-style: none; - -webkit-scrollbar-width: none; - -moz-scrollbar-width: none; - -ms-scrollbar-width: none; - scrollbar-width: none; -} - -.c18::-webkit-scrollbar { - display: none; -} - -.c24 { - position: -webkit-sticky; - position: sticky; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - margin-top: -48px; - visibility: hidden; -} - -.c25 { - background: #FFEFFF; - border-radius: 8px; - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - padding: 8px; - color: #FC72FF; - font-size: 16px; - font-weight: 535; - gap: 8px; - height: 34px; - z-index: 990; -} - -.c6 { - padding: 0px 12px; - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - min-width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - min-height: 64px; -} - -.c7 { - border: 1px solid #22222212; - border-top-right-radius: 20px; - border-top-left-radius: 20px; - overflow: auto; - width: unset; - min-height: 52px; - background: #F9F9F9; - -ms-overflow-style: none; - -webkit-scrollbar-width: none; - -moz-scrollbar-width: none; - -ms-scrollbar-width: none; - scrollbar-width: none; - overscroll-behavior: none; - opacity: 0.4; -} - -.c7::-webkit-scrollbar { - display: none; -} - -.c8 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-flex: 1; - -webkit-flex-grow: 1; - -ms-flex-positive: 1; - flex-grow: 1; -} - -.c8:last-child { - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; -} - -.c8:first-child { - -webkit-box-flex: 0; - -webkit-flex-grow: 0; - -ms-flex-positive: 0; - flex-grow: 0; -} - -.c14 { - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - cursor: pointer; - width: 100%; - gap: 4px; - -webkit-text-decoration: none; - text-decoration: none; - cursor: pointer; - -webkit-transition-duration: 125ms; - transition-duration: 125ms; -} - -.c14:hover { - opacity: 0.6; -} - -.c14:active { - opacity: 0.4; -} - -.c15 { +.c1 { height: 16px; width: 16px; color: #222222; @@ -1072,11 +487,7 @@ exports[`PoolTable renders error state 1`] = ` transform: rotate(0deg); } -.c16 { - color: #222222; -} - -.c20 { +.c2 { border-radius: 12px; border-radius: 12px; height: 24px; @@ -1091,110 +502,11 @@ exports[`PoolTable renders error state 1`] = ` background-size: 400%; } -.c9 { - min-width: 44px; - -webkit-flex: 0; - -ms-flex: 0; - flex: 0; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c11 { - width: 240px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c12 { - min-width: 120px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c17 { - min-width: 100px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c21 { +.c3 { width: 75%; height: 16px; } -.c0 { - margin: 0 auto; - max-width: 1200px; -} - -@media not all and (hover:none) { - .c19:hover { - background: #22222212; - } -} -
+
-
# -
+
-
Pool -
+
-
Transactions -
+
-
TVL -
+
-
1 day volume -
+
-
7 day volume -
+
-
1 day APR -
+
@@ -1386,626 +708,626 @@ exports[`PoolTable renders error state 1`] = `
@@ -2038,44 +1360,21 @@ exports[`PoolTable renders error state 1`] = `
Error loading data
Data is unavailable at the moment; we’re working on a fix
-
-
- - - - Loading -
-
@@ -2087,242 +1386,12 @@ exports[`PoolTable renders error state 1`] = ` exports[`PoolTable renders loading state 1`] = ` - .c24 { - height: 16px; - width: 16px; -} - -.c24 path { - stroke: #FC72FF; - background: #7D7D7D; - fill: none; -} - -.c25 { - -webkit-animation: 2s fvtopB linear infinite; - animation: 2s fvtopB linear infinite; -} - -.c4 { - box-sizing: border-box; - margin: 0; - min-width: 0; -} - -.c5 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c10 { - color: #7D7D7D; - -webkit-letter-spacing: -0.01em; - -moz-letter-spacing: -0.01em; - -ms-letter-spacing: -0.01em; - letter-spacing: -0.01em; -} - -.c1 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c13 { + .c0 { display: inline-block; height: inherit; } -.c2 { - max-width: 1200px; - max-height: px; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - margin: 0px auto 24px auto; -} - -.c3 { - width: 100%; - position: relative; - position: -webkit-sticky; - position: sticky; - position: -webkit-sticky; - top: 72px; - z-index: 990; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - background: #FFFFFF; -} - -.c3:before { - content: ''; - height: 12px; -} - -.c18 { - width: 100%; - position: relative; - overflow-x: auto; - overscroll-behavior-x: none; - border-right: 1px solid #22222212; - border-bottom: 1px solid #22222212; - border-left: 1px solid #22222212; - border-bottom-right-radius: 20px; - border-bottom-left-radius: 20px; - -ms-overflow-style: none; - -webkit-scrollbar-width: none; - -moz-scrollbar-width: none; - -ms-scrollbar-width: none; - scrollbar-width: none; -} - -.c18::-webkit-scrollbar { - display: none; -} - -.c22 { - position: -webkit-sticky; - position: sticky; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - margin-top: -48px; - visibility: hidden; -} - -.c23 { - background: #FFEFFF; - border-radius: 8px; - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - padding: 8px; - color: #FC72FF; - font-size: 16px; - font-weight: 535; - gap: 8px; - height: 34px; - z-index: 990; -} - -.c6 { - padding: 0px 12px; - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - min-width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - min-height: 64px; -} - -.c7 { - border: 1px solid #22222212; - border-top-right-radius: 20px; - border-top-left-radius: 20px; - overflow: auto; - width: unset; - min-height: 52px; - background: #F9F9F9; - -ms-overflow-style: none; - -webkit-scrollbar-width: none; - -moz-scrollbar-width: none; - -ms-scrollbar-width: none; - scrollbar-width: none; - overscroll-behavior: none; -} - -.c7::-webkit-scrollbar { - display: none; -} - -.c8 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-flex: 1; - -webkit-flex-grow: 1; - -ms-flex-positive: 1; - flex-grow: 1; -} - -.c8:last-child { - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; -} - -.c8:first-child { - -webkit-box-flex: 0; - -webkit-flex-grow: 0; - -ms-flex-positive: 0; - flex-grow: 0; -} - -.c14 { - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - cursor: pointer; - width: 100%; - gap: 4px; - -webkit-text-decoration: none; - text-decoration: none; - cursor: pointer; - -webkit-transition-duration: 125ms; - transition-duration: 125ms; -} - -.c14:hover { - opacity: 0.6; -} - -.c14:active { - opacity: 0.4; -} - -.c15 { +.c1 { height: 16px; width: 16px; color: #222222; @@ -2331,11 +1400,7 @@ exports[`PoolTable renders loading state 1`] = ` transform: rotate(0deg); } -.c16 { - color: #222222; -} - -.c20 { +.c2 { border-radius: 12px; border-radius: 12px; height: 24px; @@ -2350,110 +1415,11 @@ exports[`PoolTable renders loading state 1`] = ` background-size: 400%; } -.c9 { - min-width: 44px; - -webkit-flex: 0; - -ms-flex: 0; - flex: 0; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c11 { - width: 240px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c12 { - min-width: 120px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c17 { - min-width: 100px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c21 { +.c3 { width: 75%; height: 16px; } -.c0 { - margin: 0 auto; - max-width: 1200px; -} - -@media not all and (hover:none) { - .c19:hover { - background: #22222212; - } -} -
+
-
# -
+
-
Pool -
+
-
Transactions -
+
-
TVL -
+
-
1 day volume -
+
-
7 day volume -
+
-
1 day APR -
+
@@ -2645,648 +1621,625 @@ exports[`PoolTable renders loading state 1`] = `
-
-
- - - - Loading -
-
diff --git a/apps/web/src/components/Popups/PopupItem.tsx b/apps/web/src/components/Popups/PopupItem.tsx index b29ea2ac91e..bccef57ea85 100644 --- a/apps/web/src/components/Popups/PopupItem.tsx +++ b/apps/web/src/components/Popups/PopupItem.tsx @@ -58,10 +58,11 @@ export default function PopupItem({ } case PopupType.SwitchNetwork: { return ( - - {' '} - {getSwitchNetworkTitle(content.action, content.chainId as UniverseChainId)} - + } + text={getSwitchNetworkTitle(content.action, content.chainId as UniverseChainId)} + /> ) } } @@ -76,6 +77,6 @@ function getSwitchNetworkTitle(action: SwapTab, chainId: UniverseChainId) { case SwapTab.Send: return t('notification.send.network', { network: label }) default: - return null + return '' } } diff --git a/apps/web/src/components/Popups/ToastRegularSimple.tsx b/apps/web/src/components/Popups/ToastRegularSimple.tsx index 4d16090d64b..690454e8623 100644 --- a/apps/web/src/components/Popups/ToastRegularSimple.tsx +++ b/apps/web/src/components/Popups/ToastRegularSimple.tsx @@ -1,56 +1,63 @@ -import { PropsWithChildren } from 'react' -import { AnimatePresence } from 'ui/src' +import { Flex, Text, TouchableArea, useMedia } from 'ui/src' import { X } from 'ui/src/components/icons/X' -import { Flex } from 'ui/src/components/layout' -import { TouchableArea } from 'ui/src/components/touchable' const MAX_WIDTH = 348 // Temporary Spore-ish implementation for mweb until Spore project makes toasts consistent across all platforms export function ToastRegularSimple({ - children, + icon, + text, onDismiss, -}: PropsWithChildren<{ onDismiss?: () => void }>): JSX.Element { +}: { + icon: JSX.Element + text: string + onDismiss?: () => void +}): JSX.Element { + const media = useMedia() + return ( - - - - {children} - - {onDismiss ? ( - - - - ) : null} + + + {icon} + {text} - + {onDismiss ? ( + + + + ) : null} + ) } diff --git a/apps/web/src/components/Popups/index.tsx b/apps/web/src/components/Popups/index.tsx index fd5fdfb96d7..fb4f92537c4 100644 --- a/apps/web/src/components/Popups/index.tsx +++ b/apps/web/src/components/Popups/index.tsx @@ -4,7 +4,7 @@ import PopupItem from 'components/Popups/PopupItem' import styled from 'lib/styled-components' import { useActivePopups } from 'state/application/hooks' import { Z_INDEX } from 'theme/zIndex' -import { Flex } from 'ui/src' +import { AnimatePresence, Flex } from 'ui/src' const FixedPopupColumn = styled(AutoColumn)` position: fixed; @@ -32,9 +32,11 @@ export default function Popups() { > - {activePopups.map((item) => ( - - ))} + + {activePopups.map((item, i) => ( + + ))} + ) diff --git a/apps/web/src/components/PositionList/index.tsx b/apps/web/src/components/PositionList/index.tsx index 2aa4f790458..2fb73814396 100644 --- a/apps/web/src/components/PositionList/index.tsx +++ b/apps/web/src/components/PositionList/index.tsx @@ -3,7 +3,7 @@ import styled from 'lib/styled-components' import React from 'react' import { MEDIA_WIDTHS } from 'theme' import { PositionDetails } from 'types/position' -import { Trans } from 'uniswap/src/i18n' +import { useTranslation } from 'uniswap/src/i18n' const DesktopHeader = styled.div` display: none; @@ -70,11 +70,12 @@ export default function PositionList({ setUserHideClosedPositions, userHideClosedPositions, }: PositionListProps) { + const { t } = useTranslation() return ( <>
- + {t('pool.positions.title')} {positions && ' (' + positions.length + ')'}
@@ -84,18 +85,18 @@ export default function PositionList({ setUserHideClosedPositions(!userHideClosedPositions) }} > - {userHideClosedPositions ? : } + {userHideClosedPositions ? t('pool.showClosed') : t('pool.hideClosed')}
- + {t('pool.positions.title')} { setUserHideClosedPositions(!userHideClosedPositions) }} > - {userHideClosedPositions ? : } + {userHideClosedPositions ? t('pool.showClosed') : t('pool.hideClosed')} diff --git a/apps/web/src/components/PrivacyPolicy/index.tsx b/apps/web/src/components/PrivacyPolicy/index.tsx index 5e82e74f6eb..ba42489127b 100644 --- a/apps/web/src/components/PrivacyPolicy/index.tsx +++ b/apps/web/src/components/PrivacyPolicy/index.tsx @@ -12,7 +12,7 @@ import { ExternalLink, ThemedText } from 'theme/components' import { ModalName } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { Trans } from 'uniswap/src/i18n' -import { isMobile } from 'utilities/src/platform' +import { isMobileWeb } from 'utilities/src/platform' const Wrapper = styled.div` max-height: 70vh; @@ -111,7 +111,7 @@ function PrivacyPolicy() { draggable="true" onTouchMove={(e) => { // prevent modal gesture handler from dismissing modal when content is scrolling - if (isMobile) { + if (isMobileWeb) { e.stopPropagation() } }} diff --git a/apps/web/src/components/QuestionHelper/index.tsx b/apps/web/src/components/QuestionHelper/index.tsx index 20146b60a60..04b3e2ceee4 100644 --- a/apps/web/src/components/QuestionHelper/index.tsx +++ b/apps/web/src/components/QuestionHelper/index.tsx @@ -2,7 +2,7 @@ import { Placement } from '@popperjs/core' import { MouseoverTooltip } from 'components/Tooltip' import styled from 'lib/styled-components' import { ReactNode, useCallback, useState } from 'react' -import { InfoCircleFilled } from 'ui/src/components/icons' +import { InfoCircleFilled } from 'ui/src/components/icons/InfoCircleFilled' const QuestionWrapper = styled.div` display: flex; diff --git a/apps/web/src/components/ReceiveCryptoModal/ChooseProvider.tsx b/apps/web/src/components/ReceiveCryptoModal/ChooseProvider.tsx index cf2eaf9aa53..fcd6f38c3f0 100644 --- a/apps/web/src/components/ReceiveCryptoModal/ChooseProvider.tsx +++ b/apps/web/src/components/ReceiveCryptoModal/ChooseProvider.tsx @@ -17,7 +17,8 @@ import { Text, TouchableArea, } from 'ui/src' -import { CopySheets, QrCode } from 'ui/src/components/icons' +import { CopySheets } from 'ui/src/components/icons/CopySheets' +import { QrCode } from 'ui/src/components/icons/QrCode' import { iconSizes } from 'ui/src/theme' import { uniswapUrls } from 'uniswap/src/constants/urls' import { FORServiceProvider } from 'uniswap/src/features/fiatOnRamp/types' diff --git a/apps/web/src/components/ReceiveCryptoModal/ProviderOption.tsx b/apps/web/src/components/ReceiveCryptoModal/ProviderOption.tsx index 75b98b553ff..abfe7c0dc12 100644 --- a/apps/web/src/components/ReceiveCryptoModal/ProviderOption.tsx +++ b/apps/web/src/components/ReceiveCryptoModal/ProviderOption.tsx @@ -1,6 +1,6 @@ import { useMemo } from 'react' import { FiatOnRampTransactionStatus, FiatOnRampTransactionType } from 'state/fiatOnRampTransactions/types' -import { ExternalLink } from 'ui/src/components/icons' +import { ExternalLink } from 'ui/src/components/icons/ExternalLink' import { UNISWAP_WEB_URL } from 'uniswap/src/constants/urls' import { FORQuoteItem } from 'uniswap/src/features/fiatOnRamp/FORQuoteItem' import { FORServiceProvider } from 'uniswap/src/features/fiatOnRamp/types' diff --git a/apps/web/src/components/ReceiveCryptoModal/index.tsx b/apps/web/src/components/ReceiveCryptoModal/index.tsx index 4f07bb92529..c12330d45fb 100644 --- a/apps/web/src/components/ReceiveCryptoModal/index.tsx +++ b/apps/web/src/components/ReceiveCryptoModal/index.tsx @@ -7,7 +7,7 @@ import { ContentWrapper } from 'pages/Swap/Buy/shared' import { useCallback, useState } from 'react' import { useModalIsOpen, useToggleModal } from 'state/application/hooks' import { ApplicationModal } from 'state/application/reducer' -import { AdaptiveWebModalSheet } from 'ui/src' +import { AdaptiveWebModal } from 'ui/src' import { FORServiceProvider } from 'uniswap/src/features/fiatOnRamp/types' import { logger } from 'utilities/src/logger/logger' @@ -34,7 +34,7 @@ export function ReceiveCryptoModal() { return null } return ( - + {errorProvider ? ( )} - + ) } diff --git a/apps/web/src/components/SearchModal/CommonBases.tsx b/apps/web/src/components/SearchModal/CommonBases.tsx index fee0fd3dde9..20b3d2e8632 100644 --- a/apps/web/src/components/SearchModal/CommonBases.tsx +++ b/apps/web/src/components/SearchModal/CommonBases.tsx @@ -10,7 +10,7 @@ import { useCallback } from 'react' import { Text } from 'rebass' import { CurrencyInfo } from 'uniswap/src/features/dataApi/types' import Trace from 'uniswap/src/features/telemetry/Trace' -import { WalletEventName } from 'uniswap/src/features/telemetry/constants' +import { UniswapEventName } from 'uniswap/src/features/telemetry/constants' import { currencyId } from 'utils/currencyId' const BaseWrapper = styled.div<{ disable?: boolean }>` @@ -91,7 +91,7 @@ export default function CommonBases({ theme.surface2}; - color: ${({ theme }) => theme.neutral2}; - font-size: 14px; - border-radius: 4px; - padding: 0.25rem 0.3rem 0.25rem 0.3rem; - max-width: 6rem; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - justify-self: flex-end; - margin-right: 4px; -` - -const WarningContainer = styled.div` - margin-left: 0.3em; -` - -const LabelContainer = styled.div` - display: flex; - align-items: center; - padding: 0 20px; -` +const TextOverflowStyle = { + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis', +} satisfies TextStyle + +const StyledBalanceText = styled(Text, { + ...TextOverflowStyle, + maxWidth: '80px', +}) + +const CurrencyName = styled(Text, TextOverflowStyle) + +const Tag = styled(Text, { + backgroundColor: '$surface2', + color: '$neutral2', + fontSize: '14px', + borderRadius: '$rounded4', + p: '$spacing4', + maxWidth: '100px', + overflow: 'hidden', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + alignSelf: 'flex-end', + mr: '$spacing4', +}) function Balance({ balance }: { balance: CurrencyAmount }) { const { formatNumberOrString } = useFormatter() return ( - + {formatNumberOrString({ input: balance.toExact(), type: NumberType.TokenNonTx, @@ -90,11 +78,6 @@ function Balance({ balance }: { balance: CurrencyAmount }) { ) } -const TagContainer = styled.div` - display: flex; - justify-content: flex-end; -` - function TokenTags({ currency }: { currency: Currency }) { if (!(currency instanceof TokenFromList)) { return null @@ -108,7 +91,7 @@ function TokenTags({ currency }: { currency: Currency }) { const tag = tags[0] return ( - + {tag.name} @@ -122,7 +105,7 @@ function TokenTags({ currency }: { currency: Currency }) { ... ) : null} - + ) } @@ -133,9 +116,10 @@ const getDisplayName = (name: string | undefined) => { return name } -const RowWrapper = styled(Row)` - height: 60px; -` +const RowWrapper = styled(Flex, { + flexDirection: 'row', + height: '$spacing60', +}) export function CurrencyRow({ currency, @@ -178,7 +162,7 @@ export function CurrencyRow({ @@ -195,39 +179,34 @@ export function CurrencyRow({ selected={otherSelected || isSelected} dim={isBlockedToken} disabled={disabled} + style={{ outline: 'none' }} > - - - - - - {currencyName} - - - - - - + + + + {currencyName} + + + + {currency.symbol} - + {showAddress && currency.isToken && ( - {shortenAddress(currency.address)} + + {shortenAddress(currency.address)} + )} - - - - + + + + - - + + {showCurrencyAmount && ( - + {account.isConnected ? balance ? : : null} - + )} @@ -324,9 +303,11 @@ export default function CurrencyList({ if (row instanceof CurrencyListSectionTitle) { return ( - - {row.label} - + + + {row.label} + + ) } diff --git a/apps/web/src/components/SearchModal/CurrencySearch.tsx b/apps/web/src/components/SearchModal/CurrencySearch.tsx index de186e63641..2c08339f437 100644 --- a/apps/web/src/components/SearchModal/CurrencySearch.tsx +++ b/apps/web/src/components/SearchModal/CurrencySearch.tsx @@ -1,6 +1,5 @@ +import { InterfaceEventName, InterfaceModalName } from '@uniswap/analytics-events' import { Currency, Token } from '@uniswap/sdk-core' -import { hideSmallBalancesAtom } from 'components/AccountDrawer/SmallBalanceToggle' -import { hideSpamAtom } from 'components/AccountDrawer/SpamToggle' import { recentlySearchedAssetsAtom, useAddRecentlySearchedCurrency, @@ -18,7 +17,7 @@ import { useSwapAndLimitContext } from 'state/swap/useSwapContext' import { useAddUserToken } from 'state/user/hooks' import { useAllUserAddedTokens } from 'state/user/userAddedTokens' import { Flex } from 'ui/src' -import { TokenSelector, TokenSelectorVariation } from 'uniswap/src/components/TokenSelector/TokenSelector' +import { TokenSelectorContent, TokenSelectorVariation } from 'uniswap/src/components/TokenSelector/TokenSelector' import { useCommonTokensOptions, useFilterCallbacks, @@ -26,8 +25,10 @@ import { usePortfolioTokenOptions, useTokenSectionsForSearchResults, } from 'uniswap/src/components/TokenSelector/hooks' +import { TokenSelectorFlow } from 'uniswap/src/components/TokenSelector/types' import { TokenSearchResult } from 'uniswap/src/features/search/SearchResult' -import { TokenSelectorFlow } from 'uniswap/src/features/transactions/transfer/types' +import { useHideSmallBalancesSetting, useHideSpamTokensSetting } from 'uniswap/src/features/settings/hooks' +import Trace from 'uniswap/src/features/telemetry/Trace' import { UniverseChainId } from 'uniswap/src/types/chains' import { CurrencyField } from 'uniswap/src/types/currency' import { SwapTab } from 'uniswap/src/types/screens/interface' @@ -54,8 +55,8 @@ export function CurrencySearch({ currencyField, onCurrencySelect, onDismiss }: C const activeCurrencyCode = useActiveLocalCurrency() const activeLocale = useActiveLocale() const recentlySearchedAssets = useAtomValue(recentlySearchedAssetsAtom) - const hideSmallBalances = useAtomValue(hideSmallBalancesAtom) - const hideSpamBalances = useAtomValue(hideSpamAtom) + const hideSmallBalances = useHideSmallBalancesSetting() + const hideSpamBalances = useHideSpamTokensSetting() const addPopup = useAddPopup() const removePopup = useRemovePopup() @@ -110,88 +111,95 @@ export function CurrencySearch({ currencyField, onCurrencySelect, onDismiss }: C }, [currentTab, chainId, prevChainId, multichainUXEnabled, addPopup, removePopup]) return ( - - - formatNumber({ - input: fromAmount as number, - type: NumberType.FiatTokenPrice, - }) - } - currencyField={currencyField} - flow={TokenSelectorFlow.Swap} - formatNumberOrStringCallback={(input) => - formatNumberOrString({ - price: input.value, - currencyCode: activeCurrencyCode, - locale: activeLocale, - type: UtilitiesNumberType.TokenNonTx, - }) - } - isSurfaceReady={true} - navigateToBuyOrReceiveWithEmptyWalletCallback={() => null} - useCommonTokensOptionsHook={useCommonTokensOptions} - useFavoriteTokensOptionsHook={() => { - return { - data: [], - loading: false, + + + + formatNumber({ + input: fromAmount as number, + type: NumberType.FiatTokenPrice, + }) } - }} - useFilterCallbacksHook={useFilterCallbacks} - usePopularTokensOptionsHook={usePopularTokensOptions} - usePortfolioTokenOptionsHook={usePortfolioTokenOptions} - useTokenSectionsForEmptySearchHook={() => { - return { - data: [], - loading: false, + currencyField={currencyField} + flow={TokenSelectorFlow.Swap} + formatNumberOrStringCallback={(input) => + formatNumberOrString({ + price: input.value, + currencyCode: activeCurrencyCode, + locale: activeLocale, + type: UtilitiesNumberType.TokenNonTx, + }) } - }} - useTokenSectionsForSearchResultsHook={useTokenSectionsForSearchResults} - useTokenWarningDismissedHook={(currencyId) => { - if (!currencyId) { + isSurfaceReady={true} + navigateToBuyOrReceiveWithEmptyWalletCallback={() => null} + useCommonTokensOptionsHook={useCommonTokensOptions} + useFavoriteTokensOptionsHook={() => { return { - tokenWarningDismissed: false, - dismissWarningCallback: () => null, + data: [], + loading: false, } - } - const [chainId, address] = currencyId.split('-') - // Hardcode 18 decimals because we only check chainId and address - const token = new Token(parseInt(chainId), address, 18) + }} + useFilterCallbacksHook={useFilterCallbacks} + usePopularTokensOptionsHook={usePopularTokensOptions} + usePortfolioTokenOptionsHook={usePortfolioTokenOptions} + useTokenSectionsForEmptySearchHook={() => { + return { + data: [], + loading: false, + } + }} + useTokenSectionsForSearchResultsHook={useTokenSectionsForSearchResults} + useTokenWarningDismissedHook={(currencyId) => { + if (!currencyId) { + return { + tokenWarningDismissed: false, + dismissWarningCallback: () => null, + } + } + const [chainId, address] = currencyId.split('-') + // Hardcode 18 decimals because we only check chainId and address + const token = new Token(parseInt(chainId), address, 18) - return { - tokenWarningDismissed: !!userAddedTokens.find( - (userToken) => userToken.chainId === token.chainId && userToken.address === token.address, - ), - dismissWarningCallback: () => addToken(token), + return { + tokenWarningDismissed: !!userAddedTokens.find( + (userToken) => userToken.chainId === token.chainId && userToken.address === token.address, + ), + dismissWarningCallback: () => addToken(token), + } + }} + variation={ + currencyField === CurrencyField.INPUT + ? TokenSelectorVariation.BalancesAndPopular + : TokenSelectorVariation.SuggestedAndFavoritesAndPopular } - }} - variation={ - currencyField === CurrencyField.INPUT - ? TokenSelectorVariation.BalancesAndPopular - : TokenSelectorVariation.SuggestedAndFavoritesAndPopular - } - onClose={() => { - setFilteredChainId(null) - onDismiss() - }} - onDismiss={() => null} - onPressAnimation={() => null} - onSelectChain={(chainId) => { - setFilteredChainId(chainId) - }} - onSelectCurrency={handleCurrencySelectTokenSelectorCallback} - /> - + onClose={() => { + setFilteredChainId(null) + onDismiss() + }} + onDismiss={() => null} + onPressAnimation={() => null} + onSelectChain={(chainId) => { + setFilteredChainId(chainId) + }} + onSelectCurrency={handleCurrencySelectTokenSelectorCallback} + /> + + ) } diff --git a/apps/web/src/components/SearchModal/CurrencySearchModal.tsx b/apps/web/src/components/SearchModal/CurrencySearchModal.tsx index 4940aed7a56..a8fa0f3126b 100644 --- a/apps/web/src/components/SearchModal/CurrencySearchModal.tsx +++ b/apps/web/src/components/SearchModal/CurrencySearchModal.tsx @@ -6,6 +6,9 @@ import TokenSafety from 'components/TokenSafety' import useLast from 'hooks/useLast' import { memo, useCallback, useEffect, useState } from 'react' import { useUserAddedTokens } from 'state/user/userAddedTokens' +import { NAV_HEIGHT } from 'theme' +import { AdaptiveWebModal } from 'ui/src' +import { TOKEN_SELECTOR_WEB_MAX_WIDTH } from 'uniswap/src/components/TokenSelector/TokenSelector' import { FeatureFlags } from 'uniswap/src/features/gating/flags' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' import { CurrencyField } from 'uniswap/src/types/currency' @@ -97,7 +100,20 @@ export default memo(function CurrencySearchModal({ } break } - return ( + return multichainFlagEnabled ? ( + + {content} + + ) : ( { it('shows loading bubble', () => { diff --git a/apps/web/src/components/Table/Cell.tsx b/apps/web/src/components/Table/Cell.tsx index 5d73c2fc913..ba217c6e50f 100644 --- a/apps/web/src/components/Table/Cell.tsx +++ b/apps/web/src/components/Table/Cell.tsx @@ -1,57 +1,38 @@ import { LoadingBubble } from 'components/Tokens/loading' -import styled from 'lib/styled-components' +import deprecatedStyled from 'lib/styled-components' import { PropsWithChildren } from 'react' +import { Flex, FlexProps } from 'ui/src' -const Container = styled.div<{ - $width?: number - $minWidth?: number - $maxWidth?: number - $justifyContent?: string - $grow?: boolean -}>` - ${({ $width }) => $width && `width: ${$width}px`}; - ${({ $minWidth }) => $minWidth && `min-width: ${$minWidth}px`}; - ${({ $maxWidth }) => $maxWidth && `max-width: ${$maxWidth}px`}; - flex: ${({ $grow }) => ($grow ? '1' : '0')}; - display: flex; - justify-content: ${({ $justifyContent }) => $justifyContent ?? 'flex-end'}; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -` -const LoadingDataBubble = styled(LoadingBubble)` +const LoadingDataBubble = deprecatedStyled(LoadingBubble)` width: 75%; height: 16px; ` export function Cell({ loading, - width, - minWidth, - maxWidth, - justifyContent, - grow, children, testId, -}: PropsWithChildren<{ - loading?: boolean - width?: number - minWidth?: number - maxWidth?: number - grow?: boolean - justifyContent?: string - testId?: string -}>) { + ...rest +}: PropsWithChildren< + { + loading?: boolean + testId?: string + } & Partial +>) { return ( - {loading ? : children} - + ) } diff --git a/apps/web/src/components/Table/Filter.tsx b/apps/web/src/components/Table/Filter.tsx index 470a7e34844..d2f2076bca0 100644 --- a/apps/web/src/components/Table/Filter.tsx +++ b/apps/web/src/components/Table/Filter.tsx @@ -1,49 +1,48 @@ -import Column from 'components/Column' -import Row from 'components/Row' import { DropdownIcon } from 'components/Table/icons' import { useScreenSize } from 'hooks/screenSize' import { useOnClickOutside } from 'hooks/useOnClickOutside' -import styled from 'lib/styled-components' +import deprecatedStyled from 'lib/styled-components' import { Portal } from 'nft/components/common/Portal' import { Checkbox } from 'nft/components/layout/Checkbox' -import { Fragment, useCallback, useRef, useState } from 'react' +import { RefObject, useCallback, useRef, useState } from 'react' import { ThemedText } from 'theme/components' -import { Z_INDEX } from 'theme/zIndex' +import { Flex, styled } from 'ui/src' -const StyledDropdownIcon = styled(DropdownIcon)` +const StyledDropdownIcon = deprecatedStyled(DropdownIcon)` position: relative; ` -const FilterDropdown = styled(Column)<{ isSticky?: boolean }>` - position: absolute; - top: ${({ isSticky }) => (isSticky ? 64 : 42)}px; - padding: 8px; - border-radius: 12px; - background: ${({ theme }) => theme.surface2}; - gap: 8px; - width: 240px; - border-radius: 12px; - border: ${({ theme }) => `1px solid ${theme.surface3}`}; - box-shadow: ${({ theme }) => theme.deprecated_deepShadow}; - opacity: 1 !important; - z-index: ${Z_INDEX.modal}; +const FilterDropdown = styled(Flex, { + position: 'absolute', + p: '$padding8', + borderRadius: '$rounded12', + backgroundColor: '$surface2', + gap: '$gap8', + width: 240, + borderWidth: 1, + borderColor: '$surface3', + borderStyle: 'solid', + shadowColor: '$shadow', + opacity: 1, + zIndex: '$modal', + $md: { + position: 'fixed' as any, + bottom: 0, + left: 0, + top: 'unset', + width: '100vw', + }, +}) - @media only screen and (max-width: ${({ theme }) => `${theme.breakpoint.sm}px`}) { - position: fixed; - bottom: 0; - left: 0; - top: unset; - width: 100vw; - } -` - -const FilterRow = styled(Row)` - padding: 10px 8px; - justify-content: space-between; - border-radius: 8px; - &:hover { - background: ${({ theme }) => theme.surface3}; - } -` +const FilterRow = styled(Flex, { + row: true, + py: 10, + px: '$padding8', + justifyContent: 'space-between', + borderRadius: '$rounded8', + hoverStyle: { + backgroundColor: '$surface3', + }, +}) interface FilterProps { allFilters: T[] @@ -51,7 +50,7 @@ interface FilterProps { setFilters: (filter: T[]) => void isOpen: boolean toggleFilterModal: () => void - isSticky?: boolean + anchorRef: RefObject } export function Filter({ @@ -60,7 +59,7 @@ export function Filter({ setFilters, isOpen, toggleFilterModal, - isSticky, + anchorRef, }: FilterProps) { const [hoveredRow, setHoveredRow] = useState(-1) const isScreenSize = useScreenSize() @@ -78,19 +77,21 @@ export function Filter({ }, [activeFilter, setFilters], ) - // Need to put the modal in a Portal when on mobile to show over promo banner - const Wrapper = isMobile ? Portal : Fragment return ( <> - {isOpen && ( - - + {isOpen && anchorRef.current && ( + + {allFilters.map((filter, index) => ( { + onPress={(e) => { e.stopPropagation() e.preventDefault() handleFilterOptionClick(filter) @@ -103,7 +104,7 @@ export function Filter({ ))} - + )} ) diff --git a/apps/web/src/components/Table/__snapshots__/styled.test.tsx.snap b/apps/web/src/components/Table/__snapshots__/styled.test.tsx.snap index 9300ac70180..15e6723abc3 100644 --- a/apps/web/src/components/Table/__snapshots__/styled.test.tsx.snap +++ b/apps/web/src/components/Table/__snapshots__/styled.test.tsx.snap @@ -2,40 +2,7 @@ exports[`TokenLinkCell renders known token on a different chain 1`] = ` - .c1 { - box-sizing: border-box; - margin: 0; - min-width: 0; - max-width: 68px; -} - -.c2 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 4px; -} - -.c7 { - color: #222222; - -webkit-letter-spacing: -0.01em; - -moz-letter-spacing: -0.01em; - -ms-letter-spacing: -0.01em; - letter-spacing: -0.01em; -} - -.c4 { + .c2 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -46,19 +13,19 @@ exports[`TokenLinkCell renders known token on a different chain 1`] = ` left: 0; } -.c4 img { +.c2 img { width: 16px; height: 16px; border-radius: 50%; } -.c5 { +.c3 { width: 8px; height: 16px; border-radius: 50%; } -.c6 { +.c4 { background-color: #F9F9F9; border-radius: 2px; width: 6px; @@ -81,7 +48,7 @@ exports[`TokenLinkCell renders known token on a different chain 1`] = ` justify-content: center; } -.c3 { +.c1 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -114,12 +81,6 @@ exports[`TokenLinkCell renders known token on a different chain 1`] = ` opacity: 0.4; } -.c8 { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} -
Polygon logo
-
USDC -
+
@@ -182,40 +144,7 @@ exports[`TokenLinkCell renders known token on a different chain 1`] = ` exports[`TokenLinkCell renders known token on mainnet 1`] = ` - .c1 { - box-sizing: border-box; - margin: 0; - min-width: 0; - max-width: 68px; -} - -.c2 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 4px; -} - -.c6 { - color: #222222; - -webkit-letter-spacing: -0.01em; - -moz-letter-spacing: -0.01em; - -ms-letter-spacing: -0.01em; - letter-spacing: -0.01em; -} - -.c4 { + .c2 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -226,19 +155,19 @@ exports[`TokenLinkCell renders known token on mainnet 1`] = ` left: 0; } -.c4 img { +.c2 img { width: 16px; height: 16px; border-radius: 50%; } -.c5 { +.c3 { width: 8px; height: 16px; border-radius: 50%; } -.c3 { +.c1 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -271,12 +200,6 @@ exports[`TokenLinkCell renders known token on mainnet 1`] = ` opacity: 0.4; } -.c7 { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} -
-
USDC -
+
@@ -327,40 +251,7 @@ exports[`TokenLinkCell renders known token on mainnet 1`] = ` exports[`TokenLinkCell renders unknown token 1`] = ` - .c1 { - box-sizing: border-box; - margin: 0; - min-width: 0; - max-width: 68px; -} - -.c2 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 4px; -} - -.c6 { - color: #222222; - -webkit-letter-spacing: -0.01em; - -moz-letter-spacing: -0.01em; - -ms-letter-spacing: -0.01em; - letter-spacing: -0.01em; -} - -.c4 { + .c2 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -371,19 +262,19 @@ exports[`TokenLinkCell renders unknown token 1`] = ` left: 0; } -.c4 img { +.c2 img { width: 16px; height: 16px; border-radius: 50%; } -.c5 { +.c3 { width: 8px; height: 16px; border-radius: 50%; } -.c3 { +.c1 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -416,12 +307,6 @@ exports[`TokenLinkCell renders unknown token 1`] = ` opacity: 0.4; } -.c7 { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} -
-
UNKNOWN -
+
diff --git a/apps/web/src/components/Table/index.tsx b/apps/web/src/components/Table/index.tsx index e2010ade09d..12d8933561c 100644 --- a/apps/web/src/components/Table/index.tsx +++ b/apps/web/src/components/Table/index.tsx @@ -28,9 +28,9 @@ import { TableRowLink, } from 'components/Table/styled' import useDebounce from 'hooks/useDebounce' -import { useTheme } from 'lib/styled-components' import { useEffect, useMemo, useRef, useState } from 'react' import { ScrollSync, ScrollSyncPane } from 'react-scroll-sync' +import { NAV_HEIGHT } from 'theme' import { ThemedText } from 'theme/components' import { FadePresence } from 'theme/components/FadePresence' import { Z_INDEX } from 'theme/zIndex' @@ -147,7 +147,6 @@ export function Table({ distanceToBottom: LOAD_MORE_BOTTOM_OFFSET, }) const { distanceFromTop, distanceToBottom } = useDebounce(scrollPosition, 125) - const theme = useTheme() const tableBodyRef = useRef(null) const lastLoadedLengthRef = useRef(data?.length ?? 0) const canLoadMore = useRef(true) @@ -204,16 +203,16 @@ export function Table({ }) const headerHeight = useMemo(() => { const header = document.getElementById('AppHeader') - return header?.clientHeight || theme.navHeight - }, [theme.navHeight]) + return header?.clientHeight || NAV_HEIGHT + }, []) return (
- + - + {table.getFlatHeaders().map((header) => ( {flexRender(header.column.columnDef.header, header.getContext())} @@ -223,7 +222,7 @@ export function Table({ {showReturn && ( - + { @@ -243,16 +242,18 @@ export function Table({ )} - + - - - - - - + {loadingMore && ( + + + + + + + )}
diff --git a/apps/web/src/components/Table/styled.tsx b/apps/web/src/components/Table/styled.tsx index 399b69a748f..db03fbb3ddc 100644 --- a/apps/web/src/components/Table/styled.tsx +++ b/apps/web/src/components/Table/styled.tsx @@ -1,19 +1,18 @@ import { PortfolioLogo } from 'components/AccountDrawer/MiniPortfolio/PortfolioLogo' import { ButtonLight } from 'components/Button' -import Column from 'components/Column' -import { HideScrollBarStyles } from 'components/Common' -import Row from 'components/Row' import { useAbbreviatedTimeString } from 'components/Table/utils' import { MouseoverTooltip, TooltipSize } from 'components/Tooltip' import { NATIVE_CHAIN_ID } from 'constants/tokens' import { OrderDirection, getTokenDetailsURL, supportedChainIdFromGQLChain, unwrapToken } from 'graphql/data/util' import { useCurrency } from 'hooks/Tokens' import { useActiveLocale } from 'hooks/useActiveLocale' -import styled, { css } from 'lib/styled-components' +import deprecatedStyled from 'lib/styled-components' +import { PropsWithChildren } from 'react' import { ArrowDown, CornerLeftUp, ExternalLink as ExternalLinkIcon } from 'react-feather' import { Link } from 'react-router-dom' -import { ClickableStyle, EllipsisStyle, ExternalLink, ThemedText } from 'theme/components' +import { ClickableStyle, ClickableTamaguiStyle, EllipsisTamaguiStyle, ThemedText } from 'theme/components' import { Z_INDEX } from 'theme/zIndex' +import { Anchor, Flex, Text, View, styled } from 'ui/src' import { Token } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { useTranslation } from 'uniswap/src/i18n' import { UniverseChainId } from 'uniswap/src/types/chains' @@ -21,177 +20,227 @@ import { UniverseChainId } from 'uniswap/src/types/chains' export const SHOW_RETURN_TO_TOP_OFFSET = 500 export const LOAD_MORE_BOTTOM_OFFSET = 50 -export const TableContainer = styled(Column)<{ $maxWidth?: number; $maxHeight?: number }>` - max-width: ${({ $maxWidth }) => $maxWidth}px; - max-height: ${({ $maxHeight }) => $maxHeight}px; - // Center layout - justify-content: center; - align-items: center; - margin: 0px auto 24px auto; -` -const StickyStyles = css<{ $top: number }>` - position: sticky; - position: -webkit-sticky; - top: ${({ $top }) => $top}px; - z-index: ${Z_INDEX.under_dropdown}; +export const TableContainer = styled(Flex, { + centered: true, + m: '0 auto 24px auto', + className: 'scrollbar-hidden', +}) - :before { - content: ''; - height: 12px; +export const TableHead = (props: PropsWithChildren<{ $isSticky: boolean; $top: number }>): JSX.Element => { + if (props.$isSticky) { + return ( + + {props.$isSticky &&
} + {props.children} + + ) + } else { + return ( + + {props.children} + + ) } -` -export const TableHead = styled.div<{ $isSticky?: boolean; $top: number }>` - width: 100%; - position: relative; - ${({ $isSticky }) => ($isSticky ? StickyStyles : '')} - // Place header at bottom of container (top of container used to add distance from nav / hide rows) - display: flex; - flex-direction: column; - justify-content: flex-end; - // Solid background that matches surface, in order to hide rows as they scroll behind header - background: ${({ theme }) => theme.surface1}; -` -export const TableBodyContainer = styled(Column)` - width: 100%; - position: relative; - overflow-x: auto; - overscroll-behavior-x: none; - border-right: 1px solid ${({ theme }) => theme.surface3}; - border-bottom: 1px solid ${({ theme }) => theme.surface3}; - border-left: 1px solid ${({ theme }) => theme.surface3}; - border-bottom-right-radius: 20px; - border-bottom-left-radius: 20px; - ${HideScrollBarStyles} -` -export const ReturnButton = styled(ButtonLight)` +} + +export const TableBodyContainer = styled(View, { + width: '100%', + position: 'relative', + className: 'scrollbar-hidden', + justifyContent: 'flex-start', + borderColor: '$surface3', + borderStyle: 'solid', + borderWidth: 1, + borderTopWidth: 0, + borderBottomRightRadius: '$rounded20', + borderBottomLeftRadius: '$rounded20', + '$platform-web': { + overscrollBehaviorX: 'none', + overflowX: 'auto', + overflowY: 'scroll', + }, +}) + +export const ReturnButton = deprecatedStyled(ButtonLight)` font-size: 16px; border-radius: 900px; width: fit-content; margin-top: 8px; ` -export const ReturnIcon = styled(CornerLeftUp)` + +export const ReturnIcon = deprecatedStyled(CornerLeftUp)` width: 16px; height: 16px; margin-right: 8px; ` -export const ReturnButtonContainer = styled(Row)<{ $top?: number }>` - position: absolute; - justify-content: center; - top: ${({ $top }) => $top}px; - left: 50%; - transform: translateX(-50%); - width: max-content; -` -export const LoadingIndicatorContainer = styled(Row)<{ show: boolean }>` - position: sticky; - justify-content: center; - margin-top: -48px; - visibility: ${({ show }) => (show ? 'visible' : 'hidden')}; -` -export const LoadingIndicator = styled(Row)` - background: ${({ theme }) => theme.accent2}; - border-radius: 8px; - width: fit-content; - padding: 8px; - color: ${({ theme }) => theme.accent1}; - font-size: 16px; - font-weight: 535; - gap: 8px; - height: 34px; - z-index: ${Z_INDEX.under_dropdown}; -` -const TableRow = styled(Row)` - padding: 0px 12px; - width: fit-content; - min-width: 100%; - display: flex; - min-height: 64px; -` -export const DataRow = styled(TableRow)` - @media not all and (hover: none) { - :hover { - background: ${({ theme }) => theme.surface3}; - } - } -` -export const NoDataFoundTableRow = styled(TableRow)` - justify-content: center; -` +export const ReturnButtonContainer = styled(Flex, { + position: 'absolute', + justifyContent: 'center', + left: '50%', + transform: 'translateX(-50%)', + width: 'max-content', +}) -export const HeaderRow = styled(TableRow)<{ $dimmed?: boolean }>` - border: 1px solid ${({ theme }) => theme.surface3}; - border-top-right-radius: 20px; - border-top-left-radius: 20px; - overflow: auto; - width: unset; - min-height: 52px; - background: ${({ theme }) => theme.surface2}; - ${HideScrollBarStyles} - overscroll-behavior: none; +export const LoadingIndicatorContainer = styled(Flex, { + row: true, + alignItems: 'center', + justifyContent: 'center', + mt: -48, + '$platform-web': { + position: 'sticky', + }, +}) - ${({ $dimmed }) => $dimmed && 'opacity: 0.4;'} -` -export const CellContainer = styled.div` - display: flex; - flex-grow: 1; +export const LoadingIndicator = styled(Flex, { + row: true, + backgroundColor: '$accent2', + borderRadius: '$rounded8', + width: 'fit-content', + p: '$padding8', + gap: '$gap8', + height: 34, + zIndex: Z_INDEX.under_dropdown, +}) - &:last-child { - justify-content: flex-end; - } +const TableRow = styled(Flex, { + row: true, + alignItems: 'center', + px: '$padding12', + width: 'fit-content', + minWidth: '100%', + minHeight: 64, +}) - &:first-child { - flex-grow: 0; - } -` -export const StyledExternalLink = styled(ExternalLink)` - text-decoration: none; - ${ClickableStyle} - color: ${({ theme }) => theme.neutral1}; -` -const StyledInternalLink = styled(Link)` +export const DataRow = styled(TableRow, { + hoverStyle: { + backgroundColor: '$surface3', + }, +}) + +export const NoDataFoundTableRow = styled(TableRow, { + justifyContent: 'center', +}) + +export const HeaderRow = styled(TableRow, { + borderWidth: 1, + borderStyle: 'solid', + borderColor: '$surface3', + borderTopRightRadius: '$rounded20', + borderTopLeftRadius: '$rounded20', + width: 'unset', + minHeight: 52, + backgroundColor: '$surface2', + scrollbarWidth: 'none', + className: 'scrollbar-hidden', + + '$platform-web': { + overscrollBehavior: 'none', + overflow: 'auto', + }, + variants: { + dimmed: { + true: { + opacity: 0.4, + }, + }, + } as const, +}) + +export const CellContainer = styled(Flex, { + grow: true, + className: 'first-child-flex-grow-0 last-child-justify-end', +}) + +export const StyledExternalLink = styled(Anchor, { + textDecorationLine: 'none', + ...ClickableTamaguiStyle, + color: '$neutral1', + target: '_blank', + rel: 'noopener noreferrer', +}) +const StyledInternalLink = deprecatedStyled(Link)` text-decoration: none; ${ClickableStyle} color: ${({ theme }) => theme.neutral1}; ` -export const TableRowLink = styled(Link)` +export const TableRowLink = deprecatedStyled(Link)` color: none; text-decoration: none; cursor: pointer; ` -export const ClickableHeaderRow = styled(Row)<{ $justify?: string }>` - justify-content: ${({ $justify }) => $justify ?? 'flex-end'}; - cursor: pointer; - width: 100%; - gap: 4px; - ${ClickableStyle} -` -export const HeaderArrow = styled(ArrowDown)<{ direction: OrderDirection }>` +export const ClickableHeaderRow = styled(Flex, { + row: true, + alignItems: 'center', + justifyContent: 'flex-end', + width: '100%', + gap: '$gap4', + + ...ClickableTamaguiStyle, +}) + +export const HeaderArrow = deprecatedStyled(ArrowDown)<{ direction: OrderDirection }>` height: 16px; width: 16px; color: ${({ theme }) => theme.neutral1}; transform: ${({ direction }) => (direction === 'asc' ? 'rotate(180deg)' : 'rotate(0deg)')}; ` -export const HeaderSortText = styled(ThemedText.BodySecondary)<{ $active?: boolean }>` - ${({ $active, theme }) => $active && `color: ${theme.neutral1};`} -` -export const FilterHeaderRow = styled(Row)<{ modalOpen?: boolean }>` - ${({ modalOpen }) => !modalOpen && ClickableStyle} - cursor: pointer; - user-select: none; - gap: 4px; -` -const StyledTimestampRow = styled(StyledExternalLink)` +export const HeaderSortText = styled(Text, { + variant: 'body2', + color: '$neutral2', + + variants: { + active: { + true: { + color: '$neutral1', + }, + }, + } as const, +}) + +export const FilterHeaderRow = styled(Flex, { + row: true, + alignItems: 'center', + userSelect: 'none', + gap: '$gap4', + animation: 'fast', + + ...ClickableTamaguiStyle, + + variants: { + clickable: { + true: ClickableTamaguiStyle, + }, + } as const, +}) + +const StyledTimestampRow = deprecatedStyled(StyledExternalLink)` display: flex; flex-direction: row; align-items: center; gap: 8px; width: 100%; ` -const StyledExternalLinkIcon = styled(ExternalLinkIcon)` +const StyledExternalLinkIcon = deprecatedStyled(ExternalLinkIcon)` display: none; height: 16px; width: 16px; @@ -236,9 +285,12 @@ export const TimestampCell = ({ timestamp, link }: { timestamp: number; link: st ) } -const TokenSymbolText = styled(ThemedText.BodyPrimary)` - ${EllipsisStyle} -` +const TokenSymbolText = styled(Text, { + variant: 'body2', + color: '$neutral1', + ...EllipsisTamaguiStyle, +}) + /** * Given a token displays the Token's Logo and Symbol with a link to its TDP * @param token @@ -257,7 +309,7 @@ export const TokenLinkCell = ({ token }: { token: Token }) => { chain: token.chain, })} > - + { currencies={isNative ? [nativeCurrency] : undefined} /> {unwrappedToken?.symbol ?? t('common.unknown').toUpperCase()} - + ) } diff --git a/apps/web/src/components/TokenSafety/TokenSafetyIcon.tsx b/apps/web/src/components/TokenSafety/TokenSafetyIcon.tsx index a68101408b6..1de1d303856 100644 --- a/apps/web/src/components/TokenSafety/TokenSafetyIcon.tsx +++ b/apps/web/src/components/TokenSafety/TokenSafetyIcon.tsx @@ -1,41 +1,26 @@ import { Warning } from 'constants/tokenSafety' -import styled, { css } from 'lib/styled-components' import { AlertTriangle, Slash } from 'react-feather' +import { Flex, styled, useSporeColors } from 'ui/src' import { SafetyLevel } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' -const WarningContainer = styled.div` - margin-left: 4px; - display: flex; - justify-content: center; -` - -const WarningIconStyle = css<{ size?: string }>` - width: ${({ size }) => size ?? '1em'}; - height: ${({ size }) => size ?? '1em'}; -` - -const WarningIcon = styled(AlertTriangle)` - ${WarningIconStyle}; - color: ${({ theme }) => theme.neutral3}; -` - -export const BlockedIcon = styled(Slash)` - ${WarningIconStyle} - color: ${({ theme }) => theme.neutral2}; -` +const WarningContainer = styled(Flex, { + ml: '$spacing4', + justifyContent: 'center', +}) export default function TokenSafetyIcon({ warning }: { warning?: Warning }) { + const colors = useSporeColors() switch (warning?.level) { case SafetyLevel.Blocked: return ( - + ) case SafetyLevel.StrongWarning: return ( - + ) default: diff --git a/apps/web/src/components/Tokens/TokenDetails/ActivitySection.tsx b/apps/web/src/components/Tokens/TokenDetails/ActivitySection.tsx index 0eebc47f627..5494a45b981 100644 --- a/apps/web/src/components/Tokens/TokenDetails/ActivitySection.tsx +++ b/apps/web/src/components/Tokens/TokenDetails/ActivitySection.tsx @@ -1,22 +1,21 @@ -import Row from 'components/Row' import { TokenDetailsPoolsTable } from 'components/Tokens/TokenDetails/tables/TokenDetailsPoolsTable' import { TransactionsTable } from 'components/Tokens/TokenDetails/tables/TransactionsTable' -import styled from 'lib/styled-components' import { useTDPContext } from 'pages/TokenDetails/TDPContext' import { useState } from 'react' -import { ClickableStyle, ThemedText } from 'theme/components' +import { ClickableTamaguiStyle } from 'theme/components' +import { Flex, styled, Text } from 'ui/src' import { Trans } from 'uniswap/src/i18n' -const Container = styled.div` - width: 100%; - display: flex; - flex-direction: column; -` -const Tab = styled(ThemedText.HeadlineMedium)<{ isActive?: boolean }>` - cursor: pointer; - color: ${({ isActive, theme }) => (isActive ? theme.neutral1 : theme.neutral2)}; - ${ClickableStyle}; -` +const Container = styled(Flex, { + width: '100%', +}) + +const Tab = styled(Text, { + color: '$neutral1', + variant: 'heading3', + ...ClickableTamaguiStyle, +}) + enum ActivityTab { Txs, Pools, @@ -31,14 +30,20 @@ export function ActivitySection() { } return ( - - setActivityInView(ActivityTab.Txs)}> + + setActivityInView(ActivityTab.Txs)} + > - setActivityInView(ActivityTab.Pools)}> + setActivityInView(ActivityTab.Pools)} + > - + {activityInView === ActivityTab.Txs && } {activityInView === ActivityTab.Pools && ( diff --git a/apps/web/src/components/Tokens/TokenDetails/ChartSection/ChartTypeSelector.tsx b/apps/web/src/components/Tokens/TokenDetails/ChartSection/ChartTypeSelector.tsx index 7627566af3b..bed8b434a2a 100644 --- a/apps/web/src/components/Tokens/TokenDetails/ChartSection/ChartTypeSelector.tsx +++ b/apps/web/src/components/Tokens/TokenDetails/ChartSection/ChartTypeSelector.tsx @@ -1,22 +1,24 @@ import { CHART_TYPE_LABELS, ChartType, PriceChartType } from 'components/Charts/utils' import { DropdownSelector, InternalMenuItem } from 'components/DropdownSelector' import { MouseoverTooltip } from 'components/Tooltip' -import { css, useTheme } from 'lib/styled-components' -import { useReducer } from 'react' +import { useTheme } from 'lib/styled-components' +import { useState } from 'react' import { Check, Info } from 'react-feather' +import { FlexProps } from 'ui/src' import { Trans } from 'uniswap/src/i18n' -import { isMobile } from 'utilities/src/platform' +import { isMobileWeb } from 'utilities/src/platform' -const StyledDropdownButton = css` - border-radius: 20px; - width: 100%; - height: 36px; -` -const StyledMenuFlyout = css` - min-width: 130px; - border-radius: 16px; - right: 0px; -` +const StyledDropdownButton = { + borderRadius: 20, + width: '100%', + height: 36, +} satisfies FlexProps + +const StyledMenuFlyout = { + minWidth: 130, + borderRadius: '$rounded16', + right: 0, +} satisfies FlexProps interface ChartTypeSelectorOption { value: T // Value to be selected/stored, used as default display value @@ -48,7 +50,7 @@ export function ChartTypeDropdown({ tooltipText?: string }) { const theme = useTheme() - const [isMenuOpen, toggleMenu] = useReducer((s) => !s, false) + const [isMenuOpen, toggleMenu] = useState(false) return ( ({ } - placement={!isMobile ? 'right' : undefined} + placement={!isMobileWeb ? 'right' : undefined} > { + onPress={() => { if (disabled) { return } onSelectOption(chartType) - toggleMenu() + toggleMenu(false) }} disabled={disabled} > {display ?? CHART_TYPE_LABELS[chartType]} {chartType === currentChartType && } - {disabled && } + {disabled && } ) @@ -86,8 +88,9 @@ export function ChartTypeDropdown({ } tooltipText={tooltipText} - buttonCss={StyledDropdownButton} - menuFlyoutCss={StyledMenuFlyout} + buttonStyle={StyledDropdownButton} + dropdownStyle={StyledMenuFlyout} + adaptToSheet={false} /> ) } diff --git a/apps/web/src/components/Tokens/TokenDetails/ChartSection/index.tsx b/apps/web/src/components/Tokens/TokenDetails/ChartSection/index.tsx index 281d6162589..92432d66ae0 100644 --- a/apps/web/src/components/Tokens/TokenDetails/ChartSection/index.tsx +++ b/apps/web/src/components/Tokens/TokenDetails/ChartSection/index.tsx @@ -22,9 +22,9 @@ import { } from 'components/Tokens/TokenTable/TimeSelector' import { TimePeriod, toHistoryDuration } from 'graphql/data/util' import { useAtomValue } from 'jotai/utils' -import styled from 'lib/styled-components' import { useTDPContext } from 'pages/TokenDetails/TDPContext' import { useMemo, useState } from 'react' +import { Flex, styled } from 'ui/src' import { Chain } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { Trans } from 'uniswap/src/i18n' @@ -36,34 +36,17 @@ export const DEFAULT_PILL_TIME_SELECTOR_OPTIONS = ORDERED_TIMES.map((time: TimeP value: DISPLAYS[time], })) as PillMultiToggleOption[] -export const ChartActionsContainer = styled.div` - display: flex; - flex-direction: row-reverse; - width: 100%; - justify-content: space-between; - align-items: center; - margin-top: 12px; - - @media only screen and (max-width: ${({ theme }) => theme.breakpoint.sm}px) { - flex-direction: column; - gap: 16px; - } -` -const TimePeriodSelectorContainer = styled.div` - @media only screen and (max-width: ${({ theme }) => theme.breakpoint.sm}px) { - width: 100%; - } -` - -const ChartTypeSelectorContainer = styled.div` - display: flex; - gap: 8px; - @media only screen and (max-width: ${({ theme }) => theme.breakpoint.sm}px) { - width: 100%; - display: grid; - grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); - } -` +export const ChartActionsContainer = styled(Flex, { + flexDirection: 'row-reverse', + width: '100%', + justifyContent: 'space-between', + alignItems: 'center', + mt: 12, + $md: { + flexDirection: 'column', + gap: 16, + }, +}) /** Represents a variety of query result shapes, discriminated via additional `chartType` field. */ type ActiveQuery = @@ -178,13 +161,23 @@ function ChartControls() { return ( - + {activeQuery.chartType === ChartType.PRICE && ( - +
+ +
)} -
- + + - +
) } diff --git a/apps/web/src/components/Tokens/TokenDetails/ShareButton.tsx b/apps/web/src/components/Tokens/TokenDetails/ShareButton.tsx index 3e74f993ed3..033162bfb1d 100644 --- a/apps/web/src/components/Tokens/TokenDetails/ShareButton.tsx +++ b/apps/web/src/components/Tokens/TokenDetails/ShareButton.tsx @@ -1,22 +1,18 @@ import { DropdownSelector } from 'components/DropdownSelector' -import { CheckMark } from 'components/Icons/CheckMark' import { Share as ShareIcon } from 'components/Icons/Share' import { TwitterXLogo } from 'components/Icons/TwitterX' import { ActionButtonStyle, ActionMenuFlyoutStyle } from 'components/Tokens/TokenDetails/shared' import useCopyClipboard from 'hooks/useCopyClipboard' -import useDisableScrolling from 'hooks/useDisableScrolling' -import { useOnClickOutside } from 'hooks/useOnClickOutside' -import styled, { useTheme } from 'lib/styled-components' -import { useRef } from 'react' +import styled from 'lib/styled-components' +import { useState } from 'react' import { Link } from 'react-feather' import { useSearchParams } from 'react-router-dom' -import { useModalIsOpen, useToggleModal } from 'state/application/hooks' -import { ApplicationModal } from 'state/application/reducer' import { colors } from 'theme/colors' -import { ThemedText } from 'theme/components' import { opacify } from 'theme/utils' -import { Trans, t } from 'uniswap/src/i18n' -import { isMobile } from 'utilities/src/platform' +import { Text, useSporeColors } from 'ui/src' +import { Check } from 'ui/src/components/icons' +import { useTranslation } from 'uniswap/src/i18n/useTranslation' +import { isMobileWeb } from 'utilities/src/platform' const TWITTER_WIDTH = 560 const TWITTER_HEIGHT = 480 @@ -49,56 +45,47 @@ export function openShareTweetWindow(name: string) { } export default function ShareButton({ name, utmSource }: { name: string; utmSource: string }) { - const theme = useTheme() - const node = useRef(null) - const open = useModalIsOpen(ApplicationModal.SHARE) - const toggleShare = useToggleModal(ApplicationModal.SHARE) - useOnClickOutside(node, open ? toggleShare : undefined) - - useDisableScrolling(open) + const colors = useSporeColors() + const { t } = useTranslation() + const [isOpen, setIsOpen] = useState(false) const [searchParams] = useSearchParams() - const utmTag = `${searchParams.size > 0 ? '&' : '?'}utm_source=${utmSource}&utm_medium=${isMobile ? 'mobile' : 'web'}` + const utmTag = `${searchParams.size > 0 ? '&' : '?'}utm_source=${utmSource}&utm_medium=${isMobileWeb ? 'mobile' : 'web'}` const currentLocation = window.location.href + utmTag const [isCopied, setCopied] = useCopyClipboard() return ( -
- } - tooltipText={t('common.share')} - internalMenuItems={ - <> - setCopied(currentLocation)}> - {isCopied ? ( - - ) : ( - - )} - - {isCopied ? : } - - - { - toggleShare() - openShareTweetWindow(name) - }} - > - - - - - - - } - hideChevron - buttonCss={ActionButtonStyle} - menuFlyoutCss={ActionMenuFlyoutStyle} - /> -
+ } + tooltipText={t('common.share')} + internalMenuItems={ + <> + setCopied(currentLocation)}> + {isCopied ? ( + + ) : ( + + )} + {isCopied ? t('common.copied') : t('common.copyLink.button')} + + { + setIsOpen(false) + openShareTweetWindow(name) + }} + > + + {t('common.share.shareToTwitter')} + + + } + hideChevron + buttonStyle={ActionButtonStyle} + dropdownStyle={ActionMenuFlyoutStyle} + adaptToSheet={false} + /> ) } diff --git a/apps/web/src/components/Tokens/TokenDetails/Skeleton.tsx b/apps/web/src/components/Tokens/TokenDetails/Skeleton.tsx index 8c73d332f4e..c73a012705a 100644 --- a/apps/web/src/components/Tokens/TokenDetails/Skeleton.tsx +++ b/apps/web/src/components/Tokens/TokenDetails/Skeleton.tsx @@ -2,7 +2,6 @@ import { Currency } from '@uniswap/sdk-core' import { BreadcrumbNavContainer, BreadcrumbNavLink } from 'components/BreadcrumbNav' import { ChartSkeleton } from 'components/Charts/LoadingState' import { ChartType } from 'components/Charts/utils' -import Row from 'components/Row' import { AboutContainer, AboutHeader } from 'components/Tokens/TokenDetails/About' import { TDP_CHART_HEIGHT_PX } from 'components/Tokens/TokenDetails/ChartSection' import { StatPair, StatWrapper, StatsWrapper } from 'components/Tokens/TokenDetails/StatsSection' @@ -13,168 +12,185 @@ import { useChainFromUrlParam } from 'constants/chains' import { NATIVE_CHAIN_ID } from 'constants/tokens' import { getSupportedGraphQlChain } from 'graphql/data/util' import { useCurrency } from 'hooks/Tokens' -import styled, { css } from 'lib/styled-components' +import deprecatedStyled from 'lib/styled-components' import { ReactNode } from 'react' import { ChevronRight } from 'react-feather' import { useParams } from 'react-router-dom' -import { BREAKPOINTS } from 'theme' -import { ClickableStyle } from 'theme/components' -import { textFadeIn } from 'theme/styles' +import { ClickableTamaguiStyle } from 'theme/components' import { capitalize } from 'tsafe' +import { Anchor, Flex, Text, TextProps, styled } from 'ui/src' import { Trans } from 'uniswap/src/i18n' import { ExplorerDataType, getExplorerLink } from 'utils/getExplorerLink' const SWAP_COMPONENT_WIDTH = 360 -export const TokenDetailsLayout = styled.div` - display: flex; - padding: 0 16px 52px; - justify-content: center; - width: 100%; - gap: 40px; +export const TokenDetailsLayout = styled(Flex, { + row: true, + justifyContent: 'center', + width: '100%', + gap: 40, + py: '$spacing48', + px: '$padding20', - @media screen and (min-width: ${({ theme }) => theme.breakpoint.md}px) { - padding: 48px 20px; - } - @media screen and (max-width: ${({ theme }) => theme.breakpoint.lg}px) { - flex-direction: column; - align-items: center; - } - @media screen and (min-width: ${({ theme }) => theme.breakpoint.xl}px) { - gap: 60px; - } -` + $lg: { + pt: 0, + px: '$padding16', + pb: 52, + }, + $xl: { + flexDirection: 'column', + alignItems: 'center', + }, + $xxl: { + gap: 60, + }, +}) -export const LeftPanel = styled.div` - flex: 1; - max-width: 780px; - overflow: hidden; - width: 100%; -` -export const RightPanel = styled.div` - display: flex; - padding-top: 53px; - flex-direction: column; - gap: 40px; - width: ${SWAP_COMPONENT_WIDTH}px; +export const LeftPanel = styled(Flex, { + maxWidth: 780, + overflow: 'hidden', + width: '100%', + flexGrow: 1, + flexShrink: 1, +}) - @media screen and (max-width: ${({ theme }) => theme.breakpoint.lg}px) { - width: 100%; - max-width: 780px; - } -` +export const RightPanel = styled(Flex, { + pt: 53, + gap: 40, + width: SWAP_COMPONENT_WIDTH, + + $xl: { + width: '100%', + maxWidth: 780, + }, +}) + +export const TokenInfoContainer = styled(Flex, { + row: true, + justifyContent: 'space-between', + alignItems: 'center', + gap: '$gap20', + pt: '$padding8', + mb: '$spacing20', + animation: 'quick', +}) + +export const TokenNameCell = styled(Flex, { + flexDirection: 'row', + gap: '$gap12', + alignItems: 'center', + pt: '$spacing4', + minWidth: 32, + $md: { + flexDirection: 'column', + alignItems: 'flex-start', + }, +}) -export const TokenInfoContainer = styled.div` - display: flex; - justify-content: space-between; - align-items: center; - padding-top: 8px; - margin-bottom: 20px; - gap: 20px; - ${textFadeIn}; - animation-duration: ${({ theme }) => theme.transition.duration.medium}; -` -export const TokenNameCell = styled.div` - display: flex; - gap: 12px; - font-size: 20px; - line-height: 28px; - align-items: center; - padding-top: 4px; - min-width: 32px; - @media screen and (max-width: ${({ theme }) => theme.breakpoint.sm}px) { - flex-direction: column; - align-items: flex-start; - } -` /* Loading state bubbles */ -const DetailBubble = styled(LoadingBubble)` +const DetailBubble = deprecatedStyled(LoadingBubble)` height: 16px; width: 180px; ` -const SquaredBubble = styled(DetailBubble)` + +const SquaredBubble = deprecatedStyled(DetailBubble)` height: 32px; border-radius: 8px; ` -const NavBubble = styled(DetailBubble)` + +const NavBubble = deprecatedStyled(DetailBubble)` width: 169px; ` -const TokenLogoBubble = styled(DetailBubble)` + +const TokenLogoBubble = deprecatedStyled(DetailBubble)` width: 32px; height: 32px; border-radius: 50%; ` -const TitleBubble = styled(DetailBubble)` +const TitleBubble = deprecatedStyled(DetailBubble)` height: 36px; width: 136px; ` -const SectionBubble = styled(SquaredBubble)` +const SectionBubble = deprecatedStyled(SquaredBubble)` width: 120px; ` -const StatTitleBubble = styled(DetailBubble)` +const StatTitleBubble = deprecatedStyled(DetailBubble)` width: 80px; margin-bottom: 4px; ` -const StatBubble = styled(SquaredBubble)` + +const StatBubble = deprecatedStyled(SquaredBubble)` width: 116px; ` -const WideBubble = styled(DetailBubble)` +const WideBubble = deprecatedStyled(DetailBubble)` margin-bottom: 6px; width: 100%; ` -const ThinTitleBubble = styled(WideBubble)` +const ThinTitleBubble = deprecatedStyled(WideBubble)` width: 120px; ` -const HalfWideBubble = styled(WideBubble)` +const HalfWideBubble = deprecatedStyled(WideBubble)` width: 50%; ` -const StatsLoadingContainer = styled.div` - width: 100%; - display: flex; - flex-wrap: wrap; -` - -const ExtraDetailsContainer = styled.div` - padding-top: 24px; -` +const StatsLoadingContainer = styled(Flex, { + row: true, + flexWrap: 'wrap', + width: '100%', +}) -const Space = styled.div<{ heightSize: number }>` - height: ${({ heightSize }) => `${heightSize}px`}; -` +const ExtraDetailsContainer = styled(Flex, { + row: true, + pt: '$spacing24', +}) -const loadingFooterTextCss = css` - color: ${({ theme }) => theme.neutral3}; - font-size: 12px; - font-weight: 500; - line-height: 16px; - text-decoration: none; -` +const loadingFooterTextStyle = { + color: '$neutral3', + fontSize: 12, + fontWeight: '500', + lineHeight: 16, + '$platform-web': { + textDecoration: 'none', + }, +} satisfies TextProps -const LoadingFooterHeaderContainer = styled(Row)` - align-items: center; - ${loadingFooterTextCss} +const LoadingFooterHeaderContainer = styled(Flex, { + row: true, + alignItems: 'center', + pt: '$padding16', + pr: 90, + pb: '$padding8', + pl: 0, + bottom: 0, + right: 0, + justifyContent: 'flex-end', + ...loadingFooterTextStyle, - @media screen and (min-width: ${BREAKPOINTS.md}px) { - padding: 16px 90px 8px 0; - position: fixed; - bottom: 0; - right: 0; - justify-content: flex-end; - } -` + '$platform-web': { + position: 'fixed', + }, + $lg: { + p: 'unset', + position: 'unset', + bottom: 'unset', + right: 'unset', + justifyContent: 'unset', + }, +}) -const LoadingFooterHeader = styled.h1` - ${loadingFooterTextCss} -` +const LoadingFooterHeader = styled(Text, { + variant: 'heading1', + ...loadingFooterTextStyle, +}) -const LoadingFooterLink = styled.a` - ${loadingFooterTextCss} - ${ClickableStyle} -` +const LoadingFooterLink = styled(Anchor, { + fontFamily: '$body', + ...loadingFooterTextStyle, + ...ClickableTamaguiStyle, +}) // exported for testing export function getLoadingTitle( @@ -274,7 +290,7 @@ function TokenDetailsSkeleton() { - +
diff --git a/apps/web/src/components/Tokens/TokenDetails/TokenDescription.test.tsx b/apps/web/src/components/Tokens/TokenDetails/TokenDescription.test.tsx index 09b3ced1ed2..361c6ca6fc2 100644 --- a/apps/web/src/components/Tokens/TokenDetails/TokenDescription.test.tsx +++ b/apps/web/src/components/Tokens/TokenDetails/TokenDescription.test.tsx @@ -50,12 +50,12 @@ describe('TokenDescription', () => { const truncatedDescription = screen.getByTestId('token-description-truncated') const fullDescription = screen.getByTestId('token-description-full') - expect(truncatedDescription).toHaveStyleRule('display', 'inline') - expect(fullDescription).toHaveStyleRule('display', 'none') + expect(truncatedDescription).toHaveClass('_display-inline') + expect(fullDescription).toHaveClass('_display-none') await act(() => userEvent.click(screen.getByText('Show more'))) - expect(truncatedDescription).toHaveStyleRule('display', 'none') - expect(fullDescription).toHaveStyleRule('display', 'inline') + expect(truncatedDescription).toHaveClass('_display-none') + expect(fullDescription).toHaveClass('_display-inline') expect(screen.getByText('Hide')).toBeVisible() }) diff --git a/apps/web/src/components/Tokens/TokenDetails/TokenDescription.tsx b/apps/web/src/components/Tokens/TokenDetails/TokenDescription.tsx index 33295772833..c8c2b774ed9 100644 --- a/apps/web/src/components/Tokens/TokenDetails/TokenDescription.tsx +++ b/apps/web/src/components/Tokens/TokenDetails/TokenDescription.tsx @@ -1,73 +1,82 @@ -import Column from 'components/Column' import { EtherscanLogo } from 'components/Icons/Etherscan' import { Globe } from 'components/Icons/Globe' import { TwitterXLogo } from 'components/Icons/TwitterX' -import Row from 'components/Row' import { FOTTooltipContent } from 'components/swap/SwapLineItem' import { NoInfoAvailable, truncateDescription, TruncateDescriptionButton } from 'components/Tokens/TokenDetails/shared' import Tooltip, { MouseoverTooltip, TooltipSize } from 'components/Tooltip' import useCopyClipboard from 'hooks/useCopyClipboard' import { useSwapTaxes } from 'hooks/useSwapTaxes' -import styled, { useTheme } from 'lib/styled-components' +import { useTheme } from 'lib/styled-components' import { useTDPContext } from 'pages/TokenDetails/TDPContext' import { useCallback, useReducer } from 'react' import { Copy } from 'react-feather' -import { ClickableStyle, EllipsisStyle, ExternalLink, ThemedText } from 'theme/components' +import { ClickableTamaguiStyle, EllipsisTamaguiStyle, ExternalLink, ThemedText } from 'theme/components' +import { Flex, Paragraph, styled, Text } from 'ui/src' import { t, Trans } from 'uniswap/src/i18n' import { UniverseChainId } from 'uniswap/src/types/chains' import { shortenAddress } from 'utilities/src/addresses' import { useFormatter } from 'utils/formatNumbers' import { ExplorerDataType, getExplorerLink } from 'utils/getExplorerLink' -const TokenInfoSection = styled(Column)` - gap: 16px; - width: 100%; +const TokenInfoSection = styled(Flex, { + gap: '$gap16', + width: '100%', + $xl: { + gap: 24, + }, +}) - @media screen and (max-width: ${({ theme }) => theme.breakpoint.lg}px) { - gap: 24px; - } -` - -const InfoSectionHeader = styled(ThemedText.HeadlineSmall)` - @media screen and (max-width: ${({ theme }) => theme.breakpoint.lg}px) { - font-size: 28px !important; - line-height: 36px !important; - } -` +const InfoSectionHeader = styled(Text, { + variant: 'subheading1', +}) -const TokenNameRow = styled(Row)` - gap: 8px; - width: 100%; -` +const TokenNameRow = styled(Flex, { + row: true, + gap: '$gap8', + width: '100%', +}) -const TokenButtonRow = styled(TokenNameRow)` - flex-wrap: wrap; -` +const TokenButtonRow = styled(TokenNameRow, { + flexWrap: 'wrap', +}) -const TokenInfoButton = styled(Row)` - gap: 8px; - padding: 8px 12px; - border-radius: 20px; - color: ${({ theme }) => theme.neutral1}; - background-color: ${({ theme }) => theme.surface2}; - font-size: 14px; - font-weight: 535; - line-height: 16px; - width: max-content; - ${ClickableStyle} -` +const TokenInfoButton = styled(Text, { + variant: 'buttonLabel3', + display: 'flex', + flexDirection: 'row', + gap: '$gap8', + py: '$padding8', + px: '$padding12', + borderRadius: '$rounded20', + backgroundColor: '$surface2', + width: 'max-content', + ...ClickableTamaguiStyle, + color: '$neutral1', +}) -const TokenDescriptionContainer = styled(ThemedText.BodyPrimary)` - ${EllipsisStyle} - max-width: 100%; - // max-height: fit-content; - line-height: 24px; - white-space: pre-wrap; -` +const TokenDescriptionContainer = styled(Text, { + variant: 'body1', + color: '$neutral1', + maxWidth: '100%', + maxHeight: 'fit-content', + ...EllipsisTamaguiStyle, + whiteSpace: 'pre-wrap', + lineHeight: 24, +}) -const DescriptionVisibilityWrapper = styled.p<{ $visible: boolean }>` - display: ${({ $visible }) => ($visible ? 'inline' : 'none')}; -` +const DescriptionVisibilityWrapper = styled(Paragraph, { + fontWeight: '$book', + variants: { + visible: { + true: { + display: 'inline', + }, + false: { + display: 'none', + }, + }, + } as const, +}) const TRUNCATE_CHARACTER_COUNT = 200 @@ -108,7 +117,7 @@ export function TokenDescription() { {!currency.isNative && ( - + {shortenAddress(currency.address)} @@ -149,10 +158,10 @@ export function TokenDescription() { )} {description && ( <> - + {description} - + {truncatedDescription} @@ -180,7 +189,7 @@ export function TokenDescription() { } > - + {sameFee ? ( {currency.symbol}  @@ -201,7 +210,7 @@ export function TokenDescription() { {' '} )} - +
)} diff --git a/apps/web/src/components/Tokens/TokenDetails/TokenDetailsHeader.tsx b/apps/web/src/components/Tokens/TokenDetails/TokenDetailsHeader.tsx index c7fd406f9af..da8cebc75e1 100644 --- a/apps/web/src/components/Tokens/TokenDetails/TokenDetailsHeader.tsx +++ b/apps/web/src/components/Tokens/TokenDetails/TokenDetailsHeader.tsx @@ -1,138 +1,38 @@ -import { ReactComponent as MenuIcon } from 'assets/images/menu.svg' import { PortfolioLogo } from 'components/AccountDrawer/MiniPortfolio/PortfolioLogo' -import { CheckMark } from 'components/Icons/CheckMark' import { EtherscanLogo } from 'components/Icons/Etherscan' import { ExplorerIcon } from 'components/Icons/ExplorerIcon' import { Globe } from 'components/Icons/Globe' import { Share as ShareIcon } from 'components/Icons/Share' import { TwitterXLogo } from 'components/Icons/TwitterX' -import Row from 'components/Row' import ShareButton, { openShareTweetWindow } from 'components/Tokens/TokenDetails/ShareButton' import { TokenNameCell } from 'components/Tokens/TokenDetails/Skeleton' import { ActionButtonStyle } from 'components/Tokens/TokenDetails/shared' import { MouseoverTooltip, TooltipSize } from 'components/Tooltip' -import { useScreenSize } from 'hooks/screenSize' import useCopyClipboard from 'hooks/useCopyClipboard' -import { useOnClickOutside } from 'hooks/useOnClickOutside' -import styled, { useTheme } from 'lib/styled-components' import { useTDPContext } from 'pages/TokenDetails/TDPContext' -import { useReducer, useRef } from 'react' -import { Link } from 'react-feather' +import { useMemo, useState } from 'react' +import { Link, MoreHorizontal } from 'react-feather' import { useSearchParams } from 'react-router-dom' -import { ClickableStyle, EllipsisStyle, ExternalLink, ThemedText } from 'theme/components' -import { opacify } from 'theme/utils' -import { Z_INDEX } from 'theme/zIndex' -import { Trans, t } from 'uniswap/src/i18n' +import { EllipsisTamaguiStyle } from 'theme/components' +import { Flex, Text, WebBottomSheet, useMedia, useSporeColors } from 'ui/src' +import { Check } from 'ui/src/components/icons' +import { iconSizes } from 'ui/src/theme' +import { useTranslation } from 'uniswap/src/i18n' import { UniverseChainId } from 'uniswap/src/types/chains' -import { isMobile } from 'utilities/src/platform' +import { isMobileWeb } from 'utilities/src/platform' import { ExplorerDataType, getExplorerLink } from 'utils/getExplorerLink' -const HeaderActionsContainer = styled.div` - display: flex; - gap: 8px; - align-items: center; - - @media screen and (max-width: ${({ theme }) => theme.breakpoint.xs}px) { - flex-direction: column; - position: fixed; - bottom: 0; - left: 0; - align-items: unset; - width: 100vw; - padding: 8px; - background: ${({ theme }) => theme.surface2}; - border-radius: 12px 12px 0 0; - border: ${({ theme }) => `1px solid ${theme.surface3}`}; - box-shadow: ${({ theme }) => theme.deprecated_deepShadow}; - opacity: 1 !important; - z-index: ${Z_INDEX.modal}; - } -` - -const StyledMenuIcon = styled(MenuIcon)` - padding: 8px 12px; - border-radius: 20px; - color: ${({ theme }) => theme.neutral1}; - background-color: ${({ theme }) => opacify(12, theme.neutral1)}; - width: 40px; - height: 32px; - margin-top: 8px; - ${ClickableStyle} - - path { - stroke: ${({ theme }) => theme.neutral1}; - } -` - -const ActionButton = styled(Row)` - ${ActionButtonStyle} - - @media screen and (max-width: ${({ theme }) => theme.breakpoint.xs}px) { - color: unset; - background-color: unset; - width: unset; - - align-items: center; - text-decoration: none; - cursor: pointer; - gap: 12px; - padding: 10px 8px; - border-radius: 8px; - &:hover { - background: ${({ theme }) => theme.surface3}; - opacity: 1; - } - } -` - -const TokenTitle = styled.div` - display: flex; - gap: 8px; - overflow: hidden; - white-space: nowrap; -` - -const TokenSymbol = styled(ThemedText.SubHeaderSmall)` - font-size: 24px !important; - line-height: inherit; - margin-top: 0; - margin-bottom: 0; - - text-transform: uppercase; - - @media screen and (max-width: ${({ theme }) => theme.breakpoint.sm}px) { - display: none; - } -` - -const TokenName = styled(ThemedText.HeadlineMedium)` - ${EllipsisStyle} - font-size: 24px !important; - min-width: 40px; -` - -export const StyledExternalLink = styled(ExternalLink)` - &:hover { - // Override hover behavior from ExternalLink - opacity: 1; - } -` export const TokenDetailsHeader = () => { const { address, currency, tokenQuery } = useTDPContext() - const theme = useTheme() - const screenSize = useScreenSize() - const isMobileScreen = !screenSize['xs'] + const { t } = useTranslation() + const colors = useSporeColors() + const media = useMedia() + const isMobileScreen = media.sm - const [actionsModalIsOpen, toggleActionsModal] = useReducer((s) => !s, false) - const actionsRef = useRef(null) - useOnClickOutside(actionsRef, actionsModalIsOpen ? toggleActionsModal : undefined) + const [mobileSheetOpen, toggleMobileSheet] = useState(false) - const [isShareModalOpen, toggleShareModal] = useReducer((s) => !s, false) - const shareMenuRef = useRef(null) - useOnClickOutside(shareMenuRef, isShareModalOpen ? toggleShareModal : undefined) - - const tokenSymbolName = currency.symbol ?? + const tokenSymbolName = currency.symbol ?? t('tdp.symbolNotFound') const explorerUrl = getExplorerLink( currency.chainId, @@ -144,7 +44,7 @@ export const TokenDetailsHeader = () => { const twitterUrl = twitterName && `https://x.com/${twitterName}` const [searchParams] = useSearchParams() - const utmTag = `${searchParams.size > 0 ? '&' : '?'}utm_source=share-tdp&utm_medium=${isMobile ? 'mobile' : 'web'}` + const utmTag = `${searchParams.size > 0 ? '&' : '?'}utm_source=share-tdp&utm_medium=${isMobileWeb ? 'mobile' : 'web'}` const currentLocation = window.location.href + utmTag const twitterShareName = @@ -154,110 +54,124 @@ export const TokenDetailsHeader = () => { const [isCopied, setCopied] = useCopyClipboard() + const HeaderActions = useMemo(() => { + return [ + { + title: t('common.explorer'), + icon: + currency.chainId === UniverseChainId.Mainnet ? ( + + ) : ( + + ), + onPress: () => window.open(explorerUrl, '_blank'), + show: !!explorerUrl, + }, + { + title: t('common.website'), + icon: , + onPress: () => window.open(homepageUrl, '_blank'), + show: !!homepageUrl, + }, + { + title: t('common.twitter'), + icon: , + onPress: () => window.open(twitterUrl, '_blank'), + show: !!twitterUrl, + }, + { + title: isCopied ? t('common.copied') : t('common.copyLink.button'), + icon: isCopied ? ( + + ) : ( + + ), + onPress: () => setCopied(currentLocation), + show: isMobileScreen, + }, + { + title: t('common.share.shareToTwitter'), + icon: , + onPress: () => openShareTweetWindow(twitterShareName), + show: isMobileScreen, + }, + ] + }, [ + explorerUrl, + homepageUrl, + twitterUrl, + currency.chainId, + colors, + t, + isCopied, + setCopied, + currentLocation, + isMobileScreen, + twitterShareName, + ]) + return ( <> - - {currency.name ?? } - {tokenSymbolName} - + + + {currency.name ?? t('tdp.nameNotFound')} + + + {tokenSymbolName} + + -
- {isMobileScreen && } - {!isMobileScreen || (isMobileScreen && actionsModalIsOpen) ? ( - - {explorerUrl && ( - - - - {currency.chainId === UniverseChainId.Mainnet ? ( - - ) : ( - - )} - {isMobileScreen && ( - - - - )} - - - - )} - {homepageUrl && ( - - - - - {isMobileScreen && ( - - - - )} - - - - )} - {twitterUrl && ( - - - - - {isMobileScreen && ( - - - - )} - - - - )} - {isMobileScreen ? ( - <> - setCopied(currentLocation)}> - {isCopied ? ( - - ) : ( - - )} - - {isCopied ? : } - - - { - toggleActionsModal() - openShareTweetWindow(twitterShareName) - }} - > - - - - - - - ) : ( - - )} - - ) : null} -
+ {isMobileScreen ? ( + + toggleMobileSheet(true)} {...ActionButtonStyle}> + + + toggleMobileSheet(false)}> + + {HeaderActions.map( + (action) => + action.show && ( + { + toggleMobileSheet(false) + action.onPress() + }} + > + {action.icon} + {action.title} + + ), + )} + + + + ) : ( + + {HeaderActions.map( + (action) => + action.show && ( + + + {action.icon} + + + ), + )} + + + )} ) } diff --git a/apps/web/src/components/Tokens/TokenDetails/__snapshots__/Skeleton.test.tsx.snap b/apps/web/src/components/Tokens/TokenDetails/__snapshots__/Skeleton.test.tsx.snap index a03c80ebb89..f718a23ac61 100644 --- a/apps/web/src/components/Tokens/TokenDetails/__snapshots__/Skeleton.test.tsx.snap +++ b/apps/web/src/components/Tokens/TokenDetails/__snapshots__/Skeleton.test.tsx.snap @@ -2,13 +2,13 @@ exports[`TDP Skeleton should render correctly 1`] = ` - .c11 { + .c7 { box-sizing: border-box; margin: 0; min-width: 0; } -.c12 { +.c8 { width: 100%; display: -webkit-box; display: -webkit-flex; @@ -25,7 +25,7 @@ exports[`TDP Skeleton should render correctly 1`] = ` justify-content: flex-start; } -.c24 { +.c18 { color: #222222; -webkit-letter-spacing: -0.01em; -moz-letter-spacing: -0.01em; @@ -33,7 +33,7 @@ exports[`TDP Skeleton should render correctly 1`] = ` letter-spacing: -0.01em; } -.c2 { +.c0 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -52,7 +52,7 @@ exports[`TDP Skeleton should render correctly 1`] = ` width: fit-content; } -.c3 { +.c1 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -68,22 +68,22 @@ exports[`TDP Skeleton should render correctly 1`] = ` text-decoration: none; } -.c3:hover { +.c1:hover { color: #CECECE; } -.c23 { +.c17 { gap: 16px; padding: 24px 0px; -webkit-animation: iAjNNh 125ms ease-in; animation: iAjNNh 125ms ease-in; } -.c25 { +.c19 { font-size: 28px !important; } -.c4 { +.c2 { border-radius: 12px; border-radius: 12px; height: 24px; @@ -98,7 +98,7 @@ exports[`TDP Skeleton should render correctly 1`] = ` background-size: 400%; } -.c19 { +.c13 { color: #7D7D7D; font-size: 14px; min-width: 121px; @@ -109,7 +109,7 @@ exports[`TDP Skeleton should render correctly 1`] = ` padding-bottom: 0px; } -.c18 { +.c12 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -122,19 +122,19 @@ exports[`TDP Skeleton should render correctly 1`] = ` flex-wrap: wrap; } -.c14 { +.c9 { gap: 16px; -webkit-animation: iAjNNh 125ms ease-in; animation: iAjNNh 125ms ease-in; } -.c22 { +.c16 { background-color: #22222212; border: none; height: 0.5px; } -.c39 { +.c31 { border-radius: 12px; height: 40px; width: 40px; @@ -149,7 +149,7 @@ exports[`TDP Skeleton should render correctly 1`] = ` z-index: 2; } -.c41 { +.c33 { display: -webkit-inline-box; display: -webkit-inline-flex; display: -ms-inline-flexbox; @@ -166,7 +166,7 @@ exports[`TDP Skeleton should render correctly 1`] = ` height: 100%; } -.c40 { +.c32 { position: absolute; left: 50%; -webkit-transform: translate(-50%,-50%); @@ -175,7 +175,7 @@ exports[`TDP Skeleton should render correctly 1`] = ` margin: 0; } -.c31 { +.c23 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -194,37 +194,37 @@ exports[`TDP Skeleton should render correctly 1`] = ` background-color: #FFFFFF; } -.c35 { +.c27 { background-color: #F9F9F9; border-radius: 4px; height: 56px; width: 60px; } -.c37 { +.c29 { background-color: #F9F9F9; border-radius: 16px; height: 56px; width: 100px; } -.c42 { +.c34 { background-color: #F9F9F9; border-radius: 16px; height: 56px; width: 100%; } -.c36 { +.c28 { background-color: #22222212; height: 36px; } -.c32 { +.c24 { padding: 8px; } -.c34 { +.c26 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -239,7 +239,7 @@ exports[`TDP Skeleton should render correctly 1`] = ` justify-content: space-between; } -.c33 { +.c25 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -257,203 +257,67 @@ exports[`TDP Skeleton should render correctly 1`] = ` padding: 48px 12px; } -.c38 { - position: relative; -} - -.c0 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0 16px 52px; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - width: 100%; - gap: 40px; -} - -.c1 { - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - max-width: 780px; - overflow: hidden; - width: 100%; -} - .c30 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding-top: 53px; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - gap: 40px; - width: 360px; -} - -.c7 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - padding-top: 8px; - margin-bottom: 20px; - gap: 20px; - -webkit-animation: iAjNNh 125ms ease-in; - animation: iAjNNh 125ms ease-in; - -webkit-animation-duration: 250ms; - animation-duration: 250ms; -} - -.c8 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - gap: 12px; - font-size: 20px; - line-height: 28px; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - padding-top: 4px; - min-width: 32px; + position: relative; } -.c5 { +.c3 { height: 16px; width: 180px; } -.c15 { +.c10 { height: 32px; border-radius: 8px; } -.c6 { +.c4 { width: 169px; } -.c9 { +.c5 { width: 32px; height: 32px; border-radius: 50%; } -.c10 { +.c6 { height: 36px; width: 136px; } -.c16 { +.c11 { width: 120px; } -.c20 { +.c14 { width: 80px; margin-bottom: 4px; } -.c21 { +.c15 { width: 116px; } -.c26 { +.c20 { margin-bottom: 6px; width: 100%; } -.c29 { +.c22 { width: 120px; } -.c27 { +.c21 { width: 50%; } -.c17 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-wrap: wrap; - -ms-flex-wrap: wrap; - flex-wrap: wrap; -} - -.c28 { - padding-top: 24px; -} - -.c13 { - height: 4px; -} - @media screen and (max-width:640px) { - .c19 { + .c13 { min-width: 168px; } } -@media screen and (min-width:768px) { - .c0 { - padding: 48px 20px; - } -} - -@media screen and (max-width:1024px) { - .c0 { - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - } -} - -@media screen and (min-width:1280px) { - .c0 { - gap: 60px; - } -} - -@media screen and (max-width:1024px) { - .c30 { - width: 100%; - max-width: 780px; - } -} - -@media screen and (max-width:640px) { - .c8 { - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-align-items: flex-start; - -webkit-box-align: flex-start; - -ms-flex-align: flex-start; - align-items: flex-start; - } -} -

Swap
@@ -900,7 +765,7 @@ exports[`TDP Skeleton should render correctly 1`] = `
@@ -914,29 +779,7 @@ exports[`TDP Skeleton should render correctly 1`] = ` exports[`getLoadingTitle should return correct title 1`] = ` - .c0 { - color: #CECECE; - font-size: 12px; - font-weight: 500; - line-height: 16px; - -webkit-text-decoration: none; - text-decoration: none; - -webkit-text-decoration: none; - text-decoration: none; - cursor: pointer; - -webkit-transition-duration: 125ms; - transition-duration: 125ms; -} - -.c0:hover { - opacity: 0.6; -} - -.c0:active { - opacity: 0.4; -} - - @@ -948,9 +791,11 @@ exports[`getLoadingTitle should return correct title 1`] = ` > token data for USD//C (USDC) diff --git a/apps/web/src/components/Tokens/TokenDetails/__snapshots__/TokenDescription.test.tsx.snap b/apps/web/src/components/Tokens/TokenDetails/__snapshots__/TokenDescription.test.tsx.snap index b8eed37d75c..8706d70fdcd 100644 --- a/apps/web/src/components/Tokens/TokenDetails/__snapshots__/TokenDescription.test.tsx.snap +++ b/apps/web/src/components/Tokens/TokenDetails/__snapshots__/TokenDescription.test.tsx.snap @@ -2,52 +2,7 @@ exports[`TokenDescription no description or social buttons shown when not available 1`] = ` - .c0 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c4 { - box-sizing: border-box; - margin: 0; - min-width: 0; -} - -.c5 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c2 { - color: #222222; - -webkit-letter-spacing: -0.01em; - -moz-letter-spacing: -0.01em; - -ms-letter-spacing: -0.01em; - letter-spacing: -0.01em; -} - -.c10 { + .c1 { -webkit-text-decoration: none; text-decoration: none; cursor: pointer; @@ -58,90 +13,25 @@ exports[`TokenDescription no description or social buttons shown when not availa font-weight: 500; } -.c10:hover { +.c1:hover { opacity: 0.6; } -.c10:active { +.c1:active { opacity: 0.4; } -.c8 { +.c0 { display: inline-block; height: inherit; } -.c12 { +.c2 { color: #CECECE; font-weight: 485; font-size: 16px; } -.c1 { - gap: 16px; - width: 100%; -} - -.c6 { - gap: 8px; - width: 100%; -} - -.c7 { - -webkit-flex-wrap: wrap; - -ms-flex-wrap: wrap; - flex-wrap: wrap; -} - -.c9 { - gap: 8px; - padding: 8px 12px; - border-radius: 20px; - color: #222222; - background-color: #F9F9F9; - font-size: 14px; - font-weight: 535; - line-height: 16px; - width: -webkit-max-content; - width: -moz-max-content; - width: max-content; - -webkit-text-decoration: none; - text-decoration: none; - cursor: pointer; - -webkit-transition-duration: 125ms; - transition-duration: 125ms; -} - -.c9:hover { - opacity: 0.6; -} - -.c9:active { - opacity: 0.4; -} - -.c11 { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - max-width: 100%; - line-height: 24px; - white-space: pre-wrap; -} - -@media screen and (max-width:1024px) { - .c1 { - gap: 24px; - } -} - -@media screen and (max-width:1024px) { - .c3 { - font-size: 28px !important; - line-height: 36px !important; - } -} -
-
Info -
+
-

No token information available

-
+
@@ -245,52 +139,7 @@ exports[`TokenDescription no description or social buttons shown when not availa exports[`TokenDescription renders token information correctly with defaults 1`] = ` - .c0 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c4 { - box-sizing: border-box; - margin: 0; - min-width: 0; -} - -.c5 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c2 { - color: #222222; - -webkit-letter-spacing: -0.01em; - -moz-letter-spacing: -0.01em; - -ms-letter-spacing: -0.01em; - letter-spacing: -0.01em; -} - -.c10 { + .c1 { -webkit-text-decoration: none; text-decoration: none; cursor: pointer; @@ -301,105 +150,32 @@ exports[`TokenDescription renders token information correctly with defaults 1`] font-weight: 500; } -.c10:hover { +.c1:hover { opacity: 0.6; } -.c10:active { +.c1:active { opacity: 0.4; } -.c8 { +.c0 { display: inline-block; height: inherit; } -.c14 { +.c2 { color: #7D7D7D; font-weight: 485; font-size: 0.85em; padding-top: 0.5em; } -.c14:hover, -.c14:focus { +.c2:hover, +.c2:focus { color: #636363; cursor: pointer; } -.c1 { - gap: 16px; - width: 100%; -} - -.c6 { - gap: 8px; - width: 100%; -} - -.c7 { - -webkit-flex-wrap: wrap; - -ms-flex-wrap: wrap; - flex-wrap: wrap; -} - -.c9 { - gap: 8px; - padding: 8px 12px; - border-radius: 20px; - color: #222222; - background-color: #F9F9F9; - font-size: 14px; - font-weight: 535; - line-height: 16px; - width: -webkit-max-content; - width: -moz-max-content; - width: max-content; - -webkit-text-decoration: none; - text-decoration: none; - cursor: pointer; - -webkit-transition-duration: 125ms; - transition-duration: 125ms; -} - -.c9:hover { - opacity: 0.6; -} - -.c9:active { - opacity: 0.4; -} - -.c11 { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - max-width: 100%; - line-height: 24px; - white-space: pre-wrap; -} - -.c12 { - display: none; -} - -.c13 { - display: inline; -} - -@media screen and (max-width:1024px) { - .c1 { - gap: 24px; - } -} - -@media screen and (max-width:1024px) { - .c3 { - font-size: 28px !important; - line-height: 36px !important; - } -} -
-
Info -
+ -

USDC is a fully collateralized US dollar stablecoin. USDC is the bridge between dollars and trading on cryptocurrency exchanges. The technology behind CENTRE makes it possible to exchange value between people, businesses and financial institutions just like email between mail services and texts between SMS providers. We believe by removing artificial economic borders, we can create a more inclusive global economy.

USDC is a fully collateralized US dollar stablecoin. USDC is the bridge between dollars and trading on cryptocurrency exchanges. The technology behind CENTRE makes it possible to exchange value...

Show more
-
+
@@ -566,52 +348,7 @@ exports[`TokenDescription renders token information correctly with defaults 1`] exports[`TokenDescription truncates description and shows more 1`] = ` - .c0 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c4 { - box-sizing: border-box; - margin: 0; - min-width: 0; -} - -.c5 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c2 { - color: #222222; - -webkit-letter-spacing: -0.01em; - -moz-letter-spacing: -0.01em; - -ms-letter-spacing: -0.01em; - letter-spacing: -0.01em; -} - -.c10 { + .c1 { -webkit-text-decoration: none; text-decoration: none; cursor: pointer; @@ -622,105 +359,32 @@ exports[`TokenDescription truncates description and shows more 1`] = ` font-weight: 500; } -.c10:hover { +.c1:hover { opacity: 0.6; } -.c10:active { +.c1:active { opacity: 0.4; } -.c8 { +.c0 { display: inline-block; height: inherit; } -.c14 { +.c2 { color: #7D7D7D; font-weight: 485; font-size: 0.85em; padding-top: 0.5em; } -.c14:hover, -.c14:focus { +.c2:hover, +.c2:focus { color: #636363; cursor: pointer; } -.c1 { - gap: 16px; - width: 100%; -} - -.c6 { - gap: 8px; - width: 100%; -} - -.c7 { - -webkit-flex-wrap: wrap; - -ms-flex-wrap: wrap; - flex-wrap: wrap; -} - -.c9 { - gap: 8px; - padding: 8px 12px; - border-radius: 20px; - color: #222222; - background-color: #F9F9F9; - font-size: 14px; - font-weight: 535; - line-height: 16px; - width: -webkit-max-content; - width: -moz-max-content; - width: max-content; - -webkit-text-decoration: none; - text-decoration: none; - cursor: pointer; - -webkit-transition-duration: 125ms; - transition-duration: 125ms; -} - -.c9:hover { - opacity: 0.6; -} - -.c9:active { - opacity: 0.4; -} - -.c11 { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - max-width: 100%; - line-height: 24px; - white-space: pre-wrap; -} - -.c12 { - display: none; -} - -.c13 { - display: inline; -} - -@media screen and (max-width:1024px) { - .c1 { - gap: 24px; - } -} - -@media screen and (max-width:1024px) { - .c3 { - font-size: 28px !important; - line-height: 36px !important; - } -} -
-
Info -
+ -

USDC is a fully collateralized US dollar stablecoin. USDC is the bridge between dollars and trading on cryptocurrency exchanges. The technology behind CENTRE makes it possible to exchange value between people, businesses and financial institutions just like email between mail services and texts between SMS providers. We believe by removing artificial economic borders, we can create a more inclusive global economy.

USDC is a fully collateralized US dollar stablecoin. USDC is the bridge between dollars and trading on cryptocurrency exchanges. The technology behind CENTRE makes it possible to exchange value...

Show more
-
+
diff --git a/apps/web/src/components/Tokens/TokenDetails/index.tsx b/apps/web/src/components/Tokens/TokenDetails/index.tsx index 02d6c7bca49..12215391d9c 100644 --- a/apps/web/src/components/Tokens/TokenDetails/index.tsx +++ b/apps/web/src/components/Tokens/TokenDetails/index.tsx @@ -20,20 +20,20 @@ import { useScreenSize } from 'hooks/screenSize' import { useAccount } from 'hooks/useAccount' import useParsedQueryString from 'hooks/useParsedQueryString' import { ScrollDirection, useScroll } from 'hooks/useScroll' -import styled from 'lib/styled-components' +import deprecatedStyled from 'lib/styled-components' import { Swap } from 'pages/Swap' import { useTDPContext } from 'pages/TokenDetails/TDPContext' import { PropsWithChildren, useCallback, useMemo, useState } from 'react' import { ChevronRight } from 'react-feather' import { useNavigate } from 'react-router-dom' import { CurrencyState } from 'state/swap/types' -import { useIsTouchDevice } from 'ui/src' +import { Flex, useIsTouchDevice } from 'ui/src' import Trace from 'uniswap/src/features/telemetry/Trace' import { Trans } from 'uniswap/src/i18n' import { addressesAreEquivalent } from 'utils/addressesAreEquivalent' import { getInitialLogoUrl } from 'utils/getInitialLogoURL' -const DividerLine = styled(Hr)` +const DividerLine = deprecatedStyled(Hr)` margin-top: 40px; margin-bottom: 40px; @media screen and (max-width: ${({ theme }) => theme.breakpoint.sm}px) { @@ -41,9 +41,6 @@ const DividerLine = styled(Hr)` margin-bottom: 0; } ` -const BalanceSummaryContainer = styled.div` - margin-top: 40px; -` function TDPBreadcrumb() { const { address, currency, currencyChain } = useTDPContext() @@ -209,9 +206,9 @@ export default function TokenDetails() { {!showRightPanel && !!pageChainBalance && ( - + - + )} @@ -227,7 +224,7 @@ export default function TokenDetails() { diff --git a/apps/web/src/components/Tokens/TokenDetails/shared.ts b/apps/web/src/components/Tokens/TokenDetails/shared.ts index e20ae317078..44ebc73fc38 100644 --- a/apps/web/src/components/Tokens/TokenDetails/shared.ts +++ b/apps/web/src/components/Tokens/TokenDetails/shared.ts @@ -1,48 +1,47 @@ -import styled, { css } from 'lib/styled-components' +import deprecatedStyled from 'lib/styled-components' import { darken } from 'polished' -import { ClickableStyle } from 'theme/components' -import { opacify } from 'theme/utils' +import { TamaguiClickableStyle } from 'theme/components' +import { FlexProps, TextProps } from 'ui/src' -export const ActionButtonStyle = css` - display: flex; - align-items: center; - justify-content: flex-start; - padding: 8px 12px; - border-radius: 20px; - border: none; - background-color: ${({ theme }) => theme.surface2}; - width: max-content; - ${ClickableStyle} +export const ActionButtonStyle = { + display: 'flex', + alignItems: 'center', + justifyContent: 'flex-start', + py: '$spacing8', + px: '$spacing12', + borderRadius: 20, + borderWidth: 0, + backgroundColor: '$surface2', + width: 'maxContent', + ...TamaguiClickableStyle, - // Override FilterButton background-color - :hover { - background-color: ${({ theme }) => opacify(12, theme.neutral1)}; - } - :focus { - background-color: ${({ theme }) => opacify(12, theme.neutral1)}; - } -` + hoverStyle: { + backgroundColor: '$surface2Hovered', + }, + focusStyle: { + backgroundColor: '$surface1Hovered', + }, +} satisfies TextProps -export const ActionMenuFlyoutStyle = css` - width: 200px; - top: 40px; - right: 0px; - overflow: auto; -` +export const ActionMenuFlyoutStyle = { + width: 200, + top: 'calc(100% + 8px)', + right: 0, +} satisfies FlexProps -export const Hr = styled.hr` +export const Hr = deprecatedStyled.hr` background-color: ${({ theme }) => theme.surface3}; border: none; height: 0.5px; ` -export const NoInfoAvailable = styled.p` +export const NoInfoAvailable = deprecatedStyled.p` color: ${({ theme }) => theme.neutral3}; font-weight: 485; font-size: 16px; ` -export const TruncateDescriptionButton = styled.div` +export const TruncateDescriptionButton = deprecatedStyled.div` color: ${({ theme }) => theme.neutral2}; font-weight: 485; font-size: 0.85em; diff --git a/apps/web/src/components/Tokens/TokenDetails/tables/TransactionsTable.tsx b/apps/web/src/components/Tokens/TokenDetails/tables/TransactionsTable.tsx index 0219d4ad54c..6b68277d0ca 100644 --- a/apps/web/src/components/Tokens/TokenDetails/tables/TransactionsTable.tsx +++ b/apps/web/src/components/Tokens/TokenDetails/tables/TransactionsTable.tsx @@ -1,7 +1,6 @@ import { ApolloError } from '@apollo/client' import { createColumnHelper } from '@tanstack/react-table' import { Token } from '@uniswap/sdk-core' -import Row from 'components/Row' import { Table } from 'components/Table' import { Cell } from 'components/Table/Cell' import { Filter } from 'components/Table/Filter' @@ -18,24 +17,28 @@ import { useUpdateManualOutage } from 'featureFlags/flags/outageBanner' import { TokenTransactionType, useTokenTransactions } from 'graphql/data/useTokenTransactions' import { OrderDirection, unwrapToken } from 'graphql/data/util' import { useActiveLocalCurrency } from 'hooks/useActiveLocalCurrency' -import styled from 'lib/styled-components' -import { useMemo, useReducer, useState } from 'react' -import { EllipsisStyle, ThemedText } from 'theme/components' +import { useMemo, useReducer, useRef, useState } from 'react' +import { EllipsisTamaguiStyle } from 'theme/components' +import { Flex, Text, styled } from 'ui/src' import { Token as GQLToken } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { Trans } from 'uniswap/src/i18n' import { shortenAddress } from 'utilities/src/addresses' import { useFormatter } from 'utils/formatNumbers' import { ExplorerDataType, getExplorerLink } from 'utils/getExplorerLink' -const StyledSwapAmount = styled(ThemedText.BodyPrimary)` - display: inline-block; - ${EllipsisStyle} - max-width: 75px; -` +const StyledSwapAmount = styled(Text, { + display: 'inline-block' as any, + maxWidth: 75, + variant: 'body2', + color: '$neutral1', + ...EllipsisTamaguiStyle, +}) + +const TableWrapper = styled(Flex, { + position: 'relative', + minHeight: 158, +}) -const TableWrapper = styled.div` - min-height: 158px; -` interface SwapTransaction { hash: string timestamp: number @@ -62,6 +65,7 @@ export function TransactionsTable({ const activeLocalCurrency = useActiveLocalCurrency() const { formatNumber, formatFiatPrice } = useFormatter() const [filterModalIsOpen, toggleFilterModal] = useReducer((s) => !s, false) + const filterAnchorRef = useRef(null) const [filter, setFilters] = useState([TokenTransactionType.BUY, TokenTransactionType.SELL]) const { transactions, loading, loadMore, errorV2, errorV3 } = useTokenTransactions( referenceToken.address, @@ -115,12 +119,12 @@ export function TransactionsTable({ id: 'timestamp', header: () => ( - + - + - + ), cell: (row) => ( @@ -136,17 +140,23 @@ export function TransactionsTable({ id: 'swap-type', header: () => ( - + - + - + ), @@ -154,9 +164,9 @@ export function TransactionsTable({ const isBuy = String(outputTokenAddress.getValue?.()).toLowerCase() === referenceToken.address.toLowerCase() return ( - + {isBuy ? : } - + ) }, @@ -170,16 +180,18 @@ export function TransactionsTable({ id: 'reference-amount', header: () => ( - ${unwrappedReferenceToken.symbol} + + ${unwrappedReferenceToken.symbol} + ), cell: (inputTokenAmount) => ( - + {formatNumber({ input: Math.abs(inputTokenAmount.getValue?.()) || 0, })} - + ), }, @@ -189,23 +201,23 @@ export function TransactionsTable({ const nonReferenceSwapLeg = row.input.address?.toLowerCase() === referenceToken.address.toLowerCase() ? row.output : row.input return ( - + {formatNumber({ input: Math.abs(nonReferenceSwapLeg.amount) || 0, })} - + ) }, { id: 'non-reference-amount', header: () => ( - + - + ), cell: (swapOutput) => ( @@ -219,14 +231,16 @@ export function TransactionsTable({ id: 'fiat-value', header: () => ( - + {activeLocalCurrency} - + ), cell: (fiat) => ( - {formatFiatPrice({ price: fiat.getValue?.() })} + + {formatFiatPrice({ price: fiat.getValue?.() })} + ), }), @@ -234,9 +248,9 @@ export function TransactionsTable({ id: 'maker-address', header: () => ( - + - + ), cell: (makerAddress) => ( diff --git a/apps/web/src/components/Tokens/TokenDetails/tables/__snapshots__/TokenDetailsPoolsTable.test.tsx.snap b/apps/web/src/components/Tokens/TokenDetails/tables/__snapshots__/TokenDetailsPoolsTable.test.tsx.snap index 034f81dcbc4..39032b33f41 100644 --- a/apps/web/src/components/Tokens/TokenDetails/tables/__snapshots__/TokenDetailsPoolsTable.test.tsx.snap +++ b/apps/web/src/components/Tokens/TokenDetails/tables/__snapshots__/TokenDetailsPoolsTable.test.tsx.snap @@ -2,80 +2,7 @@ exports[`TDPPoolTable renders data filled state 1`] = ` - .c29 { - height: 16px; - width: 16px; -} - -.c29 path { - stroke: #FC72FF; - background: #7D7D7D; - fill: none; -} - -.c30 { - -webkit-animation: 2s fvtopB linear infinite; - animation: 2s fvtopB linear infinite; -} - -.c3 { - box-sizing: border-box; - margin: 0; - min-width: 0; -} - -.c4 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c20 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 8px; -} - -.c9 { - color: #7D7D7D; - -webkit-letter-spacing: -0.01em; - -moz-letter-spacing: -0.01em; - -ms-letter-spacing: -0.01em; - letter-spacing: -0.01em; -} - -.c24 { - color: #222222; - -webkit-letter-spacing: -0.01em; - -moz-letter-spacing: -0.01em; - -ms-letter-spacing: -0.01em; - letter-spacing: -0.01em; -} - -.c22 { + .c4 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -86,220 +13,47 @@ exports[`TDPPoolTable renders data filled state 1`] = ` left: 0; } -.c22 img { +.c4 img { width: 14px; height: 28px; object-fit: cover; } -.c22 img:first-child { +.c4 img:first-child { border-radius: 14px 0 0 14px; object-position: 0 0; } -.c22 img:last-child { +.c4 img:last-child { border-radius: 0 14px 14px 0; object-position: 100% 0; } -.c23 { +.c5 { width: 14px; height: 28px; border-radius: 50%; } -.c21 { +.c3 { position: relative; top: 0; left: 0; } .c0 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c12 { display: inline-block; height: inherit; } -.c1 { - max-width: px; - max-height: 600px; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - margin: 0px auto 24px auto; -} - .c2 { - width: 100%; - position: relative; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - background: #FFFFFF; -} - -.c17 { - width: 100%; - position: relative; - overflow-x: auto; - overscroll-behavior-x: none; - border-right: 1px solid #22222212; - border-bottom: 1px solid #22222212; - border-left: 1px solid #22222212; - border-bottom-right-radius: 20px; - border-bottom-left-radius: 20px; - -ms-overflow-style: none; - -webkit-scrollbar-width: none; - -moz-scrollbar-width: none; - -ms-scrollbar-width: none; - scrollbar-width: none; -} - -.c17::-webkit-scrollbar { - display: none; -} - -.c27 { - position: -webkit-sticky; - position: sticky; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - margin-top: -48px; - visibility: hidden; -} - -.c28 { - background: #FFEFFF; - border-radius: 8px; - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - padding: 8px; - color: #FC72FF; - font-size: 16px; - font-weight: 535; - gap: 8px; - height: 34px; - z-index: 990; -} - -.c5 { - padding: 0px 12px; - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - min-width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - min-height: 64px; -} - -.c6 { - border: 1px solid #22222212; - border-top-right-radius: 20px; - border-top-left-radius: 20px; - overflow: auto; - width: unset; - min-height: 52px; - background: #F9F9F9; - -ms-overflow-style: none; - -webkit-scrollbar-width: none; - -moz-scrollbar-width: none; - -ms-scrollbar-width: none; - scrollbar-width: none; - overscroll-behavior: none; -} - -.c6::-webkit-scrollbar { - display: none; -} - -.c7 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-flex: 1; - -webkit-flex-grow: 1; - -ms-flex-positive: 1; - flex-grow: 1; -} - -.c7:last-child { - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; -} - -.c7:first-child { - -webkit-box-flex: 0; - -webkit-flex-grow: 0; - -ms-flex-positive: 0; - flex-grow: 0; -} - -.c18 { color: none; -webkit-text-decoration: none; text-decoration: none; cursor: pointer; } -.c13 { - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - cursor: pointer; - width: 100%; - gap: 4px; - -webkit-text-decoration: none; - text-decoration: none; - cursor: pointer; - -webkit-transition-duration: 125ms; - transition-duration: 125ms; -} - -.c13:hover { - opacity: 0.6; -} - -.c13:active { - opacity: 0.4; -} - -.c14 { +.c1 { height: 16px; width: 16px; color: #222222; @@ -308,116 +62,6 @@ exports[`TDPPoolTable renders data filled state 1`] = ` transform: rotate(0deg); } -.c15 { - color: #222222; -} - -.c8 { - min-width: 44px; - -webkit-flex: 0; - -ms-flex: 0; - flex: 0; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c10 { - width: 240px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c11 { - min-width: 120px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c16 { - min-width: 100px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c25 { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.c26 { - padding: 2px 6px; - background: #F9F9F9; - border-radius: 5px; -} - -@media not all and (hover:none) { - .c19:hover { - background: #22222212; - } -} -
-
# -
+
-
Pool -
+
-
TVL -
+
-
1 day volume -
+
-
7 day volume -
+
-
1 day APR -
+
@@ -585,147 +235,131 @@ exports[`TDPPoolTable renders data filled state 1`] = `
-
-
- - - - Loading -
-
@@ -737,62 +371,23 @@ exports[`TDPPoolTable renders data filled state 1`] = ` exports[`TDPPoolTable renders error state 1`] = ` - .c25 { - height: 16px; - width: 16px; -} - -.c25 path { - stroke: #FC72FF; - background: #7D7D7D; - fill: none; -} - -.c26 { - -webkit-animation: 2s fvtopB linear infinite; - animation: 2s fvtopB linear infinite; -} - -.c3 { - box-sizing: border-box; - margin: 0; - min-width: 0; -} - -.c4 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c9 { - color: #7D7D7D; + .c6 { + color: #222222; -webkit-letter-spacing: -0.01em; -moz-letter-spacing: -0.01em; -ms-letter-spacing: -0.01em; letter-spacing: -0.01em; } -.c22 { - color: #222222; +.c7 { + color: #7D7D7D; -webkit-letter-spacing: -0.01em; -moz-letter-spacing: -0.01em; -ms-letter-spacing: -0.01em; letter-spacing: -0.01em; } -.c0 { +.c5 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -806,7 +401,7 @@ exports[`TDPPoolTable renders error state 1`] = ` justify-content: flex-start; } -.c21 { +.c4 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -836,172 +431,12 @@ exports[`TDPPoolTable renders error state 1`] = ` border-radius: 20px; } -.c12 { +.c0 { display: inline-block; height: inherit; } .c1 { - max-width: px; - max-height: 600px; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - margin: 0px auto 24px auto; -} - -.c2 { - width: 100%; - position: relative; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - background: #FFFFFF; -} - -.c17 { - width: 100%; - position: relative; - overflow-x: auto; - overscroll-behavior-x: none; - border-right: 1px solid #22222212; - border-bottom: 1px solid #22222212; - border-left: 1px solid #22222212; - border-bottom-right-radius: 20px; - border-bottom-left-radius: 20px; - -ms-overflow-style: none; - -webkit-scrollbar-width: none; - -moz-scrollbar-width: none; - -ms-scrollbar-width: none; - scrollbar-width: none; -} - -.c17::-webkit-scrollbar { - display: none; -} - -.c23 { - position: -webkit-sticky; - position: sticky; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - margin-top: -48px; - visibility: hidden; -} - -.c24 { - background: #FFEFFF; - border-radius: 8px; - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - padding: 8px; - color: #FC72FF; - font-size: 16px; - font-weight: 535; - gap: 8px; - height: 34px; - z-index: 990; -} - -.c5 { - padding: 0px 12px; - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - min-width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - min-height: 64px; -} - -.c6 { - border: 1px solid #22222212; - border-top-right-radius: 20px; - border-top-left-radius: 20px; - overflow: auto; - width: unset; - min-height: 52px; - background: #F9F9F9; - -ms-overflow-style: none; - -webkit-scrollbar-width: none; - -moz-scrollbar-width: none; - -ms-scrollbar-width: none; - scrollbar-width: none; - overscroll-behavior: none; - opacity: 0.4; -} - -.c6::-webkit-scrollbar { - display: none; -} - -.c7 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-flex: 1; - -webkit-flex-grow: 1; - -ms-flex-positive: 1; - flex-grow: 1; -} - -.c7:last-child { - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; -} - -.c7:first-child { - -webkit-box-flex: 0; - -webkit-flex-grow: 0; - -ms-flex-positive: 0; - flex-grow: 0; -} - -.c13 { - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - cursor: pointer; - width: 100%; - gap: 4px; - -webkit-text-decoration: none; - text-decoration: none; - cursor: pointer; - -webkit-transition-duration: 125ms; - transition-duration: 125ms; -} - -.c13:hover { - opacity: 0.6; -} - -.c13:active { - opacity: 0.4; -} - -.c14 { height: 16px; width: 16px; color: #222222; @@ -1010,11 +445,7 @@ exports[`TDPPoolTable renders error state 1`] = ` transform: rotate(0deg); } -.c15 { - color: #222222; -} - -.c19 { +.c2 { border-radius: 12px; border-radius: 12px; height: 24px; @@ -1029,105 +460,11 @@ exports[`TDPPoolTable renders error state 1`] = ` background-size: 400%; } -.c8 { - min-width: 44px; - -webkit-flex: 0; - -ms-flex: 0; - flex: 0; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c10 { - width: 240px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c11 { - min-width: 120px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c16 { - min-width: 100px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c20 { +.c3 { width: 75%; height: 16px; } -@media not all and (hover:none) { - .c18:hover { - background: #22222212; - } -} -
-
# -
+
-
Pool -
+
-
TVL -
+
-
1 day volume -
+
-
7 day volume -
+
-
1 day APR -
+
@@ -1295,542 +638,542 @@ exports[`TDPPoolTable renders error state 1`] = `
@@ -1863,44 +1206,21 @@ exports[`TDPPoolTable renders error state 1`] = `
Error loading data
Data is unavailable at the moment; we’re working on a fix
-
-
- - - - Loading -
-
@@ -1912,232 +1232,12 @@ exports[`TDPPoolTable renders error state 1`] = ` exports[`TDPPoolTable renders loading state 1`] = ` - .c23 { - height: 16px; - width: 16px; -} - -.c23 path { - stroke: #FC72FF; - background: #7D7D7D; - fill: none; -} - -.c24 { - -webkit-animation: 2s fvtopB linear infinite; - animation: 2s fvtopB linear infinite; -} - -.c3 { - box-sizing: border-box; - margin: 0; - min-width: 0; -} - -.c4 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c9 { - color: #7D7D7D; - -webkit-letter-spacing: -0.01em; - -moz-letter-spacing: -0.01em; - -ms-letter-spacing: -0.01em; - letter-spacing: -0.01em; -} - -.c0 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c12 { + .c0 { display: inline-block; height: inherit; } .c1 { - max-width: px; - max-height: 600px; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - margin: 0px auto 24px auto; -} - -.c2 { - width: 100%; - position: relative; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - background: #FFFFFF; -} - -.c17 { - width: 100%; - position: relative; - overflow-x: auto; - overscroll-behavior-x: none; - border-right: 1px solid #22222212; - border-bottom: 1px solid #22222212; - border-left: 1px solid #22222212; - border-bottom-right-radius: 20px; - border-bottom-left-radius: 20px; - -ms-overflow-style: none; - -webkit-scrollbar-width: none; - -moz-scrollbar-width: none; - -ms-scrollbar-width: none; - scrollbar-width: none; -} - -.c17::-webkit-scrollbar { - display: none; -} - -.c21 { - position: -webkit-sticky; - position: sticky; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - margin-top: -48px; - visibility: hidden; -} - -.c22 { - background: #FFEFFF; - border-radius: 8px; - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - padding: 8px; - color: #FC72FF; - font-size: 16px; - font-weight: 535; - gap: 8px; - height: 34px; - z-index: 990; -} - -.c5 { - padding: 0px 12px; - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - min-width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - min-height: 64px; -} - -.c6 { - border: 1px solid #22222212; - border-top-right-radius: 20px; - border-top-left-radius: 20px; - overflow: auto; - width: unset; - min-height: 52px; - background: #F9F9F9; - -ms-overflow-style: none; - -webkit-scrollbar-width: none; - -moz-scrollbar-width: none; - -ms-scrollbar-width: none; - scrollbar-width: none; - overscroll-behavior: none; -} - -.c6::-webkit-scrollbar { - display: none; -} - -.c7 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-flex: 1; - -webkit-flex-grow: 1; - -ms-flex-positive: 1; - flex-grow: 1; -} - -.c7:last-child { - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; -} - -.c7:first-child { - -webkit-box-flex: 0; - -webkit-flex-grow: 0; - -ms-flex-positive: 0; - flex-grow: 0; -} - -.c13 { - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - cursor: pointer; - width: 100%; - gap: 4px; - -webkit-text-decoration: none; - text-decoration: none; - cursor: pointer; - -webkit-transition-duration: 125ms; - transition-duration: 125ms; -} - -.c13:hover { - opacity: 0.6; -} - -.c13:active { - opacity: 0.4; -} - -.c14 { height: 16px; width: 16px; color: #222222; @@ -2146,11 +1246,7 @@ exports[`TDPPoolTable renders loading state 1`] = ` transform: rotate(0deg); } -.c15 { - color: #222222; -} - -.c19 { +.c2 { border-radius: 12px; border-radius: 12px; height: 24px; @@ -2165,105 +1261,11 @@ exports[`TDPPoolTable renders loading state 1`] = ` background-size: 400%; } -.c8 { - min-width: 44px; - -webkit-flex: 0; - -ms-flex: 0; - flex: 0; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c10 { - width: 240px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c11 { - min-width: 120px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c16 { - min-width: 100px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-pack: end; - -webkit-justify-content: flex-end; - -ms-flex-pack: end; - justify-content: flex-end; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - font-variant-numeric: lining-nums tabular-nums; - overflow: hidden; - padding: 12px 8px; -} - -.c20 { +.c3 { width: 75%; height: 16px; } -@media not all and (hover:none) { - .c18:hover { - background: #22222212; - } -} -
-
# -
+
-
Pool -
+
-
TVL -
+
-
1 day volume -
+
-
7 day volume -
+
-
1 day APR -
+
@@ -2431,564 +1439,541 @@ exports[`TDPPoolTable renders loading state 1`] = `
-
-
- - - - Loading -
-
diff --git a/apps/web/src/components/Tokens/TokenTable/NetworkFilter.tsx b/apps/web/src/components/Tokens/TokenTable/NetworkFilter.tsx index 987947ae526..8e65c2f4f22 100644 --- a/apps/web/src/components/Tokens/TokenTable/NetworkFilter.tsx +++ b/apps/web/src/components/Tokens/TokenTable/NetworkFilter.tsx @@ -9,48 +9,48 @@ import { useIsSupportedChainIdCallback, } from 'constants/chains' import { getSupportedGraphQlChain, supportedChainIdFromGQLChain } from 'graphql/data/util' -import styled, { css, useTheme } from 'lib/styled-components' +import deprecatedStyled, { useTheme } from 'lib/styled-components' import { ExploreTab } from 'pages/Explore' import { useExploreParams } from 'pages/Explore/redirects' -import { useReducer } from 'react' +import { useState } from 'react' import { Check } from 'react-feather' import { useNavigate } from 'react-router-dom' -import { EllipsisStyle } from 'theme/components' +import { EllipsisTamaguiStyle } from 'theme/components' +import { Flex, FlexProps, ScrollView, Text, styled } from 'ui/src' import { UNIVERSE_CHAIN_INFO } from 'uniswap/src/constants/chains' import { FeatureFlags } from 'uniswap/src/features/gating/flags' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' import { useTranslation } from 'uniswap/src/i18n' -const NetworkLabel = styled.div` - ${EllipsisStyle} - display: flex; - gap: 8px; - align-items: center; -` +const NetworkLabel = styled(Flex, { + flexDirection: 'row', + alignItems: 'center', + gap: '$gap8', +}) -const Tag = styled(Badge)` +const Tag = deprecatedStyled(Badge)` background-color: ${({ theme }) => theme.surface2}; color: ${({ theme }) => theme.neutral2}; font-size: 10px; opacity: 1; padding: 4px 6px; ` -const StyledButton = css` - height: 40px; -` -const StyledMenuFlyout = css` - max-height: 350px; - min-width: 256px; - right: 0px; - @media screen and (max-width: ${({ theme }) => `${theme.breakpoint.lg}px`}) { - left: 0px; - } -` +const StyledDropdown = { + maxHeight: 350, + minWidth: 256, + right: 0, + px: 0, + $lg: { + left: 0, + right: undefined, + }, +} satisfies FlexProps + export default function TableNetworkFilter() { const { t } = useTranslation() const theme = useTheme() const navigate = useNavigate() - const [isMenuOpen, toggleMenu] = useReducer((s) => !s, false) + const [isMenuOpen, toggleMenu] = useState(false) const isSupportedChainCallback = useIsSupportedChainIdCallback() const isMultichainExploreEnabled = useFeatureFlag(FeatureFlags.MultichainExplore) @@ -73,18 +73,21 @@ export default function TableNetworkFilter() { } internalMenuItems={ - <> + {isMultichainExploreEnabled && ( { + onPress={() => { navigate(`/explore/${tab ?? ExploreTab.Tokens}`) - toggleMenu() + toggleMenu(false) }} > - {t('transaction.network.all')} + {' '} + + {t('transaction.network.all')} + {!exploreParams.chainName && } @@ -97,13 +100,16 @@ export default function TableNetworkFilter() { { + onPress={() => { navigate(`/explore/${tab ?? ExploreTab.Tokens}/${network.toLowerCase()}`) - toggleMenu() + toggleMenu(false) }} > - {chainInfo?.label} + {' '} + + {chainInfo?.label} + {network === currentChain.backendChain.chain && exploreParams.chainName && ( @@ -117,16 +123,19 @@ export default function TableNetworkFilter() { return chainInfo ? ( - {chainInfo.label} + {' '} + + {chainInfo.label} + Coming soon ) : null })} - + } - buttonCss={StyledButton} - menuFlyoutCss={StyledMenuFlyout} + buttonStyle={{ height: 40 }} + dropdownStyle={StyledDropdown} />
) diff --git a/apps/web/src/components/Tokens/TokenTable/TimeSelector.tsx b/apps/web/src/components/Tokens/TokenTable/TimeSelector.tsx index ffdb13170ab..9e1b60ed117 100644 --- a/apps/web/src/components/Tokens/TokenTable/TimeSelector.tsx +++ b/apps/web/src/components/Tokens/TokenTable/TimeSelector.tsx @@ -3,9 +3,10 @@ import { filterTimeAtom } from 'components/Tokens/state' import { TimePeriod } from 'graphql/data/util' import { useScreenSize } from 'hooks/screenSize' import { useAtom } from 'jotai' -import { css, useTheme } from 'lib/styled-components' -import { useReducer } from 'react' +import { useTheme } from 'lib/styled-components' +import { useState } from 'react' import { Check } from 'react-feather' +import { FlexProps } from 'ui/src' import { useTranslation } from 'uniswap/src/i18n' export enum TimePeriodDisplay { @@ -47,15 +48,20 @@ export const ORDERED_TIMES: TimePeriod[] = [ TimePeriod.YEAR, ] -const StyledMenuFlyout = css` - max-height: 300px; - left: 0px; -` +const StyledDropdown = { + maxHeight: 300, + right: 0, + top: 'calc(100% + 20px)', + $xl: { + left: 0, + }, +} satisfies FlexProps + // TODO: change this to reflect data pipeline export default function TimeSelector() { const { t } = useTranslation() const theme = useTheme() - const [isMenuOpen, toggleMenu] = useReducer((s) => !s, false) + const [isMenuOpen, toggleMenu] = useState(false) const [activeTime, setTime] = useAtom(filterTimeAtom) const screenSize = useScreenSize() @@ -77,9 +83,9 @@ export default function TimeSelector() { { + onPress={() => { setTime(time) - toggleMenu() + toggleMenu(false) }} >
@@ -91,10 +97,8 @@ export default function TimeSelector() { } dataTestId="time-selector" - buttonCss={css` - height: 40px; - `} - menuFlyoutCss={StyledMenuFlyout} + buttonStyle={{ height: 40 }} + dropdownStyle={StyledDropdown} />
) diff --git a/apps/web/src/components/Tokens/TokenTable/index.tsx b/apps/web/src/components/Tokens/TokenTable/index.tsx index cf03b40f247..9eb298e9dde 100644 --- a/apps/web/src/components/Tokens/TokenTable/index.tsx +++ b/apps/web/src/components/Tokens/TokenTable/index.tsx @@ -4,7 +4,6 @@ import { InterfaceElementName } from '@uniswap/analytics-events' import { ParentSize } from '@visx/responsive' import SparklineChart from 'components/Charts/SparklineChart' import QueryTokenLogo from 'components/Logo/QueryTokenLogo' -import Row from 'components/Row' import { Table } from 'components/Table' import { Cell } from 'components/Table/Cell' import { ClickableHeaderRow, HeaderArrow, HeaderSortText } from 'components/Table/styled' @@ -24,28 +23,33 @@ import { NATIVE_CHAIN_ID } from 'constants/tokens' import { SparklineMap, TopToken, useTopTokens } from 'graphql/data/TopTokens' import { OrderDirection, getSupportedGraphQlChain, getTokenDetailsURL } from 'graphql/data/util' import { useAtomValue } from 'jotai/utils' -import styled from 'lib/styled-components' import { ReactElement, ReactNode, useMemo } from 'react' -import { EllipsisStyle, ThemedText } from 'theme/components' +import { Flex, Text, styled } from 'ui/src' import { Trans } from 'uniswap/src/i18n' import { NumberType, useFormatter } from 'utils/formatNumbers' -const TableWrapper = styled.div` - margin: 0 auto; - max-width: ${MAX_WIDTH_MEDIA_BREAKPOINT}; -` +const TableWrapper = styled(Flex, { + m: '0 auto', + maxWidth: MAX_WIDTH_MEDIA_BREAKPOINT, +}) -export const NameText = styled(ThemedText.BodyPrimary)` - ${EllipsisStyle} -` -const ValueText = styled(ThemedText.BodyPrimary)` - ${EllipsisStyle} -` +export const EllipsisText = styled(Text, { + variant: 'body2', + color: '$neutral1', + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis', +}) -const SparklineContainer = styled.div` - width: 124px; - height: 40px; -` +const SparklineContainer = styled(Flex, { + width: '124px', + height: '$spacing40', +}) + +const TokenTableText = styled(Text, { + variant: 'body2', + color: '$neutral2', +}) interface TokenTableValue { index: number @@ -63,11 +67,17 @@ interface TokenTableValue { function TokenDescription({ token }: { token: TopToken }) { return ( - + - {token?.project?.name ?? token?.name} - {token?.symbol} - + {token?.project?.name ?? token?.name} + + {token?.symbol} + + ) } @@ -118,9 +128,9 @@ function TokenTableHeader({ return ( - + {isCurrentSortMethod && } - {HEADER_TEXT[category]} + {HEADER_TEXT[category]} ) @@ -224,12 +234,12 @@ function TokenTable({ id: 'index', header: () => ( - # + # ), cell: (index) => ( - {index.getValue?.()} + {index.getValue?.()} ), }), @@ -237,9 +247,9 @@ function TokenTable({ id: 'tokenDescription', header: () => ( - + - + ), cell: (tokenDescription) => ( @@ -261,12 +271,12 @@ function TokenTable({ ), cell: (price) => ( - + {/* A simple 0 price indicates the price is not currently available from the api */} {price.getValue?.() === 0 ? '-' : formatFiatPrice({ price: price.getValue?.(), type: NumberType.FiatTokenPrice })} - + ), }), @@ -317,7 +327,7 @@ function TokenTable({ ), cell: (fdv) => ( - {formatNumber({ input: fdv.getValue?.(), type: NumberType.FiatTokenStats })} + {formatNumber({ input: fdv.getValue?.(), type: NumberType.FiatTokenStats })} ), }), @@ -334,7 +344,7 @@ function TokenTable({ ), cell: (volume) => ( - {formatNumber({ input: volume.getValue?.(), type: NumberType.FiatTokenStats })} + {formatNumber({ input: volume.getValue?.(), type: NumberType.FiatTokenStats })} ), }), diff --git a/apps/web/src/components/Tokens/loading.tsx b/apps/web/src/components/Tokens/loading.tsx index bfcc25cc316..64f3bc94cd0 100644 --- a/apps/web/src/components/Tokens/loading.tsx +++ b/apps/web/src/components/Tokens/loading.tsx @@ -1,9 +1,9 @@ import { loadingAnimation } from 'components/Loader/styled' -import styled from 'lib/styled-components' +import deprecatedStyled from 'lib/styled-components' import { lighten } from 'polished' /* Loading state bubbles (animation style from: src/components/Loader/styled.tsx) */ -export const LoadingBubble = styled.div<{ +export const LoadingBubble = deprecatedStyled.div<{ height?: string width?: string round?: boolean diff --git a/apps/web/src/components/WalletModal/UniswapWalletOptions.tsx b/apps/web/src/components/WalletModal/UniswapWalletOptions.tsx index 6783a630e6f..f2d5f54983f 100644 --- a/apps/web/src/components/WalletModal/UniswapWalletOptions.tsx +++ b/apps/web/src/components/WalletModal/UniswapWalletOptions.tsx @@ -9,7 +9,7 @@ import styled from 'lib/styled-components' import { Z_INDEX } from 'theme/zIndex' import { Image, Text } from 'ui/src' import { UNISWAP_LOGO } from 'ui/src/assets' -import { ScanQr } from 'ui/src/components/icons' +import { ScanQr } from 'ui/src/components/icons/ScanQr' import { iconSizes } from 'ui/src/theme' import { FeatureFlags } from 'uniswap/src/features/gating/flags' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' diff --git a/apps/web/src/components/WalletModal/useOrderedConnections.test.tsx b/apps/web/src/components/WalletModal/useOrderedConnections.test.tsx index 62659123310..72c610ef648 100644 --- a/apps/web/src/components/WalletModal/useOrderedConnections.test.tsx +++ b/apps/web/src/components/WalletModal/useOrderedConnections.test.tsx @@ -39,7 +39,7 @@ const DEFAULT_CONNECTORS = [ describe('useOrderedConnections', () => { beforeEach(() => { - UserAgentMock.isMobile = false + UserAgentMock.isMobileWeb = false mocked(useConnect).mockReturnValue({ connectors: DEFAULT_CONNECTORS, } as unknown as ReturnType) @@ -88,14 +88,14 @@ describe('useOrderedConnections', () => { }) it('should return only injected connectors for in-wallet browsers', () => { - UserAgentMock.isMobile = true + UserAgentMock.isMobileWeb = true const { result } = renderHook(() => useOrderedConnections()) expect(result.current.length).toEqual(1) expect(result.current[0].id).toEqual(CONNECTION.METAMASK_RDNS) }) it('should return only the Coinbase injected connector in the Coinbase Wallet', async () => { - UserAgentMock.isMobile = true + UserAgentMock.isMobileWeb = true mocked(useConnect).mockReturnValue({ connectors: [ UNISWAP_MOBILE_CONNECTOR, @@ -147,7 +147,7 @@ describe('useOrderedConnections', () => { }) it('should include only the fallback injected provider when no eip6963 injectors are present on mobile', async () => { - UserAgentMock.isMobile = true + UserAgentMock.isMobileWeb = true window.ethereum = true as any mocked(useConnect).mockReturnValue({ connectors: [UNISWAP_MOBILE_CONNECTOR, INJECTED_CONNECTOR, WALLET_CONNECT_CONNECTOR, COINBASE_SDK_CONNECTOR], diff --git a/apps/web/src/components/WalletModal/useOrderedConnections.tsx b/apps/web/src/components/WalletModal/useOrderedConnections.tsx index 16ea9b83001..773af15ddc8 100644 --- a/apps/web/src/components/WalletModal/useOrderedConnections.tsx +++ b/apps/web/src/components/WalletModal/useOrderedConnections.tsx @@ -1,7 +1,7 @@ import { CONNECTION, useRecentConnectorId } from 'components/Web3Provider/constants' import { useConnect } from 'hooks/useConnect' import { useCallback, useMemo } from 'react' -import { isMobile, isTouchable, isWebAndroid, isWebIOS } from 'utilities/src/platform' +import { isMobileWeb, isTouchable, isWebAndroid, isWebIOS } from 'utilities/src/platform' import { Connector } from 'wagmi' type ConnectorID = (typeof CONNECTION)[keyof typeof CONNECTION] @@ -42,7 +42,7 @@ function getInjectedConnectors(connectors: readonly Connector[], excludeUniswapC const injectedConnectors = connectors.filter((c) => { // Special-case: Ignore coinbase eip6963-injected connector; coinbase connection is handled via the SDK connector. if (c.id === CONNECTION.COINBASE_RDNS) { - if (isMobile) { + if (isMobileWeb) { isCoinbaseWalletBrowser = true } return false @@ -102,7 +102,7 @@ export function useOrderedConnections(excludeUniswapConnections?: boolean): Inje } // Special-case: Only display the injected connector for in-wallet browsers. - if (isMobile && injectedConnectors.length === 1) { + if (isMobileWeb && injectedConnectors.length === 1) { return injectedConnectors } diff --git a/apps/web/src/components/Web3Provider/WebUniswapContext.tsx b/apps/web/src/components/Web3Provider/WebUniswapContext.tsx new file mode 100644 index 00000000000..183a7897f4f --- /dev/null +++ b/apps/web/src/components/Web3Provider/WebUniswapContext.tsx @@ -0,0 +1,44 @@ +import { useAccount } from 'hooks/useAccount' +import { useEthersProvider } from 'hooks/useEthersProvider' +import { useEthersSigner } from 'hooks/useEthersSigner' +import { PropsWithChildren, useMemo } from 'react' +import { UniswapProvider } from 'uniswap/src/contexts/UniswapContext' +import { AccountMeta, AccountType } from 'uniswap/src/features/accounts/types' +import { FeatureFlags } from 'uniswap/src/features/gating/flags' +import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' + +// Adapts useEthersProvider to fit uniswap context hook shape +function useWebProvider(chainId: number) { + return useEthersProvider({ chainId }) +} + +function useWagmiAccount(): AccountMeta { + const account = useAccount() + return useMemo(() => { + // TODO(WEB-4736): remove this default account stub once swap flow supports unconnected state. + if (!account.address) { + return { + address: '0x67d615D6bccAA1562B1cca9786384b4840597ecD', + type: AccountType.Readonly, + } + } + return { + address: account.address, + type: AccountType.SignerMnemonic, + } + }, [account.address]) +} + +// Abstracts web-specific transaction flow objects for usage in cross-platform flows in the `uniswap` package. +export function WebUniswapProvider({ children }: PropsWithChildren) { + const account = useWagmiAccount() + const signer = useEthersSigner() + + const sharedSwapEnabled = useFeatureFlag(FeatureFlags.UniversalSwap) + + return ( + + {children} + + ) +} diff --git a/apps/web/src/components/Web3Provider/wagmi.ts b/apps/web/src/components/Web3Provider/wagmi.ts index acc839273c5..07e2d4d4b14 100644 --- a/apps/web/src/components/Web3Provider/wagmi.ts +++ b/apps/web/src/components/Web3Provider/wagmi.ts @@ -3,6 +3,7 @@ import { injectedWithFallback } from 'components/Web3Provider/injectedWithFallba import { WC_PARAMS, uniswapWalletConnect } from 'components/Web3Provider/walletConnect' import { UNISWAP_LOGO } from 'ui/src/assets' import { UNIVERSE_CHAIN_INFO } from 'uniswap/src/constants/chains' +import { UNISWAP_WEB_URL } from 'uniswap/src/constants/urls' import { UniverseChainId, WEB_SUPPORTED_CHAIN_IDS } from 'uniswap/src/types/chains' import { createClient } from 'viem' import { createConfig, http } from 'wagmi' @@ -26,7 +27,9 @@ export const wagmiConfig = createConfig({ uniswapWalletConnect(), coinbaseWallet({ appName: 'Uniswap', - appLogoUrl: UNISWAP_LOGO, + // CB SDK doesn't pass the parent origin context to their passkey site + // Flagged to CB team and can remove UNISWAP_WEB_URL once fixed + appLogoUrl: `${UNISWAP_WEB_URL}${UNISWAP_LOGO}`, reloadOnDisconnect: false, enableMobileWalletLink: true, }), diff --git a/apps/web/src/components/Web3Status/index.tsx b/apps/web/src/components/Web3Status/index.tsx index 5a9762f858f..09a12f0227f 100644 --- a/apps/web/src/components/Web3Status/index.tsx +++ b/apps/web/src/components/Web3Status/index.tsx @@ -17,7 +17,7 @@ import { darken } from 'polished' import { RefObject, useCallback, useEffect, useRef } from 'react' import { useAppSelector } from 'state/hooks' import { flexRowNoWrap } from 'theme/styles' -import { Unitag } from 'ui/src/components/icons' +import { Unitag } from 'ui/src/components/icons/Unitag' import Trace from 'uniswap/src/features/telemetry/Trace' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { Trans } from 'uniswap/src/i18n' diff --git a/apps/web/src/components/addLiquidity/PoolWarning.tsx b/apps/web/src/components/addLiquidity/PoolWarning.tsx index f0d66941234..c32e3556bfe 100644 --- a/apps/web/src/components/addLiquidity/PoolWarning.tsx +++ b/apps/web/src/components/addLiquidity/PoolWarning.tsx @@ -4,7 +4,7 @@ import styled from 'lib/styled-components' import { ReactNode } from 'react' import { ExternalLink } from 'theme/components' import { Text } from 'ui/src' -import { AlertTriangle } from 'ui/src/components/icons' +import { AlertTriangle } from 'ui/src/components/icons/AlertTriangle' import { iconSizes } from 'ui/src/theme' import { Trans } from 'uniswap/src/i18n' diff --git a/apps/web/src/components/swap/PriceImpactModal.tsx b/apps/web/src/components/swap/PriceImpactModal.tsx index 54c65f4a06b..afe31970910 100644 --- a/apps/web/src/components/swap/PriceImpactModal.tsx +++ b/apps/web/src/components/swap/PriceImpactModal.tsx @@ -1,9 +1,8 @@ import { Percent } from '@uniswap/sdk-core' import Modal from 'components/Modal' import { GetHelpHeader } from 'components/Modal/GetHelpHeader' -import { useTheme } from 'lib/styled-components' import { Button, Flex, Text } from 'ui/src' -import { AlertTriangle } from 'ui/src/components/icons' +import { AlertTriangle } from 'ui/src/components/icons/AlertTriangle' import { Trans } from 'uniswap/src/i18n' import { useFormatter } from 'utils/formatNumbers' @@ -14,7 +13,6 @@ interface PriceImpactModalProps { } export default function PriceImpactModal({ priceImpact, onDismiss, onContinue }: PriceImpactModalProps) { - const theme = useTheme() const { formatPercent } = useFormatter() const impact = `${formatPercent(priceImpact)}` @@ -23,7 +21,7 @@ export default function PriceImpactModal({ priceImpact, onDismiss, onContinue }: - + diff --git a/apps/web/src/constants/localCurrencies.tsx b/apps/web/src/constants/localCurrencies.tsx index afc28bcd437..f1094466be0 100644 --- a/apps/web/src/constants/localCurrencies.tsx +++ b/apps/web/src/constants/localCurrencies.tsx @@ -9,6 +9,7 @@ import { IDR_ICON, INR_ICON, JPY_ICON, + KRW_ICON, NGN_ICON, PKR_ICON, RUB_ICON, @@ -34,6 +35,7 @@ export const SUPPORTED_LOCAL_CURRENCIES = [ Currency.Idr, Currency.Inr, Currency.Jpy, + Currency.Krw, Currency.Ngn, Currency.Pkr, Currency.Rub, @@ -60,6 +62,7 @@ export const LOCAL_CURRENCY_SYMBOL_DISPLAY_TYPE: Record case Currency.Jpy: return + case Currency.Krw: + return case Currency.Vnd: return case Currency.Sgd: diff --git a/apps/web/src/constants/localCurrencyIcons.tsx b/apps/web/src/constants/localCurrencyIcons.tsx index 3fa145bd81a..1e2a81bc571 100644 --- a/apps/web/src/constants/localCurrencyIcons.tsx +++ b/apps/web/src/constants/localCurrencyIcons.tsx @@ -755,3 +755,54 @@ export const CNY_ICON = (props: SVGProps) => ( ) + +export const KRW_ICON = (props: SVGProps) => ( + + + + + + + + + + + + + + + + + + +) diff --git a/apps/web/src/env.d.ts b/apps/web/src/env.d.ts index 086831add5e..f06fa56d347 100644 --- a/apps/web/src/env.d.ts +++ b/apps/web/src/env.d.ts @@ -5,11 +5,15 @@ // eslint-disable-next-line @typescript-eslint/triple-slash-reference /// -import { config } from 'tamagui.config' +import { config, TamaguiGroupNames } from 'tamagui.config' type Conf = typeof config declare module 'tamagui' { // eslint-disable-next-line @typescript-eslint/no-empty-interface interface TamaguiCustomConfig extends Conf {} + + interface TypeOverride { + groupNames(): TamaguiGroupNames + } } diff --git a/apps/web/src/global.css b/apps/web/src/global.css new file mode 100644 index 00000000000..52899c09fbe --- /dev/null +++ b/apps/web/src/global.css @@ -0,0 +1,59 @@ +/* Add styles here only for things Tamagui doesn't support. Ideally very few + things go here, but stuff like keyframe CSS animations that Tamagui doesn't + support can be added here. Be sure to try `$platform-web` style prop first as + that should avoid needing to add here. */ + +.text-wrap-pretty { + text-wrap: pretty; +} + +.text-decoration-none { + text-decoration: none; +} + +@media screen and (max-width: 864px) { + /* the :root:root:root is to have higher specificity than tamagui */ + :root:root:root .connect-with-us-layout { + display: flex; + flex-direction: column; + } +} + +@keyframes token-float-animation { + 0% { + transform: translateY(-8px); + } + 50% { + transform: translateY(8px); + } + 100% { + transform: translateY(-8px); + } +} + +@keyframes token-rotate-animation { + 0% { + transform: rotate(-22deg); + } + 100% { + transform: rotate(22deg); + } +} + +.scrollbar-hidden { + ::-webkit-scrollbar { + display: none; + } + -ms-overflow-style: none; + scrollbar-width: none; +} +.last-child-flex-end { + &:last-child { + justify-content: flex-end; + } +} +.first-child-flex-grow-0 { + &:first-child { + flex-grow: 0; + } +} diff --git a/apps/web/src/graphql/data/apollo/TokenBalancesProvider.tsx b/apps/web/src/graphql/data/apollo/TokenBalancesProvider.tsx index bbe9b1ab032..684907de9cc 100644 --- a/apps/web/src/graphql/data/apollo/TokenBalancesProvider.tsx +++ b/apps/web/src/graphql/data/apollo/TokenBalancesProvider.tsx @@ -1,12 +1,9 @@ import { usePendingActivity } from 'components/AccountDrawer/MiniPortfolio/Activity/hooks' -import { hideSmallBalancesAtom } from 'components/AccountDrawer/SmallBalanceToggle' -import { hideSpamAtom } from 'components/AccountDrawer/SpamToggle' import { createAdaptiveRefetchContext } from 'graphql/data/apollo/AdaptiveRefetch' import { useAssetActivitySubscription } from 'graphql/data/apollo/AssetActivityProvider' import { GQL_MAINNET_CHAINS_MUTABLE } from 'graphql/data/util' import { useAccount } from 'hooks/useAccount' -import { useAtomValue } from 'jotai/utils' -import { PropsWithChildren, useCallback, useMemo } from 'react' +import { PropsWithChildren, useCallback, useEffect, useMemo } from 'react' import { OnAssetActivitySubscription, PortfolioBalancesWebQueryResult, @@ -16,6 +13,9 @@ import { } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { FeatureFlags } from 'uniswap/src/features/gating/flags' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' +import { useHideSmallBalancesSetting, useHideSpamTokensSetting } from 'uniswap/src/features/settings/hooks' +import { UniswapEventName } from 'uniswap/src/features/telemetry/constants' +import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { InterfaceChainId } from 'uniswap/src/types/chains' import { SUBSCRIPTION_CHAINIDS } from 'utilities/src/apollo/constants' import { usePrevious } from 'utilities/src/react/hooks' @@ -73,8 +73,8 @@ function usePortfolioValueModifiers(): { includeSmallBalances: boolean includeSpamTokens: boolean } { - const hideSmallBalances = useAtomValue(hideSmallBalancesAtom) - const hideSpamTokens = useAtomValue(hideSpamAtom) + const hideSmallBalances = useHideSmallBalancesSetting() + const hideSpamTokens = useHideSpamTokensSetting() return useMemo( () => ({ includeSmallBalances: !hideSmallBalances, @@ -85,7 +85,7 @@ function usePortfolioValueModifiers(): { } export function TokenBalancesProvider({ children }: PropsWithChildren) { - const [lazyFetch, query] = usePortfolioBalancesWebLazyQuery() + const [lazyFetch, query] = usePortfolioBalancesWebLazyQuery({ errorPolicy: 'all' }) const account = useAccount() const hasAccountUpdate = useHasAccountUpdate() const valueModifiers = usePortfolioValueModifiers() @@ -124,4 +124,21 @@ export function useTotalBalancesUsdForAnalytics(): number | undefined { return useTokenBalancesQuery({ cacheOnly: true }).data?.portfolios?.[0]?.tokensTotalDenominatedValue?.value } +export function useReportTotalBalancesUsdForAnalytics() { + const account = useAccount() + const portfolioBalanceUsd = useTotalBalancesUsdForAnalytics() + + useEffect(() => { + if (!portfolioBalanceUsd || !account.address) { + return + } + + sendAnalyticsEvent(UniswapEventName.BalancesReport, { + total_balances_usd: portfolioBalanceUsd, + wallets: [account.address], + balances: [portfolioBalanceUsd], + }) + }, [portfolioBalanceUsd, account.address]) +} + export { PrefetchBalancesWrapper, useTokenBalancesQuery } diff --git a/apps/web/src/hooks/Tokens.test.ts b/apps/web/src/hooks/Tokens.test.ts new file mode 100644 index 00000000000..63b38971d23 --- /dev/null +++ b/apps/web/src/hooks/Tokens.test.ts @@ -0,0 +1,69 @@ +import { Token } from '@uniswap/sdk-core' +import { DAI, NATIVE_CHAIN_ID } from 'constants/tokens' +import { useCurrencyInfo } from 'hooks/Tokens' +import { TEST_TOKEN_1 } from 'test-utils/constants' +import { renderHook } from 'test-utils/render' +import { UNIVERSE_CHAIN_INFO } from 'uniswap/src/constants/chains' +import { NativeCurrency } from 'uniswap/src/features/tokens/NativeCurrency' +import { useCurrencyInfo as useUniswapCurrencyInfo } from 'uniswap/src/features/tokens/useCurrencyInfo' +import { UniverseChainId } from 'uniswap/src/types/chains' + +jest.mock('uniswap/src/features/tokens/useCurrencyInfo', () => ({ + useCurrencyInfo: jest.fn(), +})) + +describe('useCurrencyInfo', () => { + it('returns undefined if no address is provided', () => { + const { result } = renderHook(() => useCurrencyInfo(undefined, UniverseChainId.Mainnet)) + + expect(result.current).toBeUndefined() + }) + + it('returns undefined if skip is true and no common base is found', () => { + const { result } = renderHook(() => useCurrencyInfo(TEST_TOKEN_1.address, UniverseChainId.Mainnet, true)) + + expect(result.current).toBeUndefined() + }) + + describe('ERC20', () => { + it('calls useUniswapCurrencyInfo with the correct arguments', () => { + renderHook(() => useCurrencyInfo(DAI.address, UniverseChainId.Mainnet)) + + expect(useUniswapCurrencyInfo).toHaveBeenCalledWith(`${UniverseChainId.Mainnet}-${DAI.address}`) + }) + + it('calls useUniswapCurrencyInfo with the correct arguments when Currency is provided', () => { + const currency = new Token(UniverseChainId.Mainnet, DAI.address, 18, DAI.symbol, DAI.name) + renderHook(() => useCurrencyInfo(currency)) + + expect(useUniswapCurrencyInfo).toHaveBeenCalledWith(`${UniverseChainId.Mainnet}-${DAI.address}`) + }) + }) + + describe(`${NATIVE_CHAIN_ID}`, () => { + it('calls useUniswapCurrencyInfo with the correct arguments', () => { + renderHook(() => useCurrencyInfo('ETH', UniverseChainId.Mainnet)) + + expect(useUniswapCurrencyInfo).toHaveBeenCalledWith( + `${UniverseChainId.Mainnet}-${UNIVERSE_CHAIN_INFO[UniverseChainId.Mainnet].nativeCurrency.address}`, + ) + }) + + it('calls useUniswapCurrencyInfo with the correct arguments when no address is provided', () => { + renderHook(() => useCurrencyInfo(undefined, UniverseChainId.Mainnet)) + + expect(useUniswapCurrencyInfo).toHaveBeenCalledWith( + `${UniverseChainId.Mainnet}-${UNIVERSE_CHAIN_INFO[UniverseChainId.Mainnet].nativeCurrency.address}`, + ) + }) + + it('calls useUniswapCurrencyInfo with the correct arguments when Currency is provided', () => { + const currency = NativeCurrency.onChain(UniverseChainId.Mainnet) + renderHook(() => useCurrencyInfo(currency)) + + expect(useUniswapCurrencyInfo).toHaveBeenCalledWith( + `${UniverseChainId.Mainnet}-${UNIVERSE_CHAIN_INFO[UniverseChainId.Mainnet].nativeCurrency.address}`, + ) + }) + }) +}) diff --git a/apps/web/src/hooks/Tokens.ts b/apps/web/src/hooks/Tokens.ts index 0eb89b8fbca..d723e8073f8 100644 --- a/apps/web/src/hooks/Tokens.ts +++ b/apps/web/src/hooks/Tokens.ts @@ -1,34 +1,20 @@ import { Currency, Token } from '@uniswap/sdk-core' -import { - SupportedInterfaceChainId, - chainIdToBackendChain, - getChain, - isSupportedChainId, - useSupportedChainId, -} from 'constants/chains' -import { COMMON_BASES, buildCurrencyInfo } from 'constants/routing' -import { NATIVE_CHAIN_ID, UNKNOWN_TOKEN_SYMBOL } from 'constants/tokens' -import { arrayify, parseBytes32String } from 'ethers/lib/utils' -import { gqlTokenToCurrencyInfo } from 'graphql/data/types' +import { SupportedInterfaceChainId, useSupportedChainId } from 'constants/chains' +import { COMMON_BASES } from 'constants/routing' +import { NATIVE_CHAIN_ID } from 'constants/tokens' import { useAccount } from 'hooks/useAccount' -import { useBytes32TokenContract, useTokenContract } from 'hooks/useContract' -import { NEVER_RELOAD, useSingleCallResult } from 'lib/hooks/multicall' import { TokenAddressMap } from 'lib/hooks/useTokenList/utils' import { useMemo } from 'react' import { useCombinedInactiveLists } from 'state/lists/hooks' import { TokenFromList } from 'state/lists/tokenFromList' import { useUserAddedTokens } from 'state/user/userAddedTokens' -import { - Token as GqlToken, - SafetyLevel, - useSimpleTokenQuery, -} from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' +import { UNIVERSE_CHAIN_INFO } from 'uniswap/src/constants/chains' + import { CurrencyInfo } from 'uniswap/src/features/dataApi/types' -import { InterfaceChainId } from 'uniswap/src/types/chains' +import { useCurrencyInfo as useUniswapCurrencyInfo } from 'uniswap/src/features/tokens/useCurrencyInfo' +import { InterfaceChainId, UniverseChainId } from 'uniswap/src/types/chains' +import { buildCurrencyId } from 'uniswap/src/utils/currencyId' import { isAddress, isSameAddress } from 'utilities/src/addresses' -import { DEFAULT_ERC20_DECIMALS } from 'utilities/src/tokens/constants' -import { currencyId } from 'utils/currencyId' -import { getNativeTokenDBAddress } from 'utils/nativeTokens' type Maybe = T | undefined @@ -99,76 +85,78 @@ export function useCurrencyInfo( skip?: boolean, ): Maybe { const { chainId: connectedChainId } = useAccount() - const fallbackListTokens = useFallbackListTokens(chainId ?? connectedChainId) - - const address = - typeof addressOrCurrency === 'string' - ? addressOrCurrency - : addressOrCurrency?.isNative - ? NATIVE_CHAIN_ID - : addressOrCurrency?.address const chainIdWithFallback = (typeof addressOrCurrency === 'string' ? chainId : addressOrCurrency?.chainId) ?? connectedChainId + const nativeAddressWithFallback = + UNIVERSE_CHAIN_INFO[chainIdWithFallback as UniverseChainId]?.nativeCurrency.address ?? + UNIVERSE_CHAIN_INFO[UniverseChainId.Mainnet]?.nativeCurrency.address + + const isNative = useMemo(() => checkIsNative(addressOrCurrency), [addressOrCurrency]) + const address = useMemo( + () => getAddress(isNative, nativeAddressWithFallback, addressOrCurrency), + [isNative, nativeAddressWithFallback, addressOrCurrency], + ) const supportedChainId = useSupportedChainId(chainIdWithFallback) - const backendChainName = chainIdToBackendChain({ - chainId: supportedChainId, - withFallback: true, - }) - const isNative = - address === NATIVE_CHAIN_ID || address?.toLowerCase() === 'native' || address?.toLowerCase() === 'eth' - - const commonBase = chainIdWithFallback - ? COMMON_BASES[chainIdWithFallback]?.find( - (base) => - (base.currency.isNative && isNative) || - (base.currency.isToken && isSameAddress(base.currency.address, address)), - ) - : undefined - - const { data } = useSimpleTokenQuery({ - variables: { - chain: backendChainName, - address: isNative ? getNativeTokenDBAddress(backendChainName) : address ?? '', - }, - skip: - (!address && !isNative) || - skip || - !!commonBase || - !getChain({ chainId: supportedChainId })?.backendChain.backendSupported, - fetchPolicy: 'cache-first', - }) - - // Some chains are not supported by the backend, so we need to fetch token - // details directly from the blockchain. - const networkToken = useTokenFromActiveNetwork( - address, - getChain({ chainId: chainId ?? connectedChainId })?.backendChain.backendSupported, - ) + const addressWithFallback = isNative || !address ? nativeAddressWithFallback : address + + const currencyId = buildCurrencyId(supportedChainId ?? UniverseChainId.Mainnet, addressWithFallback) + const currencyInfo = useUniswapCurrencyInfo(currencyId) return useMemo(() => { + const commonBase = getCommonBase(chainIdWithFallback, isNative, address) + if (commonBase) { return commonBase } - const fallbackListToken = fallbackListTokens[address ?? ''] - if (fallbackListToken instanceof TokenFromList && !skip) { - return { - currency: fallbackListToken, - currencyId: currencyId(fallbackListToken), - logoUrl: fallbackListToken.tokenInfo.logoURI, - safetyLevel: SafetyLevel.Verified, - isSpam: false, - } + if (!currencyInfo || !addressOrCurrency || skip) { + return undefined + } + + return currencyInfo + }, [addressOrCurrency, currencyInfo, chainIdWithFallback, isNative, address, skip]) +} + +const checkIsNative = (addressOrCurrency?: string | Currency): boolean => { + return typeof addressOrCurrency === 'string' + ? [NATIVE_CHAIN_ID, 'native', 'eth'].includes(addressOrCurrency.toLowerCase()) + : addressOrCurrency?.isNative ?? false +} + +const getCommonBase = (chainId?: number, isNative?: boolean, address?: string): CurrencyInfo | undefined => { + if (!address || !chainId) { + return undefined + } + return COMMON_BASES[chainId]?.find( + (base) => + (base.currency.isNative && isNative) || (base.currency.isToken && isSameAddress(base.currency.address, address)), + ) +} + +const getAddress = ( + isNative: boolean, + nativeAddressWithFallback: string, + addressOrCurrency?: string | Currency, +): string | undefined => { + if (typeof addressOrCurrency === 'string') { + if (isNative) { + return nativeAddressWithFallback + } else { + return addressOrCurrency } + } - if (!data?.token || !address || skip) { - return networkToken ? buildCurrencyInfo(networkToken) : undefined + if (addressOrCurrency) { + if (addressOrCurrency.isNative) { + return nativeAddressWithFallback + } else if (addressOrCurrency) { + return addressOrCurrency.address } + } - return gqlTokenToCurrencyInfo(data.token as GqlToken) - }, [commonBase, fallbackListTokens, address, skip, data?.token, networkToken]) + return undefined } export function useToken(tokenAddress?: string, chainId?: SupportedInterfaceChainId): Maybe { @@ -183,68 +171,3 @@ export function useToken(tokenAddress?: string, chainId?: SupportedInterfaceChai return undefined }, [currency]) } - -// parse a name or symbol from a token response -const BYTES32_REGEX = /^0x[a-fA-F0-9]{64}$/ - -function parseStringOrBytes32(str: string | undefined, bytes32: string | undefined, defaultValue: string): string { - return str && str.length > 0 - ? str - : // need to check for proper bytes string and valid terminator - bytes32 && BYTES32_REGEX.test(bytes32) && arrayify(bytes32)[31] === 0 - ? parseBytes32String(bytes32) - : defaultValue -} - -const UNKNOWN_TOKEN_NAME = 'Unknown Token' - -/** - * Returns a Token from the tokenAddress. - * Returns null if token is loading or null was passed. - * Returns undefined if tokenAddress is invalid or token does not exist. - */ -function useTokenFromActiveNetwork(tokenAddress: string | undefined, skip?: boolean): Token | undefined { - const { chainId } = useAccount() - - const formattedAddress = isAddress(tokenAddress) - const tokenContract = useTokenContract(formattedAddress ? formattedAddress : undefined, false) - const tokenContractBytes32 = useBytes32TokenContract(formattedAddress ? formattedAddress : undefined, false) - - // TODO (WEB-1709): reduce this to one RPC call instead of 5 - // TODO: Fix redux-multicall so that these values do not reload. - const tokenName = useSingleCallResult(skip ? undefined : tokenContract, 'name', undefined, NEVER_RELOAD) - const tokenNameBytes32 = useSingleCallResult(skip ? undefined : tokenContractBytes32, 'name', undefined, NEVER_RELOAD) - const symbol = useSingleCallResult(skip ? undefined : tokenContract, 'symbol', undefined, NEVER_RELOAD) - const symbolBytes32 = useSingleCallResult(skip ? undefined : tokenContractBytes32, 'symbol', undefined, NEVER_RELOAD) - const decimals = useSingleCallResult(skip ? undefined : tokenContract, 'decimals', undefined, NEVER_RELOAD) - - const isLoading = useMemo( - () => decimals.loading || symbol.loading || tokenName.loading, - [decimals.loading, symbol.loading, tokenName.loading], - ) - const parsedDecimals = useMemo(() => decimals?.result?.[0] ?? DEFAULT_ERC20_DECIMALS, [decimals.result]) - - const parsedSymbol = useMemo( - () => parseStringOrBytes32(symbol.result?.[0], symbolBytes32.result?.[0], UNKNOWN_TOKEN_SYMBOL), - [symbol.result, symbolBytes32.result], - ) - const parsedName = useMemo( - () => parseStringOrBytes32(tokenName.result?.[0], tokenNameBytes32.result?.[0], UNKNOWN_TOKEN_NAME), - [tokenName.result, tokenNameBytes32.result], - ) - - return useMemo(() => { - // If the token is on another chain, we cannot fetch it on-chain, and it is invalid. - if (!tokenAddress || !isSupportedChainId(chainId) || !formattedAddress) { - return undefined - } - if (isLoading || !chainId) { - return undefined - } - if (!decimals?.result?.[0] && parsedSymbol === UNKNOWN_TOKEN_SYMBOL && parsedName === UNKNOWN_TOKEN_NAME) { - return undefined - } - - return new Token(chainId, formattedAddress, parsedDecimals, parsedSymbol, parsedName) - }, [tokenAddress, chainId, formattedAddress, isLoading, decimals?.result, parsedDecimals, parsedSymbol, parsedName]) -} diff --git a/apps/web/src/hooks/useContract.ts b/apps/web/src/hooks/useContract.ts index d4f943d7b5d..2bef7b8e660 100644 --- a/apps/web/src/hooks/useContract.ts +++ b/apps/web/src/hooks/useContract.ts @@ -24,7 +24,6 @@ import ENS_PUBLIC_RESOLVER_ABI from 'uniswap/src/abis/ens-public-resolver.json' import ENS_ABI from 'uniswap/src/abis/ens-registrar.json' import ERC1155_ABI from 'uniswap/src/abis/erc1155.json' import ERC20_ABI from 'uniswap/src/abis/erc20.json' -import ERC20_BYTES32_ABI from 'uniswap/src/abis/erc20_bytes32.json' import ERC721_ABI from 'uniswap/src/abis/erc721.json' import { ArgentWalletDetector, @@ -143,10 +142,6 @@ export function useENSRegistrarContract() { return useMainnetContract(ENS_REGISTRAR_ADDRESSES[UniverseChainId.Mainnet], ENS_ABI) } -export function useBytes32TokenContract(tokenAddress?: string, withSignerIfPossible?: boolean): Contract | null { - return useContract(tokenAddress, ERC20_BYTES32_ABI, withSignerIfPossible) -} - export function useENSResolverContract(address: string | undefined) { return useMainnetContract(address, ENS_PUBLIC_RESOLVER_ABI) } diff --git a/apps/web/src/hooks/useDisableScrolling.test.ts b/apps/web/src/hooks/useDisableScrolling.test.ts index 8eb5f6df512..c9bb002dd83 100644 --- a/apps/web/src/hooks/useDisableScrolling.test.ts +++ b/apps/web/src/hooks/useDisableScrolling.test.ts @@ -3,27 +3,27 @@ import useDisableScrolling from 'hooks/useDisableScrolling' const UserAgentMock = jest.requireMock('utilities/src/platform') jest.mock('utilities/src/platform', () => ({ - isMobile: true, + isMobileWeb: true, })) describe('useDisableScrolling', () => { it('should disable scrolling on mobile', () => { - UserAgentMock.isMobile = true + UserAgentMock.isMobileWeb = true renderHook(() => useDisableScrolling(true)) expect(document.body.style.overflow).toBe('hidden') }) it('should enable scrolling on mobile', () => { - UserAgentMock.isMobile = true + UserAgentMock.isMobileWeb = true renderHook(() => useDisableScrolling(false)) expect(document.body.style.overflow).toBe('auto') }) it('should not disable scrolling on desktop', () => { - UserAgentMock.isMobile = false + UserAgentMock.isMobileWeb = false renderHook(() => useDisableScrolling(true)) expect(document.body.style.overflow).toBe('auto') }) it('should not enable scrolling on desktop', () => { - UserAgentMock.isMobile = false + UserAgentMock.isMobileWeb = false renderHook(() => useDisableScrolling(false)) expect(document.body.style.overflow).toBe('auto') }) diff --git a/apps/web/src/hooks/useDisableScrolling.ts b/apps/web/src/hooks/useDisableScrolling.ts index fa8f4eb3112..b361dd26923 100644 --- a/apps/web/src/hooks/useDisableScrolling.ts +++ b/apps/web/src/hooks/useDisableScrolling.ts @@ -1,10 +1,10 @@ import { useEffect } from 'react' -import { isMobile } from 'utilities/src/platform' +import { isMobileWeb } from 'utilities/src/platform' /** Disables scrolling of the main body on mobile when `true` is passed. Generally used for modals. */ export default function useDisableScrolling(disable: boolean | undefined | null) { useEffect(() => { - if (!isMobile) { + if (!isMobileWeb) { return } document.body.style.overflow = disable ? 'hidden' : 'auto' diff --git a/apps/web/src/hooks/useEthersSigner.ts b/apps/web/src/hooks/useEthersSigner.ts index 02fb7512faf..593966a50a6 100644 --- a/apps/web/src/hooks/useEthersSigner.ts +++ b/apps/web/src/hooks/useEthersSigner.ts @@ -20,7 +20,7 @@ function clientToSigner(client?: Client) } /** Hook to convert a Viem Client to an ethers.js Signer. */ -export function useEthersSigner({ chainId }: { chainId?: number } = {}) { - const { data: client } = useConnectorClient({ chainId }) +export function useEthersSigner() { + const { data: client } = useConnectorClient() return useMemo(() => clientToSigner(client), [client]) } diff --git a/apps/web/src/hooks/useFilterPossiblyMaliciousPositions.ts b/apps/web/src/hooks/useFilterPossiblyMaliciousPositions.ts index 06e69b8567b..a6e2dd85165 100644 --- a/apps/web/src/hooks/useFilterPossiblyMaliciousPositions.ts +++ b/apps/web/src/hooks/useFilterPossiblyMaliciousPositions.ts @@ -9,9 +9,9 @@ import { useMemo } from 'react' import { PositionDetails } from 'types/position' import { SafetyLevel, - SimpleTokenDocument, - SimpleTokenQuery, Token, + TokenDocument, + TokenQuery, } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { hasURL } from 'utils/urlChecks' @@ -26,16 +26,16 @@ function getPositionCurrencyInfosQueryOptions(position: PositionDetails, chainId queryKey: ['positionCurrencyInfo', position], queryFn: async () => { const queries = [ - apolloClient.query({ - query: SimpleTokenDocument, + apolloClient.query({ + query: TokenDocument, variables: { address: position.token0, chain: chainIdToBackendChain({ chainId }), }, fetchPolicy: 'cache-first', }), - apolloClient.query({ - query: SimpleTokenDocument, + apolloClient.query({ + query: TokenDocument, variables: { address: position.token1, chain: chainIdToBackendChain({ chainId }), diff --git a/apps/web/src/hooks/useIsLandingPage.ts b/apps/web/src/hooks/useIsLandingPage.ts index 9a10c150769..8a6f9693f55 100644 --- a/apps/web/src/hooks/useIsLandingPage.ts +++ b/apps/web/src/hooks/useIsLandingPage.ts @@ -2,5 +2,5 @@ import { useLocation } from 'react-router-dom' export function useIsLandingPage() { const { pathname } = useLocation() - return pathname.endsWith('/') + return pathname === '/' } diff --git a/apps/web/src/hooks/useKeyPress.ts b/apps/web/src/hooks/useKeyPress.ts index c73db78ab73..33badc6078f 100644 --- a/apps/web/src/hooks/useKeyPress.ts +++ b/apps/web/src/hooks/useKeyPress.ts @@ -24,7 +24,9 @@ export const useKeyPress = ({ } const onKeyPress = (event: any) => { const wasAnyKeyPressed = keys.some((key) => event.key === key) - if (wasAnyKeyPressed) { + // Do not prevent default if the target element is an input + const targetWasNotAnInput = !['input', 'textarea'].includes(event.target.tagName.toLowerCase()) + if (wasAnyKeyPressed && targetWasNotAnInput) { if (preventDefault) { event.preventDefault() } diff --git a/apps/web/src/hooks/useParsedQueryString.ts b/apps/web/src/hooks/useParsedQueryString.ts index 0d9bfd0123b..3abd77ced3d 100644 --- a/apps/web/src/hooks/useParsedQueryString.ts +++ b/apps/web/src/hooks/useParsedQueryString.ts @@ -2,16 +2,12 @@ import { parse, ParsedQs } from 'qs' import { useMemo } from 'react' import { useLocation } from 'react-router-dom' -export function parsedQueryString(search?: string): ParsedQs { - if (!search) { - // react-router-dom places search string in the hash - const hash = window.location.hash - search = hash.substr(hash.indexOf('?')) - } - return search && search.length > 1 ? parse(search, { parseArrays: false, ignoreQueryPrefix: true }) : {} -} - export default function useParsedQueryString(): ParsedQs { const { search } = useLocation() - return useMemo(() => parsedQueryString(search), [search]) + return useMemo(() => { + const hash = window.location.hash + const query = search || hash.substr(hash.indexOf('?')) + + return query && query.length > 1 ? parse(query, { parseArrays: false, ignoreQueryPrefix: true }) : {} + }, [search]) } diff --git a/apps/web/src/hooks/useSwitchChain.ts b/apps/web/src/hooks/useSwitchChain.ts index 3d2553afa17..64e28b880e1 100644 --- a/apps/web/src/hooks/useSwitchChain.ts +++ b/apps/web/src/hooks/useSwitchChain.ts @@ -18,7 +18,7 @@ export function useSwitchChain() { const isSupportedChainCallback = useIsSupportedChainIdCallback() const multichainUXEnabled = useFeatureFlag(FeatureFlags.MultichainUX) const { switchChain } = useSwitchChainWagmi() - const { connector } = useAccount() + const account = useAccount() const [searchParams, setSearchParams] = useSearchParams() const { pathname } = useLocation() @@ -28,7 +28,11 @@ export function useSwitchChain() { (chainId: InterfaceChainId) => { const isSupportedChain = isSupportedChainCallback(chainId) if (!isSupportedChain) { - throw new Error(`Chain ${chainId} not supported for connector (${connector?.name})`) + throw new Error(`Chain ${chainId} not supported for connector (${account.connector?.name})`) + } + if (account.chainId === chainId) { + // some wallets (e.g. SafeWallet) only support single-chain & will throw error on `switchChain` even if already on the correct chain + return } return trace( { name: 'Switch chain', op: 'wallet.switch_chain' }, @@ -67,7 +71,8 @@ export function useSwitchChain() { }, [ isSupportedChainCallback, - connector?.name, + account.chainId, + account.connector?.name, dispatch, switchChain, multichainUXEnabled, diff --git a/apps/web/src/hooks/useWrapCallback.tsx b/apps/web/src/hooks/useWrapCallback.tsx index 99e43605637..dc84dda0e3b 100644 --- a/apps/web/src/hooks/useWrapCallback.tsx +++ b/apps/web/src/hooks/useWrapCallback.tsx @@ -13,11 +13,11 @@ import { useTransactionAdder } from 'state/transactions/hooks' import { TransactionType } from 'state/transactions/types' import { trace } from 'tracing/trace' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' +import { WrapType } from 'uniswap/src/features/transactions/types/wrap' import { Trans } from 'uniswap/src/i18n' -import { WrapType } from 'uniswap/src/types/wrap' import { logger } from 'utilities/src/logger/logger' -const NOT_APPLICABLE = { wrapType: WrapType.NOT_APPLICABLE } +const NOT_APPLICABLE = { wrapType: WrapType.NotApplicable } enum WrapInputError { NO_ERROR, // must be equal to 0 so all other errors are truthy @@ -103,7 +103,7 @@ export default function useWrapCallback( if (inputCurrency.isNative && weth.equals(outputCurrency)) { return { - wrapType: WrapType.WRAP, + wrapType: WrapType.Wrap, execute: sufficientBalance && inputAmount ? () => @@ -121,7 +121,7 @@ export default function useWrapCallback( ...eventProperties, contract_address: wethContract.address, contract_chain_id: network.chainId, - type: WrapType.WRAP, + type: WrapType.Wrap, }) const error = new Error(`Invalid WETH contract Please file a bug detailing how this happened - https://github.com/Uniswap/interface/issues/new?labels=bug&template=bug-report.md&title=Invalid%20WETH%20contract`) @@ -140,7 +140,7 @@ Please file a bug detailing how this happened - https://github.com/Uniswap/inter }) sendAnalyticsEvent(InterfaceEventName.WRAP_TOKEN_TXN_SUBMITTED, { ...eventProperties, - type: WrapType.WRAP, + type: WrapType.Wrap, }) return txReceipt.hash }) @@ -153,7 +153,7 @@ Please file a bug detailing how this happened - https://github.com/Uniswap/inter } } else if (weth.equals(inputCurrency) && outputCurrency.isNative) { return { - wrapType: WrapType.UNWRAP, + wrapType: WrapType.Unwrap, execute: sufficientBalance && inputAmount ? () => @@ -174,7 +174,7 @@ Please file a bug detailing how this happened - https://github.com/Uniswap/inter }) sendAnalyticsEvent(InterfaceEventName.WRAP_TOKEN_TXN_SUBMITTED, { ...eventProperties, - type: WrapType.UNWRAP, + type: WrapType.Unwrap, }) return txReceipt.hash } catch (error) { diff --git a/apps/web/src/index.tsx b/apps/web/src/index.tsx index e22bac5ced3..435628b5754 100644 --- a/apps/web/src/index.tsx +++ b/apps/web/src/index.tsx @@ -4,8 +4,9 @@ import 'sideEffects' import { getDeviceId } from '@amplitude/analytics-browser' import { ApolloProvider } from '@apollo/client' import { PortalProvider } from '@tamagui/portal' -import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { QueryClientProvider } from '@tanstack/react-query' import Web3Provider from 'components/Web3Provider' +import { WebUniswapProvider } from 'components/Web3Provider/WebUniswapContext' import { AssetActivityProvider } from 'graphql/data/apollo/AssetActivityProvider' import { TokenBalancesProvider } from 'graphql/data/apollo/TokenBalancesProvider' import { apolloClient } from 'graphql/data/apollo/client' @@ -30,6 +31,7 @@ import { ThemeProvider, ThemedGlobalStyle } from 'theme' import RadialGradientByChainUpdater from 'theme/components/RadialGradientByChainUpdater' import { SystemThemeUpdater, ThemeColorMetaUpdater } from 'theme/components/ThemeToggle' import { TamaguiProvider } from 'theme/tamaguiProvider' +import { SharedQueryClient } from 'uniswap/src/data/apiClients/SharedQueryClient' import { DUMMY_STATSIG_SDK_KEY } from 'uniswap/src/features/gating/constants' import { UnitagUpdaterContextProvider } from 'uniswap/src/features/unitags/context' import { getEnvName } from 'utilities/src/environment' @@ -97,23 +99,15 @@ function StatsigProvider({ children }: PropsWithChildren) { ) } -const queryClient = new QueryClient({ - defaultOptions: { - queries: { - staleTime: 1000 * 20, // 20 seconds - }, - }, -}) - const container = document.getElementById('root') as HTMLElement const Router = isBrowserRouterEnabled() ? BrowserRouter : HashRouter createRoot(container).render( - + - + @@ -121,15 +115,17 @@ createRoot(container).render( - - - - - - - - - + + + + + + + + + + + @@ -140,16 +136,9 @@ createRoot(container).render( - , + , ) -// TODO(EXT-1229): We had to remove `React.StrictMode` because it's not -// currently supported by Reanimated Web. We should consider re-enabling -// once Reanimated fixes this. -function OptionalStrictMode(props: { children: React.ReactNode }): JSX.Element { - return process.env.ENABLE_STRICT_MODE ? {props.children} : <>{props.children} -} - // We once had a ServiceWorker, and users who have not visited since then may still have it registered. // This ensures it is truly gone. unregisterServiceWorker() diff --git a/apps/web/src/lib/hooks/useTokenList/fetchTokenList.test.ts b/apps/web/src/lib/hooks/useTokenList/fetchTokenList.test.ts index 244a9a86022..c9e0d354c9d 100644 --- a/apps/web/src/lib/hooks/useTokenList/fetchTokenList.test.ts +++ b/apps/web/src/lib/hooks/useTokenList/fetchTokenList.test.ts @@ -47,7 +47,7 @@ describe('fetchTokenList', () => { ) const url = 'example.eth' const contenthash = '0xe3010170122013e051d1cfff20606de36845d4fe28deb9861a319a5bc8596fa4e610e8803918' - const translatedUri = 'https://cloudflare-ipfs.com/ipfs/QmPgEqyV3m8SB52BS2j2mJpu9zGprhj2BGCHtRiiw2fdM1/' + const translatedUri = 'https://ipfs.io/ipfs/QmPgEqyV3m8SB52BS2j2mJpu9zGprhj2BGCHtRiiw2fdM1/' resolver.mockResolvedValue(contenthash) fetch.mockOnceIf(translatedUri, () => Promise.resolve(JSON.stringify(defaultTokenList))) await expect(fetchTokenList(url, resolver)).resolves.toStrictEqual(defaultTokenList) diff --git a/apps/web/src/lib/utils/analytics.ts b/apps/web/src/lib/utils/analytics.ts index 95aee9d0d3c..20c1f7996f8 100644 --- a/apps/web/src/lib/utils/analytics.ts +++ b/apps/web/src/lib/utils/analytics.ts @@ -2,6 +2,7 @@ import { Currency, CurrencyAmount, Percent, Price, Token } from '@uniswap/sdk-co import { NATIVE_CHAIN_ID } from 'constants/tokens' import { InterfaceTrade, QuoteMethod, SubmittableTrade } from 'state/routing/types' import { isClassicTrade, isSubmittableTrade, isUniswapXTrade } from 'state/routing/utils' +import { TransactionOriginType } from 'uniswap/src/features/transactions/types/transactionDetails' import { computeRealizedPriceImpact } from 'utils/prices' export const getDurationUntilTimestampSeconds = (futureTimestampInSecondsSinceEpoch?: number): number | undefined => { @@ -73,6 +74,7 @@ export function formatCommonPropertiesForTrade( token_out_detected_tax: formatPercentNumber(trade.outputTax), token_in_detected_tax: formatPercentNumber(trade.inputTax), offchain_order_type: isUniswapXTrade(trade) ? trade.offchainOrderType : undefined, + transactionOriginType: TransactionOriginType.Internal, } } @@ -121,5 +123,6 @@ export const formatSwapQuoteReceivedEventProperties = ( token_in_amount_max: trade.maximumAmountIn(allowedSlippage).toExact(), token_out_amount_min: trade.minimumAmountOut(allowedSlippage).toExact(), quote_latency_milliseconds: swapQuoteLatencyMs, + transactionOriginType: TransactionOriginType.Internal, } } diff --git a/apps/web/src/nft/components/bag/BagFooter.test.tsx b/apps/web/src/nft/components/bag/BagFooter.test.tsx index 0b287bacd1f..9b3b4010782 100644 --- a/apps/web/src/nft/components/bag/BagFooter.test.tsx +++ b/apps/web/src/nft/components/bag/BagFooter.test.tsx @@ -1,3 +1,5 @@ +import 'test-utils/tokens/mocks' + import { BigNumber } from '@ethersproject/bignumber' import { CurrencyAmount, Percent } from '@uniswap/sdk-core' import { UNIVERSAL_ROUTER_ADDRESS } from '@uniswap/universal-router-sdk' diff --git a/apps/web/src/nft/components/collection/Filters.tsx b/apps/web/src/nft/components/collection/Filters.tsx index f9442e77172..3cf07de4e1c 100644 --- a/apps/web/src/nft/components/collection/Filters.tsx +++ b/apps/web/src/nft/components/collection/Filters.tsx @@ -13,7 +13,7 @@ import { Trait } from 'nft/hooks/useCollectionFilters' import { TraitPosition } from 'nft/hooks/useTraitsOpen' import { DropDownOption } from 'nft/types' import { useMemo, useReducer } from 'react' -import { isMobile } from 'utilities/src/platform' +import { isMobileWeb } from 'utilities/src/platform' export const Filters = ({ traitsByGroup }: { traitsByGroup: Record }) => { const { buyNow, setBuyNow } = useCollectionFilters((state) => ({ @@ -59,7 +59,7 @@ export const Filters = ({ traitsByGroup }: { traitsByGroup: Record - {isMobile && } + {isMobileWeb && } {Object.entries(traitsByGroup).length > 0 && ( diff --git a/apps/web/src/nft/css/sprinkles.css.ts b/apps/web/src/nft/css/sprinkles.css.ts index 553b8226763..61140e404da 100644 --- a/apps/web/src/nft/css/sprinkles.css.ts +++ b/apps/web/src/nft/css/sprinkles.css.ts @@ -47,7 +47,7 @@ export type Theme = typeof themeContractValues export const themeVars = createGlobalThemeContract(themeContractValues, (_, path) => `genie-${path.join('-')}`) -export const navDimensions = { +const navDimensions = { height: 72, verticalPad: 20, } diff --git a/apps/web/src/pages/AddLiquidity/index.tsx b/apps/web/src/pages/AddLiquidity/index.tsx index 9fefe0a024b..d2552b244cb 100644 --- a/apps/web/src/pages/AddLiquidity/index.tsx +++ b/apps/web/src/pages/AddLiquidity/index.tsx @@ -65,8 +65,8 @@ import { Wrapper, } from 'pages/AddLiquidity/styled' import { BodyWrapper } from 'pages/App/AppBody' -import { PositionPageUnsupportedContent } from 'pages/Pool/PositionPage' -import { Dots } from 'pages/Pool/styled' +import { PositionPageUnsupportedContent } from 'pages/LegacyPool/PositionPage' +import { Dots } from 'pages/LegacyPool/styled' import { useCallback, useEffect, useMemo, useState } from 'react' import { AlertTriangle } from 'react-feather' import { Helmet } from 'react-helmet-async/lib/index' @@ -622,7 +622,9 @@ function AddLiquidity() { } error={!isValid && !!parsedAmounts[Field.CURRENCY_A] && !!parsedAmounts[Field.CURRENCY_B]} > - {errorMessage ? errorMessage : } + + {errorMessage ? errorMessage : } + ) @@ -700,7 +702,7 @@ function AddLiquidity() { )} bottomContent={() => ( - + diff --git a/apps/web/src/pages/AddLiquidityV2/index.tsx b/apps/web/src/pages/AddLiquidityV2/index.tsx index 9f6c6c736ae..7665e93990e 100644 --- a/apps/web/src/pages/AddLiquidityV2/index.tsx +++ b/apps/web/src/pages/AddLiquidityV2/index.tsx @@ -36,7 +36,7 @@ import styled, { useTheme } from 'lib/styled-components' import { ConfirmAddModalBottom } from 'pages/AddLiquidityV2/ConfirmAddModalBottom' import { PoolPriceBar } from 'pages/AddLiquidityV2/PoolPriceBar' import AppBody from 'pages/App/AppBody' -import { Dots, Wrapper } from 'pages/Pool/styled' +import { Dots, Wrapper } from 'pages/LegacyPool/styled' import { useCallback, useState } from 'react' import { Plus } from 'react-feather' import { useLocation, useNavigate, useParams } from 'react-router-dom' @@ -516,7 +516,7 @@ export default function AddLiquidity() { ) : ( )} diff --git a/apps/web/src/pages/App/Header.tsx b/apps/web/src/pages/App/Header.tsx index 9ba508f74dc..ad58e6e7f8a 100644 --- a/apps/web/src/pages/App/Header.tsx +++ b/apps/web/src/pages/App/Header.tsx @@ -7,6 +7,7 @@ import { useBag } from 'nft/hooks' import { GRID_AREAS } from 'pages/App/utils/shared' import { memo } from 'react' import { useLocation } from 'react-router-dom' +import { NAV_HEIGHT } from 'theme' import { Z_INDEX } from 'theme/zIndex' import { useIsTouchDevice } from 'ui/src' @@ -27,7 +28,7 @@ const NavOnScroll = styled.div<{ $hide: boolean; $transparent?: boolean }>` transition: transform ${({ theme }) => theme.transition.duration.slow}; background-color: ${({ theme, $transparent }) => !$transparent && theme.surface1}; border-bottom: ${({ theme, $transparent }) => !$transparent && `1px solid ${theme.surface3}`}; - ${({ $hide, theme }) => $hide && `transform: translateY(-${theme.navHeight}px);`} + ${({ $hide }) => $hide && `transform: translateY(-${NAV_HEIGHT}px);`} ` export const Header = memo(function Header() { diff --git a/apps/web/src/pages/CreateProposal/index.tsx b/apps/web/src/pages/CreateProposal/index.tsx index ef3ee6609b6..7eb34e07ce9 100644 --- a/apps/web/src/pages/CreateProposal/index.tsx +++ b/apps/web/src/pages/CreateProposal/index.tsx @@ -20,7 +20,7 @@ import { } from 'pages/CreateProposal/ProposalActionSelector' import { ProposalEditor } from 'pages/CreateProposal/ProposalEditor' import { ProposalSubmissionModal } from 'pages/CreateProposal/ProposalSubmissionModal' -import { Wrapper } from 'pages/Pool/styled' +import { Wrapper } from 'pages/LegacyPool/styled' import { useCallback, useMemo, useState } from 'react' import { ArrowLeft } from 'react-feather' import { Link } from 'react-router-dom' diff --git a/apps/web/src/pages/Explore/charts/ExploreChartsSection.tsx b/apps/web/src/pages/Explore/charts/ExploreChartsSection.tsx index 641115b6852..3ff226708d5 100644 --- a/apps/web/src/pages/Explore/charts/ExploreChartsSection.tsx +++ b/apps/web/src/pages/Explore/charts/ExploreChartsSection.tsx @@ -8,17 +8,16 @@ import { CustomVolumeChartModel } from 'components/Charts/VolumeChart/CustomVolu import { StackedHistogramData } from 'components/Charts/VolumeChart/renderer' import { getCumulativeSum, getCumulativeVolume, getVolumeProtocolInfo } from 'components/Charts/VolumeChart/utils' import { ChartType } from 'components/Charts/utils' -import Column from 'components/Column' -import { RowBetween } from 'components/Row' import { DataQuality } from 'components/Tokens/TokenDetails/ChartSection/util' import { MAX_WIDTH_MEDIA_BREAKPOINT } from 'components/Tokens/constants' import { SupportedInterfaceChainId, chainIdToBackendChain, useChainFromUrlParam } from 'constants/chains' import { useDailyProtocolTVL, useHistoricalProtocolVolume } from 'graphql/data/protocolStats' import { TimePeriod, getProtocolColor, getSupportedGraphQlChain } from 'graphql/data/util' import { useScreenSize } from 'hooks/screenSize' -import styled, { useTheme } from 'lib/styled-components' +import { useTheme } from 'lib/styled-components' import { ReactNode, useMemo, useState } from 'react' -import { EllipsisStyle, ThemedText } from 'theme/components' +import { EllipsisTamaguiStyle } from 'theme/components' +import { Flex, Text, styled } from 'ui/src' import { HistoryDuration, PriceSource } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { Trans } from 'uniswap/src/i18n' import { NumberType, useFormatter } from 'utils/formatNumbers' @@ -32,49 +31,39 @@ const TIME_SELECTOR_OPTIONS = [ { time: TimePeriod.MONTH, display: 'M' }, ] -const StyledTimePeriodSelector = styled(TimePeriodSelector)` - & > button { - padding: 4px 8px; - margin: 4px 0px; - font-size: 14px; - } -` -const ChartsContainer = styled(RowBetween)` - max-width: ${MAX_WIDTH_MEDIA_BREAKPOINT}; - width: 100%; - margin-left: auto; - margin-right: auto; - padding-bottom: 56px; -` -// a 6% gap is achieved using two 47% width containers, as a parent gap causes an autosizing error with side-by-side lightweight-charts -const SectionContainer = styled(Column)` - position: relative; - width: 47%; - gap: 4px; - - > * { - ${EllipsisStyle} - } +const ChartsContainer = styled(Flex, { + row: true, + justifyContent: 'space-between', + maxWidth: MAX_WIDTH_MEDIA_BREAKPOINT, + width: '100%', + ml: 'auto', + mr: 'auto', + pb: 56, +}) - @media only screen and (max-width: ${({ theme }) => `${theme.breakpoint.sm}px`}) { - background-color: ${({ theme }) => theme.surface2}; - border-radius: 20px; - height: 120px; - padding: 20px; - } - - @media only screen and (max-width: ${({ theme }) => `${theme.breakpoint.xs}px`}) { - height: 112px; - padding: 16px; - } -` -const SectionTitle = styled(ThemedText.SubHeader)` - color: ${({ theme }) => theme.neutral2}; - white-space: nowrap; -` -const StyledChart: typeof Chart = styled(Chart)` - height: ${EXPLORE_CHART_HEIGHT_PX}px; -` +// a 6% gap is achieved using two 47% width containers, as a parent gap causes an autosizing error with side-by-side lightweight-charts +const SectionContainer = styled(Flex, { + position: 'relative', + width: '47%', + gap: '$gap4', + ...EllipsisTamaguiStyle, + $md: { + backgroundColor: '$surface2', + borderRadius: '$rounded20', + height: 120, + p: '$padding20', + }, + $xs: { + height: 112, + p: '$padding16', + }, +}) + +const SectionTitle = styled(Text, { + name: 'SectionTitle', + fontWeight: '300', + whiteSpace: 'nowrap', +}) function VolumeChartSection({ chainId }: { chainId: SupportedInterfaceChainId }) { const [timePeriod, setTimePeriod] = useState(TimePeriod.DAY) @@ -123,18 +112,16 @@ function VolumeChartSection({ chainId }: { chainId: SupportedInterfaceChainId }) return ( - + -
- -
-
+ +
{(() => { if (dataQuality === DataQuality.INVALID) { const errorText = loading ? undefined : @@ -143,7 +130,7 @@ function VolumeChartSection({ chainId }: { chainId: SupportedInterfaceChainId }) ) } return ( - } params={params}> + } params={params} height={EXPLORE_CHART_HEIGHT_PX}> {(crosshairData) => ( )} - + ) })()} @@ -180,7 +167,7 @@ function TVLChartSection({ chainId }: { chainId: SupportedInterfaceChainId }) { return ( - + {(() => { @@ -190,7 +177,7 @@ function TVLChartSection({ chainId }: { chainId: SupportedInterfaceChainId }) { } return ( - + {(crosshairData) => ( (sum += v), 0)} @@ -201,7 +188,7 @@ function TVLChartSection({ chainId }: { chainId: SupportedInterfaceChainId }) { }))} /> )} - + ) })()} @@ -213,11 +200,13 @@ function MinimalStatDisplay({ title, value, time }: { title: ReactNode; value: n return ( - {title} - - {formatFiatPrice({ price: value, type: NumberType.ChartFiatValue })} - - {time && {time}} + {title} + {formatFiatPrice({ price: value, type: NumberType.ChartFiatValue })} + {time && ( + + {time} + + )} ) } diff --git a/apps/web/src/pages/Explore/index.tsx b/apps/web/src/pages/Explore/index.tsx index 61c266bdde5..13ae9b31ca2 100644 --- a/apps/web/src/pages/Explore/index.tsx +++ b/apps/web/src/pages/Explore/index.tsx @@ -1,6 +1,5 @@ import { InterfaceElementName, InterfacePageName, SharedEventName } from '@uniswap/analytics-events' import { TopPoolTable } from 'components/Pools/PoolTable/PoolTable' -import { AutoRow } from 'components/Row' import { TopTokensTable } from 'components/Tokens/TokenTable' import TableNetworkFilter from 'components/Tokens/TokenTable/NetworkFilter' import SearchBar from 'components/Tokens/TokenTable/SearchBar' @@ -11,66 +10,18 @@ import { manualChainOutageAtom } from 'featureFlags/flags/outageBanner' import { getTokenExploreURL, isBackendSupportedChain } from 'graphql/data/util' import { useOnGlobalChainSwitch } from 'hooks/useGlobalChainSwitch' import { useResetAtom } from 'jotai/utils' -import styled from 'lib/styled-components' import { ExploreChartsSection } from 'pages/Explore/charts/ExploreChartsSection' import { useExploreParams } from 'pages/Explore/redirects' import RecentTransactions from 'pages/Explore/tables/RecentTransactions' import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useNavigate } from 'react-router-dom' -import { StyledInternalLink, ThemedText } from 'theme/components' +import { StyledInternalLink } from 'theme/components' +import { Flex, Text } from 'ui/src' import { UNIVERSE_CHAIN_INFO } from 'uniswap/src/constants/chains' import Trace from 'uniswap/src/features/telemetry/Trace' import { Trans } from 'uniswap/src/i18n' import { UniverseChainId } from 'uniswap/src/types/chains' -const ExploreContainer = styled.div` - width: 100%; - min-width: 320px; - padding: 48px 40px 0px; - - @media only screen and (max-width: ${({ theme }) => `${theme.breakpoint.sm}px`}) { - padding: 16px; - padding-bottom: 0px; - } -` - -const NavWrapper = styled.div` - display: flex; - max-width: ${MAX_WIDTH_MEDIA_BREAKPOINT}; - margin: 0 auto; - margin-bottom: 4px; - color: ${({ theme }) => theme.neutral3}; - flex-direction: row; - justify-content: space-between; - @media screen and (max-width: ${({ theme }) => `${theme.breakpoint.lg}px`}) { - flex-direction: column; - gap: 16px; - } -` -const TabBar = styled(AutoRow)` - gap: 24px; - @media screen and (max-width: ${({ theme }) => theme.breakpoint.md}px) { - gap: 16px; - } -` -const TabItem = styled(ThemedText.HeadlineMedium)<{ active?: boolean }>` - align-items: center; - color: ${({ theme, active }) => (active ? theme.neutral1 : theme.neutral2)}; - cursor: pointer; - transition: ${({ theme }) => `${theme.transition.duration.medium} ${theme.transition.timing.ease} color`}; - - @media screen and (max-width: ${({ theme }) => theme.breakpoint.md}px) { - font-size: 24px !important; - line-height: 32px !important; - } -` -const FiltersContainer = styled.div` - display: flex; - gap: 8px; - height: 40px; - justify-content: flex-start; -` - export enum ExploreTab { Tokens = 'tokens', Pools = 'pools', @@ -158,10 +109,34 @@ const Explore = ({ initialTab }: { initialTab?: ExploreTab }) => { return ( - + - - + + {Pages.map(({ title, loggingElementName, key }, index) => { return ( { key={index} > setCurrentTab(index)} to={`/explore/${key}` + (chain.id !== UniverseChainId.Mainnet ? `/${chain.urlParam}` : '')} > - setCurrentTab(index)} active={currentTab === index} key={key}> + {title} - + ) })} - - + + {currentKey === ExploreTab.Tokens && } {currentKey !== ExploreTab.Transactions && } - - + +
- +
) } diff --git a/apps/web/src/pages/Explore/tables/RecentTransactions.tsx b/apps/web/src/pages/Explore/tables/RecentTransactions.tsx index bcc1034da08..3f4a1d11a5b 100644 --- a/apps/web/src/pages/Explore/tables/RecentTransactions.tsx +++ b/apps/web/src/pages/Explore/tables/RecentTransactions.tsx @@ -1,6 +1,5 @@ import { ApolloError } from '@apollo/client' import { createColumnHelper } from '@tanstack/react-table' -import Row from 'components/Row' import { Table } from 'components/Table' import { Cell } from 'components/Table/Cell' import { Filter } from 'components/Table/Filter' @@ -17,9 +16,8 @@ import { useUpdateManualOutage } from 'featureFlags/flags/outageBanner' import { BETypeToTransactionType, TransactionType, useAllTransactions } from 'graphql/data/useAllTransactions' import { OrderDirection, getSupportedGraphQlChain } from 'graphql/data/util' import { useActiveLocalCurrency } from 'hooks/useActiveLocalCurrency' -import { useMemo, useReducer, useState } from 'react' -import { ThemedText } from 'theme/components' -import { Text } from 'ui/src' +import { useMemo, useReducer, useRef, useState } from 'react' +import { Flex, Text, styled } from 'ui/src' import { PoolTransaction, PoolTransactionType, @@ -29,10 +27,17 @@ import { shortenAddress } from 'utilities/src/addresses' import { useFormatter } from 'utils/formatNumbers' import { ExplorerDataType, getExplorerLink } from 'utils/getExplorerLink' +const TableRow = styled(Flex, { + row: true, + gap: '$gap4', + alignItems: 'center', +}) + export default function RecentTransactions() { const activeLocalCurrency = useActiveLocalCurrency() const { formatNumber, formatFiatPrice } = useFormatter() const [filterModalIsOpen, toggleFilterModal] = useReducer((s) => !s, false) + const filterAnchorRef = useRef(null) const [filter, setFilters] = useState([ TransactionType.SWAP, TransactionType.REMOVE, @@ -56,12 +61,12 @@ export default function RecentTransactions() { id: 'timestamp', header: () => ( - + - + - + ), cell: (transaction) => ( @@ -77,27 +82,27 @@ export default function RecentTransactions() { id: 'swap-type', header: () => ( - toggleFilterModal()}> + toggleFilterModal()} ref={filterAnchorRef}> - + - + ), cell: (transaction) => { const amountWithSymbolA = ( <> - + {BETypeToTransactionType[transaction.getValue?.().type]} - + ) @@ -132,12 +137,16 @@ export default function RecentTransactions() { id: 'fiat-value', header: () => ( - {activeLocalCurrency} + + {activeLocalCurrency} + ), cell: (fiat) => ( - {formatFiatPrice({ price: fiat.getValue?.() })} + + {formatFiatPrice({ price: fiat.getValue?.() })} + ), }), @@ -145,21 +154,21 @@ export default function RecentTransactions() { id: 'token-amount-0', header: () => ( - + - + ), cell: (transaction) => ( - - + + {formatNumber({ input: Math.abs(parseFloat(transaction.getValue?.().token0Quantity)) || 0, })} - + - + ), }), @@ -167,21 +176,21 @@ export default function RecentTransactions() { id: 'token-amount-1', header: () => ( - + - + ), cell: (transaction) => ( - - + + {formatNumber({ input: Math.abs(parseFloat(transaction.getValue?.().token1Quantity)) || 0, })} - + - + ), }), @@ -189,9 +198,9 @@ export default function RecentTransactions() { id: 'maker-address', header: () => ( - + - + ), cell: (makerAddress) => ( diff --git a/apps/web/src/pages/Landing/Fold.tsx b/apps/web/src/pages/Landing/Fold.tsx index 8c3da1b1c06..68b991f2c79 100644 --- a/apps/web/src/pages/Landing/Fold.tsx +++ b/apps/web/src/pages/Landing/Fold.tsx @@ -1,31 +1,27 @@ -import styled from 'lib/styled-components' import { DirectToDefi } from 'pages/Landing/sections/DirectToDefi' import { Footer } from 'pages/Landing/sections/Footer' import { NewsletterEtc } from 'pages/Landing/sections/NewsletterEtc' import { Stats } from 'pages/Landing/sections/Stats' import { forwardRef } from 'react' - -const Container = styled.div` - gap: 120px; - @media (max-width: 1024px) { - gap: 80px; - } - position: relative; - display: flex; - flex-direction: column; - align-items: center; - width: 100%; - z-index: 1; -` +import { Flex } from 'ui/src' const Fold = forwardRef(function Fold(props, scrollAnchor) { return ( - +