From 29c499f076e51d0e982dc926d272c8e2312c2a26 Mon Sep 17 00:00:00 2001 From: Uniswap Labs Service Account Date: Fri, 4 Oct 2024 15:23:37 +0000 Subject: [PATCH] ci(release): publish latest release --- CODEOWNERS | 1 - RELEASE | 28 +- VERSION | 2 +- apps/extension/jest-setup.js | 3 - apps/extension/package.json | 4 +- apps/extension/src/app/OnboardingApp.tsx | 22 +- .../src/app/features/accounts/AccountItem.tsx | 10 +- .../accounts/AccountSwitcherScreen.tsx | 6 +- apps/extension/src/app/features/dapp/store.ts | 38 +- .../dappRequests/DappRequestContent.tsx | 4 +- .../src/app/features/dappRequests/accounts.ts | 2 +- .../EthSend/Approve/ApproveRequestContent.tsx | 8 +- .../SignTypedDataRequestContent.tsx | 2 - .../src/app/features/dappRequests/utils.ts | 1 - .../src/app/features/home/HomeScreen.tsx | 3 - .../app/features/home/TokenBalanceList.tsx | 2 +- .../home/introCards/HomeIntroCardStack.tsx | 20 - .../features/onboarding/ClaimUnitagScreen.tsx | 60 - .../features/onboarding/OnboardingScreen.tsx | 2 +- .../onboarding/OnboardingStepsContext.tsx | 1 - .../onboarding/create/PasswordCreate.tsx | 13 +- .../onboarding/create/ViewMnemonic.tsx | 2 +- .../features/onboarding/intro/IntroScreen.tsx | 10 +- .../onboarding/scan/ScanToOnboard.tsx | 2 +- .../send/SendFormScreen/SendFormScreen.tsx | 5 +- .../internal/EllipsisDropdown.tsx | 4 +- .../src/app/features/swap/SwapFlowScreen.tsx | 2 +- .../features/warnings/StorageWarningModal.tsx | 6 +- .../app/hooks/useOpeningKeyboardShortCut.ts | 1 - .../extension/src/app/navigation/constants.ts | 1 - apps/extension/src/app/navigation/utils.ts | 2 +- .../src/contentScript/WindowEthereumProxy.ts | 1 - apps/extension/src/manifest.json | 2 +- apps/mobile/android/app/build.gradle | 6 +- .../ios/Uniswap.xcodeproj/project.pbxproj | 48 +- .../ios/WidgetsCore/Utils/DataQueries.swift | 14 +- apps/mobile/jest-setup.js | 2 +- apps/mobile/package.json | 2 +- apps/mobile/src/app/migrations.ts | 2 +- apps/mobile/src/app/modals/AppModals.tsx | 5 + .../src/app/modals/BackupWarningModal.tsx | 8 +- .../src/app/modals/HiddenTokenInfoModal.tsx | 67 + apps/mobile/src/app/modals/SwapModal.tsx | 2 +- apps/mobile/src/app/navigation/NavBar.tsx | 82 +- .../__snapshots__/Text.test.tsx.snap | 4 +- .../RemoveWallet/useModalContent.tsx | 2 - .../RequestModal/KidSuperCheckinModal.tsx | 2 +- .../src/components/Requests/ScanSheet/util.ts | 5 +- .../src/components/Requests/Uwulink/utils.ts | 2 +- .../Requests/WalletConnectModals.tsx | 4 +- .../Settings/BiometricAuthWarningModal.tsx | 8 +- .../TokenBalanceList/TokenBalanceList.tsx | 55 +- .../TokenDetails/TokenDetailsHeader.tsx | 4 +- .../components/accounts/AccountList.test.tsx | 7 +- .../src/components/accounts/AccountList.tsx | 1 - .../__snapshots__/AccountHeader.test.tsx.snap | 10 +- .../components/explore/ExploreSections.tsx | 22 +- .../components/explore/FavoriteHeaderRow.tsx | 4 +- .../explore/FavoriteTokenCard.test.tsx | 15 +- .../components/explore/FavoriteTokenCard.tsx | 6 +- .../src/components/explore/TokenItem.tsx | 2 - .../FavoriteHeaderRow.test.tsx.snap | 21 +- .../FavoriteWalletCard.test.tsx.snap | 2 +- .../__snapshots__/RemoveButton.test.tsx.snap | 2 +- .../__snapshots__/TokenItem.test.tsx.snap | 22 +- .../explore/search/SearchEmptySection.tsx | 2 +- .../search/SearchPopularNFTCollections.tsx | 2 +- .../search/SearchPopularTokens.graphql | 2 +- .../explore/search/SearchPopularTokens.tsx | 3 +- .../explore/search/SearchResultsSection.tsx | 4 +- .../components/explore/search/utils.test.ts | 16 +- .../src/components/explore/search/utils.ts | 8 +- .../forceUpgrade/ForceUpgradeModal.tsx | 4 +- .../src/components/home/HomeExploreTab.tsx | 4 +- .../home}/introCards/IntroCard.test.tsx | 4 +- .../components/home}/introCards/IntroCard.tsx | 9 +- .../home}/introCards/IntroCardStack.tsx | 10 +- .../introCards/OnboardingIntroCardStack.tsx | 48 +- apps/mobile/src/components/icons/Favorite.tsx | 11 +- .../components/mnemonic/SeedPhraseDisplay.tsx | 12 +- .../contexts/LayoutContextProvider.tsx | 2 - .../__snapshots__/DecimalNumber.test.tsx.snap | 4 +- .../TextWithFuseMatches.test.tsx.snap | 30 +- .../src/components/tooltip/TooltipButton.tsx | 2 +- .../src/components/unitags/AvatarSelection.ts | 1 - .../src/components/unitags/UnitagBanner.tsx | 34 +- .../CloudBackupProcessingAnimation.tsx | 1 - apps/mobile/src/features/appRating/saga.ts | 2 +- .../fiatOnRamp/FiatOnRampAmountSection.tsx | 25 +- .../src/features/import/GenericImportForm.tsx | 8 +- .../import/InputWithSuffix.android.tsx | 4 +- .../features/import/InputWithSuffix.ios.tsx | 2 + .../GenericImportForm.test.tsx.snap | 8 +- .../mobile/src/features/modals/ModalsState.ts | 1 + apps/mobile/src/features/modals/modalSlice.ts | 6 + apps/mobile/src/features/nfts/item/traits.tsx | 2 +- .../onboarding/BackupSpeedBumpModal.tsx | 1 - .../src/features/openai/OpenAIContext.tsx | 3 +- .../src/features/send/SendFormScreen.tsx | 7 +- .../send/SendRecipientSelectFullScreen.tsx | 3 +- .../src/features/send/SendTokenForm.tsx | 4 +- .../unitags/ChooseProfilePictureScreen.tsx | 1 - .../unitags/EditUnitagProfileScreen.tsx | 4 +- .../features/unitags/useUnitagClaimHandler.ts | 30 +- .../src/features/walletConnect/selectors.ts | 8 +- .../src/features/walletConnect/utils.ts | 3 +- .../src/screens/ExternalProfileScreen.tsx | 2 +- apps/mobile/src/screens/FiatOnRampScreen.tsx | 11 +- apps/mobile/src/screens/HomeScreen.tsx | 2 +- .../screens/Import/OnDeviceRecoveryScreen.tsx | 8 +- .../RestoreCloudBackupLoadingScreen.tsx | 2 +- .../RestoreCloudBackupPasswordScreen.tsx | 1 - ...oreCloudBackupPasswordScreen.test.tsx.snap | 4 +- .../src/screens/NFTCollectionScreen.tsx | 2 +- .../screens/Onboarding/ManualBackupScreen.tsx | 6 +- .../__snapshots__/BackupScreen.test.tsx.snap | 12 +- .../src/screens/SettingsCloudBackupStatus.tsx | 6 +- .../mobile/src/screens/TokenDetailsScreen.tsx | 48 +- .../src/utils/useOpenBackupReminderModal.ts | 4 +- apps/web/.env | 10 +- apps/web/.env.production | 1 - apps/web/cypress/support/e2e.ts | 2 +- apps/web/package.json | 9 +- apps/web/public/nfts-sitemap.xml | 308 +- apps/web/public/pools-sitemap.xml | 3892 +++---------- apps/web/public/tokens-sitemap.xml | 4932 +++-------------- .../AccountDrawer/AuthenticatedHeader.tsx | 2 +- .../components/AccountDrawer/DefaultMenu.tsx | 3 +- .../components/AccountDrawer/IconButton.tsx | 4 +- .../Activity/OffchainActivityModal.tsx | 6 +- .../OffchainActivityModal.test.tsx.snap | 18 +- .../MiniPortfolio/Activity/parseLocal.ts | 1 - .../MiniPortfolio/Activity/parseRemote.tsx | 2 +- .../MiniPortfolio/Activity/utils.ts | 12 +- .../Pools/useMultiChainPositions.tsx | 4 +- .../MiniPortfolio/Tokens/TokensTab.tsx | 6 +- .../__snapshots__/PortfolioLogo.test.tsx.snap | 4 +- .../src/components/AccountDrawer/index.tsx | 11 +- apps/web/src/components/AddressQRModal.tsx | 2 - .../components/Charts/VolumeChart/index.tsx | 1 - .../components/Charts/VolumeChart/utils.ts | 2 +- apps/web/src/components/Charts/utils.tsx | 1 - .../components/ConfirmSwapModal/Pending.tsx | 2 +- .../ConfirmSwapModal/ProgressIndicator.tsx | 4 +- .../src/components/ConfirmSwapModal/Step.tsx | 25 +- .../src/components/ConfirmSwapModal/index.tsx | 8 +- .../LimitPriceInputLabel.tsx | 2 +- .../LimitPriceInputPanel.tsx | 2 +- .../SwapCurrencyInputPanel.tsx | 2 +- .../components/CurrencyInputPanel/index.tsx | 2 +- .../src/components/DropdownSelector/index.tsx | 4 +- .../FeatureFlagModal/FeatureFlagModal.tsx | 4 - .../Liquidity/FeeTierSearchModal.tsx | 308 - .../LiquidityPositionAmountsTile.tsx | 63 - .../Liquidity/LiquidityPositionCard.tsx | 1 - .../Liquidity/LiquidityPositionInfo.tsx | 13 +- .../LiquidityPositionInfoBadges.test.tsx | 10 +- .../Liquidity/LiquidityPositionInfoBadges.tsx | 42 +- .../LiquidityPositionPriceRangeTile.tsx | 130 - .../src/components/Liquidity/PositionNFT.tsx | 79 - apps/web/src/components/Liquidity/utils.tsx | 87 +- apps/web/src/components/Logo/DoubleLogo.tsx | 2 +- .../NavBar/NavDropdown/NavDropdown.tsx | 11 +- .../NavBar/SearchBar/SuggestionRow.tsx | 45 +- .../SearchBarDropdown.test.tsx.snap | 6 +- .../NavBar/accountCTAsExperimentUtils.ts | 10 + .../NavBar/accountCTAsExperimentUtils.tsx | 25 - apps/web/src/components/NavBar/index.tsx | 5 +- apps/web/src/components/PercentInput.tsx | 16 +- .../Pools/PoolDetails/ChartSection/index.tsx | 2 - .../PoolDetails/PoolDetailsStatsButtons.tsx | 2 +- .../PoolDetailsHeader.test.tsx.snap | 2 +- .../PoolDetailsLink.test.tsx.snap | 2 +- .../PoolDetailsPositionTable.test.tsx.snap | 6 +- .../__snapshots__/PoolTable.test.tsx.snap | 2 +- .../src/components/Popups/PopupContent.tsx | 16 +- .../SearchModal/CurrencySearchModal.tsx | 8 +- .../Settings/MultipleRoutingOptions.tsx | 4 +- .../src/components/Settings/index.test.tsx | 6 +- apps/web/src/components/Settings/index.tsx | 4 +- apps/web/src/components/Table/index.tsx | 6 +- .../TokenSafety/TokenSafetyModal.tsx | 30 +- apps/web/src/components/TokenSafety/index.tsx | 19 +- .../TokenDetails/ChartSection/index.tsx | 59 +- .../components/Tokens/TokenDetails/index.tsx | 50 +- .../TokenDetailsPoolsTable.test.tsx.snap | 2 +- .../TokenTable/VolumeTimeFrameSelector.tsx | 1 - .../components/Tokens/TokenTable/index.tsx | 2 +- apps/web/src/components/Tooltip.tsx | 3 +- .../web/src/components/Web3Provider/index.tsx | 2 +- .../Web3Provider/{wagmiConfig.ts => wagmi.ts} | 0 apps/web/src/components/Web3Status/index.tsx | 2 +- .../addLiquidity/AddLiquidityContext.tsx | 14 +- .../src/components/addLiquidity/InputForm.tsx | 48 +- .../web/src/components/addLiquidity/hooks.tsx | 116 +- .../src/components/swap/SwapHeader.test.tsx | 4 +- apps/web/src/components/swap/SwapLineItem.tsx | 11 +- .../components/swap/SwapModalHeaderAmount.tsx | 4 +- .../src/components/swap/SwapPreview.test.tsx | 16 +- apps/web/src/components/swap/SwapPreview.tsx | 6 +- .../__snapshots__/SwapLineItem.test.tsx.snap | 10 +- .../__snapshots__/SwapPreview.test.tsx.snap | 20 +- apps/web/src/components/swap/constants.ts | 5 + apps/web/src/constants/chains.ts | 17 +- apps/web/src/constants/routing.test.ts | 2 +- .../useFeatureFlagUrlOverrides.tsx | 6 +- apps/web/src/graphql/data/ConversionRate.ts | 19 + .../graphql/data/apollo/AdaptiveRefetch.tsx | 2 +- .../apollo/AdaptiveTokenBalancesProvider.tsx | 10 - .../apollo/TokenBalancesProvider.test.tsx | 2 +- .../data/apollo/TokenBalancesProvider.tsx | 53 +- .../useReportTotalBalancesUsdForAnalytics.ts | 36 - .../apollo/useTotalBalancesUsdForAnalytics.ts | 9 - apps/web/src/graphql/data/types.ts | 4 +- apps/web/src/graphql/data/util.tsx | 5 +- apps/web/src/hooks/useConfirmModalState.ts | 7 +- apps/web/src/hooks/useEthersProvider.ts | 2 +- apps/web/src/hooks/useKeyPress.ts | 2 +- apps/web/src/hooks/useSelectChain.ts | 4 +- apps/web/src/hooks/useSwapTaxes.ts | 1 - apps/web/src/hooks/useSwitchChain.ts | 6 +- apps/web/src/hooks/useTokenBalances.test.ts | 6 +- apps/web/src/hooks/useTokenBalances.ts | 2 +- apps/web/src/hooks/useTransactionGasFee.ts | 4 +- apps/web/src/hooks/useUSDTokenUpdater.ts | 2 +- apps/web/src/hooks/useUniswapXSwapCallback.ts | 29 +- apps/web/src/hooks/useUniversalRouter.ts | 2 +- apps/web/src/hooks/useUnmountingAnimation.ts | 2 +- .../hooks/routing/useRoutingAPIArguments.ts | 22 +- apps/web/src/lib/hooks/useBlockNumber.tsx | 2 +- apps/web/src/lib/hooks/useInterval.ts | 2 +- .../web/src/lib/hooks/useTokenList/sorting.ts | 2 +- apps/web/src/lib/utils/analytics.ts | 86 +- apps/web/src/nft/components/bag/BagRow.tsx | 2 +- .../src/nft/components/bag/ButtonStates.tsx | 3 +- apps/web/src/nft/components/card/utils.tsx | 7 +- .../src/nft/components/collection/Sweep.tsx | 1 - .../nft/components/details/AssetDetails.tsx | 1 - apps/web/src/nft/hooks/useSendTransaction.ts | 2 +- apps/web/src/nft/pages/profile/index.tsx | 3 +- apps/web/src/nft/utils/urlParams.ts | 2 +- .../pages/AddLiquidity/AddLiquidityModal.tsx | 7 +- apps/web/src/pages/AddLiquidity/index.tsx | 15 +- apps/web/src/pages/AddLiquidityV2/index.tsx | 15 +- apps/web/src/pages/App/Header.tsx | 9 +- apps/web/src/pages/Landing/LandingV2.tsx | 10 +- apps/web/src/pages/Landing/sections/Hero.tsx | 29 +- apps/web/src/pages/LegacyPool/NewPosition.tsx | 21 + .../web/src/pages/LegacyPool/PositionPage.tsx | 85 +- apps/web/src/pages/MigrateV3/index.tsx | 95 +- .../src/pages/Pool/Positions/PositionPage.tsx | 196 - .../pages/Pool/Positions/V2PositionPage.tsx | 175 - .../pages/Pool/Positions/create/AddHook.tsx | 60 - .../Pool/Positions/create/CreatePosition.tsx | 242 - .../create/CreatePositionContext.tsx | 49 - .../create/CreatePositionContextProvider.tsx | 35 - .../pages/Pool/Positions/create/EditStep.tsx | 93 - .../Positions/create/RangeSelectionStep.tsx | 234 - .../Pool/Positions/create/SelectTokenStep.tsx | 301 - .../src/pages/Pool/Positions/create/hooks.tsx | 28 - .../pages/Pool/Positions/create/shared.tsx | 50 - .../src/pages/Pool/Positions/create/types.ts | 51 - apps/web/src/pages/Pool/Positions/index.tsx | 31 +- apps/web/src/pages/RemoveLiquidity/index.tsx | 15 +- apps/web/src/pages/RouteDefinitions.tsx | 32 +- apps/web/src/pages/Swap/Buy/BuyFormButton.tsx | 17 +- .../src/pages/Swap/Buy/CountryListModal.tsx | 4 +- .../PredefinedAmount.test.tsx.snap | 4 +- .../pages/Swap/Limit/LimitExpirySection.tsx | 3 +- apps/web/src/pages/Swap/Limit/LimitForm.tsx | 67 +- .../pages/Swap/Send/SendCurrencyInputForm.tsx | 2 +- apps/web/src/pages/Swap/Send/SendForm.tsx | 15 +- .../SendCurrencyInputForm.test.tsx.snap | 6 +- .../SendRecipientForm.test.tsx.snap | 2 +- apps/web/src/pages/Swap/SwapForm.tsx | 131 +- apps/web/src/pages/Swap/index.tsx | 101 +- apps/web/src/pages/TokenDetails/index.tsx | 4 +- .../pages/__snapshots__/routes.test.ts.snap | 34 +- apps/web/src/pages/paths.ts | 6 +- apps/web/src/setupTests.ts | 3 - apps/web/src/state/activity/polling/orders.ts | 11 +- .../state/activity/polling/transactions.ts | 2 +- .../web/src/state/application/reducer.test.ts | 15 +- apps/web/src/state/application/reducer.ts | 9 +- apps/web/src/state/burn/hooks.tsx | 15 +- apps/web/src/state/burn/v3/hooks.tsx | 15 +- apps/web/src/state/claim/hooks.ts | 2 +- .../src/state/fiatOnRampTransactions/types.ts | 1 - apps/web/src/state/index.ts | 10 +- .../state/limit/expiryToDeadlineSeconds.ts | 1 - apps/web/src/state/limit/hooks.ts | 24 +- apps/web/src/state/migrations/14.ts | 2 +- apps/web/src/state/migrations/15.ts | 2 +- apps/web/src/state/migrations/16.ts | 2 +- apps/web/src/state/migrations/17.ts | 2 +- apps/web/src/state/migrations/18.ts | 2 +- apps/web/src/state/migrations/19.ts | 2 +- apps/web/src/state/migrations/20.ts | 2 +- apps/web/src/state/mint/hooks.tsx | 15 +- apps/web/src/state/mint/v3/hooks.tsx | 15 +- apps/web/src/state/routing/slice.ts | 14 +- apps/web/src/state/routing/types.ts | 126 +- .../state/routing/useRoutingAPITrade.test.ts | 2 - apps/web/src/state/routing/utils.test.ts | 2 - apps/web/src/state/routing/utils.ts | 69 +- apps/web/src/state/sagas/root.ts | 20 - .../src/state/sagas/transactions/swapSaga.ts | 319 -- .../src/state/sagas/transactions/uniswapx.ts | 86 - .../web/src/state/sagas/transactions/utils.ts | 169 - .../src/state/sagas/transactions/wrapSaga.ts | 80 - apps/web/src/state/signatures/hooks.ts | 12 +- apps/web/src/state/signatures/parseRemote.ts | 1 - apps/web/src/state/signatures/types.ts | 2 - apps/web/src/state/swap/SwapContext.test.tsx | 16 +- apps/web/src/state/swap/SwapContext.tsx | 6 +- apps/web/src/state/swap/hooks.test.ts | 4 +- apps/web/src/state/swap/hooks.tsx | 72 +- apps/web/src/state/swap/types.ts | 10 +- apps/web/src/test-utils/bundle-size-test.ts | 4 +- apps/web/src/theme/index.tsx | 2 + apps/web/src/tracing/errors.ts | 2 +- .../src/types/{position.ts => position.d.ts} | 5 - apps/web/src/utils/chains.tsx | 2 +- apps/web/src/utils/formatNumbers.test.ts | 38 +- apps/web/src/utils/formatNumbers.ts | 37 +- apps/web/src/utils/getFetchPolicyForKey.ts | 16 + apps/web/src/utils/prices.ts | 2 +- apps/web/src/utils/transfer.ts | 2 +- dangerfile.ts | 2 +- .../__snapshots__/preset.test.ts.snap | 24 - packages/eslint-config/base.js | 1 - packages/eslint-config/native.js | 1 - packages/ui/src/assets/icons/check.svg | 14 +- packages/ui/src/assets/icons/ellipsis.svg | 3 +- packages/ui/src/assets/icons/triple-dots.svg | 1 + packages/ui/src/assets/index.ts | 1 - .../ui/src/assets/logos/png/across-logo.png | Bin 1214 -> 0 bytes .../UniversalImage/UniversalImage.tsx | 3 - .../internal/PlainImage.native.tsx | 3 +- .../UniversalImage/internal/PlainImage.tsx | 39 +- .../internal/PlainImage.web.tsx | 38 - .../ui/src/components/UniversalImage/types.ts | 5 +- .../ui/src/components/UniversalImage/utils.ts | 1 - .../components/checkbox/LabeledCheckbox.tsx | 4 +- packages/ui/src/components/icons/Check.tsx | 12 +- packages/ui/src/components/icons/Ellipsis.tsx | 2 +- .../ui/src/components/icons/HeartWithFill.tsx | 14 - .../ui/src/components/icons/TripleDots.tsx | 33 + packages/ui/src/components/icons/Unitag.tsx | 22 +- packages/ui/src/components/icons/exported.ts | 1 + packages/ui/src/components/icons/index.tsx | 1 - .../ui/src/components/menu/ContextMenu.tsx | 2 +- .../src/components/modal/AdaptiveWebModal.tsx | 1 - .../swipeablecards/SwipeableCard.web.tsx | 60 +- .../swipeablecards/SwipeableCardStack.web.tsx | 76 - packages/ui/src/components/text/Text.tsx | 29 +- packages/ui/src/index.ts | 1 - packages/ui/src/scripts/componentize-icons.ts | 1 - packages/ui/src/theme/color/colors.ts | 6 +- .../ui/src/utils/colors/getExtractedColors.ts | 4 +- packages/uniswap/jest-setup.js | 2 +- packages/uniswap/package.json | 10 +- .../ConfirmSwapModal/ProgressIndicator.tsx | 172 +- .../src/components/ConfirmSwapModal/Step.tsx | 173 + .../ConfirmSwapModal/steps/Approve.tsx | 53 - .../ConfirmSwapModal/steps/Permit.tsx | 33 - .../steps/StepRowSkeleton.tsx | 120 - .../ConfirmSwapModal/steps/Swap.tsx | 88 - .../ConfirmSwapModal/steps/Wrap.tsx | 32 - .../src/components/ConfirmSwapModal/types.ts | 6 - .../CurrencyInputPanel/CurrencyInputPanel.tsx | 13 +- .../CurrencyLogo/CurrencyLogo.test.tsx | 4 - .../CurrencyLogo/SplitLogo.test.tsx | 4 - .../CurrencyLogo/TokenLogo.test.tsx | 4 - .../src/components/CurrencyLogo/TokenLogo.tsx | 26 +- .../__snapshots__/CurrencyLogo.test.tsx.snap | 44 +- .../__snapshots__/SplitLogo.test.tsx.snap | 44 +- .../__snapshots__/TokenLogo.test.tsx.snap | 22 +- .../HorizontalTokenList.native.tsx | 58 - .../HorizontalTokenList.tsx | 13 - .../TokenSelector/TokenOptionItem.tsx | 4 +- .../TokenSectionBaseList.web.tsx | 11 +- .../TokenSelector/TokenSectionHeader.tsx | 11 +- .../TokenSelector/TokenSelector.tsx | 22 +- .../TokenSelector/TokenSelectorList.tsx | 31 +- .../TokenSelectorSearchResultsList.tsx | 4 - .../TokenSelectorSwapInputList.tsx | 2 +- .../TokenSelectorSwapOutputList.tsx | 45 +- .../src/components/TokenSelector/hooks.tsx | 175 +- ...t.web.tsx => renderSuggestedTokenItem.tsx} | 19 +- .../suggestedTokensKeyExtractor.tsx | 5 + .../src/components/TokenSelector/types.ts | 4 - .../src/components/TokenSelector/utils.tsx | 114 +- .../dropdowns/ActionSheetDropdown.tsx | 4 +- .../src/components/modals/Modal.native.tsx | 2 - .../src/components/modals/Modal.web.tsx | 18 +- .../src/components/modals/ModalProps.tsx | 1 - .../src/components/modals/PaginatedModals.tsx | 4 +- .../modals/WarningModal/WarningModal.tsx | 168 +- packages/uniswap/src/constants/chains.ts | 5 +- packages/uniswap/src/constants/tokens.ts | 22 +- packages/uniswap/src/constants/urls.ts | 1 - .../useQueryWithImmediateGarbageCollection.ts | 2 +- .../apiClients/tradingApi/TradingApiClient.ts | 20 +- .../tradingApiSwappableTokenToCurrencyInfo.ts | 41 - .../apiClients/uniswapApi/useGasFeeQuery.ts | 2 +- .../graphql/uniswap-data-api/queries.graphql | 48 +- .../uniswap-data-api/web/ConvertWeb.graphql | 7 + packages/uniswap/src/data/rest/getPools.ts | 14 - .../uniswap/src/data/rest/getPositions.ts | 117 +- packages/uniswap/src/data/tradingApi/api.json | 2 +- .../data/tradingApi/modifyTradingApiTypes.mts | 92 - packages/uniswap/src/data/tradingApi/types.ts | 35 - packages/uniswap/src/data/types.ts | 5 +- packages/uniswap/src/entities/assets.ts | 4 +- .../src/extension/useIsChromeWindowFocused.ts | 4 +- .../src/features/address/ExplorerView.tsx | 2 +- .../useSwappableTokenWithHighestBalance.ts | 86 - .../uniswap/src/features/dataApi/balances.ts | 8 +- .../src/features/dataApi/searchTokens.ts | 2 +- .../src/features/dataApi/tokenProjects.ts | 2 +- .../uniswap/src/features/dataApi/topTokens.ts | 2 +- .../src/features/dataApi/utils.test.ts | 4 +- .../uniswap/src/features/dataApi/utils.ts | 8 +- .../src/features/fiatCurrency/conversion.ts | 4 +- .../uniswap/src/features/fiatOnRamp/hooks.ts | 2 +- packages/uniswap/src/features/gas/hooks.ts | 7 +- packages/uniswap/src/features/gas/types.ts | 2 +- .../uniswap/src/features/gating/configs.ts | 2 +- .../src/features/gating/experiments.ts | 5 - packages/uniswap/src/features/gating/flags.ts | 5 - .../features/language/LocalizationContext.tsx | 5 +- .../providers/FlashbotsRpcProvider.test.ts | 1 - .../src/features/search/searchHistorySlice.ts | 1 - .../src/features/telemetry/constants/trace.ts | 4 - .../uniswap/src/features/telemetry/types.ts | 21 +- .../src/features/tokens/TokenWarningModal.tsx | 319 +- .../features/tokens/deprecatedSafetyUtils.ts | 2 - packages/uniswap/src/features/tokens/hooks.ts | 4 +- .../src/features/tokens/safetyUtils.test.ts | 10 +- .../src/features/tokens/safetyUtils.ts | 13 +- .../src/features/tokens/slice/hooks.ts | 2 +- .../src/features/tokens/useCurrencyInfo.ts | 2 +- .../DecimalPadInput/DecimalPad.native.tsx | 36 +- .../DecimalPadInput/DecimalPadInput.tsx | 86 +- .../transactions/DecimalPadInput/types.ts | 3 +- .../TransactionDetails/TransactionDetails.tsx | 8 - .../TransactionModal/TransactionModal.web.tsx | 2 - .../TransactionModalContext.tsx | 21 - .../TransactionModalProps.tsx | 1 - .../transactions/hooks/useUSDTokenUpdater.ts | 2 +- .../modals/BlockedAddressModal.tsx | 2 +- .../transactions/modals/ViewOnlyModal.tsx | 4 +- .../src/features/transactions/selectors.ts | 5 +- .../src/features/transactions/send/types.ts | 4 +- .../src/features/transactions/slice.ts | 9 - .../features/transactions/swap/SwapFlow.tsx | 6 +- .../features/transactions/swap/analytics.ts | 12 +- .../swap/contexts/SwapFormContext.tsx | 41 +- .../transactions/swap/form/SwapFormButton.tsx | 64 +- .../transactions/swap/form/SwapFormScreen.tsx | 29 +- .../swap/form/SwapFormSettings.tsx | 2 +- .../swap/form/SwapTokenSelector.tsx | 36 +- .../form/footer/GasAndWarningRows.web.tsx | 2 +- .../swap/hooks/useAcceptedTrade.ts | 2 +- .../swap/hooks/useDerivedSwapInfo.ts | 1 - .../swap/hooks/usePermit2Signature.ts | 2 +- .../swap/hooks/useSetTradeSlippage.ts | 5 - .../swap/hooks/useSwapTxAndGasInfo.test.ts | 26 +- .../swap/hooks/useSwapTxAndGasInfo.ts | 35 +- .../swap/hooks/useSwapWarnings.test.ts | 3 +- .../swap/hooks/useTokenApprovalInfo.test.ts | 8 +- .../swap/hooks/useTokenApprovalInfo.ts | 27 +- .../transactions/swap/hooks/useTrade.ts | 9 +- .../hooks/useTransactionRequestInfo.test.ts | 123 - .../swap/hooks/useTransactionRequestInfo.ts | 69 +- .../transactions/swap/hooks/useUSDCPrice.ts | 4 +- .../swap/hooks/useWrapTransactionRequest.ts | 2 +- .../swap/modals/AcrossRoutingInfo.tsx | 77 - .../swap/modals/FeeOnTransferWarning.tsx | 2 +- .../swap/modals/NetworkFeeWarning.tsx | 2 +- .../swap/modals/PriceImpactWarning.tsx | 2 +- .../swap/modals/SwapFeeWarning.tsx | 2 +- .../swap/modals/SwapWarningModal.tsx | 4 +- .../transactions/swap/modals/UniswapXInfo.tsx | 2 +- .../swap/review/EstimatedTime.tsx | 48 - .../swap/review/MaxSlippageRow.tsx | 12 +- .../transactions/swap/review/SwapDetails.tsx | 39 +- .../swap/review/SwapReviewScreen.tsx | 126 +- .../swap/review/TransactionAmountsReview.tsx | 31 +- .../settings/configs/ProtocolPreference.tsx | 1 - .../swap/settings/configs/Slippage.native.tsx | 12 +- .../transactions/swap/types/swapCallback.ts | 9 +- .../swap/types/swapTxAndGasInfo.ts | 107 +- .../features/transactions/swap/types/trade.ts | 60 +- .../transactions/swap/types/wrapCallback.ts | 7 +- .../features/transactions/swap/utils/asset.ts | 15 - ...teps.test.ts => generateSwapSteps.test.ts} | 127 +- ...ansactionSteps.ts => generateSwapSteps.ts} | 120 +- .../transactions/swap/utils/getSwapFeeUsd.ts | 4 +- .../transactions/swap/utils/routing.ts | 4 - .../features/transactions/swap/utils/trade.ts | 36 +- .../transactions/swap/utils/tradingApi.ts | 37 +- .../transactions/types/transactionDetails.ts | 30 +- .../uniswap/src/i18n/i18n-setup-interface.tsx | 25 +- .../src/i18n/locales/source/en-US.json | 44 +- .../src/i18n/locales/translations/af-ZA.json | 7 - .../src/i18n/locales/translations/ar-SA.json | 7 - .../src/i18n/locales/translations/ca-ES.json | 7 - .../src/i18n/locales/translations/cs-CZ.json | 7 - .../src/i18n/locales/translations/da-DK.json | 7 - .../src/i18n/locales/translations/de-DE.json | 7 - .../src/i18n/locales/translations/el-GR.json | 7 - .../src/i18n/locales/translations/es-419.json | 2222 -------- .../src/i18n/locales/translations/es-ES.json | 7 - .../src/i18n/locales/translations/fi-FI.json | 7 - .../src/i18n/locales/translations/fil-PH.json | 2222 -------- .../src/i18n/locales/translations/fr-FR.json | 7 - .../src/i18n/locales/translations/he-IL.json | 7 - .../src/i18n/locales/translations/hi-IN.json | 7 - .../src/i18n/locales/translations/hu-HU.json | 7 - .../src/i18n/locales/translations/id-ID.json | 7 - .../src/i18n/locales/translations/it-IT.json | 7 - .../src/i18n/locales/translations/ja-JP.json | 7 - .../src/i18n/locales/translations/ko-KR.json | 7 - .../src/i18n/locales/translations/ms-MY.json | 7 - .../src/i18n/locales/translations/nl-NL.json | 7 - .../src/i18n/locales/translations/no-NO.json | 7 - .../src/i18n/locales/translations/pl-PL.json | 7 - .../src/i18n/locales/translations/pt-BR.json | 7 - .../src/i18n/locales/translations/pt-PT.json | 7 - .../src/i18n/locales/translations/ro-RO.json | 7 - .../src/i18n/locales/translations/ru-RU.json | 7 - .../src/i18n/locales/translations/sl-SI.json | 7 - .../src/i18n/locales/translations/sr-SP.json | 7 - .../src/i18n/locales/translations/sv-SE.json | 7 - .../src/i18n/locales/translations/sw-TZ.json | 7 - .../src/i18n/locales/translations/th-TH.json | 7 - .../src/i18n/locales/translations/tr-TR.json | 7 - .../src/i18n/locales/translations/uk-UA.json | 7 - .../src/i18n/locales/translations/ur-PK.json | 7 - .../src/i18n/locales/translations/vi-VN.json | 7 - .../src/i18n/locales/translations/zh-CN.json | 7 - .../src/i18n/locales/translations/zh-TW.json | 7 - packages/uniswap/src/test/fixtures/permit.ts | 16 - .../uniswap/src/test/fixtures/tradingApi.ts | 2 +- .../src/test/fixtures/transactions/swap.ts | 17 +- .../src/test/fixtures/wallet/balances.ts | 3 +- packages/uniswap/src/test/mocks/locale.ts | 165 +- packages/uniswap/src/theme/heights.ts | 1 - .../uniswap/src/types/screens/extension.ts | 1 - packages/uniswap/src/types/screens/mobile.ts | 4 +- .../uniswap/src/utils/clipboard.native.ts | 1 - packages/uniswap/src/utils/currency.test.ts | 11 +- packages/uniswap/tsconfig.json | 3 +- packages/utilities/package.json | 2 +- packages/utilities/src/environment/env.web.ts | 6 - packages/wallet/jest-setup.js | 2 +- packages/wallet/package.json | 4 +- .../CurrencyLogo/LogoWithTxStatus.test.tsx | 4 - .../CurrencyLogo/LogoWithTxStatus.tsx | 2 - .../LogoWithTxStatus.test.tsx.snap | 22 +- .../RecipientSelectSpeedBumps.tsx | 16 +- .../modals/NewAddressWarningModal.tsx | 6 +- .../WalletPreviewCard/WalletPreviewCard.tsx | 2 +- .../WalletPreviewCard.test.tsx.snap | 100 +- .../introCards/useSharedIntroCards.ts | 64 - .../src/components/modals/InfoLinkModal.tsx | 3 - .../src/components/nfts/NFTHiddenRow.tsx | 10 +- .../src/components/nfts/ShowNFTModal.tsx | 2 +- .../components/text/RelativeChange.test.tsx | 3 + .../src/contexts/WalletNavigationContext.tsx | 2 +- .../wallet/src/features/activity/hooks.ts | 8 +- packages/wallet/src/features/auth/saga.ts | 2 - .../src/features/behaviorHistory/slice.ts | 6 - .../wallet/src/features/gas/adjustGasFee.ts | 2 +- packages/wallet/src/features/gas/hooks.ts | 8 +- .../src/features/images/ElementAfterText.tsx | 39 - .../wallet/src/features/images/RemoteSvg.tsx | 3 +- packages/wallet/src/features/nfts/utils.ts | 2 +- .../components/NotificationToast.tsx | 35 +- .../components/SwapPendingNotification.tsx | 1 - .../src/features/notifications/selectors.ts | 2 +- .../src/features/notifications/utils.test.ts | 11 +- .../src/features/notifications/utils.ts | 1 - .../src/features/portfolio/AnimatedNumber.tsx | 2 +- .../features/portfolio/HiddenTokensRow.tsx | 40 +- .../features/portfolio/PortfolioBalance.tsx | 8 +- .../SummaryCards/DetailsModal/HeaderLogo.tsx | 3 - .../DetailsModal/TransactionDetailsModal.tsx | 6 +- .../SwapTransactionDetails.test.tsx.snap | 4 +- .../TransactionDetailsModal.test.tsx.snap | 29 +- .../SummaryCards/DetailsModal/types.ts | 5 - .../SummaryItems/TransactionSummaryLayout.tsx | 18 +- .../transactions/SummaryCards/utils.ts | 1 - .../TransactionHistoryUpdater.tsx | 12 +- .../transactions/cancelTransactionSaga.ts | 8 +- .../transactions/getAmountsFromTrade.ts | 10 +- .../extractFiatOnRampTransactionDetails.ts | 2 +- .../conversion/extractUniswapXOrderDetails.ts | 2 - .../conversion/parseTradeTransaction.ts | 10 +- .../features/transactions/history/utils.ts | 3 - .../wallet/src/features/transactions/hooks.ts | 17 +- .../useAllTransactionsBetweenAddresses.ts | 2 +- .../transactions/replaceTransactionSaga.ts | 3 +- .../transactions/send/SendReviewDetails.tsx | 15 +- .../send/hooks/useSendTransactionRequest.ts | 18 +- .../send/hooks/useSendWarnings.ts | 2 +- .../transactions/sendTransactionSaga.test.ts | 1 - .../transactions/sendTransactionSaga.ts | 24 +- .../transactions/swap/BridgingModal.tsx | 74 - .../swap/createSwapFormFromTxDetails.ts | 18 +- .../swap/hooks/useMostRecentSwapTx.ts | 9 +- .../swap/hooks/useSwapCallback.ts | 11 +- .../swap/hooks/useSwapPrefilledState.ts | 1 - .../swap/modals/QueuedOrderModal.tsx | 2 +- .../swap/modals/SwapProtectionModal.tsx | 2 +- .../transactions/swap/submitOrderSaga.test.ts | 76 +- .../transactions/swap/submitOrderSaga.ts | 40 +- .../transactions/swap/swapSaga.test.ts | 37 +- .../features/transactions/swap/swapSaga.ts | 53 +- .../transactions/swap/wrapSaga.test.ts | 1 - .../features/transactions/swap/wrapSaga.ts | 7 +- .../transactionWatcherSaga.test.ts | 2 - .../transactions/transactionWatcherSaga.ts | 114 +- .../features/unitags/ClaimUnitagContent.tsx | 64 +- .../src/features/unitags/UnitagInfoModal.tsx | 2 +- packages/wallet/src/features/wallet/hooks.ts | 2 +- packages/wallet/src/utils/linking.ts | 6 +- packages/wallet/src/utils/useNoYoloParser.ts | 2 +- yarn.lock | 105 +- 631 files changed, 4916 insertions(+), 21530 deletions(-) delete mode 100644 CODEOWNERS delete mode 100644 apps/extension/src/app/features/home/introCards/HomeIntroCardStack.tsx delete mode 100644 apps/extension/src/app/features/onboarding/ClaimUnitagScreen.tsx create mode 100644 apps/mobile/src/app/modals/HiddenTokenInfoModal.tsx rename {packages/wallet/src/components => apps/mobile/src/components/home}/introCards/IntroCard.test.tsx (74%) rename {packages/wallet/src/components => apps/mobile/src/components/home}/introCards/IntroCard.tsx (87%) rename {packages/wallet/src/components => apps/mobile/src/components/home}/introCards/IntroCardStack.tsx (59%) rename {packages/wallet => apps/mobile}/src/features/unitags/useUnitagClaimHandler.ts (59%) delete mode 100644 apps/web/src/components/Liquidity/FeeTierSearchModal.tsx delete mode 100644 apps/web/src/components/Liquidity/LiquidityPositionAmountsTile.tsx delete mode 100644 apps/web/src/components/Liquidity/LiquidityPositionPriceRangeTile.tsx delete mode 100644 apps/web/src/components/Liquidity/PositionNFT.tsx create mode 100644 apps/web/src/components/NavBar/accountCTAsExperimentUtils.ts delete mode 100644 apps/web/src/components/NavBar/accountCTAsExperimentUtils.tsx rename apps/web/src/components/Web3Provider/{wagmiConfig.ts => wagmi.ts} (100%) create mode 100644 apps/web/src/graphql/data/ConversionRate.ts delete mode 100644 apps/web/src/graphql/data/apollo/AdaptiveTokenBalancesProvider.tsx delete mode 100644 apps/web/src/graphql/data/apollo/useReportTotalBalancesUsdForAnalytics.ts delete mode 100644 apps/web/src/graphql/data/apollo/useTotalBalancesUsdForAnalytics.ts create mode 100644 apps/web/src/pages/LegacyPool/NewPosition.tsx delete mode 100644 apps/web/src/pages/Pool/Positions/PositionPage.tsx delete mode 100644 apps/web/src/pages/Pool/Positions/V2PositionPage.tsx delete mode 100644 apps/web/src/pages/Pool/Positions/create/AddHook.tsx delete mode 100644 apps/web/src/pages/Pool/Positions/create/CreatePosition.tsx delete mode 100644 apps/web/src/pages/Pool/Positions/create/CreatePositionContext.tsx delete mode 100644 apps/web/src/pages/Pool/Positions/create/CreatePositionContextProvider.tsx delete mode 100644 apps/web/src/pages/Pool/Positions/create/EditStep.tsx delete mode 100644 apps/web/src/pages/Pool/Positions/create/RangeSelectionStep.tsx delete mode 100644 apps/web/src/pages/Pool/Positions/create/SelectTokenStep.tsx delete mode 100644 apps/web/src/pages/Pool/Positions/create/hooks.tsx delete mode 100644 apps/web/src/pages/Pool/Positions/create/shared.tsx delete mode 100644 apps/web/src/pages/Pool/Positions/create/types.ts delete mode 100644 apps/web/src/state/sagas/root.ts delete mode 100644 apps/web/src/state/sagas/transactions/swapSaga.ts delete mode 100644 apps/web/src/state/sagas/transactions/uniswapx.ts delete mode 100644 apps/web/src/state/sagas/transactions/utils.ts delete mode 100644 apps/web/src/state/sagas/transactions/wrapSaga.ts rename apps/web/src/types/{position.ts => position.d.ts} (84%) create mode 100644 apps/web/src/utils/getFetchPolicyForKey.ts create mode 100644 packages/ui/src/assets/icons/triple-dots.svg delete mode 100644 packages/ui/src/assets/logos/png/across-logo.png delete mode 100644 packages/ui/src/components/UniversalImage/internal/PlainImage.web.tsx delete mode 100644 packages/ui/src/components/icons/HeartWithFill.tsx create mode 100644 packages/ui/src/components/icons/TripleDots.tsx delete mode 100644 packages/ui/src/components/swipeablecards/SwipeableCardStack.web.tsx create mode 100644 packages/uniswap/src/components/ConfirmSwapModal/Step.tsx delete mode 100644 packages/uniswap/src/components/ConfirmSwapModal/steps/Approve.tsx delete mode 100644 packages/uniswap/src/components/ConfirmSwapModal/steps/Permit.tsx delete mode 100644 packages/uniswap/src/components/ConfirmSwapModal/steps/StepRowSkeleton.tsx delete mode 100644 packages/uniswap/src/components/ConfirmSwapModal/steps/Swap.tsx delete mode 100644 packages/uniswap/src/components/ConfirmSwapModal/steps/Wrap.tsx delete mode 100644 packages/uniswap/src/components/ConfirmSwapModal/types.ts delete mode 100644 packages/uniswap/src/components/TokenSelector/HorizontalTokenList/HorizontalTokenList.native.tsx delete mode 100644 packages/uniswap/src/components/TokenSelector/HorizontalTokenList/HorizontalTokenList.tsx rename packages/uniswap/src/components/TokenSelector/{HorizontalTokenList/HorizontalTokenList.web.tsx => renderSuggestedTokenItem.tsx} (52%) create mode 100644 packages/uniswap/src/components/TokenSelector/suggestedTokensKeyExtractor.tsx delete mode 100644 packages/uniswap/src/data/apiClients/tradingApi/utils/tradingApiSwappableTokenToCurrencyInfo.ts create mode 100644 packages/uniswap/src/data/graphql/uniswap-data-api/web/ConvertWeb.graphql delete mode 100644 packages/uniswap/src/data/rest/getPools.ts delete mode 100644 packages/uniswap/src/data/tradingApi/modifyTradingApiTypes.mts delete mode 100644 packages/uniswap/src/data/tradingApi/types.ts delete mode 100644 packages/uniswap/src/features/bridging/hooks/useSwappableTokenWithHighestBalance.ts delete mode 100644 packages/uniswap/src/features/transactions/swap/hooks/useTransactionRequestInfo.test.ts delete mode 100644 packages/uniswap/src/features/transactions/swap/modals/AcrossRoutingInfo.tsx delete mode 100644 packages/uniswap/src/features/transactions/swap/review/EstimatedTime.tsx delete mode 100644 packages/uniswap/src/features/transactions/swap/utils/asset.ts rename packages/uniswap/src/features/transactions/swap/utils/{generateTransactionSteps.test.ts => generateSwapSteps.test.ts} (71%) rename packages/uniswap/src/features/transactions/swap/utils/{generateTransactionSteps.ts => generateSwapSteps.ts} (63%) delete mode 100644 packages/uniswap/src/i18n/locales/translations/es-419.json delete mode 100644 packages/uniswap/src/i18n/locales/translations/fil-PH.json delete mode 100644 packages/uniswap/src/test/fixtures/permit.ts delete mode 100644 packages/uniswap/src/theme/heights.ts delete mode 100644 packages/wallet/src/components/introCards/useSharedIntroCards.ts delete mode 100644 packages/wallet/src/features/images/ElementAfterText.tsx delete mode 100644 packages/wallet/src/features/transactions/swap/BridgingModal.tsx rename packages/{uniswap => wallet}/src/features/transactions/swap/hooks/useSwapPrefilledState.ts (98%) diff --git a/CODEOWNERS b/CODEOWNERS deleted file mode 100644 index f70773659eb..00000000000 --- a/CODEOWNERS +++ /dev/null @@ -1 +0,0 @@ -* @uniswap/web-admins diff --git a/RELEASE b/RELEASE index 85692c05e3c..f0a8979c0c2 100644 --- a/RELEASE +++ b/RELEASE @@ -1,24 +1,10 @@ -IPFS hash of the deployment: -- CIDv0: `QmZNKQNeHGqEJfGMyWbH1zYCgs8pazXe2FajiS4KVzxfPL` -- CIDv1: `bafybeifd3xryjkpe4lqgqfonwz7pdfzjtdlspryilb44sn7utv26mpxab4` +We are back with some new updates! Here’s the latest: -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://bafybeifd3xryjkpe4lqgqfonwz7pdfzjtdlspryilb44sn7utv26mpxab4.ipfs.dweb.link/ -- https://bafybeifd3xryjkpe4lqgqfonwz7pdfzjtdlspryilb44sn7utv26mpxab4.ipfs.cf-ipfs.com/ -- [ipfs://QmZNKQNeHGqEJfGMyWbH1zYCgs8pazXe2FajiS4KVzxfPL/](ipfs://QmZNKQNeHGqEJfGMyWbH1zYCgs8pazXe2FajiS4KVzxfPL/) - -### 5.49.2 (2024-10-03) - - -### Bug Fixes - -* **web:** dont respect url flag overrides on prod - prod (#12548) a2b2517 +Report Spam NFTs - You can now report spam NFTs and hide them from your feed and activity. +Other changes: +- Added explainers for hidden tokens, popular tokens, and hidden NFTs +- Removed activity feed items related to any hidden NFTs +- More optimized keyboard functionality across the app +- Various bug fixes and performance improvements \ No newline at end of file diff --git a/VERSION b/VERSION index 82e4d497170..89e1cc8c9c7 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -web/5.49.2 \ No newline at end of file +mobile/1.36 \ No newline at end of file diff --git a/apps/extension/jest-setup.js b/apps/extension/jest-setup.js index 5b05899861b..cd65e145579 100644 --- a/apps/extension/jest-setup.js +++ b/apps/extension/jest-setup.js @@ -5,7 +5,6 @@ import { AppearanceSettingType } from 'wallet/src/features/appearance/slice' import { TextEncoder, TextDecoder } from 'util' import { mockSharedPersistQueryClientProvider } from 'uniswap/src/test/mocks/mockSharedPersistQueryClientProvider' import { mockUIAssets } from 'ui/src/test/mocks/mockUIAssets' -import { mockLocalizationContext } from 'uniswap/src/test/mocks/locale' process.env.IS_UNISWAP_EXTENSION = true @@ -73,8 +72,6 @@ jest.mock('wallet/src/features/appearance/hooks', () => { } }) -jest.mock('uniswap/src/features/language/LocalizationContext', () => mockLocalizationContext({})) - jest.mock('uniswap/src/data/apiClients/SharedPersistQueryClientProvider', () => mockSharedPersistQueryClientProvider) mockUIAssets() diff --git a/apps/extension/package.json b/apps/extension/package.json index 1933bc190fe..516d29cda66 100644 --- a/apps/extension/package.json +++ b/apps/extension/package.json @@ -13,8 +13,8 @@ "@svgr/webpack": "8.0.1", "@tamagui/core": "1.108.4", "@types/uuid": "9.0.1", - "@uniswap/analytics-events": "2.37.0", - "@uniswap/uniswapx-sdk": "^2.1.0-beta.14", + "@uniswap/analytics-events": "2.36.0", + "@uniswap/uniswapx-sdk": "^2.1.0-beta.8", "@uniswap/universal-router-sdk": "2.2.0", "@uniswap/v3-sdk": "3.14.0", "dotenv-webpack": "8.0.1", diff --git a/apps/extension/src/app/OnboardingApp.tsx b/apps/extension/src/app/OnboardingApp.tsx index cf5fd3b117c..3d46a997ed0 100644 --- a/apps/extension/src/app/OnboardingApp.tsx +++ b/apps/extension/src/app/OnboardingApp.tsx @@ -9,7 +9,6 @@ import { PersistGate } from 'redux-persist/integration/react' import { ExtensionStatsigProvider } from 'src/app/StatsigProvider' import { GraphqlProvider } from 'src/app/apollo' import { ErrorElement } from 'src/app/components/ErrorElement' -import { ClaimUnitagScreen } from 'src/app/features/onboarding/ClaimUnitagScreen' import { Complete } from 'src/app/features/onboarding/Complete' import { CreateOnboardingSteps, @@ -56,14 +55,6 @@ const unsupportedRoute: RouteObject = { element: , } -const createSteps = { - [CreateOnboardingSteps.Password]: , - [CreateOnboardingSteps.ViewMnemonic]: , - [CreateOnboardingSteps.TestMnemonic]: , - [CreateOnboardingSteps.Naming]: , - [CreateOnboardingSteps.Complete]: , -} - const allRoutes = [ { path: '', @@ -75,16 +66,15 @@ const allRoutes = [ }, { path: OnboardingRoutes.Create, - element: , - }, - { - path: OnboardingRoutes.Claim, element: ( , - ...createSteps, + [CreateOnboardingSteps.Password]: , + [CreateOnboardingSteps.ViewMnemonic]: , + [CreateOnboardingSteps.TestMnemonic]: , + [CreateOnboardingSteps.Naming]: , + [CreateOnboardingSteps.Complete]: , }} /> ), diff --git a/apps/extension/src/app/features/accounts/AccountItem.tsx b/apps/extension/src/app/features/accounts/AccountItem.tsx index 8206f619652..ee2bc8f56c8 100644 --- a/apps/extension/src/app/features/accounts/AccountItem.tsx +++ b/apps/extension/src/app/features/accounts/AccountItem.tsx @@ -5,7 +5,7 @@ import { useDispatch } from 'react-redux' import { EditLabelModal } from 'src/app/features/accounts/EditLabelModal' import { removeAllDappConnectionsForAccount } from 'src/app/features/dapp/actions' import { ContextMenu, Flex, MenuContentItem, Text, TouchableArea } from 'ui/src' -import { CopySheets, Edit, Ellipsis, TrashFilled } from 'ui/src/components/icons' +import { CopySheets, Edit, TrashFilled, TripleDots } from 'ui/src/components/icons' import { iconSizes } from 'ui/src/theme' import { WarningModal } from 'uniswap/src/components/modals/WarningModal/WarningModal' import { WarningSeverity } from 'uniswap/src/components/modals/WarningModal/types' @@ -131,15 +131,15 @@ export function AccountItem({ address, onAccountSelect, balanceUSD }: AccountIte caption={t('account.recoveryPhrase.remove.mnemonic.description', { walletNames: [activeAccountDisplayName?.name ?? ''], })} - rejectText={t('common.button.cancel')} - acknowledgeText={t('common.button.continue')} + closeText={t('common.button.cancel')} + confirmText={t('common.button.continue')} icon={} isOpen={showRemoveWalletModal} modalName={ModalName.RemoveWallet} severity={WarningSeverity.High} title={t('account.wallet.remove.title', { name: displayName?.name ?? '' })} onClose={() => setShowRemoveWalletModal(false)} - onAcknowledge={onRemoveWallet} + onConfirm={onRemoveWallet} /> setShowEditLabelModal(false)} /> - + diff --git a/apps/extension/src/app/features/accounts/AccountSwitcherScreen.tsx b/apps/extension/src/app/features/accounts/AccountSwitcherScreen.tsx index a28b459c628..eec406d1861 100644 --- a/apps/extension/src/app/features/accounts/AccountSwitcherScreen.tsx +++ b/apps/extension/src/app/features/accounts/AccountSwitcherScreen.tsx @@ -166,15 +166,15 @@ export function AccountSwitcherScreen(): JSX.Element { /> } isOpen={showRemoveWalletModal} modalName={ModalName.RemoveWallet} severity={WarningSeverity.High} title={t('account.wallet.button.import')} onClose={() => setShowRemoveWalletModal(false)} - onAcknowledge={onNavigateToRemoveWallet} + onConfirm={onNavigateToRemoveWallet} /> existingAccount.address !== account?.address, - ) - - const nextConnectedAccount = dappInfo.connectedAccounts[0] - - if (!nextConnectedAccount || !account) { - delete newState[dappUrl] - return newState - } - - if (dappInfo.activeConnectedAddress === account.address) { - dappInfo.activeConnectedAddress = nextConnectedAccount.address + const updatedAccounts = account + ? dappUrlState.connectedAccounts?.filter((existingAccount) => existingAccount.address !== account.address) + : [] + + const activeConnected = updatedAccounts[0] + if (activeConnected) { + return { + ...initialState, + [dappUrl]: { + ...dappUrlState, + connectedAccounts: updatedAccounts, + activeConnectedAddress: activeConnected.address, + }, + } + } else { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { [dappUrl]: _, ...restState } = initialState + return restState } - return newState } function removeAllDappConnections(): void { diff --git a/apps/extension/src/app/features/dappRequests/DappRequestContent.tsx b/apps/extension/src/app/features/dappRequests/DappRequestContent.tsx index 21d4e86f69c..d05cd53f4c9 100644 --- a/apps/extension/src/app/features/dappRequests/DappRequestContent.tsx +++ b/apps/extension/src/app/features/dappRequests/DappRequestContent.tsx @@ -237,14 +237,14 @@ export function DappRequestFooter({ px="$spacing8" /> - diff --git a/apps/extension/src/app/features/onboarding/scan/ScanToOnboard.tsx b/apps/extension/src/app/features/onboarding/scan/ScanToOnboard.tsx index 0b95b8b6833..03b87ec8e30 100644 --- a/apps/extension/src/app/features/onboarding/scan/ScanToOnboard.tsx +++ b/apps/extension/src/app/features/onboarding/scan/ScanToOnboard.tsx @@ -156,7 +156,7 @@ export function ScanToOnboard(): JSX.Element { useEffect(() => { if (!isLoadingUUID) { qrScale.value = UNISWAP_LOGO_SCALE_DEFAULT - return undefined + return } const springConfig: SpringConfig = { diff --git a/apps/extension/src/app/features/send/SendFormScreen/SendFormScreen.tsx b/apps/extension/src/app/features/send/SendFormScreen/SendFormScreen.tsx index a998a439b45..6c3c754458e 100644 --- a/apps/extension/src/app/features/send/SendFormScreen/SendFormScreen.tsx +++ b/apps/extension/src/app/features/send/SendFormScreen/SendFormScreen.tsx @@ -14,7 +14,6 @@ import { useUSDTokenUpdater } from 'uniswap/src/features/transactions/hooks/useU import { BlockedAddressWarning } from 'uniswap/src/features/transactions/modals/BlockedAddressWarning' import { useUSDCValue } from 'uniswap/src/features/transactions/swap/hooks/useUSDCPrice' import { useIsBlocked } from 'uniswap/src/features/trm/hooks' -import { WalletChainId } from 'uniswap/src/types/chains' import { CurrencyField } from 'uniswap/src/types/currency' import { createTransactionId } from 'uniswap/src/utils/createTransactionId' import { useSendContext } from 'wallet/src/features/transactions/contexts/SendContext' @@ -169,7 +168,7 @@ export function SendFormScreen(): JSX.Element { py="$spacing12" {...inputShadowProps} > - + {!showRecipientSelector && ( <> @@ -185,7 +184,7 @@ export function SendFormScreen(): JSX.Element { /> )} - + )} diff --git a/apps/extension/src/app/features/settings/SettingsManageConnectionsScreen/internal/EllipsisDropdown.tsx b/apps/extension/src/app/features/settings/SettingsManageConnectionsScreen/internal/EllipsisDropdown.tsx index 76491520f48..8b32186707d 100644 --- a/apps/extension/src/app/features/settings/SettingsManageConnectionsScreen/internal/EllipsisDropdown.tsx +++ b/apps/extension/src/app/features/settings/SettingsManageConnectionsScreen/internal/EllipsisDropdown.tsx @@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next' import { useDispatch } from 'react-redux' import { removeAllDappConnectionsForAccount } from 'src/app/features/dapp/actions' import { ContextMenu, Flex, TouchableArea } from 'ui/src' -import { Ellipsis, Power } from 'ui/src/components/icons' +import { Power, TripleDots } from 'ui/src/components/icons' import { ExtensionEventName } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { pushNotification } from 'wallet/src/features/notifications/slice' @@ -49,7 +49,7 @@ export function EllipsisDropdown(): JSX.Element { onLeftClick={true} > - + ) diff --git a/apps/extension/src/app/features/swap/SwapFlowScreen.tsx b/apps/extension/src/app/features/swap/SwapFlowScreen.tsx index fa626880567..e99658f21a3 100644 --- a/apps/extension/src/app/features/swap/SwapFlowScreen.tsx +++ b/apps/extension/src/app/features/swap/SwapFlowScreen.tsx @@ -1,9 +1,9 @@ import { useExtensionNavigation } from 'src/app/navigation/utils' import { Flex } from 'ui/src' import { useHighestBalanceNativeCurrencyId } from 'uniswap/src/features/dataApi/balances' -import { useSwapPrefilledState } from 'uniswap/src/features/transactions/swap/hooks/useSwapPrefilledState' import { prepareSwapFormState } from 'uniswap/src/features/transactions/types/transactionState' 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 SwapFlowScreen(): JSX.Element { diff --git a/apps/extension/src/app/features/warnings/StorageWarningModal.tsx b/apps/extension/src/app/features/warnings/StorageWarningModal.tsx index 99f26f6fd56..96bc0506afb 100644 --- a/apps/extension/src/app/features/warnings/StorageWarningModal.tsx +++ b/apps/extension/src/app/features/warnings/StorageWarningModal.tsx @@ -19,15 +19,15 @@ export function StorageWarningModal({ isOnboarding }: StorageWarningModalProps): return ( { diff --git a/apps/extension/src/app/hooks/useOpeningKeyboardShortCut.ts b/apps/extension/src/app/hooks/useOpeningKeyboardShortCut.ts index eeb375d66f5..87433f2d9c0 100644 --- a/apps/extension/src/app/hooks/useOpeningKeyboardShortCut.ts +++ b/apps/extension/src/app/hooks/useOpeningKeyboardShortCut.ts @@ -15,7 +15,6 @@ export enum State { type ReducerAction = { type: 'keyUp' | 'keyDown' | 'highlight'; key: string } | { type: 'highlight' } export const useOpeningKeyboardShortCut = (shortCutPressed: boolean): KeyboardKeyProps[] => { - // eslint-disable-next-line consistent-return const reducer = (state: KeyboardKeyProps[], action: ReducerAction): KeyboardKeyProps[] => { switch (action.type) { case 'keyDown': diff --git a/apps/extension/src/app/navigation/constants.ts b/apps/extension/src/app/navigation/constants.ts index afb596ab081..7ec2c232d30 100644 --- a/apps/extension/src/app/navigation/constants.ts +++ b/apps/extension/src/app/navigation/constants.ts @@ -8,7 +8,6 @@ export enum TopLevelRoutes { export enum OnboardingRoutes { Import = 'import', Create = 'create', - Claim = 'claim', Scan = 'scan', Reset = 'reset', ResetScan = 'reset-scan', diff --git a/apps/extension/src/app/navigation/utils.ts b/apps/extension/src/app/navigation/utils.ts index 182e5ec25cb..178842daea3 100644 --- a/apps/extension/src/app/navigation/utils.ts +++ b/apps/extension/src/app/navigation/utils.ts @@ -150,7 +150,7 @@ export async function focusOrCreateTokensExploreTab({ currencyId }: { currencyId tags: { file: 'navigation/utils.ts', function: 'focusOrCreateTokensExploreTab' }, extra: { currencyId }, }) - return undefined + return } return focusOrCreateUniswapInterfaceTab({ diff --git a/apps/extension/src/contentScript/WindowEthereumProxy.ts b/apps/extension/src/contentScript/WindowEthereumProxy.ts index b06f1360bb4..2c479f5021d 100644 --- a/apps/extension/src/contentScript/WindowEthereumProxy.ts +++ b/apps/extension/src/contentScript/WindowEthereumProxy.ts @@ -106,7 +106,6 @@ export class WindowEthereumProxy extends EventEmitter { ...ethereumRequest, requestId, }) - return Promise.resolve() } catch (error) { logger.info('WindowEthereumProxy.ts', 'request', 'Invalid request', args) diff --git a/apps/extension/src/manifest.json b/apps/extension/src/manifest.json index b382fb9e62a..0532e617ce2 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.7.0", + "version": "1.6.0", "minimum_chrome_version": "116", "icons": { "16": "assets/icon16.png", diff --git a/apps/mobile/android/app/build.gradle b/apps/mobile/android/app/build.gradle index 883b1405283..762e948f5c3 100644 --- a/apps/mobile/android/app/build.gradle +++ b/apps/mobile/android/app/build.gradle @@ -90,9 +90,9 @@ if (isCI && datadogPropertiesAvailable && !isDetox) { apply from: "../../../../node_modules/@datadog/mobile-react-native/datadog-sourcemaps.gradle" } -def devVersionName = "1.37" -def betaVersionName = "1.37" -def prodVersionName = "1.37" +def devVersionName = "1.36" +def betaVersionName = "1.36" +def prodVersionName = "1.36" android { ndkVersion rootProject.ext.ndkVersion diff --git a/apps/mobile/ios/Uniswap.xcodeproj/project.pbxproj b/apps/mobile/ios/Uniswap.xcodeproj/project.pbxproj index 2607152847c..4d50741caf4 100644 --- a/apps/mobile/ios/Uniswap.xcodeproj/project.pbxproj +++ b/apps/mobile/ios/Uniswap.xcodeproj/project.pbxproj @@ -2167,7 +2167,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; @@ -2220,7 +2220,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = schemes.WidgetsCore; @@ -2273,7 +2273,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = schemes.WidgetsCore; @@ -2326,7 +2326,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = schemes.WidgetsCore; @@ -2364,7 +2364,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; @@ -2400,7 +2400,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = schemes.WidgetsCoreTests; @@ -2435,7 +2435,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = schemes.WidgetsCoreTests; @@ -2470,7 +2470,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = schemes.WidgetsCoreTests; @@ -2517,7 +2517,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; @@ -2563,7 +2563,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.widgets; @@ -2609,7 +2609,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.dev.widgets; @@ -2655,7 +2655,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.beta.widgets; @@ -2697,7 +2697,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; @@ -2740,7 +2740,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.WidgetIntentExtension; @@ -2783,7 +2783,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.dev.WidgetIntentExtension; @@ -2826,7 +2826,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.beta.WidgetIntentExtension; @@ -2862,7 +2862,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -2900,7 +2900,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -3078,7 +3078,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; @@ -3122,7 +3122,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.OneSignalNotificationServiceExtension; @@ -3222,7 +3222,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -3293,7 +3293,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.beta.OneSignalNotificationServiceExtension; @@ -3393,7 +3393,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -3464,7 +3464,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.37; + MARKETING_VERSION = 1.36; 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/ios/WidgetsCore/Utils/DataQueries.swift b/apps/mobile/ios/WidgetsCore/Utils/DataQueries.swift index d147fc40791..b74585300ec 100644 --- a/apps/mobile/ios/WidgetsCore/Utils/DataQueries.swift +++ b/apps/mobile/ios/WidgetsCore/Utils/DataQueries.swift @@ -22,7 +22,7 @@ public class DataQueries { let tokens = graphQLResult.data?.tokens ?? [] let tokenResponses = tokens.map { let symbol = $0?.symbol - let name = $0?.name + let name = $0?.project?.name let chain = $0?.chain let address = $0?.address return TokenResponse(chain: chain?.rawValue ?? "", address: address, symbol: symbol ?? "", name: name ?? "") @@ -43,7 +43,7 @@ public class DataQueries { let topTokens = graphQLResult.data?.topTokens ?? [] let tokenResponses = topTokens.map { (tokenData) -> TokenResponse in let symbol = tokenData?.symbol - let name = tokenData?.name + let name = tokenData?.project?.name let chain = tokenData?.chain let address = tokenData?.address return TokenResponse(chain: chain?.rawValue ?? "", address: address, symbol: symbol ?? "", name: name ?? "") @@ -63,11 +63,11 @@ public class DataQueries { case .success(let graphQLResult): let token = graphQLResult.data?.token let symbol = token?.symbol - let name = token?.name + let name = token?.project?.name let logoUrl = token?.project?.logoUrl ?? nil - let market = token?.market - let spotPrice = market?.price?.value - let pricePercentChange = market?.pricePercentChange?.value + let markets = token?.project?.markets + let spotPrice = (markets != nil) && !markets!.isEmpty ? markets?[0]?.price?.value : nil + let pricePercentChange = (markets != nil) && !markets!.isEmpty ? markets?[0]?.pricePercentChange24h?.value : nil let tokenPriceResponse = TokenPriceResponse(chain: chain, address: address, symbol: symbol ?? "", name: name ?? "", logoUrl: logoUrl ?? "", spotPrice: spotPrice, pricePercentChange: pricePercentChange) continuation.resume(returning: tokenPriceResponse) case .failure(let error): @@ -109,7 +109,7 @@ public class DataQueries { $0?.tokenBalances?.forEach { tokenBalance in let value = tokenBalance?.denominatedValue?.value let token = tokenBalance?.token - let tokenResponse = TokenResponse(chain: token?.chain.rawValue ?? "", address: token?.address, symbol: token?.symbol ?? "", name: token?.name ?? "") + let tokenResponse = TokenResponse(chain: token?.chain.rawValue ?? "", address: token?.address, symbol: token?.symbol ?? "", name: token?.project?.name ?? "") let isSpam = token?.project?.isSpam ?? false if (!isSpam) { tokens[tokenResponse] = (tokens[tokenResponse] ?? 0) + (value ?? 0) diff --git a/apps/mobile/jest-setup.js b/apps/mobile/jest-setup.js index 208cbed9336..fa40bf39df6 100644 --- a/apps/mobile/jest-setup.js +++ b/apps/mobile/jest-setup.js @@ -84,7 +84,7 @@ jest.mock('@react-navigation/elements', () => ({ require('react-native-reanimated').setUpTests() -jest.mock('uniswap/src/features/language/LocalizationContext', () => mockLocalizationContext({})) +jest.mock('uniswap/src/features/language/LocalizationContext', () => mockLocalizationContext) jest.mock('react-native/Libraries/Share/Share', () => ({ share: jest.fn(), diff --git a/apps/mobile/package.json b/apps/mobile/package.json index ba96ad068c7..c079a2d81fb 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -86,7 +86,7 @@ "@shopify/react-native-skia": "1.2.0", "@sparkfabrik/react-native-idfa-aaid": "1.2.0", "@uniswap/analytics": "1.7.0", - "@uniswap/analytics-events": "2.37.0", + "@uniswap/analytics-events": "2.36.0", "@uniswap/ethers-rs-mobile": "0.0.5", "@uniswap/sdk-core": "5.3.0", "@walletconnect/core": "2.11.2", diff --git a/apps/mobile/src/app/migrations.ts b/apps/mobile/src/app/migrations.ts index 66ce24dc095..96f656654ee 100644 --- a/apps/mobile/src/app/migrations.ts +++ b/apps/mobile/src/app/migrations.ts @@ -241,7 +241,7 @@ export const migrations = { 17: (state: any) => { const accounts: Record | undefined = state?.wallet?.accounts if (!accounts) { - return undefined + return } for (const account of Object.values(accounts)) { diff --git a/apps/mobile/src/app/modals/AppModals.tsx b/apps/mobile/src/app/modals/AppModals.tsx index b7b36041b10..e89bde7eb07 100644 --- a/apps/mobile/src/app/modals/AppModals.tsx +++ b/apps/mobile/src/app/modals/AppModals.tsx @@ -5,6 +5,7 @@ import { BackupReminderModal } from 'src/app/modals/BackupReminderModal' import { BackupWarningModal } from 'src/app/modals/BackupWarningModal' import { ExperimentsModal } from 'src/app/modals/ExperimentsModal' import { ExploreModal } from 'src/app/modals/ExploreModal' +import { HiddenTokenInfoModal } from 'src/app/modals/HiddenTokenInfoModal' import { KoreaCexTransferInfoModal } from 'src/app/modals/KoreaCexTransferInfoModal' import { LazyModalRenderer } from 'src/app/modals/LazyModalRenderer' import { SendTokenModal } from 'src/app/modals/SendTokenModal' @@ -35,6 +36,10 @@ export function AppModals(): JSX.Element { return ( <> + + + + diff --git a/apps/mobile/src/app/modals/BackupWarningModal.tsx b/apps/mobile/src/app/modals/BackupWarningModal.tsx index bffdea5c591..af26408413b 100644 --- a/apps/mobile/src/app/modals/BackupWarningModal.tsx +++ b/apps/mobile/src/app/modals/BackupWarningModal.tsx @@ -43,14 +43,14 @@ export function BackupWarningModal(): JSX.Element { ) } diff --git a/apps/mobile/src/app/modals/HiddenTokenInfoModal.tsx b/apps/mobile/src/app/modals/HiddenTokenInfoModal.tsx new file mode 100644 index 00000000000..46b76f3e03a --- /dev/null +++ b/apps/mobile/src/app/modals/HiddenTokenInfoModal.tsx @@ -0,0 +1,67 @@ +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, Text, useSporeColors } from 'ui/src' +import { ShieldCheck } from 'ui/src/components/icons' +import { iconSizes } from 'ui/src/theme/iconSizes' +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' +import { logger } from 'utilities/src/logger/logger' + +export function HiddenTokenInfoModal(): JSX.Element { + const dispatch = useDispatch() + const color = useSporeColors() + const { t } = useTranslation() + + const onClose = (): void => { + dispatch(closeModal({ name: ModalName.HiddenTokenInfoModal })) + } + + const openUniswapURL = async (): Promise => { + try { + await openURL(uniswapUrls.helpArticleUrls.hiddenTokenInfo) + } catch (error) { + logger.error(error, { tags: { file: 'HiddenToeknInfoModal.tsx', function: 'openUniswapURL' } }) + } + } + + return ( + dispatch(closeModal({ name: ModalName.HiddenTokenInfoModal }))} + > + + + + + + + + {t('hidden.tokens.info.text.title')} + + {t('hidden.tokens.info.text.info')} + + + + + + + ) +} diff --git a/apps/mobile/src/app/modals/SwapModal.tsx b/apps/mobile/src/app/modals/SwapModal.tsx index 57f3793aa2e..2a0340a0ec9 100644 --- a/apps/mobile/src/app/modals/SwapModal.tsx +++ b/apps/mobile/src/app/modals/SwapModal.tsx @@ -7,8 +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 { useSwapPrefilledState } from 'uniswap/src/features/transactions/swap/hooks/useSwapPrefilledState' import { WalletSwapFlow } from 'wallet/src/features/transactions/swap/WalletSwapFlow' +import { useSwapPrefilledState } from 'wallet/src/features/transactions/swap/hooks/useSwapPrefilledState' export function SwapModal(): JSX.Element { const appDispatch = useDispatch() diff --git a/apps/mobile/src/app/navigation/NavBar.tsx b/apps/mobile/src/app/navigation/NavBar.tsx index 982bfe45bac..10945f923cc 100644 --- a/apps/mobile/src/app/navigation/NavBar.tsx +++ b/apps/mobile/src/app/navigation/NavBar.tsx @@ -1,8 +1,8 @@ import { SharedEventName } from '@uniswap/analytics-events' import { BlurView } from 'expo-blur' -import React, { memo, useCallback, useEffect, useState } from 'react' +import React, { memo, useCallback } from 'react' import { useTranslation } from 'react-i18next' -import { LayoutChangeEvent, LayoutRectangle, StyleSheet } from 'react-native' +import { StyleSheet } from 'react-native' import { TapGestureHandler, TapGestureHandlerGestureEvent } from 'react-native-gesture-handler' import { cancelAnimation, @@ -11,7 +11,6 @@ import { useAnimatedStyle, useSharedValue, } from 'react-native-reanimated' -import { useSafeAreaFrame } from 'react-native-safe-area-context' import { useDispatch } from 'react-redux' import { pulseAnimation } from 'src/components/buttons/utils' import { openModal } from 'src/features/modals/modalSlice' @@ -42,9 +41,6 @@ import { useActiveAccountAddressWithThrow } from 'wallet/src/features/wallet/hoo export const NAV_BAR_HEIGHT_XS = 52 export const NAV_BAR_HEIGHT_SM = 72 -const NAV_BAR_MARGIN_SIDES = 24 -const NAV_BAR_GAP = 12 - export const SWAP_BUTTON_HEIGHT = 56 const SWAP_BUTTON_SHADOW_OFFSET = { width: 0, height: 4 } @@ -57,29 +53,9 @@ function sendSwapPressAnalyticsEvent(): void { export function NavBar(): JSX.Element { const insets = useDeviceInsets() - const { width: screenWidth } = useSafeAreaFrame() - const [isNarrow, setIsNarrow] = useState(false) - const [exploreButtonLayout, setExploreButtonLayout] = useState(null) - const [swapButtonLayout, setSwapButtonLayout] = useState(null) - const colors = useSporeColors() const isDarkMode = useIsDarkMode() - useEffect(() => { - if (isNarrow || !exploreButtonLayout?.width || !swapButtonLayout?.width) { - return - } - - // When the 2 buttons overflow, we set `isNarrow` to true and adjust the design accordingly. - // To test this, you can use an iPhone Mini set to Spanish. - setIsNarrow(exploreButtonLayout.width + swapButtonLayout.width + NAV_BAR_GAP + NAV_BAR_MARGIN_SIDES > screenWidth) - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [exploreButtonLayout?.width, swapButtonLayout?.width, screenWidth]) - - const onExploreLayout = useCallback((e: LayoutChangeEvent) => setExploreButtonLayout(e.nativeEvent.layout), []) - - const onSwapLayout = useCallback((e: LayoutChangeEvent) => setSwapButtonLayout(e.nativeEvent.layout), []) - return ( <> @@ -106,14 +82,14 @@ export function NavBar(): JSX.Element { fill row alignItems="center" - gap={NAV_BAR_GAP} + gap="$spacing12" justifyContent="space-between" mb={isAndroid ? '$spacing8' : '$none'} - mx={NAV_BAR_MARGIN_SIDES} + mx="$spacing24" pointerEvents="auto" > - - + + @@ -126,10 +102,9 @@ type SwapTabBarButtonProps = { * @default 0.96 */ activeScale?: number - onSwapLayout: (event: LayoutChangeEvent) => void } -const SwapFAB = memo(function _SwapFAB({ activeScale = 0.96, onSwapLayout }: SwapTabBarButtonProps) { +const SwapFAB = memo(function _SwapFAB({ activeScale = 0.96 }: SwapTabBarButtonProps) { const { t } = useTranslation() const dispatch = useDispatch() const { hapticFeedback } = useHapticFeedback() @@ -163,7 +138,7 @@ const SwapFAB = memo(function _SwapFAB({ activeScale = 0.96, onSwapLayout }: Swa }) return ( - + void } -function ExploreTabBarButton({ activeScale = 0.98, onLayout, isNarrow }: ExploreTabBarButtonProps): JSX.Element { +function ExploreTabBarButton({ activeScale = 0.98 }: ExploreTabBarButtonProps): JSX.Element { const dispatch = useDispatch() const colors = useSporeColors() const isDarkMode = useIsDarkMode() @@ -244,13 +217,6 @@ function ExploreTabBarButton({ activeScale = 0.98, onLayout, isNarrow }: Explore }, } - const [height, setHeight] = useState(undefined) - - const internalOnLayout = (e: LayoutChangeEvent): void => { - setHeight(e.nativeEvent.layout.height) - onLayout(e) - } - return ( - + - {isNarrow ? undefined : ( - - {t('common.input.search')} - - )} + + {t('common.input.search')} + 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 a0e839a9f3b..01d12d57d67 100644 --- a/apps/mobile/src/components/PriceExplorer/__snapshots__/Text.test.tsx.snap +++ b/apps/mobile/src/components/PriceExplorer/__snapshots__/Text.test.tsx.snap @@ -122,7 +122,7 @@ exports[`PriceText renders without error 1`] = ` jestAnimatedStyle={ { "value": { - "color": "#BFBFBF", + "color": "#CECECE", "fontSize": 106, }, } @@ -130,7 +130,7 @@ exports[`PriceText renders without error 1`] = ` maxFontSizeMultiplier={1.2} style={ { - "color": "#BFBFBF", + "color": "#CECECE", "fontFamily": "Basel Grotesk", "fontSize": 106, "fontWeight": "400", diff --git a/apps/mobile/src/components/RemoveWallet/useModalContent.tsx b/apps/mobile/src/components/RemoveWallet/useModalContent.tsx index 1c4ed3bbbf4..fce43abcbc5 100644 --- a/apps/mobile/src/components/RemoveWallet/useModalContent.tsx +++ b/apps/mobile/src/components/RemoveWallet/useModalContent.tsx @@ -149,7 +149,5 @@ export const useModalContent = ({ actionButtonTheme: 'secondary', } } - - return undefined }, [account, associatedAccounts, currentStep, displayName, isRemovingRecoveryPhrase, isReplacing, t]) } diff --git a/apps/mobile/src/components/Requests/RequestModal/KidSuperCheckinModal.tsx b/apps/mobile/src/components/Requests/RequestModal/KidSuperCheckinModal.tsx index 4a25eb3d965..26affbc414f 100644 --- a/apps/mobile/src/components/Requests/RequestModal/KidSuperCheckinModal.tsx +++ b/apps/mobile/src/components/Requests/RequestModal/KidSuperCheckinModal.tsx @@ -44,7 +44,7 @@ function useUniswapCafeLogo(): string | undefined { const logos = uwuLinkContractAllowlist.tokenRecipients.find((recipient) => recipient.name === 'Uniswap Cafe')?.logo if (!logos) { - return undefined + return } return isDarkMode ? logos.dark : logos.light diff --git a/apps/mobile/src/components/Requests/ScanSheet/util.ts b/apps/mobile/src/components/Requests/ScanSheet/util.ts index 07beb85b4e1..8c1d4fa4da2 100644 --- a/apps/mobile/src/components/Requests/ScanSheet/util.ts +++ b/apps/mobile/src/components/Requests/ScanSheet/util.ts @@ -98,8 +98,6 @@ export async function getSupportedURI( value: parseUwuLinkDataFromDeeplink(uri), } } - - return undefined } async function getWcUriWithCustomPrefix(uri: string, prefix: string): Promise<{ uri: string; type: URIType } | null> { @@ -162,7 +160,7 @@ export function parseScantasticParams(uri: string): ScantasticParams | undefined }, extra: { uri }, }) - return undefined + return } } @@ -188,6 +186,5 @@ export function parseScantasticParams(uri: string): ScantasticParams | undefined function: 'parseScantasticParams', }, }) - return undefined } } diff --git a/apps/mobile/src/components/Requests/Uwulink/utils.ts b/apps/mobile/src/components/Requests/Uwulink/utils.ts index fe1a5049398..3c9339a417f 100644 --- a/apps/mobile/src/components/Requests/Uwulink/utils.ts +++ b/apps/mobile/src/components/Requests/Uwulink/utils.ts @@ -85,7 +85,7 @@ export function findAllowedTokenRecipientForUwuLink( allowlist: UwULinkAllowlist, ): UwULinkAllowlistItem | undefined { if (request.method !== UwULinkMethod.Erc20Send) { - return undefined + return } const { chainId, recipient } = request diff --git a/apps/mobile/src/components/Requests/WalletConnectModals.tsx b/apps/mobile/src/components/Requests/WalletConnectModals.tsx index c89afaa5a4d..2858c67aeec 100644 --- a/apps/mobile/src/components/Requests/WalletConnectModals.tsx +++ b/apps/mobile/src/components/Requests/WalletConnectModals.tsx @@ -128,7 +128,7 @@ function RequestModal({ currRequest }: RequestModalProps): JSX.Element { return ( } @@ -136,7 +136,7 @@ function RequestModal({ currRequest }: RequestModalProps): JSX.Element { modalName={ModalName.WCViewOnlyWarning} severity={WarningSeverity.None} title={t('walletConnect.request.warning.title')} - onReject={onClose} + onCancel={onClose} onClose={onClose} > diff --git a/apps/mobile/src/components/Settings/BiometricAuthWarningModal.tsx b/apps/mobile/src/components/Settings/BiometricAuthWarningModal.tsx index ac1f302d227..3ad3f2ab284 100644 --- a/apps/mobile/src/components/Settings/BiometricAuthWarningModal.tsx +++ b/apps/mobile/src/components/Settings/BiometricAuthWarningModal.tsx @@ -9,7 +9,7 @@ import { isAndroid } from 'utilities/src/platform' type Props = { isOpen: boolean isTouchIdDevice: boolean - onConfirm: WarningModalProps['onAcknowledge'] + onConfirm: WarningModalProps['onConfirm'] onClose: WarningModalProps['onClose'] } @@ -23,14 +23,14 @@ export function BiometricAuthWarningModal({ isOpen, isTouchIdDevice, onConfirm, ? t('settings.setting.biometrics.warning.message.android') : t('settings.setting.biometrics.warning.message.ios', { biometricsMethod }) } - rejectText={t('common.button.back')} - acknowledgeText={t('common.button.skip')} + 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')} onClose={onClose} - onAcknowledge={onConfirm} + onConfirm={onConfirm} /> ) } diff --git a/apps/mobile/src/components/TokenBalanceList/TokenBalanceList.tsx b/apps/mobile/src/components/TokenBalanceList/TokenBalanceList.tsx index af17f53b4a5..88420b583bc 100644 --- a/apps/mobile/src/components/TokenBalanceList/TokenBalanceList.tsx +++ b/apps/mobile/src/components/TokenBalanceList/TokenBalanceList.tsx @@ -5,23 +5,21 @@ import { forwardRef, memo, useCallback, useEffect, useMemo, useRef, useState } f import { useTranslation } from 'react-i18next' import { FlatList, RefreshControl } from 'react-native' import Animated, { FadeInDown, FadeOut } from 'react-native-reanimated' +import { useDispatch } from 'react-redux' import { useAppStackNavigation } from 'src/app/navigation/types' import { TokenBalanceItemContextMenu } from 'src/components/TokenBalanceList/TokenBalanceItemContextMenu' import { useAdaptiveFooter } from 'src/components/home/hooks' import { TAB_BAR_HEIGHT, TAB_VIEW_SCROLL_THROTTLE, TabProps } from 'src/components/layout/TabHelpers' +import { openModal } from 'src/features/modals/modalSlice' import { Flex, Loader, useDeviceInsets, useSporeColors } from 'ui/src' -import { ShieldCheck } from 'ui/src/components/icons' import { AnimatedFlex } from 'ui/src/components/layout/AnimatedFlex' import { zIndices } from 'ui/src/theme' import { BaseCard } from 'uniswap/src/components/BaseCard/BaseCard' -import { uniswapUrls } from 'uniswap/src/constants/urls' -import { ModalName, WalletEventName } from 'uniswap/src/features/telemetry/constants' -import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' +import { ModalName } from 'uniswap/src/features/telemetry/constants' import { CurrencyId } from 'uniswap/src/types/currency' import { MobileScreens } from 'uniswap/src/types/screens/mobile' import { isAndroid } from 'utilities/src/platform' import { InformationBanner } from 'wallet/src/components/banners/InformationBanner' -import { InfoLinkModal } from 'wallet/src/components/modals/InfoLinkModal' import { isError, isNonPollingRequestInFlight } from 'wallet/src/data/utils' import { HiddenTokensRow } from 'wallet/src/features/portfolio/HiddenTokensRow' import { TokenBalanceItem } from 'wallet/src/features/portfolio/TokenBalanceItem' @@ -247,27 +245,22 @@ const TokenBalanceItemRow = memo(function TokenBalanceItemRow({ setHiddenTokensExpanded, } = useTokenBalanceListContext() + const dispatch = useDispatch() const { t } = useTranslation() - const [isModalVisible, setModalVisible] = useState(false) - const handlePressToken = (): void => { - setModalVisible(true) - } - - const closeModal = (): void => { - setModalVisible(false) - } - - const handleAnalytics = (): void => { - sendAnalyticsEvent(WalletEventName.ExternalLinkOpened, { - url: uniswapUrls.helpArticleUrls.hiddenTokenInfo, - }) - } + const onPressInfo = useCallback(() => { + dispatch( + openModal({ + name: ModalName.HiddenTokenInfoModal, + }), + ) + }, [dispatch]) if (item === HIDDEN_TOKEN_BALANCES_ROW) { return ( - + { @@ -276,29 +269,9 @@ const TokenBalanceItemRow = memo(function TokenBalanceItemRow({ /> {hiddenTokensExpanded && ( - + )} - - - - - } - isOpen={isModalVisible} - linkText={t('common.button.learn')} - linkUrl={uniswapUrls.helpArticleUrls.hiddenTokenInfo} - name={ModalName.HiddenTokenInfoModal} - title={t('hidden.tokens.info.text.title')} - onAnalyticsEvent={handleAnalytics} - onButtonPress={closeModal} - onDismiss={closeModal} - /> ) } diff --git a/apps/mobile/src/components/TokenDetails/TokenDetailsHeader.tsx b/apps/mobile/src/components/TokenDetails/TokenDetailsHeader.tsx index 27ce9171f76..a5cbc385775 100644 --- a/apps/mobile/src/components/TokenDetails/TokenDetailsHeader.tsx +++ b/apps/mobile/src/components/TokenDetails/TokenDetailsHeader.tsx @@ -27,7 +27,7 @@ export function TokenDetailsHeader({ @@ -40,7 +40,7 @@ export function TokenDetailsHeader({ testID={TestID.TokenDetailsHeaderText} variant="subheading1" > - {token?.name ?? '—'} + {tokenProject?.name ?? '—'} {/* Suppress warning icon on low warning level */} {(tokenProject?.safetyLevel === SafetyLevel.StrongWarning || diff --git a/apps/mobile/src/components/accounts/AccountList.test.tsx b/apps/mobile/src/components/accounts/AccountList.test.tsx index 5b4a988ad07..85cd12f126f 100644 --- a/apps/mobile/src/components/accounts/AccountList.test.tsx +++ b/apps/mobile/src/components/accounts/AccountList.test.tsx @@ -1,6 +1,5 @@ import { AccountList } from 'src/components/accounts/AccountList' import { cleanup, fireEvent, render, screen } from 'src/test/test-utils' -import { Locale } from 'uniswap/src/features/language/constants' import { ON_PRESS_EVENT_PAYLOAD, amounts, portfolio } from 'uniswap/src/test/fixtures' import { mockLocalizedFormatter } from 'uniswap/src/test/mocks' import { createArray, queryResolvers } from 'uniswap/src/test/utils' @@ -13,15 +12,13 @@ const { resolvers } = queryResolvers({ portfolios: () => [portfolio({ tokensTotalDenominatedValue })], }) -const formatter = mockLocalizedFormatter(Locale.EnglishUnitedStates) - describe(AccountList, () => { it('renders without error', async () => { const tree = render(, { resolvers }) expect( await screen.findByText( - formatter.formatNumberOrString({ + mockLocalizedFormatter.formatNumberOrString({ value: tokensTotalDenominatedValue.value, type: NumberType.PortfolioBalance, currencyCode: 'usd', @@ -39,7 +36,7 @@ describe(AccountList, () => { // go to success state expect( await screen.findByText( - formatter.formatNumberOrString({ + mockLocalizedFormatter.formatNumberOrString({ value: tokensTotalDenominatedValue.value, type: NumberType.PortfolioBalance, currencyCode: 'usd', diff --git a/apps/mobile/src/components/accounts/AccountList.tsx b/apps/mobile/src/components/accounts/AccountList.tsx index 43dc0ebc697..7d92cd9a3fb 100644 --- a/apps/mobile/src/components/accounts/AccountList.tsx +++ b/apps/mobile/src/components/accounts/AccountList.tsx @@ -135,7 +135,6 @@ export function AccountList({ accounts, onPress, isVisible }: AccountListProps): }, [hasSignerAccounts, hasViewOnlyAccounts, signerAccounts, viewOnlyAccounts]) const renderItem = useCallback( - // eslint-disable-next-line consistent-return ({ item }: { item: AccountListItem }) => { switch (item.type) { case AccountListItemType.SignerHeader: diff --git a/apps/mobile/src/components/accounts/__snapshots__/AccountHeader.test.tsx.snap b/apps/mobile/src/components/accounts/__snapshots__/AccountHeader.test.tsx.snap index 11a84bd0d0c..393ee8617ed 100644 --- a/apps/mobile/src/components/accounts/__snapshots__/AccountHeader.test.tsx.snap +++ b/apps/mobile/src/components/accounts/__snapshots__/AccountHeader.test.tsx.snap @@ -349,7 +349,7 @@ exports[`AccountHeader renders correctly 1`] = ` jestAnimatedStyle={ { "value": { - "color": "#BFBFBF", + "color": "#CECECE", "fontSize": 19, "fontWeight": "400", "lineHeight": 24, @@ -360,7 +360,7 @@ exports[`AccountHeader renders correctly 1`] = ` maxFontSizeMultiplier={1.4} style={ { - "color": "#BFBFBF", + "color": "#CECECE", "fontFamily": "Basel Grotesk", "fontSize": 19, "fontWeight": "400", @@ -415,7 +415,7 @@ exports[`AccountHeader renders correctly 1`] = ` numberOfLines={1} style={ { - "color": "#BFBFBF", + "color": "#CECECE", "fontFamily": "Basel Grotesk", "fontSize": 17, "fontWeight": "400", @@ -443,7 +443,7 @@ exports[`AccountHeader renders correctly 1`] = ` "borderWidth": 0, }, { - "color": "#BFBFBF", + "color": "#CECECE", "height": 16, "width": 16, }, @@ -454,7 +454,7 @@ exports[`AccountHeader renders correctly 1`] = ` }, ] } - tintColor="#BFBFBF" + tintColor="#CECECE" vbHeight={16} vbWidth={16} > diff --git a/apps/mobile/src/components/explore/ExploreSections.tsx b/apps/mobile/src/components/explore/ExploreSections.tsx index 446ffdb57eb..eee3060ec56 100644 --- a/apps/mobile/src/components/explore/ExploreSections.tsx +++ b/apps/mobile/src/components/explore/ExploreSections.tsx @@ -39,8 +39,6 @@ type ExploreSectionsProps = { listRef: React.MutableRefObject } -type GqlToken = NonNullable[0] - export function ExploreSections({ listRef }: ExploreSectionsProps): JSX.Element { const { t } = useTranslation() const insets = useDeviceInsets() @@ -74,31 +72,25 @@ export function ExploreSections({ listRef }: ExploreSectionsProps): JSX.Element const topTokenItems = useMemo(() => { if (!data || !data.topTokens) { - return undefined + return } // special case to replace weth with eth because the backend does not return eth data // eth will be defined only if all the required data is available // when eth data is not fully available, we do not replace weth with eth const { eth } = data - const wethAddress = getWrappedNativeAddress(UniverseChainId.Mainnet) - const isWeth = (token: GqlToken): boolean => - areAddressesEqual(token?.address, wethAddress) && token?.chain === Chain.Ethereum - - // Indentified by symbol because ETH token data comes with undefined address - const isEth = (token: GqlToken): boolean => token?.symbol === 'ETH' - const topTokens = data.topTokens - .filter((token, _, tokens) => !(isWeth(token) && tokens.some(isEth))) .map((token) => { if (!token) { - return undefined + return } + const isWeth = areAddressesEqual(token.address, wethAddress) && token?.chain === Chain.Ethereum + // manually replace weth with eth given backend only returns eth data as a proxy for eth - if (isWeth(token) && eth) { + if (isWeth && eth) { return gqlTokenToTokenItemData(eth) } @@ -232,8 +224,8 @@ function gqlTokenToTokenItemData( return null } - const { name, symbol, address, chain, project, market } = token - const { logoUrl, markets } = project + const { symbol, address, chain, project, market } = token + const { logoUrl, markets, name } = project const tokenProjectMarket = markets?.[0] const chainId = fromGraphQLChain(chain) diff --git a/apps/mobile/src/components/explore/FavoriteHeaderRow.tsx b/apps/mobile/src/components/explore/FavoriteHeaderRow.tsx index 4b107bcdc39..ecf7f85bdb8 100644 --- a/apps/mobile/src/components/explore/FavoriteHeaderRow.tsx +++ b/apps/mobile/src/components/explore/FavoriteHeaderRow.tsx @@ -1,7 +1,7 @@ import { default as React } from 'react' import { useTranslation } from 'react-i18next' import { Flex, Text, TouchableArea } from 'ui/src' -import { Ellipsis } from 'ui/src/components/icons' +import { TripleDots } from 'ui/src/components/icons' import { iconSizes } from 'ui/src/theme' import { TestID } from 'uniswap/src/test/fixtures/testIDs' @@ -24,7 +24,7 @@ export function FavoriteHeaderRow({ {!isEditing ? ( - + ) : ( diff --git a/apps/mobile/src/components/explore/FavoriteTokenCard.test.tsx b/apps/mobile/src/components/explore/FavoriteTokenCard.test.tsx index 421942d996e..cab12bedc20 100644 --- a/apps/mobile/src/components/explore/FavoriteTokenCard.test.tsx +++ b/apps/mobile/src/components/explore/FavoriteTokenCard.test.tsx @@ -9,8 +9,8 @@ import { SAMPLE_CURRENCY_ID_1, amount, ethToken, - tokenMarket, tokenProject, + tokenProjectMarket, } from 'uniswap/src/test/fixtures' import { queryResolvers } from 'uniswap/src/test/utils' import { getSymbolDisplayText } from 'uniswap/src/utils/currency' @@ -31,10 +31,13 @@ jest.mock('@react-navigation/native', () => { const mockStore = configureMockStore() const favoriteToken = ethToken({ - project: tokenProject(), - market: tokenMarket({ - price: amount({ value: 12345.67 }), - pricePercentChange: amount({ value: 4.56 }), + project: tokenProject({ + markets: [ + tokenProjectMarket({ + price: amount({ value: 12345.67 }), + pricePercentChange24h: amount({ value: 4.56 }), + }), + ], }), }) @@ -95,7 +98,7 @@ describe('FavoriteTokenCard', () => { const { findByTestId } = render(, { resolvers }) const touchable = await findByTestId(`token-box-${favoriteToken.symbol}`) - act(() => { + await act(() => { fireEvent.press(touchable, ON_PRESS_EVENT_PAYLOAD) }) diff --git a/apps/mobile/src/components/explore/FavoriteTokenCard.tsx b/apps/mobile/src/components/explore/FavoriteTokenCard.tsx index 7fb7b1eb6a7..c38a0f78509 100644 --- a/apps/mobile/src/components/explore/FavoriteTokenCard.tsx +++ b/apps/mobile/src/components/explore/FavoriteTokenCard.tsx @@ -63,8 +63,8 @@ function FavoriteTokenCard({ // Mirror behavior in top tokens list, use first chain the token is on for the symbol const chainId = fromGraphQLChain(token?.chain) ?? UniverseChainId.Mainnet - const price = convertFiatAmountFormatted(token?.market?.price?.value, NumberType.FiatTokenPrice) - const pricePercentChange = token?.market?.pricePercentChange?.value + const price = convertFiatAmountFormatted(token?.project?.markets?.[0]?.price?.value, NumberType.FiatTokenPrice) + const pricePercentChange = token?.project?.markets?.[0]?.pricePercentChange24h?.value const onRemove = useCallback(() => { if (currencyId) { @@ -124,7 +124,7 @@ function FavoriteTokenCard({ - } isOpen={showPopularInfo} modalName={ModalName.NetworkFeeInfo} diff --git a/apps/mobile/src/components/explore/search/SearchPopularNFTCollections.tsx b/apps/mobile/src/components/explore/search/SearchPopularNFTCollections.tsx index 8bf8bbafa4a..3ccf24bc7d2 100644 --- a/apps/mobile/src/components/explore/search/SearchPopularNFTCollections.tsx +++ b/apps/mobile/src/components/explore/search/SearchPopularNFTCollections.tsx @@ -16,7 +16,7 @@ export function SearchPopularNFTCollections(): JSX.Element { const formattedItems = useMemo(() => { if (!data?.topCollections?.edges) { - return undefined + return } const searchResults = data.topCollections.edges.map(({ node }) => gqlNFTToNFTCollectionSearchResult(node)) diff --git a/apps/mobile/src/components/explore/search/SearchPopularTokens.graphql b/apps/mobile/src/components/explore/search/SearchPopularTokens.graphql index 1d525085f00..dcf2b6e2fe2 100644 --- a/apps/mobile/src/components/explore/search/SearchPopularTokens.graphql +++ b/apps/mobile/src/components/explore/search/SearchPopularTokens.graphql @@ -5,9 +5,9 @@ query SearchPopularTokens { chain symbol decimals - name project { id + name logoUrl safetyLevel } diff --git a/apps/mobile/src/components/explore/search/SearchPopularTokens.tsx b/apps/mobile/src/components/explore/search/SearchPopularTokens.tsx index f3c0bccbfa9..04c6a0e5f14 100644 --- a/apps/mobile/src/components/explore/search/SearchPopularTokens.tsx +++ b/apps/mobile/src/components/explore/search/SearchPopularTokens.tsx @@ -13,7 +13,8 @@ function gqlTokenToTokenSearchResult(token: Maybe): TokenSearchResult return null } - const { name, chain, address, symbol, project, protectionInfo } = token + const { chain, address, symbol, project, protectionInfo } = token + const { name } = project const chainId = fromGraphQLChain(chain) if (!chainId || !symbol || !name) { return null diff --git a/apps/mobile/src/components/explore/search/SearchResultsSection.tsx b/apps/mobile/src/components/explore/search/SearchResultsSection.tsx index 71a0b043a33..fd9c9392527 100644 --- a/apps/mobile/src/components/explore/search/SearchResultsSection.tsx +++ b/apps/mobile/src/components/explore/search/SearchResultsSection.tsx @@ -81,7 +81,7 @@ export function SearchResultsSection({ searchQuery }: { searchQuery: string }): const tokenResults = useMemo(() => { if (!searchResultsData || !searchResultsData.searchTokens) { - return undefined + return } return formatTokenSearchResults(searchResultsData.searchTokens, searchQuery) @@ -91,7 +91,7 @@ export function SearchResultsSection({ searchQuery }: { searchQuery: string }): const nftCollectionResults = useMemo(() => { if (!searchResultsData || !searchResultsData.nftCollections) { - return undefined + return } return formatNFTCollectionSearchResults(searchResultsData.nftCollections) diff --git a/apps/mobile/src/components/explore/search/utils.test.ts b/apps/mobile/src/components/explore/search/utils.test.ts index a11d3774eed..61d9f8e9204 100644 --- a/apps/mobile/src/components/explore/search/utils.test.ts +++ b/apps/mobile/src/components/explore/search/utils.test.ts @@ -7,7 +7,15 @@ import { 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 } from 'uniswap/src/features/search/SearchResult' -import { amount, ethToken, nftCollection, nftContract, token, tokenMarket } from 'uniswap/src/test/fixtures' +import { + amount, + ethToken, + nftCollection, + nftContract, + token, + tokenMarket, + tokenProject, +} from 'uniswap/src/test/fixtures' import { createArray } from 'uniswap/src/test/utils' type ExploreSearchResult = NonNullable @@ -54,8 +62,8 @@ describe(formatTokenSearchResults, () => { it('sorts results by best search query match', () => { const data: ExploreSearchResult['searchTokens'] = [ - token({ name: 'UniswapStartingName' }), - token({ name: 'Uniswap' }), + ethToken({ project: tokenProject({ name: 'UniswapStartingName' }) }), + ethToken({ project: tokenProject({ name: 'Uniswap' }) }), ] const result = formatTokenSearchResults(data, 'uniswap') @@ -75,7 +83,7 @@ describe(formatTokenSearchResults, () => { expect(result?.[0]?.type).toEqual(SearchResultType.Token) expect(result?.[0]?.chainId).toEqual(fromGraphQLChain(searchToken.chain)) expect(result?.[0]?.address).toEqual(searchToken.address) - expect(result?.[0]?.name).toEqual(searchToken.name) + expect(result?.[0]?.name).toEqual(searchToken.project?.name) expect(result?.[0]?.symbol).toEqual(searchToken.symbol) expect(result?.[0]?.logoUrl).toEqual(searchToken.project?.logoUrl) expect(result?.[0]?.safetyLevel).toEqual(searchToken.project?.safetyLevel) diff --git a/apps/mobile/src/components/explore/search/utils.ts b/apps/mobile/src/components/explore/search/utils.ts index c40bfb0c86d..914838b43ec 100644 --- a/apps/mobile/src/components/explore/search/utils.ts +++ b/apps/mobile/src/components/explore/search/utils.ts @@ -20,7 +20,7 @@ export function formatTokenSearchResults( searchQuery: string, ): TokenSearchResult[] | undefined { if (!data) { - return undefined + return } // Prevent showing "duplicate" token search results for tokens that are on multiple chains @@ -31,14 +31,14 @@ export function formatTokenSearchResults( return tokensMap } - const { name, chain, address, symbol, project, market, protectionInfo } = token + const { chain, address, symbol, project, market, protectionInfo } = token const chainId = fromGraphQLChain(chain) if (!chainId || !project) { return tokensMap } - const { safetyLevel, logoUrl } = project + const { name, safetyLevel, logoUrl } = project const tokenResult: TokenSearchResult & { volume1D: number } = { type: SearchResultType.Token, @@ -87,7 +87,7 @@ export function formatNFTCollectionSearchResults( data: ExploreSearchResult['nftCollections'], ): NFTCollectionSearchResult[] | undefined { if (!data) { - return undefined + return } return data.edges.reduce((accum, { node }) => { diff --git a/apps/mobile/src/components/forceUpgrade/ForceUpgradeModal.tsx b/apps/mobile/src/components/forceUpgrade/ForceUpgradeModal.tsx index 29e6474c1c2..4f8ee2f170b 100644 --- a/apps/mobile/src/components/forceUpgrade/ForceUpgradeModal.tsx +++ b/apps/mobile/src/components/forceUpgrade/ForceUpgradeModal.tsx @@ -65,7 +65,7 @@ export function ForceUpgradeModal(): JSX.Element { return ( <> {t('forceUpgrade.description')} diff --git a/apps/mobile/src/components/home/HomeExploreTab.tsx b/apps/mobile/src/components/home/HomeExploreTab.tsx index e180d44e312..daa8745849e 100644 --- a/apps/mobile/src/components/home/HomeExploreTab.tsx +++ b/apps/mobile/src/components/home/HomeExploreTab.tsx @@ -188,8 +188,8 @@ function gqlTokenToTokenItemData( return null } - const { name, symbol, address, chain, project } = token - const { logoUrl, markets } = project + const { symbol, address, chain, project } = token + const { logoUrl, markets, name } = project const tokenProjectMarket = markets?.[0] const chainId = fromGraphQLChain(chain) diff --git a/packages/wallet/src/components/introCards/IntroCard.test.tsx b/apps/mobile/src/components/home/introCards/IntroCard.test.tsx similarity index 74% rename from packages/wallet/src/components/introCards/IntroCard.test.tsx rename to apps/mobile/src/components/home/introCards/IntroCard.test.tsx index c2c2ca508fc..7eadaa00cfe 100644 --- a/packages/wallet/src/components/introCards/IntroCard.test.tsx +++ b/apps/mobile/src/components/home/introCards/IntroCard.test.tsx @@ -1,6 +1,6 @@ +import { CardType, IntroCard, IntroCardProps } from 'src/components/home/introCards/IntroCard' +import { render, screen } from 'src/test/test-utils' import { Wallet } from 'ui/src/components/icons' -import { CardType, IntroCard, IntroCardProps } from 'wallet/src/components/introCards/IntroCard' -import { render, screen } from 'wallet/src/test/test-utils' describe(IntroCard, () => { it('should render the passed values', () => { diff --git a/packages/wallet/src/components/introCards/IntroCard.tsx b/apps/mobile/src/components/home/introCards/IntroCard.tsx similarity index 87% rename from packages/wallet/src/components/introCards/IntroCard.tsx rename to apps/mobile/src/components/home/introCards/IntroCard.tsx index c97d0429ef7..165d1afd29f 100644 --- a/packages/wallet/src/components/introCards/IntroCard.tsx +++ b/apps/mobile/src/components/home/introCards/IntroCard.tsx @@ -2,7 +2,6 @@ import { Gesture, GestureDetector } from 'react-native-gesture-handler' import { Flex, GeneratedIcon, IconProps, Text, ViewProps, useIsDarkMode, useShadowPropsShort } from 'ui/src' import { X } from 'ui/src/components/icons' import { useTranslation } from 'uniswap/src/i18n' -import { isExtension } from 'utilities/src/platform' export enum CardType { Required, @@ -52,7 +51,7 @@ export function IntroCard({ borderRadius="$rounded20" borderWidth={1} gap="$spacing12" - p={isExtension ? '$spacing12' : '$spacing16'} + p="$spacing16" paddingStart="$spacing12" > - + - + {title} {cardType === CardType.Required ? ( @@ -92,7 +91,7 @@ export function IntroCard({ ) : null} - + {description} diff --git a/packages/wallet/src/components/introCards/IntroCardStack.tsx b/apps/mobile/src/components/home/introCards/IntroCardStack.tsx similarity index 59% rename from packages/wallet/src/components/introCards/IntroCardStack.tsx rename to apps/mobile/src/components/home/introCards/IntroCardStack.tsx index c3f4367617b..e6ac34046de 100644 --- a/packages/wallet/src/components/introCards/IntroCardStack.tsx +++ b/apps/mobile/src/components/home/introCards/IntroCardStack.tsx @@ -1,22 +1,22 @@ +import { IntroCard, IntroCardProps } from 'src/components/home/introCards/IntroCard' import { SwipeableCardStack } from 'ui/src/components/swipeablecards/SwipeableCardStack' -import { isExtension } from 'utilities/src/platform' -import { IntroCard, IntroCardProps } from 'wallet/src/components/introCards/IntroCard' export type IntroCardWrapper = IntroCardProps & { onPress?: () => void } type IntroCardStackProps = { cards: IntroCardWrapper[] + keyExtractor: (card: IntroCardProps) => string onSwiped?: (card: IntroCardProps, index: number) => void } -export const INTRO_CARD_MIN_HEIGHT = isExtension ? 84 : 110 +export const INTRO_CARD_MIN_HEIGHT = 110 -export function IntroCardStack({ cards, onSwiped }: IntroCardStackProps): JSX.Element { +export function IntroCardStack({ cards, keyExtractor, onSwiped }: IntroCardStackProps): JSX.Element { return ( card.title} + keyExtractor={keyExtractor} minCardHeight={INTRO_CARD_MIN_HEIGHT} renderCard={(card) => } onSwiped={onSwiped} diff --git a/apps/mobile/src/components/home/introCards/OnboardingIntroCardStack.tsx b/apps/mobile/src/components/home/introCards/OnboardingIntroCardStack.tsx index a0aeca02bdb..d1eb6b7270f 100644 --- a/apps/mobile/src/components/home/introCards/OnboardingIntroCardStack.tsx +++ b/apps/mobile/src/components/home/introCards/OnboardingIntroCardStack.tsx @@ -4,21 +4,20 @@ import { FadeIn, FadeOut } from 'react-native-reanimated' 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 { INTRO_CARD_MIN_HEIGHT, IntroCardStack, IntroCardWrapper } from 'src/components/home/introCards/IntroCardStack' import { UnitagBanner } from 'src/components/unitags/UnitagBanner' -import { openModal } from 'src/features/modals/modalSlice' +import { useUnitagClaimHandler } from 'src/features/unitags/useUnitagClaimHandler' import { Flex } from 'ui/src' import { Buy, Person, ShieldCheck, UniswapLogo } from 'ui/src/components/icons' import { AnimatedFlex } from 'ui/src/components/layout/AnimatedFlex' import { AccountType } from 'uniswap/src/features/accounts/types' -import { ElementName, MobileEventName, ModalName } from 'uniswap/src/features/telemetry/constants' +import { ElementName, MobileEventName } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { OnboardingCardLoggingName } from 'uniswap/src/features/telemetry/types' import { useTranslation } from 'uniswap/src/i18n' import { ImportType, OnboardingEntryPoint } from 'uniswap/src/types/onboarding' -import { MobileScreens, OnboardingScreens, UnitagScreens } from 'uniswap/src/types/screens/mobile' -import { CardType, IntroCardProps } from 'wallet/src/components/introCards/IntroCard' -import { INTRO_CARD_MIN_HEIGHT, IntroCardStack } from 'wallet/src/components/introCards/IntroCardStack' -import { IntroCardWithLogging } from 'wallet/src/components/introCards/useSharedIntroCards' +import { MobileScreens, OnboardingScreens } from 'uniswap/src/types/screens/mobile' import { selectHasSkippedUnitagPrompt, selectHasViewedWelcomeWalletCard, @@ -26,9 +25,12 @@ import { import { setHasViewedWelcomeWalletCard } from 'wallet/src/features/behaviorHistory/slice' import { UNITAG_SUFFIX_NO_LEADING_DOT } from 'wallet/src/features/unitags/constants' import { useCanActiveAddressClaimUnitag } from 'wallet/src/features/unitags/hooks' -import { useUnitagClaimHandler } from 'wallet/src/features/unitags/useUnitagClaimHandler' import { useActiveAccountWithThrow } from 'wallet/src/features/wallet/hooks' +type IntroCardWithName = IntroCardWrapper & { + loggingName: OnboardingCardLoggingName +} + type OnboardingIntroCardStackProps = { onboardingRedesignHomeEnabled: boolean onboardingRedesignBackupEnabled: boolean @@ -42,37 +44,17 @@ export function OnboardingIntroCardStack({ const { t } = useTranslation() const dispatch = useDispatch() const activeAccount = useActiveAccountWithThrow() - const address = activeAccount.address const hasBackups = activeAccount.backups && activeAccount.backups.length > 0 const welcomeCardTitle = t('onboarding.home.intro.welcome.title') const hasViewedWelcomeWalletCard = useSelector(selectHasViewedWelcomeWalletCard) - const navigateToUnitagClaim = useCallback(() => { - navigate(MobileScreens.UnitagStack, { - screen: UnitagScreens.ClaimUnitag, - params: { - entryPoint: MobileScreens.Home, - address, - }, - }) - }, [address]) - - const navigateToUnitagIntro = useCallback(() => { - dispatch( - openModal({ - name: ModalName.UnitagsIntro, - initialState: { address, entryPoint: MobileScreens.Home }, - }), - ) - }, [dispatch, address]) - const hasSkippedUnitagPrompt = useSelector(selectHasSkippedUnitagPrompt) const { canClaimUnitag } = useCanActiveAddressClaimUnitag() const { handleClaim: handleUnitagClaim, handleDismiss: handleUnitagDismiss } = useUnitagClaimHandler({ + address: activeAccount.address, + entryPoint: MobileScreens.Home, analyticsEntryPoint: 'home', - navigateToClaim: navigateToUnitagClaim, - navigateToIntro: navigateToUnitagIntro, }) const [showFundModal, setShowFundModal] = useState(false) @@ -85,7 +67,7 @@ export function OnboardingIntroCardStack({ return [] } - const output: IntroCardWithLogging[] = [] + const output: IntroCardWithName[] = [] if (!hasViewedWelcomeWalletCard) { output.push({ @@ -185,7 +167,11 @@ export function OnboardingIntroCardStack({ if (cards.length) { return ( - {isLoading ? : } + {isLoading ? ( + + ) : ( + card.title} onSwiped={handleSwiped} /> + )} {showFundModal && setShowFundModal(false)} />} diff --git a/apps/mobile/src/components/icons/Favorite.tsx b/apps/mobile/src/components/icons/Favorite.tsx index 881564c79da..1dbf83c0b4d 100644 --- a/apps/mobile/src/components/icons/Favorite.tsx +++ b/apps/mobile/src/components/icons/Favorite.tsx @@ -1,7 +1,8 @@ import React, { useCallback, useEffect, useState } from 'react' import { useAnimatedStyle, useDerivedValue, withSequence, withTiming } from 'react-native-reanimated' -import { Flex, useSporeColors } from 'ui/src' -import { HeartWithFill } from 'ui/src/components/icons' +import { useSporeColors } from 'ui/src' +import HeartIcon from 'ui/src/assets/icons/heart.svg' +import { AnimatedFlex } from 'ui/src/components/layout/AnimatedFlex' interface FavoriteButtonProps { isFavorited: boolean @@ -37,8 +38,8 @@ export const Favorite = ({ isFavorited, size }: FavoriteButtonProps): JSX.Elemen const animatedStyle = useAnimatedStyle(() => ({ transform: [{ scale: scale.value }] }), [scale]) return ( - - - + + + ) } diff --git a/apps/mobile/src/components/mnemonic/SeedPhraseDisplay.tsx b/apps/mobile/src/components/mnemonic/SeedPhraseDisplay.tsx index 20302b6a373..8d51760921d 100644 --- a/apps/mobile/src/components/mnemonic/SeedPhraseDisplay.tsx +++ b/apps/mobile/src/components/mnemonic/SeedPhraseDisplay.tsx @@ -73,29 +73,29 @@ export function SeedPhraseDisplay({ mnemonicId, onDismiss, walletNeedsRestore }: { + onCancel={(): void => { setShowSeedPhraseViewWarningModal(false) if (!showSeedPhrase) { onDismiss?.() } }} - onAcknowledge={onConfirmWarning} + onConfirm={onConfirmWarning} /> )} setShowScreenShotWarningModal(false)} + onConfirm={(): void => setShowScreenShotWarningModal(false)} /> ) diff --git a/apps/mobile/src/components/sortableGrid/contexts/LayoutContextProvider.tsx b/apps/mobile/src/components/sortableGrid/contexts/LayoutContextProvider.tsx index c9a0aa06a7b..be649641a98 100644 --- a/apps/mobile/src/components/sortableGrid/contexts/LayoutContextProvider.tsx +++ b/apps/mobile/src/components/sortableGrid/contexts/LayoutContextProvider.tsx @@ -150,8 +150,6 @@ export function LayoutContextProvider({ } rowOffsets.value = offsets } - - return undefined }, [numColumns], ) diff --git a/apps/mobile/src/components/text/__snapshots__/DecimalNumber.test.tsx.snap b/apps/mobile/src/components/text/__snapshots__/DecimalNumber.test.tsx.snap index dac06fab0f7..5c375be5301 100644 --- a/apps/mobile/src/components/text/__snapshots__/DecimalNumber.test.tsx.snap +++ b/apps/mobile/src/components/text/__snapshots__/DecimalNumber.test.tsx.snap @@ -21,7 +21,7 @@ exports[`renders a DecimalNumber 1`] = ` maxFontSizeMultiplier={1.4} style={ { - "color": "#BFBFBF", + "color": "#CECECE", "fontFamily": "Basel Grotesk", "fontSize": 19, "fontWeight": "400", @@ -57,7 +57,7 @@ exports[`renders a DecimalNumber without a comma separator 1`] = ` maxFontSizeMultiplier={1.4} style={ { - "color": "#BFBFBF", + "color": "#CECECE", "fontFamily": "Basel Grotesk", "fontSize": 19, "fontWeight": "400", diff --git a/apps/mobile/src/components/text/__snapshots__/TextWithFuseMatches.test.tsx.snap b/apps/mobile/src/components/text/__snapshots__/TextWithFuseMatches.test.tsx.snap index 0eb50c2cfbd..8c519688ecf 100644 --- a/apps/mobile/src/components/text/__snapshots__/TextWithFuseMatches.test.tsx.snap +++ b/apps/mobile/src/components/text/__snapshots__/TextWithFuseMatches.test.tsx.snap @@ -46,7 +46,7 @@ exports[`renders text with few matches 1`] = ` maxFontSizeMultiplier={1.4} style={ { - "color": "#BFBFBF", + "color": "#CECECE", "fontFamily": "Basel Grotesk", "fontSize": 19, "fontWeight": "400", @@ -62,7 +62,7 @@ exports[`renders text with few matches 1`] = ` maxFontSizeMultiplier={1.4} style={ { - "color": "#BFBFBF", + "color": "#CECECE", "fontFamily": "Basel Grotesk", "fontSize": 19, "fontWeight": "400", @@ -158,7 +158,7 @@ exports[`renders text with few matches 1`] = ` maxFontSizeMultiplier={1.4} style={ { - "color": "#BFBFBF", + "color": "#CECECE", "fontFamily": "Basel Grotesk", "fontSize": 19, "fontWeight": "400", @@ -174,7 +174,7 @@ exports[`renders text with few matches 1`] = ` maxFontSizeMultiplier={1.4} style={ { - "color": "#BFBFBF", + "color": "#CECECE", "fontFamily": "Basel Grotesk", "fontSize": 19, "fontWeight": "400", @@ -190,7 +190,7 @@ exports[`renders text with few matches 1`] = ` maxFontSizeMultiplier={1.4} style={ { - "color": "#BFBFBF", + "color": "#CECECE", "fontFamily": "Basel Grotesk", "fontSize": 19, "fontWeight": "400", @@ -206,7 +206,7 @@ exports[`renders text with few matches 1`] = ` maxFontSizeMultiplier={1.4} style={ { - "color": "#BFBFBF", + "color": "#CECECE", "fontFamily": "Basel Grotesk", "fontSize": 19, "fontWeight": "400", @@ -222,7 +222,7 @@ exports[`renders text with few matches 1`] = ` maxFontSizeMultiplier={1.4} style={ { - "color": "#BFBFBF", + "color": "#CECECE", "fontFamily": "Basel Grotesk", "fontSize": 19, "fontWeight": "400", @@ -238,7 +238,7 @@ exports[`renders text with few matches 1`] = ` maxFontSizeMultiplier={1.4} style={ { - "color": "#BFBFBF", + "color": "#CECECE", "fontFamily": "Basel Grotesk", "fontSize": 19, "fontWeight": "400", @@ -254,7 +254,7 @@ exports[`renders text with few matches 1`] = ` maxFontSizeMultiplier={1.4} style={ { - "color": "#BFBFBF", + "color": "#CECECE", "fontFamily": "Basel Grotesk", "fontSize": 19, "fontWeight": "400", @@ -270,7 +270,7 @@ exports[`renders text with few matches 1`] = ` maxFontSizeMultiplier={1.4} style={ { - "color": "#BFBFBF", + "color": "#CECECE", "fontFamily": "Basel Grotesk", "fontSize": 19, "fontWeight": "400", @@ -286,7 +286,7 @@ exports[`renders text with few matches 1`] = ` maxFontSizeMultiplier={1.4} style={ { - "color": "#BFBFBF", + "color": "#CECECE", "fontFamily": "Basel Grotesk", "fontSize": 19, "fontWeight": "400", @@ -302,7 +302,7 @@ exports[`renders text with few matches 1`] = ` maxFontSizeMultiplier={1.4} style={ { - "color": "#BFBFBF", + "color": "#CECECE", "fontFamily": "Basel Grotesk", "fontSize": 19, "fontWeight": "400", @@ -318,7 +318,7 @@ exports[`renders text with few matches 1`] = ` maxFontSizeMultiplier={1.4} style={ { - "color": "#BFBFBF", + "color": "#CECECE", "fontFamily": "Basel Grotesk", "fontSize": 19, "fontWeight": "400", @@ -334,7 +334,7 @@ exports[`renders text with few matches 1`] = ` maxFontSizeMultiplier={1.4} style={ { - "color": "#BFBFBF", + "color": "#CECECE", "fontFamily": "Basel Grotesk", "fontSize": 19, "fontWeight": "400", @@ -350,7 +350,7 @@ exports[`renders text with few matches 1`] = ` maxFontSizeMultiplier={1.4} style={ { - "color": "#BFBFBF", + "color": "#CECECE", "fontFamily": "Basel Grotesk", "fontSize": 19, "fontWeight": "400", diff --git a/apps/mobile/src/components/tooltip/TooltipButton.tsx b/apps/mobile/src/components/tooltip/TooltipButton.tsx index f06639e4ef4..206b2042e1d 100644 --- a/apps/mobile/src/components/tooltip/TooltipButton.tsx +++ b/apps/mobile/src/components/tooltip/TooltipButton.tsx @@ -50,7 +50,7 @@ export function TooltipInfoButton({ { if (!response.didCancel && !response.errorCode && response.assets) { return response.assets[0]?.uri } - return undefined } export function useAvatarSelectionHandler({ diff --git a/apps/mobile/src/components/unitags/UnitagBanner.tsx b/apps/mobile/src/components/unitags/UnitagBanner.tsx index 65ea0f48266..d8332b6cb92 100644 --- a/apps/mobile/src/components/unitags/UnitagBanner.tsx +++ b/apps/mobile/src/components/unitags/UnitagBanner.tsx @@ -1,18 +1,14 @@ -import React, { useCallback } from 'react' +import React from 'react' import { Trans, useTranslation } from 'react-i18next' -import { useDispatch } from 'react-redux' -import { navigate } from 'src/app/navigation/rootNavigation' -import { openModal } from 'src/features/modals/modalSlice' +import { useUnitagClaimHandler } from 'src/features/unitags/useUnitagClaimHandler' import { Flex, Image, Text, TouchableArea, TouchableAreaProps, useIsDarkMode, useIsShortMobileDevice } from 'ui/src' import { UNITAGS_BANNER_VERTICAL_DARK, UNITAGS_BANNER_VERTICAL_LIGHT } from 'ui/src/assets' import { useDeviceDimensions } from 'ui/src/hooks/useDeviceDimensions' import { iconSizes } from 'ui/src/theme' -import { ModalName } from 'uniswap/src/features/telemetry/constants' import { TestID } from 'uniswap/src/test/fixtures/testIDs' -import { MobileScreens, UnitagScreens } from 'uniswap/src/types/screens/mobile' +import { MobileScreens } from 'uniswap/src/types/screens/mobile' import { dismissNativeKeyboard } from 'utilities/src/device/keyboard' import { UNITAG_SUFFIX_NO_LEADING_DOT } from 'wallet/src/features/unitags/constants' -import { useUnitagClaimHandler } from 'wallet/src/features/unitags/useUnitagClaimHandler' const IMAGE_ASPECT_RATIO = 0.42 const IMAGE_SCREEN_WIDTH_PROPORTION = 0.18 @@ -31,7 +27,6 @@ export function UnitagBanner({ const { fullWidth } = useDeviceDimensions() const isDarkMode = useIsDarkMode() const isShortDevice = useIsShortMobileDevice() - const dispatch = useDispatch() const imageWidth = compact ? COMPACT_IMAGE_SCREEN_WIDTH_PROPORTION * fullWidth @@ -39,29 +34,10 @@ export function UnitagBanner({ const imageHeight = imageWidth / IMAGE_ASPECT_RATIO const analyticsEntryPoint = entryPoint === MobileScreens.Home ? 'home' : 'settings' - const navigateToClaim = useCallback(() => { - navigate(MobileScreens.UnitagStack, { - screen: UnitagScreens.ClaimUnitag, - params: { - entryPoint: MobileScreens.Home, - address, - }, - }) - }, [address]) - - const navigateToIntro = useCallback(() => { - dispatch( - openModal({ - name: ModalName.UnitagsIntro, - initialState: { address, entryPoint: MobileScreens.Home }, - }), - ) - }, [dispatch, address]) - const { handleClaim, handleDismiss } = useUnitagClaimHandler({ + address, + entryPoint, analyticsEntryPoint, - navigateToClaim, - navigateToIntro, }) const onPressClaimNow = (): void => { diff --git a/apps/mobile/src/features/CloudBackup/CloudBackupProcessingAnimation.tsx b/apps/mobile/src/features/CloudBackup/CloudBackupProcessingAnimation.tsx index 542eeb99001..d0c7b4755f5 100644 --- a/apps/mobile/src/features/CloudBackup/CloudBackupProcessingAnimation.tsx +++ b/apps/mobile/src/features/CloudBackup/CloudBackupProcessingAnimation.tsx @@ -65,7 +65,6 @@ export function CloudBackupProcessingAnimation({ const timer = setTimeout(onBackupComplete, ONE_SECOND_MS) return () => clearTimeout(timer) } - return undefined }, [account?.backups, onBackupComplete]) // Handle backup to Cloud when screen appears diff --git a/apps/mobile/src/features/appRating/saga.ts b/apps/mobile/src/features/appRating/saga.ts index 83fb6d1603a..00f767f44b2 100644 --- a/apps/mobile/src/features/appRating/saga.ts +++ b/apps/mobile/src/features/appRating/saga.ts @@ -38,7 +38,7 @@ const getStoreReview = async () => { } catch (error) { const message = error instanceof Error ? error.message : 'Store Review import error' logger.warn('appRating/saga.ts', 'getStoreReview', message) - return undefined + return } } diff --git a/apps/mobile/src/features/fiatOnRamp/FiatOnRampAmountSection.tsx b/apps/mobile/src/features/fiatOnRamp/FiatOnRampAmountSection.tsx index d3bc230c6b4..31a7552160c 100644 --- a/apps/mobile/src/features/fiatOnRamp/FiatOnRampAmountSection.tsx +++ b/apps/mobile/src/features/fiatOnRamp/FiatOnRampAmountSection.tsx @@ -38,11 +38,13 @@ const PREDEFINED_AMOUNTS = [100, 300, 1000] type OnChangeAmount = (amount: string) => void -function OnRampError({ errorText, color }: { errorText?: string; color: ColorTokens }): JSX.Element { +function OnRampError({ errorText, color }: { errorText: string; color: ColorTokens }): JSX.Element { return ( - - {errorText} - + + + {errorText} + + ) } @@ -174,13 +176,9 @@ export const FiatOnRampAmountSection = forwardRef - {notAvailableInThisRegion ? ( - - ) : debouncedErrorText ? ( - - ) : !appFiatCurrencySupported ? ( - - ) : null} + + {debouncedErrorText} + @@ -255,6 +253,11 @@ export const FiatOnRampAmountSection = forwardRef )} + {notAvailableInThisRegion ? ( + + ) : !appFiatCurrencySupported ? ( + + ) : null} ) }, diff --git a/apps/mobile/src/features/import/GenericImportForm.tsx b/apps/mobile/src/features/import/GenericImportForm.tsx index ae1e030a98e..3febc374592 100644 --- a/apps/mobile/src/features/import/GenericImportForm.tsx +++ b/apps/mobile/src/features/import/GenericImportForm.tsx @@ -152,13 +152,7 @@ export function GenericImportForm({ py="$spacing16" top={0} > - + {placeholderLabel} diff --git a/apps/mobile/src/features/import/InputWithSuffix.android.tsx b/apps/mobile/src/features/import/InputWithSuffix.android.tsx index bb0185db220..235c46a5565 100644 --- a/apps/mobile/src/features/import/InputWithSuffix.android.tsx +++ b/apps/mobile/src/features/import/InputWithSuffix.android.tsx @@ -62,6 +62,7 @@ export default function InputWithSuffix({ px="$none" py="$none" scrollEnabled={false} + textAlignVertical="bottom" value={inputSuffix} /> ) : null @@ -85,6 +86,7 @@ export default function InputWithSuffix({ autoCapitalize="none" backgroundColor="$transparent" color="$neutral1" + flexShrink={1} fontSize={inputFontSize} lineHeight={inputFontSize} maxFontSizeMultiplier={inputMaxFontSizeMultiplier} @@ -96,8 +98,8 @@ export default function InputWithSuffix({ spellCheck={false} testID={TestID.ImportAccountInput} textAlign={isInputEmpty ? 'left' : textInputAlignment} + textAlignVertical={isInputEmpty ? 'center' : 'bottom'} value={value} - verticalAlign="center" onLayout={measureInputWidth} {...inputProps} /> diff --git a/apps/mobile/src/features/import/InputWithSuffix.ios.tsx b/apps/mobile/src/features/import/InputWithSuffix.ios.tsx index a23af8ee202..88cec2ba5da 100644 --- a/apps/mobile/src/features/import/InputWithSuffix.ios.tsx +++ b/apps/mobile/src/features/import/InputWithSuffix.ios.tsx @@ -41,6 +41,7 @@ export default function InputWithSuffix({ spellCheck={false} testID={TestID.ImportAccountInput} textAlign={isInputEmpty ? 'left' : textInputAlignment} + textAlignVertical="bottom" value={value} {...inputProps} /> @@ -56,6 +57,7 @@ export default function InputWithSuffix({ px="$none" py="$none" scrollEnabled={false} + textAlignVertical="bottom" value={inputSuffix} /> ) : null} 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 d3d63dae014..66580e8076e 100644 --- a/apps/mobile/src/features/import/__snapshots__/GenericImportForm.test.tsx.snap +++ b/apps/mobile/src/features/import/__snapshots__/GenericImportForm.test.tsx.snap @@ -62,10 +62,10 @@ exports[`GenericImportForm renders a placeholder when there is no value 1`] = ` onChangeText={[Function]} onFocus={[Function]} onSubmitEditing={[Function]} - placeholderTextColor="#BFBFBF" + placeholderTextColor="#CECECE" returnKeyType="done" scrollEnabled={false} - selectionColor="#BFBFBF" + selectionColor="#CECECE" spellCheck={false} style={ { @@ -99,6 +99,7 @@ exports[`GenericImportForm renders a placeholder when there is no value 1`] = ` } } testID="import-account-input" + textAlignVertical="bottom" /> seed phrase diff --git a/apps/mobile/src/features/modals/ModalsState.ts b/apps/mobile/src/features/modals/ModalsState.ts index b13b4d7dabe..78f2e8bf558 100644 --- a/apps/mobile/src/features/modals/ModalsState.ts +++ b/apps/mobile/src/features/modals/ModalsState.ts @@ -18,6 +18,7 @@ export interface ModalsState { [ModalName.BackupReminder]: AppModalState [ModalName.BackupReminderWarning]: AppModalState [ModalName.KoreaCexTransferInfoModal]: AppModalState + [ModalName.HiddenTokenInfoModal]: 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 28790687edc..aca01e5cad5 100644 --- a/apps/mobile/src/features/modals/modalSlice.ts +++ b/apps/mobile/src/features/modals/modalSlice.ts @@ -17,6 +17,11 @@ type AccountSwitcherModalParams = { initialState?: undefined } +type HiddenTokenInfoModalParams = { + name: typeof ModalName.HiddenTokenInfoModal + initialState?: undefined +} + type KoreaCexTransferInfoModalParams = { name: typeof ModalName.KoreaCexTransferInfoModal initialState?: undefined @@ -100,6 +105,7 @@ export type OpenModalParams = | BackupReminderParams | BackupWarningParams | KoreaCexTransferInfoModalParams + | HiddenTokenInfoModalParams | ExchangeTransferModalParams | ExperimentsModalParams | ExploreModalParams diff --git a/apps/mobile/src/features/nfts/item/traits.tsx b/apps/mobile/src/features/nfts/item/traits.tsx index d093d28545a..6fa510fa022 100644 --- a/apps/mobile/src/features/nfts/item/traits.tsx +++ b/apps/mobile/src/features/nfts/item/traits.tsx @@ -8,7 +8,7 @@ import { NftAssetTrait } from 'uniswap/src/data/graphql/uniswap-data-api/__gener const formatTraitValue = (trait: NftAssetTrait): string | undefined => { if (!trait.value) { - return undefined + return } if (trait.name?.toLowerCase().split(' ').includes('date')) { diff --git a/apps/mobile/src/features/onboarding/BackupSpeedBumpModal.tsx b/apps/mobile/src/features/onboarding/BackupSpeedBumpModal.tsx index 22fd6830026..9a3dcae0782 100644 --- a/apps/mobile/src/features/onboarding/BackupSpeedBumpModal.tsx +++ b/apps/mobile/src/features/onboarding/BackupSpeedBumpModal.tsx @@ -19,7 +19,6 @@ export function BackupSpeedBumpModal({ backupType, onContinue, onClose }: Backup const { t } = useTranslation() const [checked, setChecked] = useState(false) - // eslint-disable-next-line consistent-return const { preview, title, description, disclaimer } = useMemo(() => { switch (backupType) { case BackupType.Cloud: diff --git a/apps/mobile/src/features/openai/OpenAIContext.tsx b/apps/mobile/src/features/openai/OpenAIContext.tsx index c8bb2d63d7e..961e1005102 100644 --- a/apps/mobile/src/features/openai/OpenAIContext.tsx +++ b/apps/mobile/src/features/openai/OpenAIContext.tsx @@ -71,7 +71,7 @@ async function handleRunStatus( if (run.status === 'completed') { processMessages() } else if (run.status === 'requires_action') { - await handleRequiresAction(threadId, run, processMessages, toolsMap) + return await handleRequiresAction(threadId, run, processMessages, toolsMap) } else { logger.debug('OpenAIContext.tsx', 'handleRunStatus', `Run did not complete: ${run.id}`) } @@ -400,7 +400,6 @@ function _OpenAIContextProvider({ children }: { children: React.ReactNode }): JS }) return listener.remove } - return undefined }, [mainThread, sendMessage]) const value = { diff --git a/apps/mobile/src/features/send/SendFormScreen.tsx b/apps/mobile/src/features/send/SendFormScreen.tsx index 0ef051d6f97..211291f8cef 100644 --- a/apps/mobile/src/features/send/SendFormScreen.tsx +++ b/apps/mobile/src/features/send/SendFormScreen.tsx @@ -21,7 +21,6 @@ import { TransactionModalInnerContainer, } from 'uniswap/src/features/transactions/TransactionModal/TransactionModal' import { useTransactionModalContext } from 'uniswap/src/features/transactions/TransactionModal/TransactionModalContext' -import { WalletChainId } from 'uniswap/src/types/chains' import { CurrencyField } from 'uniswap/src/types/currency' import { useSendContext } from 'wallet/src/features/transactions/contexts/SendContext' import { useActiveAccountAddressWithThrow } from 'wallet/src/features/wallet/hooks' @@ -70,7 +69,7 @@ function SendFormScreenContent({ hideContent }: { hideContent: boolean }): JSX.E > } isOpen={showViewOnlyModal} modalName={ModalName.SwapWarning} severity={WarningSeverity.Low} title={t('send.warning.viewOnly.title')} onClose={(): void => setShowViewOnlyModal(false)} - onAcknowledge={(): void => setShowViewOnlyModal(false)} + onConfirm={(): void => setShowViewOnlyModal(false)} /> diff --git a/apps/mobile/src/features/send/SendRecipientSelectFullScreen.tsx b/apps/mobile/src/features/send/SendRecipientSelectFullScreen.tsx index 3b2eccde9d8..61d38bf37f1 100644 --- a/apps/mobile/src/features/send/SendRecipientSelectFullScreen.tsx +++ b/apps/mobile/src/features/send/SendRecipientSelectFullScreen.tsx @@ -3,7 +3,6 @@ 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 { WalletChainId } from 'uniswap/src/types/chains' 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. @@ -35,7 +34,7 @@ function SendRecipientSelectFullScreenContent({ hideContent }: { hideContent: bo {!hideContent && ( } isOpen={showWarningModal} modalName={ModalName.SendWarning} severity={transferWarning.severity} title={transferWarning.title} onClose={(): void => setShowWarningModal(false)} - onAcknowledge={(): void => setShowWarningModal(false)} + onConfirm={(): void => setShowWarningModal(false)} /> )} diff --git a/apps/mobile/src/features/unitags/ChooseProfilePictureScreen.tsx b/apps/mobile/src/features/unitags/ChooseProfilePictureScreen.tsx index e16c5e21a65..420ded255fb 100644 --- a/apps/mobile/src/features/unitags/ChooseProfilePictureScreen.tsx +++ b/apps/mobile/src/features/unitags/ChooseProfilePictureScreen.tsx @@ -89,7 +89,6 @@ export function ChooseProfilePictureScreen({ entryPoint: OnboardingEntryPoint.FreshInstallOrReplace, }, }) - return Promise.resolve() } else { return attemptClaimUnitag() } diff --git a/apps/mobile/src/features/unitags/EditUnitagProfileScreen.tsx b/apps/mobile/src/features/unitags/EditUnitagProfileScreen.tsx index acfe9683ff3..31866670d16 100644 --- a/apps/mobile/src/features/unitags/EditUnitagProfileScreen.tsx +++ b/apps/mobile/src/features/unitags/EditUnitagProfileScreen.tsx @@ -14,7 +14,7 @@ import { DeleteUnitagModal } from 'src/components/unitags/DeleteUnitagModal' import { UnitagProfilePicture } from 'src/components/unitags/UnitagProfilePicture' import { HeaderRadial, solidHeaderProps } from 'src/features/externalProfile/ProfileHeader' import { Button, Flex, LinearGradient, ScrollView, Text, getUniconColors, useIsDarkMode, useSporeColors } from 'ui/src' -import { Ellipsis, Pen } from 'ui/src/components/icons' +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' @@ -271,7 +271,7 @@ export function EditUnitagProfileScreen({ route }: UnitagStackScreenProp - + ) : undefined diff --git a/packages/wallet/src/features/unitags/useUnitagClaimHandler.ts b/apps/mobile/src/features/unitags/useUnitagClaimHandler.ts similarity index 59% rename from packages/wallet/src/features/unitags/useUnitagClaimHandler.ts rename to apps/mobile/src/features/unitags/useUnitagClaimHandler.ts index 12cf6f3fc2a..62153976923 100644 --- a/packages/wallet/src/features/unitags/useUnitagClaimHandler.ts +++ b/apps/mobile/src/features/unitags/useUnitagClaimHandler.ts @@ -1,18 +1,21 @@ import { useCallback } from 'react' import { useDispatch, useSelector } from 'react-redux' -import { UnitagEventName } from 'uniswap/src/features/telemetry/constants' +import { navigate } from 'src/app/navigation/rootNavigation' +import { openModal } from 'src/features/modals/modalSlice' +import { ModalName, UnitagEventName } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' +import { MobileScreens, OnboardingScreens, UnitagEntryPoint, UnitagScreens } from 'uniswap/src/types/screens/mobile' import { selectHasCompletedUnitagsIntroModal } from 'wallet/src/features/behaviorHistory/selectors' import { setHasSkippedUnitagPrompt } from 'wallet/src/features/behaviorHistory/slice' export function useUnitagClaimHandler({ + address, + entryPoint, analyticsEntryPoint, - navigateToClaim, - navigateToIntro, }: { + address: string + entryPoint: Exclude analyticsEntryPoint: 'home' | 'settings' - navigateToClaim: () => void - navigateToIntro: () => void }): { handleClaim: () => void handleDismiss: () => void @@ -27,11 +30,22 @@ export function useUnitagClaimHandler({ }) if (hasCompletedUnitagsIntroModal) { - navigateToClaim() + navigate(MobileScreens.UnitagStack, { + screen: UnitagScreens.ClaimUnitag, + params: { + entryPoint, + address, + }, + }) } else { - navigateToIntro() + dispatch( + openModal({ + name: ModalName.UnitagsIntro, + initialState: { address, entryPoint }, + }), + ) } - }, [analyticsEntryPoint, hasCompletedUnitagsIntroModal, navigateToClaim, navigateToIntro]) + }, [address, analyticsEntryPoint, dispatch, entryPoint, hasCompletedUnitagsIntroModal]) const handleDismiss = useCallback(() => { sendAnalyticsEvent(UnitagEventName.UnitagBannerActionTaken, { diff --git a/apps/mobile/src/features/walletConnect/selectors.ts b/apps/mobile/src/features/walletConnect/selectors.ts index 49ce9484be8..3e97e6426d8 100644 --- a/apps/mobile/src/features/walletConnect/selectors.ts +++ b/apps/mobile/src/features/walletConnect/selectors.ts @@ -10,12 +10,12 @@ export const selectSessions = (address: Maybe) => (state: MobileState): WalletConnectSession[] | undefined => { if (!address) { - return undefined + return } const wcAccount = state.walletConnect.byAccount[address] if (!wcAccount) { - return undefined + return } return Object.values(wcAccount.sessions) @@ -27,12 +27,12 @@ export const makeSelectSessions = (): Selector) => address, (sessionsByAccount, address) => { if (!address) { - return undefined + return } const wcAccount = sessionsByAccount[address] if (!wcAccount) { - return undefined + return } return Object.values(wcAccount.sessions) diff --git a/apps/mobile/src/features/walletConnect/utils.ts b/apps/mobile/src/features/walletConnect/utils.ts index 44003a0dfa4..ceee1373455 100644 --- a/apps/mobile/src/features/walletConnect/utils.ts +++ b/apps/mobile/src/features/walletConnect/utils.ts @@ -43,7 +43,7 @@ export const getSessionNamespaces = ( */ export const getSupportedWalletConnectChains = (chains?: string[]): WalletChainId[] | undefined => { if (!chains) { - return undefined + return } return chains.map((chain) => getChainIdFromEIP155String(chain)).filter((c): c is WalletChainId => Boolean(c)) @@ -166,7 +166,6 @@ export const parseTransactionRequest = ( * `signTypedData` params are ordered as [account, message] * See https://docs.walletconnect.com/2.0/advanced/rpc-reference/ethereum-rpc#personal_sign */ -// eslint-disable-next-line consistent-return export function getAddressAndMessageToSign( ethMethod: EthSignMethod, params: Web3WalletTypes.SessionRequest['params']['request']['params'], diff --git a/apps/mobile/src/screens/ExternalProfileScreen.tsx b/apps/mobile/src/screens/ExternalProfileScreen.tsx index bacaffe39b7..9c34dcfd34d 100644 --- a/apps/mobile/src/screens/ExternalProfileScreen.tsx +++ b/apps/mobile/src/screens/ExternalProfileScreen.tsx @@ -117,7 +117,7 @@ export function ExternalProfileScreen({ {...sceneProps} indicatorStyle={TAB_STYLES.activeTabIndicator} navigationState={{ index: tabIndex, routes: tabs }} - pressColor="transparent" // Android only + pressColor={colors.surface3.val} // Android only renderLabel={({ route, focused }): JSX.Element => ( )} diff --git a/apps/mobile/src/screens/FiatOnRampScreen.tsx b/apps/mobile/src/screens/FiatOnRampScreen.tsx index 078e53e275b..f6bba12c962 100644 --- a/apps/mobile/src/screens/FiatOnRampScreen.tsx +++ b/apps/mobile/src/screens/FiatOnRampScreen.tsx @@ -59,7 +59,6 @@ import { CurrencyField } from 'uniswap/src/types/currency' import { FiatOnRampScreens } from 'uniswap/src/types/screens/mobile' import { currencyIdToAddress } from 'uniswap/src/utils/currencyId' import { truncateToMaxDecimals } from 'utilities/src/format/truncateToMaxDecimals' -import { isIOS } from 'utilities/src/platform' import { usePrevious } from 'utilities/src/react/hooks' import { DEFAULT_DELAY, useDebounce } from 'utilities/src/time/timing' import { useWalletNavigation } from 'wallet/src/contexts/WalletNavigationContext' @@ -238,6 +237,9 @@ export function FiatOnRampScreen({ navigation }: Props): JSX.Element { decimalPadRef.current?.updateDisabledKeys() } + // we only show loading when there are no errors and quote value is not empty + const buttonDisabled = selectTokenLoading || !!quotesError || !selectedQuote?.destinationAmount + const onContinue = (): void => { if (quotes && quoteCurrency?.currencyInfo?.currency) { setBaseCurrencyInfo(meldSupportedFiatCurrency) @@ -336,10 +338,6 @@ export function FiatOnRampScreen({ navigation }: Props): JSX.Element { }) } - // we only show loading when there are no errors and quote value is not empty - const buttonDisabled = - notAvailableInThisRegion || selectTokenLoading || !!quotesError || !selectedQuote?.destinationAmount - return ( @@ -406,8 +404,7 @@ export function FiatOnRampScreen({ navigation }: Props): JSX.Element { gap={isShortMobileDevice ? 0 : '$spacing8'} left={0} opacity={decimalPadReady ? 1 : 0} - // android devices require more bottom padding - pb={isShortMobileDevice && isIOS ? '$spacing4' : '$spacing24'} + pb={isShortMobileDevice ? '$spacing4' : '$spacing24'} position="absolute" px="$spacing24" right={0} diff --git a/apps/mobile/src/screens/HomeScreen.tsx b/apps/mobile/src/screens/HomeScreen.tsx index bd3a16d2fb4..95337cc68eb 100644 --- a/apps/mobile/src/screens/HomeScreen.tsx +++ b/apps/mobile/src/screens/HomeScreen.tsx @@ -550,7 +550,7 @@ export function HomeScreen(props?: AppStackScreenProp): JSX. {...sceneProps} indicatorStyle={TAB_STYLES.activeTabIndicator} navigationState={{ index: tabIndex, routes }} - pressColor="transparent" // Android only + pressColor={colors.surface3.val} // Android only renderLabel={renderTabLabel} style={[ TAB_STYLES.tabBar, diff --git a/apps/mobile/src/screens/Import/OnDeviceRecoveryScreen.tsx b/apps/mobile/src/screens/Import/OnDeviceRecoveryScreen.tsx index 4e7e29b2f44..b24f5deb3d5 100644 --- a/apps/mobile/src/screens/Import/OnDeviceRecoveryScreen.tsx +++ b/apps/mobile/src/screens/Import/OnDeviceRecoveryScreen.tsx @@ -75,7 +75,6 @@ export function OnDeviceRecoveryScreen({ if (mnemonicId !== selectedMnemonicId) { return Keyring.removeMnemonic(mnemonicId) } - return Promise.resolve() }), ) } @@ -87,7 +86,6 @@ export function OnDeviceRecoveryScreen({ if (!selectedRecoveryWalletInfos.find((walletInfo) => walletInfo.address === address)) { return Keyring.removePrivateKey(address) } - return Promise.resolve() }), ) } @@ -249,15 +247,15 @@ export function OnDeviceRecoveryScreen({ } isOpen={showConfirmationModal} modalName={ModalName.OnDeviceRecoveryConfirmation} severity={WarningSeverity.None} title={t('onboarding.import.onDeviceRecovery.warning.title')} onClose={onPressClose} - onAcknowledge={onPressConfirm} + onConfirm={onPressConfirm} /> diff --git a/apps/mobile/src/screens/Import/RestoreCloudBackupLoadingScreen.tsx b/apps/mobile/src/screens/Import/RestoreCloudBackupLoadingScreen.tsx index 89a9972ca64..1e61f6696ee 100644 --- a/apps/mobile/src/screens/Import/RestoreCloudBackupLoadingScreen.tsx +++ b/apps/mobile/src/screens/Import/RestoreCloudBackupLoadingScreen.tsx @@ -70,7 +70,7 @@ export function RestoreCloudBackupLoadingScreen({ navigation, route: { params } */ useEffect(() => { if (!isLoading) { - return undefined + return } const timer = setTimeout( () => { diff --git a/apps/mobile/src/screens/Import/RestoreCloudBackupPasswordScreen.tsx b/apps/mobile/src/screens/Import/RestoreCloudBackupPasswordScreen.tsx index 0e07be9c328..636d271199e 100644 --- a/apps/mobile/src/screens/Import/RestoreCloudBackupPasswordScreen.tsx +++ b/apps/mobile/src/screens/Import/RestoreCloudBackupPasswordScreen.tsx @@ -101,7 +101,6 @@ export function RestoreCloudBackupPasswordScreen({ navigation, route: { params } return () => clearTimeout(timer) } - return undefined }, [isLockedOut, lockoutMessage, remainingLockoutTime, dispatch]), ) diff --git a/apps/mobile/src/screens/Import/__snapshots__/RestoreCloudBackupPasswordScreen.test.tsx.snap b/apps/mobile/src/screens/Import/__snapshots__/RestoreCloudBackupPasswordScreen.test.tsx.snap index 243228dde41..49fd90fa8d9 100644 --- a/apps/mobile/src/screens/Import/__snapshots__/RestoreCloudBackupPasswordScreen.test.tsx.snap +++ b/apps/mobile/src/screens/Import/__snapshots__/RestoreCloudBackupPasswordScreen.test.tsx.snap @@ -274,10 +274,10 @@ exports[`RestoreCloudBackupPasswordScreen renders correctly 1`] = ` onFocus={[Function]} onSubmitEditing={[Function]} placeholder="Enter password" - placeholderTextColor="#BFBFBF" + placeholderTextColor="#CECECE" returnKeyType="done" secureTextEntry={true} - selectionColor="#BFBFBF" + selectionColor="#CECECE" style={ { "backgroundColor": "transparent", diff --git a/apps/mobile/src/screens/NFTCollectionScreen.tsx b/apps/mobile/src/screens/NFTCollectionScreen.tsx index d7592972e7e..027403ec605 100644 --- a/apps/mobile/src/screens/NFTCollectionScreen.tsx +++ b/apps/mobile/src/screens/NFTCollectionScreen.tsx @@ -43,7 +43,7 @@ const keyExtractor = (item: NFTItem | string, index: number): string => function gqlNFTAssetToNFTItem(data: NftCollectionScreenQuery | undefined): NFTItem[] | undefined { const items = data?.nftAssets?.edges?.flatMap((item) => item.node) if (!items) { - return undefined + return } return items.map((item): NFTItem => { diff --git a/apps/mobile/src/screens/Onboarding/ManualBackupScreen.tsx b/apps/mobile/src/screens/Onboarding/ManualBackupScreen.tsx index c8efde6818c..4974a571b9f 100644 --- a/apps/mobile/src/screens/Onboarding/ManualBackupScreen.tsx +++ b/apps/mobile/src/screens/Onboarding/ManualBackupScreen.tsx @@ -89,7 +89,7 @@ export function ManualBackupScreen({ navigation, route: { params } }: Props): JS useEffect(() => { if (view !== View.SeedPhrase) { - return undefined + return } const listener = addScreenshotListener(() => setShowScreenShotWarningModal(true)) @@ -135,11 +135,11 @@ export function ManualBackupScreen({ navigation, route: { params } }: Props): JS > setShowScreenShotWarningModal(false)} + onConfirm={(): void => setShowScreenShotWarningModal(false)} /> diff --git a/apps/mobile/src/screens/Onboarding/__snapshots__/BackupScreen.test.tsx.snap b/apps/mobile/src/screens/Onboarding/__snapshots__/BackupScreen.test.tsx.snap index 8937e59a106..077ed7331a8 100644 --- a/apps/mobile/src/screens/Onboarding/__snapshots__/BackupScreen.test.tsx.snap +++ b/apps/mobile/src/screens/Onboarding/__snapshots__/BackupScreen.test.tsx.snap @@ -737,7 +737,7 @@ exports[`BackupScreen renders backup options when none are completed 1`] = ` "borderWidth": 0, }, { - "color": "#BFBFBF", + "color": "#CECECE", "height": 20, "width": 20, }, @@ -748,7 +748,7 @@ exports[`BackupScreen renders backup options when none are completed 1`] = ` }, ] } - tintColor="#BFBFBF" + tintColor="#CECECE" vbHeight={24} vbWidth={24} > @@ -782,7 +782,7 @@ exports[`BackupScreen renders backup options when none are completed 1`] = ` maxFontSizeMultiplier={1.4} style={ { - "color": "#BFBFBF", + "color": "#CECECE", "fontFamily": "Basel Grotesk", "fontSize": 17, "fontWeight": "400", @@ -1539,7 +1539,7 @@ exports[`BackupScreen renders backup options when some are completed 1`] = ` "borderWidth": 0, }, { - "color": "#BFBFBF", + "color": "#CECECE", "height": 20, "width": 20, }, @@ -1550,7 +1550,7 @@ exports[`BackupScreen renders backup options when some are completed 1`] = ` }, ] } - tintColor="#BFBFBF" + tintColor="#CECECE" vbHeight={24} vbWidth={24} > @@ -1584,7 +1584,7 @@ exports[`BackupScreen renders backup options when some are completed 1`] = ` maxFontSizeMultiplier={1.4} style={ { - "color": "#BFBFBF", + "color": "#CECECE", "fontFamily": "Basel Grotesk", "fontSize": 17, "fontWeight": "400", diff --git a/apps/mobile/src/screens/SettingsCloudBackupStatus.tsx b/apps/mobile/src/screens/SettingsCloudBackupStatus.tsx index b625ba0c4a8..45876c184a3 100644 --- a/apps/mobile/src/screens/SettingsCloudBackupStatus.tsx +++ b/apps/mobile/src/screens/SettingsCloudBackupStatus.tsx @@ -135,15 +135,15 @@ export function SettingsCloudBackupStatus({ caption={t('settings.setting.backup.delete.warning', { cloudProviderName: getCloudProviderName(), })} - rejectText={t('common.button.close')} - acknowledgeText={t('common.button.delete')} + closeText={t('common.button.close')} + confirmText={t('common.button.delete')} isOpen={showBackupDeleteWarning} modalName={ModalName.ViewSeedPhraseWarning} title={t('settings.setting.backup.delete.confirm.title')} onClose={(): void => { setShowBackupDeleteWarning(false) }} - onAcknowledge={onConfirmDeleteBackup} + onConfirm={onConfirmDeleteBackup} > {associatedAccounts.length > 1 && ( diff --git a/apps/mobile/src/screens/TokenDetailsScreen.tsx b/apps/mobile/src/screens/TokenDetailsScreen.tsx index 16c07e9ea64..07058da59e7 100644 --- a/apps/mobile/src/screens/TokenDetailsScreen.tsx +++ b/apps/mobile/src/screens/TokenDetailsScreen.tsx @@ -34,8 +34,6 @@ import { TokenDetailsScreenQuery, useTokenDetailsScreenQuery, } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' -import { AssetType } from 'uniswap/src/entities/assets' -import { useSwappableTokenWithHighestBalance } from 'uniswap/src/features/bridging/hooks/useSwappableTokenWithHighestBalance' import { fromGraphQLChain } from 'uniswap/src/features/chains/utils' import { PortfolioBalance } from 'uniswap/src/features/dataApi/types' import { currencyIdToContractInput } from 'uniswap/src/features/dataApi/utils' @@ -143,9 +141,9 @@ export function TokenDetailsScreen({ route }: AppStackScreenProp ({ address: currencyIdToAddress(_currencyId), chain: currencyIdToChain(_currencyId), - currencyName: data?.token?.name, + currencyName: data?.token?.project?.name, }), - [_currencyId, data?.token?.name], + [_currencyId, data?.token?.project?.name], ) return ( @@ -188,7 +186,7 @@ function TokenDetails({ const token = data?.token const tokenLogoUrl = token?.project?.logoUrl - const tokenSymbol = token?.name + const tokenSymbol = token?.project?.name const currencyInfo = useCurrencyInfo(_currencyId) @@ -238,12 +236,6 @@ function TokenDetails({ const safetyLevel = token?.project?.safetyLevel - const swappableTokenWithHighestBalance = useSwappableTokenWithHighestBalance({ - currencyAddress, - currencyChainId, - otherChainBalances, - }) - const onPressSend = useCallback(() => { // Do not show warning modal speedbump if user is trying to send tokens they own navigateToSend({ currencyAddress, chainId: currencyChainId }) @@ -257,38 +249,12 @@ function TokenDetails({ } else if (safetyLevel !== SafetyLevel.Verified && !tokenWarningDismissed) { setActiveTransactionType(currencyField) setShowWarningModal(true) - } else if (swappableTokenWithHighestBalance && currencyField === CurrencyField.OUTPUT) { - // When clicking "Buy", if the user has a balance in another chain, we prepopulate the input token with that token. - setActiveTransactionType(undefined) - navigateToSwapFlow({ - initialState: { - exactCurrencyField: CurrencyField.INPUT, - input: { - address: currencyIdToAddress(swappableTokenWithHighestBalance.currencyInfo.currencyId), - chainId: swappableTokenWithHighestBalance.currencyInfo.currency.chainId, - type: AssetType.Currency, - }, - output: { - address: currencyAddress, - chainId: currencyChainId, - type: AssetType.Currency, - }, - exactAmountToken: '', - }, - }) } else { setActiveTransactionType(undefined) navigateToSwapFlow({ currencyField, currencyAddress, currencyChainId }) } }, - [ - currencyAddress, - currencyChainId, - navigateToSwapFlow, - safetyLevel, - swappableTokenWithHighestBalance, - tokenWarningDismissed, - ], + [currencyAddress, currencyChainId, navigateToSwapFlow, safetyLevel, tokenWarningDismissed], ) const onPressBuyFiatOnRamp = useCallback((): void => { @@ -401,13 +367,13 @@ function TokenDetails({ {currencyInfo && ( { + onAccept={onAcceptWarning} + onClose={(): void => { setActiveTransactionType(undefined) setShowWarningModal(false) }} - onAcknowledge={onAcceptWarning} /> )} diff --git a/apps/mobile/src/utils/useOpenBackupReminderModal.ts b/apps/mobile/src/utils/useOpenBackupReminderModal.ts index 77b7feceec4..30c478bdfce 100644 --- a/apps/mobile/src/utils/useOpenBackupReminderModal.ts +++ b/apps/mobile/src/utils/useOpenBackupReminderModal.ts @@ -41,7 +41,7 @@ export function useOpenBackupReminderModal(activeAccount: Account): void { useEffect(() => { if (!enableReminder) { - return undefined + return } if (shouldOpenBackupReminderModal && onboardingBackupExperimentEnabled && backupReminderLastSeenTs === undefined) { @@ -55,8 +55,6 @@ export function useOpenBackupReminderModal(activeAccount: Account): void { return () => clearTimeout(timeoutId) } - - return undefined }, [ dispatch, shouldOpenBackupReminderModal, diff --git a/apps/web/.env b/apps/web/.env index 43fa8b11cb0..4d399aa3ef4 100644 --- a/apps/web/.env +++ b/apps/web/.env @@ -4,12 +4,12 @@ REACT_APP_AMPLITUDE_PROXY_URL="https://interface.gateway.uniswap.org/v1/amplitud REACT_APP_AWS_API_ENDPOINT="https://beta.gateway.uniswap.org/v1/graphql" REACT_APP_AWS_REALTIME_ENDPOINT="wss://beta.realtime.gateway.uniswap.org/graphql" REACT_APP_AWS_REALTIME_TOKEN="realtime-3DDE0DA0-3408-4FD0-9DC3-5E285D70D29C" -REACT_APP_BNB_RPC_URL="" +REACT_APP_BNB_RPC_URL="https://rough-sleek-hill.bsc.quiknode.pro/413cc98cbc776cda8fdf1d0f47003583ff73d9bf" REACT_APP_INFURA_KEY="4bf032f2d38a4ed6bb975b80d6340847" -REACT_APP_QUICKNODE_MAINNET_RPC_URL="" -REACT_APP_QUICKNODE_ARBITRUM_RPC_URL="" -REACT_APP_QUICKNODE_ZORA_RPC_URL="" -REACT_APP_QUICKNODE_ZKSYNC_RPC_URL="" +REACT_APP_QUICKNODE_MAINNET_RPC_URL="https://magical-alien-tab.quiknode.pro/669e87e569a8277d3fbd9e202f9df93189f19f4c" +REACT_APP_QUICKNODE_ARBITRUM_RPC_URL="https://black-ultra-valley.arbitrum-mainnet.quiknode.pro/96d7122781cfdcbccf5377cf0c68187332891e79" +REACT_APP_QUICKNODE_ZORA_RPC_URL="https://sly-fabled-breeze.zora-mainnet.quiknode.pro/b9b1f6ade530f3f32c0da16e573fe09eb0eb9132" +REACT_APP_QUICKNODE_ZKSYNC_RPC_URL="https://weathered-young-theorem.zksync-mainnet.quiknode.pro/4cff937b0c3b9c95154711ba0e337052445ef316" REACT_APP_MOONPAY_API="https://api.moonpay.com" REACT_APP_MOONPAY_LINK="https://us-central1-uniswap-mobile.cloudfunctions.net/signMoonpayLinkV2?platform=web&env=staging" REACT_APP_MOONPAY_PUBLISHABLE_KEY="pk_test_DycfESRid31UaSxhI5yWKe1r5E5kKSz" diff --git a/apps/web/.env.production b/apps/web/.env.production index e280216f3d4..736d32a3a80 100644 --- a/apps/web/.env.production +++ b/apps/web/.env.production @@ -16,4 +16,3 @@ REACT_APP_STATSIG_PROXY_URL="https://interface.gateway.uniswap.org/v1/statsig-pr REACT_APP_QUICKNODE_MAINNET_RPC_URL="https://ultra-blue-flower.quiknode.pro/770b22d5f362c537bc8fe19b034c45b22958f880" REACT_APP_QUICKNODE_ARBITRUM_RPC_URL="https://tiniest-stylish-arrow.arbitrum-mainnet.quiknode.pro/d06833352b8de605914d9e24a390d8b4d3aff7ba" REACT_APP_IS_UNISWAP_INTERFACE=true -REACT_APP_TRADING_API_KEY=gcZrVL9FxqnqjVytJd2z3oqImkOKRjZ49sF7WXy9 diff --git a/apps/web/cypress/support/e2e.ts b/apps/web/cypress/support/e2e.ts index 6429dedb4a5..cd54cee8719 100644 --- a/apps/web/cypress/support/e2e.ts +++ b/apps/web/cypress/support/e2e.ts @@ -19,7 +19,7 @@ registerSetupTests() const log = Cypress.log Cypress.log = function (options, ...args) { if (options.displayName === 'script' || options.name === 'request') { - return undefined + return } return log(options, ...args) } as typeof log diff --git a/apps/web/package.json b/apps/web/package.json index 6c11ce94c1c..d0afbe03936 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -6,7 +6,7 @@ "scripts": { "ajv": "node scripts/compile-ajv-validators.js", "check:deps:usage": "depcheck", - "check:circular": "concurrently \"../../scripts/check-circular-imports.sh ./src/pages/App.tsx 5\" \"../../scripts/check-circular-imports.sh ./src/setupTests.ts 0\"", + "check:circular": "concurrently \"../../scripts/check-circular-imports.sh ./src/pages/App.tsx 6\" \"../../scripts/check-circular-imports.sh ./src/setupTests.ts 0\"", "sitemap:generate": "node scripts/generate-sitemap.js", "start": "craco start", "start:cloud": "NODE_OPTIONS=--dns-result-order=ipv4first PORT=3001 REACT_APP_SKIP_CSP=1 npx wrangler pages dev --compatibility-flags=nodejs_compat --compatibility-date=2023-08-01 --proxy=3001 --port=3000 -- yarn start", @@ -185,9 +185,9 @@ "@types/react-scroll-sync": "0.8.7", "@types/react-window-infinite-loader": "1.0.6", "@uniswap/analytics": "1.7.0", - "@uniswap/analytics-events": "2.37.0", + "@uniswap/analytics-events": "2.36.0", "@uniswap/client-explore": "0.0.9", - "@uniswap/client-pools": "0.0.3", + "@uniswap/client-pools": "0.0.0", "@uniswap/liquidity-staker": "1.0.2", "@uniswap/merkle-distributor": "1.0.1", "@uniswap/permit2-sdk": "1.3.0", @@ -196,7 +196,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.1.0-beta.14", + "@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", @@ -272,7 +272,6 @@ "styled-components": "5.3.11", "tamagui": "1.108.4", "tiny-invariant": "1.3.1", - "typed-redux-saga": "1.5.0", "ui": "workspace:^", "uniswap": "workspace:^", "use-resize-observer": "9.1.0", diff --git a/apps/web/public/nfts-sitemap.xml b/apps/web/public/nfts-sitemap.xml index 881dd414252..5d053264215 100644 --- a/apps/web/public/nfts-sitemap.xml +++ b/apps/web/public/nfts-sitemap.xml @@ -2,697 +2,647 @@ https://app.uniswap.org/nfts/collection/0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x60e4d786628fea6478f785a6d7e704777c86a7c6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xed5af388653567af2f388e6224dc7c4b3241c544 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x34d85c9cdeb23fa97cb08333b511ac86e1c4e258 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x99a9b7c1116f9ceeb1652de04d5969cce509b069 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x49cf6f5d44e70224e2e23fdcdd2c053f30ada28b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xb7f7f6c52f2e2fdb1963eab30438024864c313f6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x23581767a106ae21c074b2276d25e5c3e136a68b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x8a90cab2b38dba80c64b7734e58ee1db38b8992e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xba30e5f9bb24caa003e9f2f0497ad287fdf95623 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xbd3531da5cf5857e7cfaa92426877b022e612cf8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x7bd29408f11d2bfc23c34f18275bbf23bb716bc7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x306b1ea3ecdf94ab739f1910bbda052ed4a9f949 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x1a92f7381b9f03921564a437210bb9396471050c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x5cc5b05a8a13e3fbdb0bb9fccd98d38e50f90c38 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x5af0d9827e0c53e4799bb226655a1de152a425a5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x3bf2922f4520a8ba0c2efc3d2a1539678dad5e9d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xe785e82358879f061bc3dcac6f0444462d4b5330 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x76be3b62873462d2142405439777e971754e8e77 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xfd43af6d3fe1b916c026f6ac35b3ede068d1ca01 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x1cb1a5e65610aeff2551a50f76a87a7d3fb649c6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xff9c1b15b16263c61d017ee9f65c50e4ae0113d7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x6339e5e072086621540d0362c4e3cea0d643e114 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xb932a70a57673d89f4acffbe830e8ed7f75fb9e0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x79fcdef22feed20eddacbb2587640e45491b757f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xa3aee8bce55beea1951ef834b99f3ac60d1abeeb - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x769272677fab02575e84945f03eca517acc544cc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x4db1f25d3d98600140dfc18deb7515be5bd293af - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x34eebee6942d8def3c125458d1a86e0a897fd6f9 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x59468516a8259058bad1ca5f8f4bff190d30e066 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x394e3d3044fc89fcdd966d3cb35ac0b32b0cda91 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x60bb1e2aa1c9acafb4d34f71585d7e959f387769 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x28472a58a490c5e09a238847f66a68a47cc76f0f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x341a1c534248966c4b6afad165b98daed4b964ef - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x82c7a8f707110f5fbb16184a5933e9f78a34c6ab - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xccc441ac31f02cd96c153db6fd5fe0a2f4e6a68d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x764aeebcf425d56800ef2c84f2578689415a2daa - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x160c404b2b49cbc3240055ceaee026df1e8497a0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xd2f668a8461d6761115daf8aeb3cdf5f40c532c6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x39ee2c7b3cb80254225884ca001f57118c8f21b6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xd774557b647330c91bf44cfeab205095f7e6c367 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x1792a96e5668ad7c167ab804a100ce42395ce54d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xf87e31492faf9a91b02ee0deaad50d51d56d5d4d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x04afa589e2b933f9463c5639f412b183ec062505 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xe75512aa3bec8f00434bbd6ad8b0a3fbff100ad6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x348fc118bcc65a92dc033a951af153d14d945312 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x892848074ddea461a15f337250da3ce55580ca85 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x5946aeaab44e65eb370ffaa6a7ef2218cff9b47d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x282bdd42f4eb70e7a9d9f40c8fea0825b7f68c5d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x4b15a9c28034dc83db40cd810001427d3bd7163d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x7ea3cca10668b8346aec0bf1844a49e995527c8b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xb852c6b5892256c264cc2c888ea462189154d8d7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x9378368ba6b85c1fba5b131b530f5f5bedf21a18 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x2acab3dea77832c09420663b0e1cb386031ba17b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x0c2e57efddba8c768147d1fdf9176a0a6ebd5d83 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x08d7c0242953446436f34b4c78fe9da38c73668d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x8943c7bac1914c9a7aba750bf2b6b09fd21037e0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x364c828ee171616a39897688a831c2499ad972ec - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x7f36182dee28c45de6072a34d29855bae76dbe2f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xf61f24c2d93bf2de187546b14425bf631f28d6dc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x797a48c46be32aafcedcfd3d8992493d8a1f256b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x123b30e25973fecd8354dd5f41cc45a3065ef88c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x6632a9d63e142f17a668064d41a21193b49b41a0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xf4ee95274741437636e748ddac70818b4ed7d043 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x57a204aa1042f6e66dd7730813f4024114d74f37 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xd1258db6ac08eb0e625b75b371c023da478e94a9 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x75e95ba5997eb235f40ecf8347cdb11f18ff640b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xd532b88607b1877fe20c181cba2550e3bbd6b31c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xa1d4657e0e6507d5a94d06da93e94dc7c8c44b51 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xedb61f74b0d09b2558f1eeb79b247c1f363ae452 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x7d8820fa92eb1584636f4f5b8515b5476b75171a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x231d3559aa848bf10366fb9868590f01d34bf240 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xad9fd7cb4fc7a0fbce08d64068f60cbde22ed34c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x0e9d6552b85be180d941f1ca73ae3e318d2d4f1f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xb716600ed99b4710152582a124c697a7fe78adbf - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xaadc2d4261199ce24a4b0a57370c4fcf43bb60aa - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x4e1f41613c9084fdb9e34e11fae9412427480e56 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x79986af15539de2db9a5086382daeda917a9cf0c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xc99c679c50033bbc5321eb88752e89a93e9e83c5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xc36cf0cfcb5d905b8b513860db0cfe63f6cf9f5c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x9c8ff314c9bc7f6e59a9d9225fb22946427edc03 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x3110ef5f612208724ca51f5761a69081809f03b7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x036721e5a769cc48b3189efbb9cce4471e8a48b1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x524cab2ec69124574082676e6f654a18df49a048 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x7ab2352b1d2e185560494d5e577f9d3c238b78c5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x32973908faee0bf825a343000fe412ebe56f802a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x7daec605e9e2a1717326eedfd660601e2753a057 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xc1caf0c19a8ac28c41fe59ba6c754e4b9bd54de9 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x33fd426905f149f8376e227d0c9d3340aad17af1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x466cfcd0525189b573e794f554b8a751279213ac - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x6be69b2a9b153737887cfcdca7781ed1511c7e36 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x80336ad7a747236ef41f47ed2c7641828a480baa - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x9401518f4ebba857baa879d9f76e1cc8b31ed197 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x4b61413d4392c806e6d0ff5ee91e6073c21d6430 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xc3f733ca98e0dad0386979eb96fb1722a1a05e69 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x09233d553058c2f42ba751c87816a8e9fae7ef10 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x960b7a6bcd451c9968473f7bbfd9be826efd549a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x36d30b3b85255473d27dd0f7fd8f35e36a9d6f06 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x698fbaaca64944376e2cdc4cad86eaa91362cf54 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x497a9a79e82e6fc0ff10a16f6f75e6fcd5ae65a8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x41a322b28d0ff354040e2cbc676f0320d8c8850d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xa9c0a07a7cb84ad1f2ffab06de3e55aab7d523e8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x942bc2d3e7a589fe5bd4a5c6ef9727dfd82f5c8a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x8821bee2ba0df28761afff119d66390d594cd280 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x8c6def540b83471664edc6d5cf75883986932674 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x8d9710f0e193d3f95c0723eaaf1a81030dc9116d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x86825dfca7a6224cfbd2da48e85df2fc3aa7c4b1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x629a673a8242c2ac4b7b8c5d8735fbeac21a6205 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x9a534628b4062e123ce7ee2222ec20b86e16ca8f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xc2c747e0f7004f9e8817db2ca4997657a7746928 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x73da73ef3a6982109c4d5bdb0db9dd3e3783f313 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xc92ceddfb8dd984a89fb494c376f9a48b999aafc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x3248e8ba90facc4fdd3814518c14f8cc4d980e4b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x67d9417c9c3c250f61a83c7e8658dac487b56b09 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xb6a37b5d14d502c3ab0ae6f3a0e058bc9517786e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x86c10d10eca1fca9daf87a279abccabe0063f247 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x4b3406a41399c7fd2ba65cbc93697ad9e7ea61e5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xb0640e8b5f24bedc63c33d371923d68fde020303 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xd3d9ddd0cf0a5f0bfb8f7fceae075df687eaebab - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xa5c0bd78d1667c13bfb403e2a3336871396713c5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x4d7d2e237d64d1484660b55c0a4cc092fa5e6716 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xfcb1315c4273954f74cb16d5b663dbf479eec62e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x66d1db16101502ed0ca428842c619ca7b62c8fef - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x128675d4fddbc4a0d3f8aa777d8ee0fb8b427c2f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x19b86299c21505cdf59ce63740b240a9c822b5e4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xacf63e56fd08970b43401492a02f6f38b6635c91 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0x0bebad1ff25c623dff9605dad4a8f782d5da37df - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.7 https://app.uniswap.org/nfts/collection/0xdceaf1652a131f32a821468dc03a92df0edd86ea - 2024-09-20T21:06:11.923Z - 0.7 - - - https://app.uniswap.org/nfts/collection/0x273f7f8e6489682df756151f5525576e322d51a3 - 2024-09-20T21:06:11.923Z - 0.7 - - - https://app.uniswap.org/nfts/collection/0x77372a4cc66063575b05b44481f059be356964a4 - 2024-09-20T21:06:11.923Z - 0.7 - - - https://app.uniswap.org/nfts/collection/0xf5b0a3efb8e8e4c201e2a935f110eaaf3ffecb8d - 2024-09-20T21:06:11.923Z - 0.7 - - - https://app.uniswap.org/nfts/collection/0x22c36bfdcef207f9c0cc941936eff94d4246d14a - 2024-09-20T21:06:11.923Z - 0.7 - - - https://app.uniswap.org/nfts/collection/0x59325733eb952a92e069c87f0a6168b29e80627f - 2024-09-20T21:06:11.923Z - 0.7 - - - https://app.uniswap.org/nfts/collection/0x0e3a2a1f2146d86a604adc220b4967a898d7fe07 - 2024-09-20T21:06:11.923Z - 0.7 - - - https://app.uniswap.org/nfts/collection/0x3af2a97414d1101e2107a70e7f33955da1346305 - 2024-09-20T21:06:11.923Z - 0.7 - - - https://app.uniswap.org/nfts/collection/0x5ab21ec0bfa0b29545230395e3adaca7d552c948 - 2024-09-20T21:06:11.923Z - 0.7 - - - https://app.uniswap.org/nfts/collection/0x617913dd43dbdf4236b85ec7bdf9adfd7e35b340 - 2024-09-20T21:06:11.923Z - 0.7 - - - https://app.uniswap.org/nfts/collection/0x3fe1a4c1481c8351e91b64d5c398b159de07cbc5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 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 32c6ec25268..0903b0778ae 100644 --- a/apps/web/public/pools-sitemap.xml +++ b/apps/web/public/pools-sitemap.xml @@ -2,6507 +2,4357 @@ https://app.uniswap.org/explore/pools/ethereum/0xcbcdf9626bc03e24f779434178a73a0b4bad62ed - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x4e68ccd3e89f51c3074ca5072bbac773960dfa36 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x4585fe77225b41b697c938b018e2ac67ac5a20c0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xc63b0708e2f7e69cb8a1df0e1389a98c35a76d52 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x99ac8ca7087fa4a2a1fb6357269965a2014abc35 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x11b815efb8f581194ae79006d24e0d814b7697f6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xa6cc3c2531fdaa6ae1a3ca84c2855806728693e8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x5777d92f208679db4b9778590fa3cab3ac9e2168 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x1d42064fc4beb5f8aaf85f4617ae8b3b5b8bd801 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xc2e9f25be6257c210d7adf0d4cd6e3e881ba25f8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x11950d141ecb863f01007add7d1a342041227b58 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xc5c134a1f112efa96003f8559dba6fac0ba77692 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x109830a1aaad605bbf02a9dfa7b0b92ec2fb7daa - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x1df4c6e36d61416813b42fe32724ef11e363eddc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x12d6867fa648d269835cf69b49f125147754b54d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x3416cf6c708da44db2624d63ea0aaef7113527c6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xe8c6c9227491c0a8156a0106a0204d881bb7e531 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x04708077eca6bb527a5bbbd6358ffb043a9c1c14 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x9db9e0e53058c89e5b94e29621a205198648425b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xf239009a101b6b930a527deaab6961b6e7dec8a6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xfe0df74636bc25c7f2400f22fe7dae32d39443d2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xf4c5e0f4590b6679b3030d29a84857f226087fef - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x5764a6f2212d502bc5970f9f129ffcd61e5d7563 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xa3f558aebaecaf0e11ca4b2199cc5ed341edfd74 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x99132b53ab44694eeb372e87bced3929e4ab8456 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x6c6bc977e13df9b0de53b251522280bb72383700 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x9d96880952b4c80a55099b9c258250f2cc5813ec - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x3afdc5e6dfc0b0a507a8e023c9dce2cafc310316 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x290a6a7460b308ee3f19023d2d00de604bcf5b42 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xac4b3dacb91461209ae9d41ec517c2b9cb1b7daf - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x60594a405d53811d3bc4766596efd80fd545a270 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x331399c614ca67dee86733e5a2fba40dbb16827c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x4b5ab61593a2401b1075b90c04cbcdd3f87ce011 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x844eb5c280f38c7462316aad3f338ef9bda62668 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xe936f0073549ad8b1fa53583600d629ba9375161 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x2f62f2b4c5fcd7570a709dec05d68ea19c82a9ec - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x381fe4eb128db1621647ca00965da3f9e09f4fac - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x97e7d56a0408570ba1a7852de36350f7713906ec - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xcd423f3ab39a11ff1d9208b7d37df56e902c932b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xe15e6583425700993bd08f51bf6e7b73cd5da91b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x69d91b94f0aaf8e8a2586909fa77a5c2c89818d5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xe42318ea3b998e8355a3da364eb9d48ec725eb45 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xad9ef19e289dcbc9ab27b83d2df53cdeff60f02d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x3b685307c8611afb2a9e83ebc8743dc20480716e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x7bea39867e4169dbe237d55c8242a8f2fcdcc387 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x7b1e5d984a43ee732de195628d20d05cfabc3cc7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x7858e59e0c01ea06df3af3d20ac7b0003275d4bf - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xae2a25cbdb19d0dc0dddd1d2f6b08a6e48c4a9a9 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x21b8065d10f73ee2e260e5b47d3344d3ced7596e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x0d4a11d5eeaac28ec3f61d100daf4d40471f1852 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x517f9dd285e75b599234f7221227339478d0fcc8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xa43fe16908251ee70ef74718545e4fe6c5ccec9f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x0af81cd5d9c124b4859d65697a4cd10ee223746a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xca7c2771d248dcbe09eabe0ce57a62e18da178c0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x09d1d767edf8fa23a64c51fa559e0688e526812f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x7b73644935b8e68019ac6356c40661e1bc315860 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x180efc1349a69390ade25667487a826164c9c6e4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x9c4fe5ffd9a9fc5678cfbd93aa2d4fd684b67c4c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xa478c2975ab1ea89e8196811f51a7b7ade33eb11 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xbb2b8038a1640196fbe3e38816f3e67cba72d940 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x9ec9367b8c4dd45ec8e7b800b1f719251053ad60 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xc91ef786fbf6d62858262c82c63de45085dea659 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x197d7010147df7b99e9025c724f13723b29313f8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x25647e01bd0967c1b9599fa3521939871d1d0888 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x2f0b1417aa42ebf0b4ca1154212847f6094d708d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x6ada49aeccf6e556bb7a35ef0119cc8ca795294a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x2a6c340bcbb0a79d3deecd3bc5cbc2605ea9259f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xda2d09fbbf8ee4b5051a0e9b562c5fcb4b393b18 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x48d20b3e529fb3dd7d91293f80638df582ab2daa - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x4028daac072e492d34a3afdbef0ba7e35d8b55c4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xc2eab7d33d3cb97692ecb231a5d0e4a649cb539d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xc5be99a02c6857f9eac67bbce58df5572498f40c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xe4b8583ccb95b25737c016ac88e539d0605949e8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x8dbee21e8586ee356130074aaa789c33159921ca - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x43de4318b6eb91a7cf37975dbb574396a7b5b5c6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x9ff68f61ca5eb0c6606dc517a9d44001e564bb66 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xa29fe6ef9592b5d408cca961d0fb9b1faf497d6d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x1b1137dd16faa651e38a9dfb5d9ffff7767fdf62 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x470e8de2ebaef52014a47cb5e6af86884947f08c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x8fb8e9921922d2ffb529a95d28a0d06d275d7a59 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xd3d2e2692501a5c9ca623199d38826e513033a17 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x97e1fcb93ae7267dbafad23f7b9afaa08264cfd8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xa5e9c917b4b821e4e0a5bbefce078ab6540d6b5e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x2cc846fff0b08fb3bffad71f53a60b4b6e6d6482 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x959873fb4fc11825fba83c80c4c632db1e936e15 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xa7480aafa8ad2af3ce24ac6853f960ae6ac7f0c4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xc7e6b676bfc73ae40bcc4577f22aab1682c691c6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x570febdf89c07f256c75686caca215289bb11cfc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x343fd171caf4f0287ae6b87d75a8964dc44516ab - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xcaa004418eb42cdf00cb057b7c9e28f0ffd840a5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xe3d3551bb608e7665472180a20280630d9e938aa - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xb6b0c651c37ec4ca81c0a128420e02001a57fac2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x4e34da137f0b317c633838458e0c923a5e088752 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xfe9e7931e55c514c33d489c88582fa36e84bd8e3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x5281e311734869c64ca60ef047fd87759397efe6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x149148acc3b06b8cc73af3a10e84189243a35925 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x8ef79d6c328c25da633559c20c75f638a4863462 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x14af1804dbbf7d621ecc2901eef292a24a0260ea - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x80a9ae39310abf666a87c743d6ebbd0e8c42158e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc31e54c7a869b9fcbecc14363cf510d1c41fa443 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x2f5e87c9312fa29aed5c179e456625d79015299c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc6962004f452be9203591991d15f6b388e09e8d0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc6f780497a95e246eb9449f5e4770916dcd6396a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x641c00a822e8b671738d32a431a4fb6074e5c79d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x92c63d0e701caae670c9415d91c474f686298f00 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x1aeedd3727a6431b8f070c0afaa81cc74f273882 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xcda53b1f66614552f834ceef361a8d12a0b8dad8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x35218a1cbac5bbc3e57fd9bd38219d37571b3537 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x17c14d2c404d167802b16c450d3c99f88f2c4f4d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x468b88941e7cc0b88c1869d68ab6b570bcef62ff - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xdbaeb7f0dfe3a0aafd798ccecb5b22e708f7852c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x149e36e72726e0bcea5c59d40df2c43f60f5a22d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xbaaf1fc002e31cb12b99e4119e5e350911ec575b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xa67f72f21bd9f91db2da2d260590da5e6c437009 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x92fd143a8fa0c84e016c2765648b9733b0aa519e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x7cf803e8d82a50504180f417b8bc7a493c0a0503 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x81c48d31365e6b526f6bbadc5c9aafd822134863 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x446bf9748b4ea044dd759d9b9311c70491df8f29 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc82819f72a9e77e2c0c3a69b3196478f44303cf4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x50c7390dfdd3756139e6efb5a461c2eb7331ceb4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x1dfc1054e0e2a10e33c9ca21aad5aa8a1cce91e3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc91b7b39bbb2c733f0e7459348fd0c80259c8471 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x59d72ddb29da32847a4665d08ffc8464a7185fae - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x09ba302a3f5ad2bf8853266e271b005a5b3716fe - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xa77d77c9773c35e910acc2e30cefe52b54a58414 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x8da66e470403b3d3eee66c67e2c61fda6e248ad1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x2f020e708811c054f146eebcc4d5a215fd4eec26 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x7e7fb3cceca5f2ac952edf221fd2a9f62e411980 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x68c685fd52a56f04665b491d491355a624540e85 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xa8328bf492ba1b77ad6381b3f7567d942b000baf - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc0cf0f380ddb44dbcaf19a86d094c8bba3efa04a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xa169d1ab5c948555954d38700a6cdaa7a4e0c3a0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x1862200e8e7ce1c0827b792d0f9546156f44f892 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x05bbaaa020ff6bea107a9a1e06d2feb7bfd79ed2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xd02a4969dc12bb889754361f8bcf3385ac1b2077 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc24f7d8e51a64dc1238880bd00bb961d54cbeb29 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x7c06736e41236fecd681dd3353aa77ecd19ea565 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc473e2aee3441bf9240be85eb122abb059a3b57c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x14353445c8329df76e6f15e9ead18fa2d45a8bb6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x2039f8c9cd32ba9cd2ea7e575d5b1abea93f7527 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xd3e11119d2680c963f1cdcffece0c4ade823fb58 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x8e295789c9465487074a65b1ae9ce0351172393f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x97bca422ec0ee4851f2110ea743c1cd0a14835a1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xbe3ad6a5669dc0b8b12febc03608860c31e2eef6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x56ebd63a756b94d3de9cea194896b4920b64fb01 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xe2ddd33585b441b9245085588169f35108f85a6e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x84436a2af97f37018db116ae8e1b691666db3d00 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x21b8065d10f73ee2e260e5b47d3344d3ced7596e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x0d4a11d5eeaac28ec3f61d100daf4d40471f1852 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x517f9dd285e75b599234f7221227339478d0fcc8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xa43fe16908251ee70ef74718545e4fe6c5ccec9f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x0af81cd5d9c124b4859d65697a4cd10ee223746a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xca7c2771d248dcbe09eabe0ce57a62e18da178c0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x09d1d767edf8fa23a64c51fa559e0688e526812f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x7b73644935b8e68019ac6356c40661e1bc315860 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x180efc1349a69390ade25667487a826164c9c6e4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x9c4fe5ffd9a9fc5678cfbd93aa2d4fd684b67c4c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xa478c2975ab1ea89e8196811f51a7b7ade33eb11 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xbb2b8038a1640196fbe3e38816f3e67cba72d940 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x9ec9367b8c4dd45ec8e7b800b1f719251053ad60 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc91ef786fbf6d62858262c82c63de45085dea659 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x197d7010147df7b99e9025c724f13723b29313f8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x25647e01bd0967c1b9599fa3521939871d1d0888 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x2f0b1417aa42ebf0b4ca1154212847f6094d708d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x6ada49aeccf6e556bb7a35ef0119cc8ca795294a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x2a6c340bcbb0a79d3deecd3bc5cbc2605ea9259f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xda2d09fbbf8ee4b5051a0e9b562c5fcb4b393b18 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x48d20b3e529fb3dd7d91293f80638df582ab2daa - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x4028daac072e492d34a3afdbef0ba7e35d8b55c4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc2eab7d33d3cb97692ecb231a5d0e4a649cb539d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc5be99a02c6857f9eac67bbce58df5572498f40c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xe4b8583ccb95b25737c016ac88e539d0605949e8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x8dbee21e8586ee356130074aaa789c33159921ca - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x43de4318b6eb91a7cf37975dbb574396a7b5b5c6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x9ff68f61ca5eb0c6606dc517a9d44001e564bb66 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xa29fe6ef9592b5d408cca961d0fb9b1faf497d6d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x1b1137dd16faa651e38a9dfb5d9ffff7767fdf62 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x470e8de2ebaef52014a47cb5e6af86884947f08c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x8fb8e9921922d2ffb529a95d28a0d06d275d7a59 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xd3d2e2692501a5c9ca623199d38826e513033a17 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x97e1fcb93ae7267dbafad23f7b9afaa08264cfd8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xa5e9c917b4b821e4e0a5bbefce078ab6540d6b5e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x2cc846fff0b08fb3bffad71f53a60b4b6e6d6482 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x959873fb4fc11825fba83c80c4c632db1e936e15 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xa7480aafa8ad2af3ce24ac6853f960ae6ac7f0c4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xc7e6b676bfc73ae40bcc4577f22aab1682c691c6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x570febdf89c07f256c75686caca215289bb11cfc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x343fd171caf4f0287ae6b87d75a8964dc44516ab - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xcaa004418eb42cdf00cb057b7c9e28f0ffd840a5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xe3d3551bb608e7665472180a20280630d9e938aa - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xb6b0c651c37ec4ca81c0a128420e02001a57fac2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x4e34da137f0b317c633838458e0c923a5e088752 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xfe9e7931e55c514c33d489c88582fa36e84bd8e3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x5281e311734869c64ca60ef047fd87759397efe6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x149148acc3b06b8cc73af3a10e84189243a35925 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x8ef79d6c328c25da633559c20c75f638a4863462 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x68f5c0a2de713a54991e01858fd27a3832401849 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x4533bad2dc588f0fadf8d2e72386d4cd6a19b519 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x85149247691df622eaf1a8bd0cafd40bc45154a9 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x0392b358ce4547601befa962680bede836606ae2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x1c3140ab59d6caf9fa7459c6f83d4b52ba881d36 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xd1f1bad4c9e6c44dec1e9bf3b94902205c5cd6c3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x03af20bdaaffb4cc0a521796a223f7d85e2aac31 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x73b14a78a0d396c521f954532d43fd5ffe385216 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xac85eaf55e9c60ed40a683de7e549d23fdfbeb33 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x04f6c85a1b00f6d9b75f91fd23835974cc07e65c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x730691cdac3cbd4d41fc5eb9d8abbb0cea795b94 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x535541f1aa08416e69dc4d610131099fa2ae7222 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xfc1f3296458f9b2a27a0b91dd7681c4020e09d05 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x85c31ffa3706d1cce9d525a00f1c7d4a2911754c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xd52533a3309b393afebe3176620e8ccfb6159f8a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xff7fbdf7832ae524deda39ca402e03d92adff7a5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xb589969d38ce76d3d7aa319de7133bc9755fd840 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xf334f6104a179207ddacfb41fa3567feea8595c2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x1fb3cf6e48f1e7b10213e7b6d87d4c073c7fdb7b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xd4344ea0c5ade7e22b9b275f0bde7a145dec5a23 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x5b42a63d6741416ce9a7b9f4f16d8c9231ccddd4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x252cbdff917169775be2b552ec9f6781af95e7f6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x2ab22ac86b25bd448a4d9dc041bd2384655299c4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xc858a329bf053be78d6239c4a4343b8fbd21472b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xa73c628eaf6e283e26a7b1f8001cf186aa4c0e8e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xb533c12fb4e7b53b5524eab9b47d93ff6c7a456f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x2ae3d6096d8215ac2acddf30c60caa984ea5debe - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x19ea026886cbb7a900ecb2458636d72b5cae223b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x6f32061f59a21086c334d0d45f804089ce374aaf - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xfaf037caafa9620bfaebc04c298bf4a104963613 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xadb35413ec50e0afe41039eac8b930d313e94fa4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xe9e3893921de87b1194a8108f9d70c24bde71c27 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xf1f199342687a7d78bcc16fce79fa2665ef870e1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xf44acaa38be5e965c5ddf374e7a2ba270e580684 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x36e42931a765022790b797963e42c5522d6b585a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x5adba6c5589c50791dd65131df29677595c7efa7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x3249e3e3e4133ee18e65347daf586610cc265f54 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xca1b837c87c6563910c2befa48834fa2a8c3d72d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x6ef7b14bcd8d989cef8f8ec8ba4bf371b2ac95fd - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x37ffd11972128fd624337ebceb167c8c0a5115ff - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xe62bd99a9501ca33d98913105fc2bec5bae6e5dd - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xb2ac2e5a3684411254d58b1c5a542212b782114d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xb0efaf46a1de55c54f333f93b1f0641e73bc16d0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xd0fa3b5264ccde31e8b094b86bca4a1e97d3c603 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xad4c666fc170b468b19988959eb931a3676f0e9f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x790fde1fd6d2568050061a88c375d5c2e06b140b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xaefc1edaede6adadcdf3bb344577d45a80b19582 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xa8a5356ee5d02fe33d72355e4f698782f8f199e8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x55bc964fe3b0c8cc2d4c63d65f1be7aef9bb1a3c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x95d9d28606ee55de7667f0f176ebfc3215cfd9c0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x21b8065d10f73ee2e260e5b47d3344d3ced7596e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x0d4a11d5eeaac28ec3f61d100daf4d40471f1852 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x517f9dd285e75b599234f7221227339478d0fcc8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xa43fe16908251ee70ef74718545e4fe6c5ccec9f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x0af81cd5d9c124b4859d65697a4cd10ee223746a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xca7c2771d248dcbe09eabe0ce57a62e18da178c0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x09d1d767edf8fa23a64c51fa559e0688e526812f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x7b73644935b8e68019ac6356c40661e1bc315860 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x180efc1349a69390ade25667487a826164c9c6e4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x9c4fe5ffd9a9fc5678cfbd93aa2d4fd684b67c4c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xa478c2975ab1ea89e8196811f51a7b7ade33eb11 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xbb2b8038a1640196fbe3e38816f3e67cba72d940 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x9ec9367b8c4dd45ec8e7b800b1f719251053ad60 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xc91ef786fbf6d62858262c82c63de45085dea659 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x197d7010147df7b99e9025c724f13723b29313f8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x25647e01bd0967c1b9599fa3521939871d1d0888 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x2f0b1417aa42ebf0b4ca1154212847f6094d708d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x6ada49aeccf6e556bb7a35ef0119cc8ca795294a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x2a6c340bcbb0a79d3deecd3bc5cbc2605ea9259f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xda2d09fbbf8ee4b5051a0e9b562c5fcb4b393b18 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x48d20b3e529fb3dd7d91293f80638df582ab2daa - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x4028daac072e492d34a3afdbef0ba7e35d8b55c4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xc2eab7d33d3cb97692ecb231a5d0e4a649cb539d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xc5be99a02c6857f9eac67bbce58df5572498f40c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xe4b8583ccb95b25737c016ac88e539d0605949e8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x8dbee21e8586ee356130074aaa789c33159921ca - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x43de4318b6eb91a7cf37975dbb574396a7b5b5c6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x9ff68f61ca5eb0c6606dc517a9d44001e564bb66 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xa29fe6ef9592b5d408cca961d0fb9b1faf497d6d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x1b1137dd16faa651e38a9dfb5d9ffff7767fdf62 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x470e8de2ebaef52014a47cb5e6af86884947f08c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x8fb8e9921922d2ffb529a95d28a0d06d275d7a59 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xd3d2e2692501a5c9ca623199d38826e513033a17 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x97e1fcb93ae7267dbafad23f7b9afaa08264cfd8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xa5e9c917b4b821e4e0a5bbefce078ab6540d6b5e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x2cc846fff0b08fb3bffad71f53a60b4b6e6d6482 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x959873fb4fc11825fba83c80c4c632db1e936e15 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xa7480aafa8ad2af3ce24ac6853f960ae6ac7f0c4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xc7e6b676bfc73ae40bcc4577f22aab1682c691c6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x570febdf89c07f256c75686caca215289bb11cfc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x343fd171caf4f0287ae6b87d75a8964dc44516ab - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xcaa004418eb42cdf00cb057b7c9e28f0ffd840a5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xe3d3551bb608e7665472180a20280630d9e938aa - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xb6b0c651c37ec4ca81c0a128420e02001a57fac2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x4e34da137f0b317c633838458e0c923a5e088752 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xfe9e7931e55c514c33d489c88582fa36e84bd8e3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x5281e311734869c64ca60ef047fd87759397efe6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x149148acc3b06b8cc73af3a10e84189243a35925 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x8ef79d6c328c25da633559c20c75f638a4863462 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x45dda9cb7c25131df268515131f647d726f50608 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x50eaedb835021e4a108b7290636d62e9765cc6d7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x167384319b41f7094e62f7506409eb38079abff8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa374094527e1673a86de625aa59517c5de346d32 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x86f1d8390222a3691c28938ec7404a1661e618e0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xeda1094f59a4781456734e5d258b95e6be20b983 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x847b64f9d3a95e977d157866447a5c0a5dfa0ee5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x94ab9e4553ffb839431e37cc79ba8905f45bfbea - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x0e44ceb592acfc5d3f09d996302eb4c499ff8c10 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x1e5bd2ab4c308396c06c182e1b7e7ba8b2935b83 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x9b08288c3be4f62bbf8d1c20ac9c5e6f9467d8b7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xb6e57ed85c4c9dbfef2a68711e9d6f36c56e0fcb - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x3e31ab7f37c048fc6574189135d108df80f0ea26 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xd36ec33c8bed5a9f7b6630855f1533455b98a418 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xdac8a8e6dbf8c690ec6815e0ff03491b2770255d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xfe343675878100b344802a6763fd373fdeed07a4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x0a28c2f5e0e8463e047c203f00f649812ae67e4f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x88f3c15523544835ff6c738ddb30995339ad57d6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x98b9162161164de1ed182a0dfa08f5fbf0f733ca - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xeef1a9507b3d505f0062f2be9453981255b503c8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xc4c06c9a239f94fc0a1d3e04d23c159ebe8316f1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x849ec65748107aedc518dbc42961f358ea1361a7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x2db87c4831b2fec2e35591221455834193b50d1b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa4d8c89f0c20efbe54cba9e7e7a7e509056228d9 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x642f28a89fa9d0fa30e664f71804bfdd7341d21f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x2aceda63b5e958c45bd27d916ba701bc1dc08f7a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x781067ef296e5c4a4203f81c593274824b7c185d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x4ccd010148379ea531d6c587cfdd60180196f9b1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xd866fac7db79994d08c0ca2221fee08935595b4b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x941061770214613ba0ca3db9a700c39587bb89b6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa9077cdb3d13f45b8b9d87c43e11bce0e73d8631 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa01f64fa1b923dd9c5c7618b39a6ba8098a88863 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa830ff28bb7a46570a7e43dc24a35a663b9cfc2e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x8837a61644d523cbe5216dde226f8f85e3aa9be3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xca5d44977d6de1846530eb434167b208752fba7d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x4d05f2a005e6f36633778416764e82d1d12e7fbb - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x41e64a5bc929fa8e6a9c8d7e3b81a13b21ff3045 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x3ea34cfc9322273311f7843826a2581c4a00fd39 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x785061ed819414dc4269d2a5d5974069c0daea96 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x3f5228d0e7d75467366be7de2c31d0d098ba2c23 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x2e3f22e9a1c2470b2e293351f48c99e1fd788f32 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x2a08c38c7e1fa969325e2b64047abb085dec3756 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xe6c36eed27c2e8ecb9a233bf12da06c9730b5955 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xefa98fdf168f372e5e9e9b910fcdfd65856f3986 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x76fa081e510f43ac8335efdb4db88c9ff1894413 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xc6832ef0af793336aa44a936e54b992bff47e7cd - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x865f456479a21e2b3d866561d7171a3d0a7b112d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xbd934a7778771a7e2d9bf80596002a214d8c9304 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x9ab9f658104467604b5afa9a3e1df62f35f7b208 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x6e430d59ba145c59b73a6db674fe3d53c1f31cae - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x21b8065d10f73ee2e260e5b47d3344d3ced7596e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x0d4a11d5eeaac28ec3f61d100daf4d40471f1852 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x517f9dd285e75b599234f7221227339478d0fcc8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa43fe16908251ee70ef74718545e4fe6c5ccec9f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x0af81cd5d9c124b4859d65697a4cd10ee223746a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xca7c2771d248dcbe09eabe0ce57a62e18da178c0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x09d1d767edf8fa23a64c51fa559e0688e526812f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x7b73644935b8e68019ac6356c40661e1bc315860 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x180efc1349a69390ade25667487a826164c9c6e4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x9c4fe5ffd9a9fc5678cfbd93aa2d4fd684b67c4c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa478c2975ab1ea89e8196811f51a7b7ade33eb11 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xbb2b8038a1640196fbe3e38816f3e67cba72d940 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x9ec9367b8c4dd45ec8e7b800b1f719251053ad60 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xc91ef786fbf6d62858262c82c63de45085dea659 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x197d7010147df7b99e9025c724f13723b29313f8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x25647e01bd0967c1b9599fa3521939871d1d0888 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x2f0b1417aa42ebf0b4ca1154212847f6094d708d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x6ada49aeccf6e556bb7a35ef0119cc8ca795294a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x2a6c340bcbb0a79d3deecd3bc5cbc2605ea9259f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xda2d09fbbf8ee4b5051a0e9b562c5fcb4b393b18 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x48d20b3e529fb3dd7d91293f80638df582ab2daa - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x4028daac072e492d34a3afdbef0ba7e35d8b55c4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xc2eab7d33d3cb97692ecb231a5d0e4a649cb539d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xc5be99a02c6857f9eac67bbce58df5572498f40c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xe4b8583ccb95b25737c016ac88e539d0605949e8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x8dbee21e8586ee356130074aaa789c33159921ca - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x43de4318b6eb91a7cf37975dbb574396a7b5b5c6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x9ff68f61ca5eb0c6606dc517a9d44001e564bb66 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa29fe6ef9592b5d408cca961d0fb9b1faf497d6d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x1b1137dd16faa651e38a9dfb5d9ffff7767fdf62 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x470e8de2ebaef52014a47cb5e6af86884947f08c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x8fb8e9921922d2ffb529a95d28a0d06d275d7a59 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xd3d2e2692501a5c9ca623199d38826e513033a17 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x97e1fcb93ae7267dbafad23f7b9afaa08264cfd8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa5e9c917b4b821e4e0a5bbefce078ab6540d6b5e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x2cc846fff0b08fb3bffad71f53a60b4b6e6d6482 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x959873fb4fc11825fba83c80c4c632db1e936e15 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa7480aafa8ad2af3ce24ac6853f960ae6ac7f0c4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xc7e6b676bfc73ae40bcc4577f22aab1682c691c6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x570febdf89c07f256c75686caca215289bb11cfc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x343fd171caf4f0287ae6b87d75a8964dc44516ab - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xcaa004418eb42cdf00cb057b7c9e28f0ffd840a5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xe3d3551bb608e7665472180a20280630d9e938aa - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xb6b0c651c37ec4ca81c0a128420e02001a57fac2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x4e34da137f0b317c633838458e0c923a5e088752 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xfe9e7931e55c514c33d489c88582fa36e84bd8e3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x5281e311734869c64ca60ef047fd87759397efe6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x149148acc3b06b8cc73af3a10e84189243a35925 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x8ef79d6c328c25da633559c20c75f638a4863462 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x9e37cb775a047ae99fc5a24dded834127c4180cd - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x48413707b70355597404018e7c603b261fcadf3f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xade9bcd4b968ee26bed102dd43a55f6a8c2416df - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xda679706ff21114ac9fac5198bff24543f357a16 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xba3f945812a83471d709bce9c3ca699a19fb46f7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xc9034c3e7f58003e6ae0c8438e7c8f4598d5acaa - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x4c36388be6f416a29c8d8eee81c771ce6be14b18 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xa1b2457c0b627f97f6cc892946a382451e979014 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x4b0aaf3ebb163dd45f663b38b6d93f6093ebc2d3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xae2ce200bdb67c472030b31f602f0756c9aeb61c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x3bc5180d5439b500f381f9a46f15dd6608101671 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x5122e02898ece3bc62df8c1efdb29a9e914244d3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x24e1cbd6fed006ceed9af0dce688acc7951d57a9 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x2556230ac694093d4d3b7b965a2f2d77d4c403a4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xdaca082c2c7d052a96fa83ea9d3a7b6839e39586 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xa555149210075702a734968f338d5e1cbd509354 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x10648ba41b8565907cfa1496765fa4d95390aa0d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x00bcec1526dae1e170a53017b8775a93b7810d7c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x20e068d76f9e90b90604500b84c7e19dcb923e7e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x6b93950a9b589bc32b82a5df4e5148f98a7fae27 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xd9caa6dbe6791fcb7fc9fb59d1a6b3dd8c1c2339 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x62e81e93136ac42a1ada48d4098f5f9e703e7455 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x84206d33845c9d811438b6fe4e7a0c634748dc50 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xd0b53d9277642d899df5c87a3966a349a798f224 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xcfa7c4bb565915f1c4f9475e2a0536d31efad776 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xa7de21f28ca460b45373b217cd4eb111c3faeff8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xb64dff20dd5c47e6dbb56ead80d23568006dec1e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xad4e969f4193878e5cc89cefb57faf6c7c0048da - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xdf5eb97e3e23ca7f5a5fd2264680377c211310ba - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xf16baaae8eb7b37f4280e72924479f69e7a61f32 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xe745a591970e0fa981204cf525e170a2b9e4fb93 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x64b74c66b9ba60ca668b781289767ae7298f37ae - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x17e1ebd791e7253a5e606fd94c5b66c14d873136 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x46715bd57b9ec01deadb35fe096fb44acda79414 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x3447accd4b8e735329d1065244aad2ed630f0122 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x2feb7f3ffc243f7de94d5ea5975533d301584e07 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x0d5959a52e7004b601f0be70618d01ac3cdce976 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x2170ca774e48a3f51559917ada6f9d7ae8f7bfea - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x62a76dfa8951aefcff787e790782db3633ebf422 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x8073679e0b3b2d1d665777cf1b2b5b1c2d3d2d0c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x143f1a6f3fb32e6ab3f22d3cc6b417b5c2197599 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x82ad659c2f152aad59bb37cbc5e7663a2de0c607 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xa4efe9e8e2a2d5a2ac46805f233b8e49d0e11955 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xfcc89a1f250d76de198767d33e1ca9138a7fb54b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x2faa2b42b782d578a160f61bb7cd763a17476730 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xdd44c0e83c2570062d1e6fdd440b4724862e8f31 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xe3930a14641786e123e7bbe842d701fa1cbfe2df - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x6d03360ce4764e862ed81660c1f76cc2711b14b6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xc055f66f228105072315247785c00299d0ce27e8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xcae1d141ab11cef0a415cf0440025e1e5e962e06 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x21b8065d10f73ee2e260e5b47d3344d3ced7596e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x0d4a11d5eeaac28ec3f61d100daf4d40471f1852 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x517f9dd285e75b599234f7221227339478d0fcc8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xa43fe16908251ee70ef74718545e4fe6c5ccec9f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x0af81cd5d9c124b4859d65697a4cd10ee223746a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xca7c2771d248dcbe09eabe0ce57a62e18da178c0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x09d1d767edf8fa23a64c51fa559e0688e526812f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x7b73644935b8e68019ac6356c40661e1bc315860 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x180efc1349a69390ade25667487a826164c9c6e4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x9c4fe5ffd9a9fc5678cfbd93aa2d4fd684b67c4c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xa478c2975ab1ea89e8196811f51a7b7ade33eb11 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xbb2b8038a1640196fbe3e38816f3e67cba72d940 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x9ec9367b8c4dd45ec8e7b800b1f719251053ad60 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xc91ef786fbf6d62858262c82c63de45085dea659 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x197d7010147df7b99e9025c724f13723b29313f8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x25647e01bd0967c1b9599fa3521939871d1d0888 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x2f0b1417aa42ebf0b4ca1154212847f6094d708d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x6ada49aeccf6e556bb7a35ef0119cc8ca795294a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x2a6c340bcbb0a79d3deecd3bc5cbc2605ea9259f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xda2d09fbbf8ee4b5051a0e9b562c5fcb4b393b18 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x48d20b3e529fb3dd7d91293f80638df582ab2daa - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x4028daac072e492d34a3afdbef0ba7e35d8b55c4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xc2eab7d33d3cb97692ecb231a5d0e4a649cb539d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xc5be99a02c6857f9eac67bbce58df5572498f40c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xe4b8583ccb95b25737c016ac88e539d0605949e8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x8dbee21e8586ee356130074aaa789c33159921ca - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x43de4318b6eb91a7cf37975dbb574396a7b5b5c6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x9ff68f61ca5eb0c6606dc517a9d44001e564bb66 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xa29fe6ef9592b5d408cca961d0fb9b1faf497d6d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x1b1137dd16faa651e38a9dfb5d9ffff7767fdf62 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x470e8de2ebaef52014a47cb5e6af86884947f08c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x8fb8e9921922d2ffb529a95d28a0d06d275d7a59 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xd3d2e2692501a5c9ca623199d38826e513033a17 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x97e1fcb93ae7267dbafad23f7b9afaa08264cfd8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xa5e9c917b4b821e4e0a5bbefce078ab6540d6b5e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x2cc846fff0b08fb3bffad71f53a60b4b6e6d6482 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x959873fb4fc11825fba83c80c4c632db1e936e15 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xa7480aafa8ad2af3ce24ac6853f960ae6ac7f0c4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xc7e6b676bfc73ae40bcc4577f22aab1682c691c6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x570febdf89c07f256c75686caca215289bb11cfc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x343fd171caf4f0287ae6b87d75a8964dc44516ab - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xcaa004418eb42cdf00cb057b7c9e28f0ffd840a5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xe3d3551bb608e7665472180a20280630d9e938aa - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xb6b0c651c37ec4ca81c0a128420e02001a57fac2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x4e34da137f0b317c633838458e0c923a5e088752 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xfe9e7931e55c514c33d489c88582fa36e84bd8e3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x5281e311734869c64ca60ef047fd87759397efe6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x149148acc3b06b8cc73af3a10e84189243a35925 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x8ef79d6c328c25da633559c20c75f638a4863462 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x0f338ec12d3f7c3d77a4b9fcc1f95f3fb6ad0ea6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x4eaa90264d6a3567228dcb5cfc242200da586437 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x6fe9e9de56356f7edbfcbb29fab7cd69471a4869 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xf420603317a0996a3fce1b1a80993eaef6f7ae1a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x47a90a2d92a8367a91efa1906bfc8c1e05bf10c4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x41bf5eeae051fbd2e97b76b5f8f0fdcc1a1e526b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x28df0835942396b7a1b7ae1cd068728e6ddbbafd - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xa3f3664a52f01b42557524bd14556e379daf5669 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x1fd22fa7274bafebdfb1881321709f1219744829 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xe39cfc1a2e51a09ecbd060a24ee4eef5a97697bb - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x06396509195eb9e07c38a016694dc9ff535b128a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x5a1c486edefda2f09d3b349fadc38524f1743826 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x5bf1cf153c102a79d9e18b7fb7c79ba57fa70d0c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x2c3c320d49019d4f9a92352e947c7e5acfe47d68 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x4141325bac36affe9db165e854982230a14e6d48 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x17507bef4c3abc1bc715be723ee1baf571256e05 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x8149b92ea743cc382aada523b68b8834733b9015 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xc98f01bf2141e1140ef8f8cad99d4b021d10718f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x7f9d307973cdabe42769d9712df8ee1cc1a28d10 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x5c87da28a45e5089b762dcbbd86f743d14c54317 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x2cd97604ef77bbcb1fa0cff47545dff8ec7def08 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x7862d9b4be2156b15d54f41ee4ede2d5b0b455e4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x554548b404213c7efcdbab933f52edfe3c581834 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x63008c5ea4e47f5421e0e1428b1c5043a507d0d0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x0350ca994791c4b07a5b02b08aaf9d6fc8ab510e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x32776ed4d96ed069a2d812773f0ad8ad9ef83cf8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x84f3ca9b7a1579ff74059bd0e8929424d3fa330e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x5289a8dbf7029ee0b0498a84777ed3941d9acfec - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xb2bc284ab4c953b7f7a06d59c0ceb2de26405f22 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x508acf810857fefa86281499068ad5d19ebce325 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xccdfcd1aac447d5b29980f64b831c532a6a33726 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x4fb87838a29b37598099ef5aa6b3fbeeef987c50 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x515e94dc736b9d8b7d28ecf1cece0aba3d75da97 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xfd6e5b7c30538dff2752058e425ad01a56b831cc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xcb99fe720124129520f7a09ca3cbef78d58ed934 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xd2f21358c1549be193537b2a4c5dc7f0228ae011 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x93094ed1c907e4bca7eb041cb659da94f7e1b58e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xd37e6ecb991d1a0e7610c89666817665713362a7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x73234630bd159384c8d43f145407312d64614f43 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xad1ddf00c4ae50573e4dc98e6c5ee93baa04a0c4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xa765593c821f7df9ad81119509a37961e7ffa6c5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x9b501a7ad3087d603ceb34424b7b2a6c348ad0b7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xafebb7cfa1a15fcac4121b609b456cbce3137c20 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x0adaf134ae0c4583b3a38fc3168a83e33162651e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xf9878a5dd55edc120fde01893ea713a4f032229c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x84e47c7f2fe86f6b5efbe14fee46b8bb871b2e05 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xf3e5bec78654049990965f666b0612e116b94fb2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x33e59edd3214e97cb68450c6d3d6c167de072aba - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x2ca76c7e466e560e0cb11a91269bb953e41254bc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xbb124e35ab9e85f8d59ba83500e559dc052b9368 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x21b8065d10f73ee2e260e5b47d3344d3ced7596e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x0d4a11d5eeaac28ec3f61d100daf4d40471f1852 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x517f9dd285e75b599234f7221227339478d0fcc8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xa43fe16908251ee70ef74718545e4fe6c5ccec9f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x0af81cd5d9c124b4859d65697a4cd10ee223746a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xca7c2771d248dcbe09eabe0ce57a62e18da178c0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x09d1d767edf8fa23a64c51fa559e0688e526812f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x7b73644935b8e68019ac6356c40661e1bc315860 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x180efc1349a69390ade25667487a826164c9c6e4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x9c4fe5ffd9a9fc5678cfbd93aa2d4fd684b67c4c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xa478c2975ab1ea89e8196811f51a7b7ade33eb11 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xbb2b8038a1640196fbe3e38816f3e67cba72d940 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x9ec9367b8c4dd45ec8e7b800b1f719251053ad60 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xc91ef786fbf6d62858262c82c63de45085dea659 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x197d7010147df7b99e9025c724f13723b29313f8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x25647e01bd0967c1b9599fa3521939871d1d0888 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x2f0b1417aa42ebf0b4ca1154212847f6094d708d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x6ada49aeccf6e556bb7a35ef0119cc8ca795294a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x2a6c340bcbb0a79d3deecd3bc5cbc2605ea9259f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xda2d09fbbf8ee4b5051a0e9b562c5fcb4b393b18 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x48d20b3e529fb3dd7d91293f80638df582ab2daa - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x4028daac072e492d34a3afdbef0ba7e35d8b55c4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xc2eab7d33d3cb97692ecb231a5d0e4a649cb539d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xc5be99a02c6857f9eac67bbce58df5572498f40c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xe4b8583ccb95b25737c016ac88e539d0605949e8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x8dbee21e8586ee356130074aaa789c33159921ca - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x43de4318b6eb91a7cf37975dbb574396a7b5b5c6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x9ff68f61ca5eb0c6606dc517a9d44001e564bb66 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xa29fe6ef9592b5d408cca961d0fb9b1faf497d6d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x1b1137dd16faa651e38a9dfb5d9ffff7767fdf62 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x470e8de2ebaef52014a47cb5e6af86884947f08c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x8fb8e9921922d2ffb529a95d28a0d06d275d7a59 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xd3d2e2692501a5c9ca623199d38826e513033a17 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x97e1fcb93ae7267dbafad23f7b9afaa08264cfd8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xa5e9c917b4b821e4e0a5bbefce078ab6540d6b5e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x2cc846fff0b08fb3bffad71f53a60b4b6e6d6482 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x959873fb4fc11825fba83c80c4c632db1e936e15 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xa7480aafa8ad2af3ce24ac6853f960ae6ac7f0c4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xc7e6b676bfc73ae40bcc4577f22aab1682c691c6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x570febdf89c07f256c75686caca215289bb11cfc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x343fd171caf4f0287ae6b87d75a8964dc44516ab - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xcaa004418eb42cdf00cb057b7c9e28f0ffd840a5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xe3d3551bb608e7665472180a20280630d9e938aa - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xb6b0c651c37ec4ca81c0a128420e02001a57fac2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x4e34da137f0b317c633838458e0c923a5e088752 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xfe9e7931e55c514c33d489c88582fa36e84bd8e3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x5281e311734869c64ca60ef047fd87759397efe6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x149148acc3b06b8cc73af3a10e84189243a35925 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x8ef79d6c328c25da633559c20c75f638a4863462 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xd88d5f9e6c10e6febc9296a454f6c2589b1e8fae - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xb90fe7da36ac89448e6dfd7f2bb1e90a66659977 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xbd6313d0796984c578cae6bc5b5e23b27c5540c5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x1f18cd7d1c7ba0dbe3d9abe0d3ec84ce1ad10066 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x7da99753ff017f1b7afb2c8c0542718dc9f15f21 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x079e7a44f42e9cd2442c3b9536244be634e8f888 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x1c8dafd358d308b880f71edb5170b010b106ca60 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xbd0f6f34baa3c1329448a69bab90111a20756f01 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x3420720e561f3082f1e514a4545f0f2e0c955a5d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xea3fb6e3313a2a90757e4ca3d6749efd0107b0b6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xf130f72f8190f662522774c3367e6e8814f5e219 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x4a46c053bd5c10a959aea258228217b9d3405f3d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xb83258bf5940c98abf54f26c5a02710bd6b83b2c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x6a209c5329f0a225fa1890d4177823c096016f34 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xdb24905b1b080f65dedb0ad978aad5c76363d3c6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xddff2cdad11898b901a661e32e9fa010780263a0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x72dd8fe09b5b493012e5816068dfc6fb26a2a9e6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x54fc722a66abfb6500a36d8b7b2646129d0e836a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x53b612b32233c80ec439a64325a29766ce95be7f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xe5edcbe72d1bc223097a1bed1fe6c0e404b4290c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xb928c37b8bd9754d321dc3d3c6ef374d332fe761 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x2d70cbabf4d8e61d5317b62cbe912935fd94e0fe - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x953e2937f0515c43ca7995e80c84aedcbbb9385e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x84394d80830ae963b599ded7d9149b90059f182f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xa1777e082fa1746eb78dd9c1fbb515419cf6e538 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x112466c8b6e5abe42c78c47eb1b9d40baa3f943c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x9491d57c5687ab75726423b55ac2d87d1cda2c3f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x978799f1845c00c9a4d9fd2629b9ce18df66e488 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xdc55d1fd1c04e005051a40bd59c5f95623257bc5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x34757893070b0fc5de37aaf2844255ff90f7f1e0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x7faf167615419228f3f7d71d52d840dab154913c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xa4d7b6a50dd4c55334ca6f175dbc6561f269d264 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x0ed413cefde954d8e5c54d981d7d182b587e98e3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x524375d0c6a04439128428f400b00eae81a2e9e4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x4b7a4530d56ff55a4dce089d917ede812e543307 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x84bb5b9bf1b6782c87cfa3e396f2f571c8e49646 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x723292eea7e1576ae482a5c317934054c0199e24 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x9b42940e8184d866aac6595a91f8d8952a59d3b9 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x37622453c614f625d288151101ffe48fd222ced1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x4a94130b9e8eb0a0959c2c0f1ee9583213773fd9 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x51514b3dc24afc1db95586242b99f0063bea17c5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xc130254e9196d48bbd9f91240390a6e8203132e9 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x60ac25da2ada3be14a2a8c04e45b072bed965966 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x4e392a3883a84225260ff857318517eb50e5d128 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xca0aa06385a42242fe9523cd7015f6d01cd8f6b2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x3e448c17043ce1481bbe53c0fd19481bad8b98a6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x81060e6bf2a683f208b8799a33c7c09830cabed1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x463fe9f646b61ccfb43a022bf947075411cd71c7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x21b8065d10f73ee2e260e5b47d3344d3ced7596e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x0d4a11d5eeaac28ec3f61d100daf4d40471f1852 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x517f9dd285e75b599234f7221227339478d0fcc8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xa43fe16908251ee70ef74718545e4fe6c5ccec9f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x0af81cd5d9c124b4859d65697a4cd10ee223746a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xca7c2771d248dcbe09eabe0ce57a62e18da178c0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x09d1d767edf8fa23a64c51fa559e0688e526812f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x7b73644935b8e68019ac6356c40661e1bc315860 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x180efc1349a69390ade25667487a826164c9c6e4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x9c4fe5ffd9a9fc5678cfbd93aa2d4fd684b67c4c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xa478c2975ab1ea89e8196811f51a7b7ade33eb11 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xbb2b8038a1640196fbe3e38816f3e67cba72d940 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x9ec9367b8c4dd45ec8e7b800b1f719251053ad60 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xc91ef786fbf6d62858262c82c63de45085dea659 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x197d7010147df7b99e9025c724f13723b29313f8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x25647e01bd0967c1b9599fa3521939871d1d0888 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x2f0b1417aa42ebf0b4ca1154212847f6094d708d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x6ada49aeccf6e556bb7a35ef0119cc8ca795294a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x2a6c340bcbb0a79d3deecd3bc5cbc2605ea9259f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xda2d09fbbf8ee4b5051a0e9b562c5fcb4b393b18 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x48d20b3e529fb3dd7d91293f80638df582ab2daa - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x4028daac072e492d34a3afdbef0ba7e35d8b55c4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xc2eab7d33d3cb97692ecb231a5d0e4a649cb539d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xc5be99a02c6857f9eac67bbce58df5572498f40c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xe4b8583ccb95b25737c016ac88e539d0605949e8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x8dbee21e8586ee356130074aaa789c33159921ca - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x43de4318b6eb91a7cf37975dbb574396a7b5b5c6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x9ff68f61ca5eb0c6606dc517a9d44001e564bb66 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xa29fe6ef9592b5d408cca961d0fb9b1faf497d6d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x1b1137dd16faa651e38a9dfb5d9ffff7767fdf62 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x470e8de2ebaef52014a47cb5e6af86884947f08c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x8fb8e9921922d2ffb529a95d28a0d06d275d7a59 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xd3d2e2692501a5c9ca623199d38826e513033a17 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x97e1fcb93ae7267dbafad23f7b9afaa08264cfd8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xa5e9c917b4b821e4e0a5bbefce078ab6540d6b5e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x2cc846fff0b08fb3bffad71f53a60b4b6e6d6482 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x959873fb4fc11825fba83c80c4c632db1e936e15 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xa7480aafa8ad2af3ce24ac6853f960ae6ac7f0c4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xc7e6b676bfc73ae40bcc4577f22aab1682c691c6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x570febdf89c07f256c75686caca215289bb11cfc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x343fd171caf4f0287ae6b87d75a8964dc44516ab - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xcaa004418eb42cdf00cb057b7c9e28f0ffd840a5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xe3d3551bb608e7665472180a20280630d9e938aa - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xb6b0c651c37ec4ca81c0a128420e02001a57fac2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x4e34da137f0b317c633838458e0c923a5e088752 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xfe9e7931e55c514c33d489c88582fa36e84bd8e3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x5281e311734869c64ca60ef047fd87759397efe6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x149148acc3b06b8cc73af3a10e84189243a35925 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x8ef79d6c328c25da633559c20c75f638a4863462 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x0f23d49bc92ec52ff591d091b3e16c937034496e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x0f23d49bc92ec52ff591d091b3e16c937034496e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xbf16ef186e715668aa29cef57e2fd7f9d48adfe6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x0f23d49bc92ec52ff591d091b3e16c937034496e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x5645dcb64c059aa11212707fbf4e7f984440a8cf - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x0f23d49bc92ec52ff591d091b3e16c937034496e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x3ad4913fa896391c9822a81d8d869cc0d783bdd7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x0f23d49bc92ec52ff591d091b3e16c937034496e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x0f23d49bc92ec52ff591d091b3e16c937034496e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x0f23d49bc92ec52ff591d091b3e16c937034496e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x7a415b19932c0105c82fdb6b720bb01b0cc2cae3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x9b3423373e6e786c9ac367120533abe4ee398373 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x4a25dbdf9629b1782c3e2c7de3bdce41f1c7f801 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xbe80225f09645f172b079394312220637c440a63 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x059615ebf32c946aaab3d44491f78e4f8e97e1d3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x435664008f38b0650fbc1c9fc971d0a3bc2f1e47 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x4b62fa30fea125e43780dc425c2be5acb4ba743b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xc3db44adc1fcdfd5671f555236eae49f4a8eea18 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xddd23787a6b80a794d952f5fb036d0b31a8e6aff - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xa86aca6d7c393c06dcdc30473ea3d1b05c358dff - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x1ffec7119e315b15852557f654ae0052f76e6ae1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x0f027d40c80d8f70f77d3884776531f80b21d20e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x69c66beafb06674db41b22cfc50c34a93b8d82a2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xeedff72a683058f8ff531e8c98575f920430fdc5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x811cfb75567a252bea23474e2ccd1286927bfe0a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x2caccf71bdf8fff97c06a46eca29b611b1a74b5e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0xf07a84f0732dfe8eea0d3961bcd8f62c761ff508 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/ethereum/0x8c1c499b1796d7f3c2521ac37186b52de024e58c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xe5cf22ee4988d54141b77050967e1052bd9c7f7a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x7f580f8a02b759c350e6b8340e7c2d4b8162b6a9 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x48b0ab72c2591849e678e7d6f272b75ef9b863f7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x74d0ae8b8e1fca6039707564704a25ad2ee036b0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x5969efdde3cf5c0d9a88ae51e47d721096a97203 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xe32efff8f8b5fdc53803405aa3f623f03f8a8767 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xe8629b6a488f366d27dad801d1b5b445199e2ada - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x066b28f0c160935cf285f75ed600967bf8417035 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xddd23787a6b80a794d952f5fb036d0b31a8e6aff - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xa86aca6d7c393c06dcdc30473ea3d1b05c358dff - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x1ffec7119e315b15852557f654ae0052f76e6ae1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x0f027d40c80d8f70f77d3884776531f80b21d20e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x69c66beafb06674db41b22cfc50c34a93b8d82a2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xeedff72a683058f8ff531e8c98575f920430fdc5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x811cfb75567a252bea23474e2ccd1286927bfe0a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x2caccf71bdf8fff97c06a46eca29b611b1a74b5e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0xf07a84f0732dfe8eea0d3961bcd8f62c761ff508 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/arbitrum/0x8c1c499b1796d7f3c2521ac37186b52de024e58c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x146b020399769339509c98b7b353d19130c150ec - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xd28f71e383e93c570d3edfe82ebbceb35ec6c412 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xadab76dd2dca7ae080a796f0ce86170e482afb4a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x0fb07e6d6e1f52c839608e1436d2ea810cf07257 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xddd23787a6b80a794d952f5fb036d0b31a8e6aff - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xa86aca6d7c393c06dcdc30473ea3d1b05c358dff - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x1ffec7119e315b15852557f654ae0052f76e6ae1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x0f027d40c80d8f70f77d3884776531f80b21d20e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x69c66beafb06674db41b22cfc50c34a93b8d82a2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xeedff72a683058f8ff531e8c98575f920430fdc5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x811cfb75567a252bea23474e2ccd1286927bfe0a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x2caccf71bdf8fff97c06a46eca29b611b1a74b5e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0xf07a84f0732dfe8eea0d3961bcd8f62c761ff508 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/optimism/0x8c1c499b1796d7f3c2521ac37186b52de024e58c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x95d2483d2a0fff034004f91c53d649623d993896 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x19c5505638383337d2972ce68b493ad78e315147 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xc143161ed3ed8049bb63d8da42907c08a10e2269 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xc3286373599dd5af2a17a572ebb7561f05f88bec - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xbb98b3d2b18aef63a3178023a920971cf5f29be4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x647fb01a63de9a551b39c7915693b25e6bcec502 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa90c1c009dc8292bd04ced30f9b53a5ff7a806a0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xddd23787a6b80a794d952f5fb036d0b31a8e6aff - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xa86aca6d7c393c06dcdc30473ea3d1b05c358dff - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x1ffec7119e315b15852557f654ae0052f76e6ae1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x0f027d40c80d8f70f77d3884776531f80b21d20e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x69c66beafb06674db41b22cfc50c34a93b8d82a2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xeedff72a683058f8ff531e8c98575f920430fdc5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x811cfb75567a252bea23474e2ccd1286927bfe0a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x2caccf71bdf8fff97c06a46eca29b611b1a74b5e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0xf07a84f0732dfe8eea0d3961bcd8f62c761ff508 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/polygon/0x8c1c499b1796d7f3c2521ac37186b52de024e58c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xfb765ff72a14735550f1d798a5efd1311f2ddee7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x3537f2a5f99f08f59eb1417073db1fadbebf0c74 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xde8ed0277ee0e84c25756a73ffa7374e4aeadf46 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xd8f3a72d2b2220a5067abe8c38aea57dc2d69a5e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x7ec18abf80e865c6799069df91073335935c4185 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x14b1911dd6b451c2771661ae8cd70637d726c356 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x9ae8084c21752971d867597c07f2673765d949a1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xcfaf75a3d292c3535ea3acdb16ed2ee58c2bb091 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x8055e6de251e414e8393b20adab096afb3cf8399 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xffec10fe1355c2d8df4f62affcdeffdb04f06569 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xc16454420f100b2e771d8bc4c5b6200068129a34 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x046f405e4ae1d0e786eda4959adadbd417d13ad8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xeccb34691c06c1c9c31ceb2228b22cbd242b5879 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xe22a2dfaaaaec8a7b2b7acb4909eaaa5c5bd6e64 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xe2dda0911e227e73d9fd94745b851c8bc6504610 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x0f082a7870908f8cebbb2cd27a42a9225c19f898 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x69d667281778db0c3bc8177efea3a91ee95c3068 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x30d61bb28a6789f9f49d8c7fb198d63b6aba4b61 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x090f3fd9110621df127c3f9be5c6f58c02f2d5eb - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xd56f086e7b796b313d49f2bc926fac4bdd2a2b0b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x7eb847a214192aab8fa1b503f4d4c9ddd2a08db6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x81b3bc0ef974c16d71b8614adb8c22ccc045da01 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xc9b44ca4159dbaf5722a3dc8618e9d4b5f39d5b2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xbeef35a63fc62a3334630d9d3b4db27093d95317 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x3d5d143381916280ff91407febeb52f2b60f33cf - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x68c9325cc268df8b9ed4a06429587f28471b5f84 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xa00cc1fb7ac185222294777c6b23a13c013f07ce - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x77021e63bcbd3c5296b0cdd8a3c3770fb0ea8fa2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xcc28456d4ff980cee3457ca809a257e52cd9cdb0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xec0b7e8e44c9d60efd67a89dba1d4a6e02a7a4a0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x0c8fed5dd65542ca5f0add1acab14c2e470c9110 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xd56da2b74ba826f19015e6b7dd9dae1903e85da1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x5482c2b11951bbb92b87858242e17abde802b398 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xd95bae63641d822dc591bd4aca7a64e53eac76f9 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x06959273e9a65433de71f5a452d529544e07ddd0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x24bf2ee2e09477082d1ddf2f0603baa460b3f5f3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x56d8f846415e08c5e663d89505e79f522d33f947 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x548e923281f372d28a40287d3a2d30dce482fc66 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x9d744d3d905897608d24c1b8c1c7db0d30c36cd4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xddd23787a6b80a794d952f5fb036d0b31a8e6aff - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xa86aca6d7c393c06dcdc30473ea3d1b05c358dff - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x1ffec7119e315b15852557f654ae0052f76e6ae1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x0f027d40c80d8f70f77d3884776531f80b21d20e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x69c66beafb06674db41b22cfc50c34a93b8d82a2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xeedff72a683058f8ff531e8c98575f920430fdc5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x811cfb75567a252bea23474e2ccd1286927bfe0a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x2caccf71bdf8fff97c06a46eca29b611b1a74b5e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0xf07a84f0732dfe8eea0d3961bcd8f62c761ff508 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/base/0x8c1c499b1796d7f3c2521ac37186b52de024e58c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xab46d39cb398fb3649ecba781180016fef75f50b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x25048028ad87484b7fce99bc4e22dcb6c3307470 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xdb2177fee5b0ebdc7b8038cb70f3964bb6d14143 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x42d749f736051d8933b118324cded52d1f92bec1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xb1a1b707b143b911c36e1a0f4f901c5017791aca - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x3319a81a316abd4c086f7048904e31ff86648b38 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x4a978a2d4fb7393063babfb0cee741b8bcd4dd4b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xea403e36fb592fdfdc342c38e94284ddbb0d2105 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xe3fb01794d6912f0773171e32e723471ee8df061 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x916d7f23ccbb1d10118dcfc6ad5a10b6446ff73e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xddd23787a6b80a794d952f5fb036d0b31a8e6aff - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xa86aca6d7c393c06dcdc30473ea3d1b05c358dff - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x1ffec7119e315b15852557f654ae0052f76e6ae1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x0f027d40c80d8f70f77d3884776531f80b21d20e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x69c66beafb06674db41b22cfc50c34a93b8d82a2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xeedff72a683058f8ff531e8c98575f920430fdc5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x811cfb75567a252bea23474e2ccd1286927bfe0a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x2caccf71bdf8fff97c06a46eca29b611b1a74b5e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0xf07a84f0732dfe8eea0d3961bcd8f62c761ff508 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/bnb/0x8c1c499b1796d7f3c2521ac37186b52de024e58c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x6cde5f5a192fbf3fd84df983aa6dc30dbd9f8fac - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xd80d28850bebe6208433c298334392bc940b4fc7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x7f7c4335ccac291ddedcef4429a626c442b627ed - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x628cb3a5a206956423d158009612813b64b19dab - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x116361f4f45e310347b43cd098fdfa459760ea7f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x5dc631ad6c26bea1a59fbf2c2680cf3df43d249f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x1a810e0b6c2dd5629afa2f0c898b9512c6f78846 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xac1cb6d3d419da9ead0b53e62d6fb4bb53473523 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x0115d04a88990889471a88e85817aac9e961c07b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xd3409b7f3f54bb097433d0f4cd31c48ac33e569b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x493bfc1adb2e60805693197f23132350ffd2a04e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xcf4f103759770c21f945413781ca787620316988 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xb135ebde27d366b0d62e579bae4118cb991b820e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xecbc2f008c20729b9239317408367377c5473812 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x96e0c440d3377c2dfe4f2a82add0b045e46cbe64 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x6f5304c22ac77e228e8af4732ac6677c46e09030 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xcb037f27eb3952222810966e28e0ceb650c65cd9 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xddd23787a6b80a794d952f5fb036d0b31a8e6aff - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xa86aca6d7c393c06dcdc30473ea3d1b05c358dff - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x1ffec7119e315b15852557f654ae0052f76e6ae1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x0f027d40c80d8f70f77d3884776531f80b21d20e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x69c66beafb06674db41b22cfc50c34a93b8d82a2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xeedff72a683058f8ff531e8c98575f920430fdc5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x811cfb75567a252bea23474e2ccd1286927bfe0a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x2caccf71bdf8fff97c06a46eca29b611b1a74b5e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0xf07a84f0732dfe8eea0d3961bcd8f62c761ff508 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/pools/celo/0x8c1c499b1796d7f3c2521ac37186b52de024e58c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x7baece5d47f1bc5e1953fbe0e9931d54dab6d810 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x83abecf7204d5afc1bea5df734f085f2535a9976 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x4eefe02fce5b53ca33c7717bbd8ad3c9cb0609f1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xaf996125e98b5804c00ffdb4f7ff386307c99a00 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x7924a818013f39cf800f5589ff1f1f0def54f31f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xb2eb5849e2606f99fc492e9add0103c667f806d3 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x53c6ca2597711ca7a73b6921faf4031eedf71339 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x4eefe02fce5b53ca33c7717bbd8ad3c9cb0609f1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xaf996125e98b5804c00ffdb4f7ff386307c99a00 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x7924a818013f39cf800f5589ff1f1f0def54f31f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0xd35937ecd47b04a1474f8569f457fc5ac395921a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x4eefe02fce5b53ca33c7717bbd8ad3c9cb0609f1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0xaf996125e98b5804c00ffdb4f7ff386307c99a00 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x7924a818013f39cf800f5589ff1f1f0def54f31f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x6b75f2189f0e11c52e814e09e280eb1a9a8a094a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xb372b5abdb7c2ab8ad9e614be9835a42d0009153 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xf369277650ad6654f25412ea8bfbd5942733babc - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x4eefe02fce5b53ca33c7717bbd8ad3c9cb0609f1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xaf996125e98b5804c00ffdb4f7ff386307c99a00 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x7924a818013f39cf800f5589ff1f1f0def54f31f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x4898cf312fbff8814cab80a8d7f6ee5ad0dc73fb - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x5e78afc6c804d4382bede3a0712d210e657e9b4f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x86b211ca7915a0c8d4659dd98242d9e801d88ab4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xb637f7c82fd774c280e23cebc725e7cd807c66d0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xd249c43faabc58d6dd4b0a4de598b5a956c5d8d7 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x1fbae785ce68b79f7ed4f7b27c3af3ef0e0bc3d4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x3c1376fb8487da57d4ffb263d9d01b578c7b586b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x7b24bed19856f4bb1d4c0421cfb328026cd936bd - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x7cf887a863d81e6a483ee947dee05cb51914923c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x588c8cf031809486f015908864ee8699b44017e4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x3987d38a4ff8520a8ef6bcc6f98d6da8bcd69b89 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x4eefe02fce5b53ca33c7717bbd8ad3c9cb0609f1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xaf996125e98b5804c00ffdb4f7ff386307c99a00 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x7924a818013f39cf800f5589ff1f1f0def54f31f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0xde67d05242b18af00b28678db34feec883cc9cd6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x4eefe02fce5b53ca33c7717bbd8ad3c9cb0609f1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0xaf996125e98b5804c00ffdb4f7ff386307c99a00 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x7924a818013f39cf800f5589ff1f1f0def54f31f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x4a5a8b0108f446df7c1c8a459fcfb54e844b7343 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xf6ba006abf768ab2d1b5bba2d22d9f13eb1269d4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x4eefe02fce5b53ca33c7717bbd8ad3c9cb0609f1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xaf996125e98b5804c00ffdb4f7ff386307c99a00 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x7924a818013f39cf800f5589ff1f1f0def54f31f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x92c2fc5f306405eab0ff0958f6d85d7f8892cf4d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xcbe856765eeec3fdc505ddebf9dc612da995e593 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x92c2fc5f306405eab0ff0958f6d85d7f8892cf4d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xcbe856765eeec3fdc505ddebf9dc612da995e593 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0xc1738d90e2e26c35784a0d3e3d8a9f795074bca4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x92c2fc5f306405eab0ff0958f6d85d7f8892cf4d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0xcbe856765eeec3fdc505ddebf9dc612da995e593 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xda908c0bf14ad0b61ea5ebe671ac59b2ce091cbf - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x254aa3a898071d6a2da0db11da73b02b4646078f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x92c2fc5f306405eab0ff0958f6d85d7f8892cf4d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xcbe856765eeec3fdc505ddebf9dc612da995e593 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x41824081f2e7beb83048bf52465ddd7c8e471da2 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xa0c2ce1723b3939f47ad01a293292f2f75dc629d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xc42442f6402b68626e791a447d87b35cb1c6236e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x84537db6f6aaa2afdb71f325d14b9f5f7825bef1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x13933689ed2c6c66e83aed64336df14896efb7e2 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x92c2fc5f306405eab0ff0958f6d85d7f8892cf4d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xcbe856765eeec3fdc505ddebf9dc612da995e593 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x039df62583ddc1c5fda75db152b87113d863b6d6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x92c2fc5f306405eab0ff0958f6d85d7f8892cf4d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0xcbe856765eeec3fdc505ddebf9dc612da995e593 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x92c2fc5f306405eab0ff0958f6d85d7f8892cf4d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xcbe856765eeec3fdc505ddebf9dc612da995e593 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xc39e83fe4e412a885c0577c08eb53bdb6548004a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xdbac78be00503d10ae0074e5e5873a61fc56647c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xc1cd3d0913f4633b43fcddbcd7342bc9b71c676f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x6c4c7f46d9d4ef6bc5c9e155f011ad19fc4ef321 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xb2c86ff752f18499b70e8f642b3421405d50d6e9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x16588709ca8f7b84829b43cc1c5cb7e84a321b16 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xd0a4c8a1a14530c7c9efdad0ba37e8cf4204d230 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xf92f2e3fca01491baba0975264362cc38b1cab7b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x3e6e23198679419cd73bb6376518dcc5168c8260 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x531b6a4b3f962208ea8ed5268c642c84bb29be0b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x553e9c493678d8606d6a5ba284643db2110df823 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xe3170d65018882a336743a9c396c52ea4b9c5563 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x1385fc1fe0418ea0b4fcf7adc61fc7535ab7f80d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x5cd0ad98ba6288ed7819246a1ebc0386c32c314b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xe945683b3462d2603a18bdfbb19261c6a4f03ad1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xa1bf0e900fb272089c9fd299ea14bfccb1d1c2c0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xe46935ae80e05cdebd4a4008b6ccaa36d2845370 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x3041cbd36888becc7bbcbc0045e3b1f144466f5f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x0ad1e922e764df5ab6d636f5d21ecc2e41e827f0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xe945683b3462d2603a18bdfbb19261c6a4f03ad1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xa1bf0e900fb272089c9fd299ea14bfccb1d1c2c0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xe46935ae80e05cdebd4a4008b6ccaa36d2845370 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x3041cbd36888becc7bbcbc0045e3b1f144466f5f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x6b3a3d6ed64faf933a7a4b1bd44b2efba47614ac - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x4ce4a1a593ea9f2e6b2c05016a00a2d300c9ffd8 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x0843e0f56b9e7fdc4fb95fabba22a01ef4088f41 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x8323d063b1d12acce4742f1e3ed9bc46d71f4222 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0xe945683b3462d2603a18bdfbb19261c6a4f03ad1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0xa1bf0e900fb272089c9fd299ea14bfccb1d1c2c0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0xe46935ae80e05cdebd4a4008b6ccaa36d2845370 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x3041cbd36888becc7bbcbc0045e3b1f144466f5f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xe30e4dfdbb10949c27501922f845e20cfa579f09 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x7e02ae3f794ebade542c92973eb1c46d7e2e935d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xfa22d298e3b0bc1752e5ef2849cec1149d596674 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x8066ee17156e4184d69277e26fa8cbca3a845edf - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x418de8e0ab58abfe916a47821a055c59b9502deb - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xfb9caae5a5c0ab91f68542124c05d1efbb97d151 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xb68606a75b117906e06caa0755896ad2b3dd0272 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x6e33c0f5e16b45114679eac217e0c0138cefcd2e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xd64fb39a5681908ad488b487d65f5d8479cb235c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xe945683b3462d2603a18bdfbb19261c6a4f03ad1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xa1bf0e900fb272089c9fd299ea14bfccb1d1c2c0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xe46935ae80e05cdebd4a4008b6ccaa36d2845370 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x3041cbd36888becc7bbcbc0045e3b1f144466f5f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x0217fc17c642d29b890bcf888e21be2378493e01 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x099d23a43da5a8a9282266dbefeaaef958150300 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xd92e0767473d1e3ff11ac036f2b1db90ad0ae55f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xe945683b3462d2603a18bdfbb19261c6a4f03ad1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xa1bf0e900fb272089c9fd299ea14bfccb1d1c2c0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xe46935ae80e05cdebd4a4008b6ccaa36d2845370 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x3041cbd36888becc7bbcbc0045e3b1f144466f5f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x40c547e7fd88f60d94788953b83d9342d8d133c6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x397433498c7befde4b4049b98a7ff081a2c17387 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0xf9be03505869d719ba194757943575ed2af001f2 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x18c40bb9281a07627ff25cea45b7511f68fd0076 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x270d89e983d9821a418bf193684736414fab78c5 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0xb125aa15ad943d96e813e4a06d0c34716f897e26 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x813c0decbb1097fff46d0ed6a39fb5f6a83043f4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x9a7ac628ba9f330341486380af729c8975388959 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0xf2c9339945bff71dd0bffd3c142164112cd05dc6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x12a4619c0bd9710732fbc458e9baa73df6c3d35f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x96530dac7817f186390b64ba63d13becd079b28d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x18fc1e95adb68b556212ebbad777f3fbb644db98 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0xabbeb324b090550ca6d15ec71019915813f54f90 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x86d708404d0db1d97843e66d4ed6b86d11be705b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0xbfbba3de6a260c8374f8299c38898312c2d6e9a6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0xe945683b3462d2603a18bdfbb19261c6a4f03ad1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0xa1bf0e900fb272089c9fd299ea14bfccb1d1c2c0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0xe46935ae80e05cdebd4a4008b6ccaa36d2845370 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x3041cbd36888becc7bbcbc0045e3b1f144466f5f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xe945683b3462d2603a18bdfbb19261c6a4f03ad1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xa1bf0e900fb272089c9fd299ea14bfccb1d1c2c0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xe46935ae80e05cdebd4a4008b6ccaa36d2845370 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x3041cbd36888becc7bbcbc0045e3b1f144466f5f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xd31d41dffa3589bb0c0183e46a1eed983a5e5978 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x391e8501b626c623d39474afca6f9e46c2686649 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xd0fc8ba7e267f2bc56044a7715a489d851dc6d78 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x4fd47e5102dfbf95541f64ed6fe13d4ed26d2546 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0xe9033c0011f35547fa90d3f8a6ad4b666a590759 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x0c3561d3b72e17378d99684414aa8669daeb8bd0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x14653ce9f406ba7f35a7ffa43c81fa7ecd99c788 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x3204e9734a56a4d7c6f4f5822e14182d9d1a43c4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x43faefd4c0c25e969ac211cd97a4a51e52c729b7 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xa652ab3be697c7a01fbdce4d73f8e8acd990251c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x29962083891241aad61ad97bae46d032c9c0c55c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x26bf3601b77be9c31b13b22ebca02914db9c7468 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x0d2edd335982f56662d772b93d86901eb9bd2ff9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xbaed273edd493930711fe88690ebd1f30f7f55ab - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x16033643947bf4d8a1ae37b055edf57cb183106a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xf59abf32c1e8c5d2c6e3faa2131533bbcd466194 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x0312187403bf72b8d2d80729894d6ac3300bd63f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x416fdbc4fb8d4d1f48d0d3778c59dfa5352e9b15 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x90908e414d3525e33733d320798b5681508255ea - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x5918aca9ae924e6eaaa3d293bb92bdec9ab79338 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x8270e64d22cf13e92c641c4006408c7d7e3ff341 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x16503510c58da73486950b72a12ead3d1d8355dd - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x90908e414d3525e33733d320798b5681508255ea - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x7505159f644ddc5eae21c119e328d0d5bee574b0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0xe870bfe4aacb6e234b645e535d26c53790d50e78 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x2e2d190ad4e0d7be9569baebd4d33298379b0502 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x90908e414d3525e33733d320798b5681508255ea - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xb834093d7e46f7644be45e77281394d31003e866 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xb5a1fd804342cfb679bd8ada75718bc3ec43097e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x90908e414d3525e33733d320798b5681508255ea - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x9e71e2b14d7e6d30811628ab0965f28e4e2edbce - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xa011da4a0c9261ecf4694bf73a74d113aa261133 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x7ab922c1bfdf7df977c7531c5782074d866f3adc - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xe2d2050430e341a8f3988e2726e44d9370f8cd3a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xed66ba3ea44425805a085b1ca80d00467b055b38 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x40dade19adc198125ec237a2c48b3408568b2f81 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x166bc40da621d3cb978e24334f844b84ddef25f8 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x76bf0abd20f1e0155ce40a62615a90a709a6c3d8 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x90908e414d3525e33733d320798b5681508255ea - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x6948d6c8532c6b0006cb67c6fb9c399792c8ac91 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x90908e414d3525e33733d320798b5681508255ea - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x4e40cf4a7d8724e5adc2b791bbf9451d1e260b93 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x90908e414d3525e33733d320798b5681508255ea - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xc0067d751fb1172dbab1fa003efe214ee8f419b6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xc3d7aa944105d3fafe07fc1822102449c916a8d0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xd6b4cce96ddf8aab2e5750983af9a901f17fbc36 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x4cef551255ec96d89fec975446301b5c4e164c59 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xc0067d751fb1172dbab1fa003efe214ee8f419b6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xc3d7aa944105d3fafe07fc1822102449c916a8d0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0xdd0c6bae8ad5998c358b823df15a2a4181da1b80 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0xc0067d751fb1172dbab1fa003efe214ee8f419b6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0xc3d7aa944105d3fafe07fc1822102449c916a8d0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xc0067d751fb1172dbab1fa003efe214ee8f419b6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xc3d7aa944105d3fafe07fc1822102449c916a8d0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x5e6ff2fa4ca244b6b33c7286d368120822eacc11 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x98efd62b4bfbde6393b18b063c506ce5a77f4810 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x3c5096df639262db0a6cd0172f08709d4161094b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xae31f0e673fc5f33cfc0e9abb426d8051404a7c5 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xc0067d751fb1172dbab1fa003efe214ee8f419b6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xc3d7aa944105d3fafe07fc1822102449c916a8d0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0xc0067d751fb1172dbab1fa003efe214ee8f419b6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0xc3d7aa944105d3fafe07fc1822102449c916a8d0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xd10456ce05b9af05c8eede0f93ea8aa80a0daa2f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x065c22a16f6531706681fabbc8df135fe6eb1c2e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x8ab8d851c6b31d8a4d42fd7d3e47b20861b025f2 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xc0067d751fb1172dbab1fa003efe214ee8f419b6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xc3d7aa944105d3fafe07fc1822102449c916a8d0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x2982d3295a0e1a99e6e88ece0e93ffdfc5c761ae - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xc593fe9193b745447e86b45ea0bf62565ee030cc - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x88051b0eea095007d3bef21ab287be961f3d8598 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xaf21b0ec0197e63a5c6cc30c8e947eb8165c6212 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x9c84f58bb51fabd18698efe95f5bab4f33e96e8f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xb31273fd2dfc05e6fd91a3b8a2a681aeb0fbcf48 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xaf7b48ae2f4773fd44f9208cca3db5ae7bfa7e37 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xc2125a452115ff5a300cc2a6ffae99637f6e329d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xb08a8794a5d3ccca3725d92964696858d3201909 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xaf21b0ec0197e63a5c6cc30c8e947eb8165c6212 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x9c84f58bb51fabd18698efe95f5bab4f33e96e8f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0xae99efe6b04bbe5b8b4ad567946fb84b35681abb - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0xaf21b0ec0197e63a5c6cc30c8e947eb8165c6212 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x9c84f58bb51fabd18698efe95f5bab4f33e96e8f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xaf21b0ec0197e63a5c6cc30c8e947eb8165c6212 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x9c84f58bb51fabd18698efe95f5bab4f33e96e8f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x6696710b8e3dc0d844c8b9244767962a4a61ad97 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xcde77ef185a8f886d03b109573cc1dcdcf3cf1f8 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xaf21b0ec0197e63a5c6cc30c8e947eb8165c6212 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x9c84f58bb51fabd18698efe95f5bab4f33e96e8f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x35f5387decce5a234da1a32ca3c9e338a48bcf37 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x4178dd7eb2eb983ba7f7e41648cf91db6be20190 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0xaf21b0ec0197e63a5c6cc30c8e947eb8165c6212 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x9c84f58bb51fabd18698efe95f5bab4f33e96e8f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xb6c8f9490314394cfc6edacb8717bfdc1eb8dab5 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x1625fe58cdb3726e5841fb2bb367dde9aaa009b3 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xb1ed164c736909ba7ddbc1feb7ced4eaad854a87 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x95faa9a91cd6c1c018e4b1a6fc4c89d4f1695e5d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xa143ccf73c25eec6f38bd1b741043ebea228b8e9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x2e067e0eab7fd31c01473c0f56f3295afb82e461 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xbc83c60e853398d263c1d88899cf5a8b408f9654 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xaf21b0ec0197e63a5c6cc30c8e947eb8165c6212 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x9c84f58bb51fabd18698efe95f5bab4f33e96e8f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x202a6012894ae5c288ea824cbc8a9bfb26a49b93 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x744159757cac173a7a3ecf5e97adb10d1a725377 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x127452f3f9cdc0389b0bf59ce6131aa3bd763598 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x5ced44f03ff443bbe14d8ea23bc24425fb89e3ed - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x5ced44f03ff443bbe14d8ea23bc24425fb89e3ed - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x2264ba9dc0b257c69eeae7782e8ff608cc65d6a7 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x5ced44f03ff443bbe14d8ea23bc24425fb89e3ed - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x00a59c2d0f0f4837028d47a391decbffc1e10608 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x5ced44f03ff443bbe14d8ea23bc24425fb89e3ed - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xad6e8f6a34087bddfb03815e2c10e4f7bfd4395b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xd5bb156cb73bfca62f68dc3dff7e5ec4e305b861 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xc0d8f259578c985947a050802fb4857261af0bf3 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x5ced44f03ff443bbe14d8ea23bc24425fb89e3ed - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x74f7a360eb36a46b675ea932ea07094a3ace441f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x626761cc5b9fafe4696bf8def4aa015576bb4bef - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x5ced44f03ff443bbe14d8ea23bc24425fb89e3ed - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xc767c0b2e2e56c455fd29f9ee9b6e6f035c71ed4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x625cb959213d18a9853973c2220df7287f1e5b7d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x5ced44f03ff443bbe14d8ea23bc24425fb89e3ed - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x7138eae57e8a214f7297e5e67bb6e183df3572d5 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xc7bbec68d12a0d1830360f8ec58fa599ba1b0e9b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x840deeef2f115cf50da625f7368c24af6fe74410 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x69c7bd26512f52bf6f76fab834140d13dda673ca - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x69c7bd26512f52bf6f76fab834140d13dda673ca - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x69c7bd26512f52bf6f76fab834140d13dda673ca - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xda71299ff6bdac31bdcafde52a41d460f17e3ad9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xabebc245a9a47166ecd10933d43817c8ef6fb825 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x69c7bd26512f52bf6f76fab834140d13dda673ca - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x69c7bd26512f52bf6f76fab834140d13dda673ca - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0xb007dda6ca7a57785ce04981c30a1934995a197a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x0de383928e4fcf0f90ad2d6a5ee18eb3b9d16a55 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x0a36df020fe3f132e6557899f272bf3d4591620e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x69c7bd26512f52bf6f76fab834140d13dda673ca - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x69c7bd26512f52bf6f76fab834140d13dda673ca - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x8c9d230d45d6cfee39a6680fb7cb7e8de7ea8e71 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xcb198a55e2a88841e855be4eacaad99422416b33 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x9b371948735f612be19195f5f6e5ebc03839cdaf - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0xb3709d0e16b618b15ee4bcf82d19b9e7d4100914 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xe426e1305f5e6093864762bf9d2d8b44bc211c59 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x7b9a5bc920610f54881f2f6359007957de504862 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xfb82dd4d657033133eea6e5b7015042984c5825f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x92560c178ce069cc014138ed3c2f5221ba71f58a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x6ef7d514d75b5a5a3c500dba1b161a81e842e7a4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xac70bd92f89e6739b3a08db9b6081a923912f73d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x1ebcf8831b93450ea81b0619c5e05b98751c8322 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x470d0d72c975a7f328bd63808bfffd28194b3eb6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xa961f0473da4864c5ed28e00fcc53a3aab056c1b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x6ef7d514d75b5a5a3c500dba1b161a81e842e7a4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0xa5b6d588ceb3aa1bf543d095038479188f884690 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x6ef7d514d75b5a5a3c500dba1b161a81e842e7a4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x6ef7d514d75b5a5a3c500dba1b161a81e842e7a4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xb1419a7f9e8c6e434b1d05377e0dbc4154e3de78 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x6ef7d514d75b5a5a3c500dba1b161a81e842e7a4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x70c132a2ddeccf0d76cc9b64a749ffe375a79a21 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x6ef7d514d75b5a5a3c500dba1b161a81e842e7a4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x6ef7d514d75b5a5a3c500dba1b161a81e842e7a4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x1b942ce8bf08290f740b9e825c91e07fcd0bfe75 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x5016cd7b785a773f7f3a3ff4035a1e7a76543946 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xf6c4e4f339912541d3f8ed99dba64a1372af5e5b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x4f122edcd91af8cda38c3a87158afa8687bab57c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xed3fe08bd12f24dad0f1a1e58610644debe374fb - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x5016cd7b785a773f7f3a3ff4035a1e7a76543946 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xf6c4e4f339912541d3f8ed99dba64a1372af5e5b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x7bc815ca2c2115f896bb14b31b8196388c05e99b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x5016cd7b785a773f7f3a3ff4035a1e7a76543946 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0xf6c4e4f339912541d3f8ed99dba64a1372af5e5b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xd29c2df656b2e4ae6b6817ccc2ebe932fc6a950b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x1f6082db7c8f4b199e17090cd5c8831a1dad1997 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x5016cd7b785a773f7f3a3ff4035a1e7a76543946 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xf6c4e4f339912541d3f8ed99dba64a1372af5e5b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xc64f886397988ff16d72123dbe3d46e5bf33ffac - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x0d2c430c6f7ef48ed34bf4aad0ec377e03cc53cf - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x5016cd7b785a773f7f3a3ff4035a1e7a76543946 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xf6c4e4f339912541d3f8ed99dba64a1372af5e5b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x2b11a34f52e354ef197f0a2397008699b875ae7e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x5016cd7b785a773f7f3a3ff4035a1e7a76543946 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0xf6c4e4f339912541d3f8ed99dba64a1372af5e5b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xde27bdec962a74a72fa1c5ef50bff6f3da083e05 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x7766bdc5ff15d3aceb4d37914963aebaccf3de15 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x5016cd7b785a773f7f3a3ff4035a1e7a76543946 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xf6c4e4f339912541d3f8ed99dba64a1372af5e5b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x67ab7dc903a10838a0de8861dfdff3287cf98e5c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x88aaeed1fcfca2eda30749afa9ad45a75c80e292 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x2c8e9a1586ed822f79c0a241e1a4d48e839b3182 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x847165954680b989902e354f34d08b09afab3cd9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x590269935821d760c54b32d31db66ba47d4e53b4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x03d70bf9e6afbf8cac09ef0c45f9a00a841c2bed - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x8b238f615c1f312d22a65762bcf601a37f1eeec7 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x5280d5e63b416277d0f81fae54bb1e0444cabdaa - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xf4e43a4a17d2820c7cf724e46844943931a47894 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x5ab53ee1d50eef2c1dd3d5402789cd27bb52c1bb - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xe6ff8b9a37b0fab776134636d9981aa778c4e718 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x44af8d03393e498eec5fcfc7936ebc381f02974d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x4094915f7849b26e8d43dee1f7e3b7b477a0b5bb - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xc3f5e0d4cdff86e85486cf6bd20cc0884df5f98e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x87428a53e14d24ab19c6ca4939b4df93b8996ca9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x9dbe5dffaeb4ac2e0ac14f8b4e08b3bc55de5232 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xc3576f38c32e95e36bbd8d91e6cbe646a3723110 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x8d58e202016122aae65be55694dbce1b810b4072 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xc3576f38c32e95e36bbd8d91e6cbe646a3723110 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x8d58e202016122aae65be55694dbce1b810b4072 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0xa7bb0d95c6ba0ed0aca70c503b34bc7108589a47 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0xbcfac19a0036ada56496316ee5cf388c2af2bf58 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x296b88b607ea3a03c821ca4dc34dd9e7e4efa041 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0xc3576f38c32e95e36bbd8d91e6cbe646a3723110 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x8d58e202016122aae65be55694dbce1b810b4072 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x019c29d5c97f8cbaa67013e2cf4b6506a5cf183a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xc3576f38c32e95e36bbd8d91e6cbe646a3723110 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x8d58e202016122aae65be55694dbce1b810b4072 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x30442fcebbd75a5bb58377c0174d5ce637e297d7 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x6c561b446416e1a00e8e93e221854d6ea4171372 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x0fb597d6cfe5be0d5258a7f017599c2a4ece34c7 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xe9b7057f9b81a0120c09306d35f22859473f18cb - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x8deb37b048f4b3c7bd61eca7dfccbef7cba726de - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x455fd3ae52a8ab80f319a1bf912457aa8296695a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xe11d03bef391ee0a4b670176e23eb44aad490f12 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xe7f850731fed6af4c36cce93eccfbcda0634a030 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xadad4ce0c68f50a19cf5063e0b91d701daab1df1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x5e9bb3d7682a9537db831060176c4247ab80d1ec - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xe9ed60539a8ea7a4da04ebfa524e631b1fd48525 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x0511791eb6fb175a1aaa645114f0f5c8689ec163 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xf3c7b93db3f28580b0fd10365e619eedceb40e76 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x58ecf9cec06bc58fde9280d348f79ed8f3d3046e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xedc7f0dfd9751ef95bb8786a3b130f490743bb0e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xc3576f38c32e95e36bbd8d91e6cbe646a3723110 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x8d58e202016122aae65be55694dbce1b810b4072 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x6bcb0ba386e9de0c29006e46b2f01f047ca1806e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0xc3576f38c32e95e36bbd8d91e6cbe646a3723110 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x8d58e202016122aae65be55694dbce1b810b4072 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xc3576f38c32e95e36bbd8d91e6cbe646a3723110 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x8d58e202016122aae65be55694dbce1b810b4072 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x34a43471377dcce420ce8e3ffd9360b2e08fa7b4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x34a43471377dcce420ce8e3ffd9360b2e08fa7b4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x34a43471377dcce420ce8e3ffd9360b2e08fa7b4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x34a43471377dcce420ce8e3ffd9360b2e08fa7b4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x34a43471377dcce420ce8e3ffd9360b2e08fa7b4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x34a43471377dcce420ce8e3ffd9360b2e08fa7b4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x34a43471377dcce420ce8e3ffd9360b2e08fa7b4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x766854992bd5363ebeeff0113f5a5795796befab - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x9438a9d1bdeece02ed4431ac59613a128201e0b9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x0a63d3910ffc1529190e80e10855c4216407cc45 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x89084692453ab2305f5f8ac7d70d5efd37a86b8f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xb34a5657988da5b9888952c439756594613507aa - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x05efb437e4e97efea6450321eca8d7585a731369 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xc973c86afc23ed731ce1a14d7179003a1601205f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x0f44a1c2b66418f784607d2067fe695703809bff - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x0da6253560822973185297d5f32ff8fa38243afe - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x622270721fb38fde831ab23a8e177665557f6fa9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xa95b0f5a65a769d82ab4f3e82842e45b8bbaf101 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x622270721fb38fde831ab23a8e177665557f6fa9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x886b4f0cb357e0d6ec07b7a3985f346cc17ece7d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x622270721fb38fde831ab23a8e177665557f6fa9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x50defb73a76efe5d5d35cf267ffb02dfd6cd96bc - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x622270721fb38fde831ab23a8e177665557f6fa9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x7aea2e8a3843516afa07293a10ac8e49906dabd1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x8c7080564b5a792a33ef2fd473fba6364d5495e5 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x8f81b80d950e5996346530b76aba2962da5c9edb - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x7bc0f74d8d94e8e9fdaa40bbc04cc44fb8e0f081 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x09c149c856e6fb6e40aa39209142411b554b1a41 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x622270721fb38fde831ab23a8e177665557f6fa9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x7ef0a523c49b1dd07e3593198c5260a95ad7859a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x622270721fb38fde831ab23a8e177665557f6fa9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x622270721fb38fde831ab23a8e177665557f6fa9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x15aa01580ae866f9ff4dbe45e06e307941d90c7b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0x4548280ac92507c9092a511c7396cbea78fa9e49 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xe0554a476a092703abdb3ef35c80e0d76d32939f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/ethereum/0xc555d55279023e732ccd32d812114caf5838fd46 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x421803da50d3932caa36bd1731d36a0e2af93542 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xc555d55279023e732ccd32d812114caf5838fd46 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0xc555d55279023e732ccd32d812114caf5838fd46 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x258a4b7373f6863db5a17de191e0cebb1e0bbc8a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0x45126b956401daaec92afba2a9953e14b16fb83f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/polygon/0xc555d55279023e732ccd32d812114caf5838fd46 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xa3eaa52b505cf61aadcfe21424d43a6847dd6331 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x722bcf6c16dadcc29914e4e64290c46aa1406de8 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0x1e1367dcebe168554e82552e0e659a4116926d10 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xc555d55279023e732ccd32d812114caf5838fd46 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0x4d170f8714367c44787ae98259ce8adb72240067 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/bnb/0xc555d55279023e732ccd32d812114caf5838fd46 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xaa97f0689660ea15b7d6f84f2e5250b63f2b381a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0xc555d55279023e732ccd32d812114caf5838fd46 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xb736330326cf379ecd918dba10614bd63c2713da - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0xe3d4faff3179f0a664a3a84c3e1da3b90e27f186 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/pools/arbitrum/0x50e7b9293aef80c304234e86c84a01be8401c530 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x87dddd2e152bf1955e7e03d9f23a9dcc163eebf6 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0xd9dd34576c7034beb0b11a99afffc49e91011235 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/pools/optimism/0x394a9fcbab8599437d9ec4e5a4a0eb7cb1fd2f69 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xb3adde966b8a1a6f22a04914ee9fe0798e71fc5b - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/pools/base/0xa2d4a8e00daad32acace1a0dd0905f6aaf57e84e - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/pools/celo/0x2392ae4ba6daf181ce7343d237b695cdf525e233 - 2024-09-27T19:51:14.628Z + 2024-05-20T17:20:52.753Z 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 954e3a4d21d..e727529afef 100644 --- a/apps/web/public/tokens-sitemap.xml +++ b/apps/web/public/tokens-sitemap.xml @@ -2,6842 +2,3182 @@ https://app.uniswap.org/explore/tokens/ethereum/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xdac17f958d2ee523a2206206994597c13d831ec7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x2260fac5e5542a773aa44fbcfedf7c193bc2c599 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x6982508145454ce325ddbe47a25d4ec3d2311933 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x6b175474e89094c44da98b954eedeac495271d0f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x6123b0049f904d730db3c36a31167d9d4121fa6b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x1f9840a85d5af5bf1d1762f925bdaddc4201f984 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xcf0c122c6b73ff809c693db761e7baebe62b6a2e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xfaba6f8e4a5e8ab82f62fe7c39859fa577269be3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x58cb30368ceb2d194740b144eab4c2da8a917dcb - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x4c9edd5852cd905f086c759e8383e09bff1e68b3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xaaee1a9723aadb7afa2810263653a34ba2c21c7a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x514910771af9ca656af840dff83e8264ecf986ca - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x5b7533812759b45c2b44c19e320ba2cd2681b542 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xae78736cd615f374d3085123a210448e74fc6393 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xb9f599ce614feb2e1bbe58f180f370d05b39344e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xd5f7838f5c461feff7fe49ea5ebaf7728bb0adfa - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xd31a59c85ae9d8edefec411d448f90841571b89c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x6a7eff1e2c355ad6eb91bebb5ded49257f3fed98 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x576e2bed8f7b46d34016198911cdf9886f78bea7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x1258d60b224c0c5cd888d37bbf31aa5fcfb7e870 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x62d0a8458ed7719fdaf978fe5929c6d342b0bfce - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x77e06c9eccf2e797fd462a92b6d7642ef85b0a44 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x24fcfc492c1393274b6bcd568ac9e225bec93584 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x27702a26126e0b3702af63ee09ac4d1a084ef628 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xd46ba6d942050d489dbd938a2c909a5d5039a161 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xbe9895146f7af43049ca1c1ae358b0541ea49704 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x72f713d11480dcf08b37e1898670e736688d218d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x0001a500a6b18995b03f44bb040a5ffc28e45cb0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x9e9fbde7c7a83c43913bddc8779158f1368f0413 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x5f98805a4e8be255a32880fdec7f6728c6568ba0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x2b591e99afe9f32eaa6214f7b7629768c40eeb39 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x1ae7e1d0ce06364ced9ad58225a1705b3e5db92b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x046eee2cc3188071c02bfc1745a6b17c656e3f3d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x84018071282d4b2996272659d9c01cb08dd7327f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x12970e6868f88f6557b76120662c1b3e50a646bf - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xaea46a60368a7bd060eec7df8cba43b7ef41ad85 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x6de037ef9ad2725eb40118bb1702ebb27e4aeb24 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xc01154b4ccb518232d6bbfc9b9e6c5068b766f82 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x5a98fcbea516cf06857215779fd812ca3bef1b32 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x102c776ddb30c754ded4fdcc77a19230a60d4e4f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x72e4f9f808c49a2a61de9c5896298920dc4eeea9 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x467719ad09025fcc6cf6f8311755809d45a5e5f3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xf19308f923582a6f7c465e5ce7a9dc1bec6665b1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x710287d1d39dcf62094a83ebb3e736e79400068a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xf951e335afb289353dc249e82926178eac7ded78 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xf017d3690346eb8234b85f74cee5e15821fee1f4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x8c282c35b5e1088bb208991c151182a782637699 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xeaa63125dd63f10874f99cdbbb18410e7fc79dd3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xde342a3e269056fc3305f9e315f4c40d917ba521 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x2dff88a56767223a5529ea5960da7a3f5f766406 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x626e8036deb333b408be468f951bdb42433cbf18 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xdd66781d0e9a08d4fbb5ec7bac80b691be27f21d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xb23d80f5fefcddaa212212f028021b41ded428cf - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xbaac2b4491727d78d2b78815144570b9f2fe8899 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xf8ebf4849f1fa4faf0dff2106a173d3a6cb2eb3a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xb90b2a35c65dbc466b04240097ca756ad2005295 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x1614f18fc94f47967a3fbe5ffcd46d4e7da3d787 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xf1df7305e4bab3885cab5b1e4dfc338452a67891 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x91fbb2503ac69702061f1ac6885759fc853e6eae - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xa9e8acf069c58aec8825542845fd754e41a9489a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x2c95d751da37a5c1d9c5a7fd465c1d50f3d96160 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xe453c3409f8ad2b1fe1ed08e189634d359705a5b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x89d584a1edb3a70b3b07963f9a3ea5399e38b136 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x4507cef57c46789ef8d1a19ea45f4216bae2b528 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xd1d2eb1b1e90b638588728b4130137d262c87cae - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xe92344b4edf545f3209094b192e46600a19e7c2d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x8a0a9b663693a22235b896f70a229c4a22597623 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x1bbe973bef3a977fc51cbed703e8ffdefe001fed - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xa41d2f8ee4f47d3b860a149765a7df8c3287b7f0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x761d38e5ddf6ccf6cf7c55759d5210750b5d60f3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xc18360217d8f7ab5e7c516566761ea12ce7f9d72 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xe28b3b32b6c345a34ff64674606124dd5aceca30 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x168e209d7b2f58f1f24b8ae7b7d35e662bbf11cc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xb131f4a55907b10d1f0a50d8ab8fa09ec342cd74 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x3472a5a71965499acd81997a54bba8d852c6e53d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x7dd9c5cba05e151c895fde1cf355c9a1d5da6429 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x19efa7d0fc88ffe461d1091f8cbe56dc2708a84f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x14fee680690900ba0cccfc76ad70fd1b95d10e16 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x3c3a81e81dc49a522a592e7622a7e711c06bf354 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xa1290d69c65a6fe4df752f95823fae25cb99e5a7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x92f419fb7a750aed295b0ddf536276bf5a40124f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x2c06ba9e7f0daccbc1f6a33ea67e85bb68fbee3a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x3d658390460295fb963f54dc0899cfb1c30776df - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x8e870d67f660d95d5be530380d0ec0bd388289e1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x853d955acef822db058eb8505911ed77f175b99e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x1294f4183763743c7c9519bec51773fb3acd78fd - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x4e15361fd6b4bb609fa63c81a2be19d873717870 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x695d38eb4e57e0f137e36df7c1f0f2635981246b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x40a7df3df8b56147b781353d379cb960120211d7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xaaef88cea01475125522e117bfe45cf32044e238 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x163f8c2467924be0ae7b5347228cabf260318753 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x30672ae2680c319ec1028b69670a4a786baa0f35 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xc944e90c64b2c07662a292be6244bdf05cda44a7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x15e6e0d4ebeac120f9a97e71faa6a0235b85ed12 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x7d225c4cc612e61d26523b099b0718d03152edef - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x82af49447d8a07e3bd95bd0d56f35241523fbab1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xaf88d065e77c8cc2239327c5edb3a432268e5831 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xff970a61a04b1ca14834a43f5de4533ebddb5cc8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x912ce59144191c1204e64559fe8253a0e49e6548 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x5979d7b546e38e414f7e9822514be443a4800529 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x35751007a407ca6feffe80b3cb397736d2cf4dbe - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xda10009cbd5d07dd0cecc66161fc93d7c9000da1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xeb466342c4d449bc9f53a865d5cb90586f405215 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xfc5a1a6eb076a2c7ad06ed22c90d7e710e35ad0a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x0c880f6761f1af8d9aa9c466984b80dab9a8c9e8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xf97f4df75117a78c1a5a0dbb814af92458539fb4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x9623063377ad1b27544c965ccd7342f7ea7e88c7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x539bde0d7dbd336b79148aa742883198bbf60342 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x3082cc23568ea640225c2467653db90e9250aaa0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x18c11fd286c5ec11c3b683caa813b77f5163a122 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x289ba1701c2f088cf0faf8b3705246331cb8a839 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x4cb9a7ae498cedcbb5eae9f25736ae7d428c9d66 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x00cbcf7b3d37844e44b888bc747bdd75fcf4e555 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xfa7f8980b0f1e64a2062791cc3b0871572f1f7f0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xd79bb960dc8a206806c3a428b31bca49934d18d7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x3096e7bfd0878cc65be71f8899bc4cfb57187ba3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x13ad51ed4f1b7e9dc168d8a00cb3f4ddd85efa60 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x4e352cf164e64adcbad318c3a1e222e9eba4ce42 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x11cdb42b0eb46d95f990bedd4695a6e3fa034978 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xba5ddd1f9d7f570dc94a51479a000e3bce967196 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xc8ccbd97b96834b976c995a67bf46e5754e2c48e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xd07d35368e04a839dee335e213302b21ef14bb4a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x323665443cef804a3b5206103304bd4872ea4253 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x83d6c8c06ac276465e4c92e7ac8c23740f435140 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x87aaffdf26c6885f6010219208d5b161ec7609c0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x1b8d516e2146d7a32aca0fcbf9482db85fd42c3a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xafccb724e3aec1657fc9514e3e53a0e71e80622d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x4425742f1ec8d98779690b5a3a6276db85ddc01a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xec70dcb4a1efa46b8f2d97c310c9c4790ba5ffa8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x3419875b4d3bca7f3fdda2db7a476a79fd31b4fe - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x3b60ff35d3f7f62d636b067dd0dc0dfdad670e4e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x58b9cb810a68a7f3e1e4f8cb45d1b9b3c79705e8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xfa5ed56a203466cbbc2430a43c66b9d8723528e7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x95146881b86b3ee99e63705ec87afe29fcc044d9 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x088cd8f5ef3652623c22d48b1605dcfe860cd704 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xbfd5206962267c7b4b4a8b3d76ac2e1b2a5c4d5e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x6daf586b7370b14163171544fca24abcc0862ac5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x9d2f299715d94d8a7e6f5eaa8e654e8c74a988a7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x580e933d90091b9ce380740e3a4a39c67eb85b4c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x655a6beebf2361a19549a99486ff65f709bd2646 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x9e64d3b9e8ec387a9a58ced80b71ed815f8d82b5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x2297aebd383787a160dd0d9f71508148769342e3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x6694340fc020c5e6b96567843da2df01b2ce1eb6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x772598e9e62155d7fdfe65fdf01eb5a53a8465be - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x431402e8b9de9aa016c743880e04e517074d8cec - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xd74f5255d557944cf7dd0e45ff521520002d5748 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x6fd58f5a2f3468e35feb098b5f59f04157002407 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x561877b6b3dd7651313794e5f2894b2f18be0766 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xf9ca0ec182a94f6231df9b14bd147ef7fb9fa17c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xd77b108d4f6cefaa0cae9506a934e825becca46e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xd56734d7f9979dd94fae3d67c7e928234e71cd4c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xf1264873436a0771e440e2b28072fafcc5eebd01 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x5575552988a3a80504bbaeb1311674fcfd40ad4b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x0341c0c0ec423328621788d4854119b97f44e391 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x764bfc309090e7f93edce53e5befa374cdcb7b8e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xaaa6c1e32c55a7bfa8066a6fae9b42650f262418 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x9e20461bc2c4c980f62f1b279d71734207a6a356 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x7fb7ede54259cb3d4e1eaf230c7e2b1ffc951e9a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x3a18dcc9745edcd1ef33ecb93b0b6eba5671e7ca - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x000000000026839b3f4181f2cf69336af6153b99 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x8b0e6f19ee57089f7649a455d89d7bc6314d04e8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x31c91d8fb96bff40955dd2dbc909b36e8b104dde - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x25d887ce7a35172c62febfd67a1856f20faebb00 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xd4d42f0b6def4ce0383636770ef773390d85c61a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xf8388c2b6edf00e2e27eef5200b1befb24ce141d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x619c82392cb6e41778b7d088860fea8447941f4c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x94025780a1ab58868d9b2dbbb775f44b32e8e6e5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xad4b9c1fbf4923061814dd9d5732eb703faa53d4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xd7a892f28dedc74e6b7b33f93be08abfc394a360 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x3269a3c00ab86c753856fd135d97b87facb0d848 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x4568ca00299819998501914690d6010ae48a59ba - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x21e60ee73f17ac0a411ae5d690f908c3ed66fe12 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xd3188e0df68559c0b63361f6160c57ad88b239d8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x2b41806cbf1ffb3d9e31a9ece6b738bf9d6f645f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xf19547f9ed24aa66b03c3a552d181ae334fbb8db - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x35e6a59f786d9266c7961ea28c7b768b33959cbb - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x59a729658e9245b0cf1f8cb9fb37945d2b06ea27 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xb56c29413af8778977093b9b4947efeea7136c36 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x43ab8f7d2a8dd4102ccea6b438f6d747b1b9f034 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x1d987200df3b744cfa9c14f713f5334cb4bc4d5d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x3404149e9ee6f17fb41db1ce593ee48fbdcd9506 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x080f6aed32fc474dd5717105dba5ea57268f46eb - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xb5a628803ee72d82098d4bcaf29a42e63531b441 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x1622bf67e6e5747b81866fe0b85178a93c7f86e3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x7dd747d63b094971e6638313a6a2685e80c7fb2e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xa2f9ecf83a48b86265ff5fd36cdbaaa1f349916c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x17a8541b82bf67e10b0874284b4ae66858cb1fd5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xbcd4d5ac29e06e4973a1ddcd782cd035d04bc0b7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x42069d11a2cc72388a2e06210921e839cfbd3280 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xbbea044f9e7c0520195e49ad1e561572e7e1b948 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xe85b662fe97e8562f4099d8a1d5a92d4b453bf30 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x3d9907f9a368ad0a51be60f7da3b97cf940982d8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x4e51ac49bc5e2d87e0ef713e9e5ab2d71ef4f336 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x4200000000000000000000000000000000000006 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x7f5c764cbc14f9669b88837ca1490cca17c31607 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x4200000000000000000000000000000000000042 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x0b2c639c533813f4aa9d7837caf62653d097ff85 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x1f32b1c2345538c0c6f582fcb022739c4a194ebb - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x68f180fcce6836688e9084f035309e29bf0a2095 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x94b008aa00579c1307b0ef2c499ad98a8ce58e58 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0xda10009cbd5d07dd0cecc66161fc93d7c9000da1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0xdc6ff44d5d932cbd77b52e5612ba0529dc6226f1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x8c6f28f2f1a3c87f0f938b96d27520d9751ec8d9 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x8700daec35af8ff88c16bdf0418774cb3d7599b4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x920cf626a271321c151d027030d5d08af699456b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x6c84a8f1c29108f47a79964b5fe888d4f4d0de40 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x9e1028f5f1d5ede59748ffcee5532509976840e0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0xeb466342c4d449bc9f53a865d5cb90586f405215 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x350a791bfc2c21f9ed5d10980dad2e2638ffa7f6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x17aabf6838a6303fc6e9c5a227dc1eb6d95c829a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0xf467c7d5a4a9c4687ffc7986ac6ad5a4c81e1404 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x76fb31fb4af56892a25e32cfc43de717950c9278 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0xc5b001dc33727f8f26880b184090d3e252470d45 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x9560e827af36c94d2ac33a39bce1fe78631088db - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x9bcef72be871e61ed4fbbc7630889bee758eb81d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x50c5725949a6f0c72e6c4a641f24049a917db0cb - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0xf98dcd95217e15e05d8638da4c91125e59590b07 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x4b03afc91295ed778320c2824bad5eb5a1d852dd - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0xc40f949f8a4e094d1b49a23ea9241d289b7b2819 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x323665443cef804a3b5206103304bd4872ea4253 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x50bce64397c75488465253c0a034b8097fea6578 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x296f55f8fb28e498b858d0bcda06d955b2cb3f97 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x2598c30330d5771ae9f983979209486ae26de875 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x0994206dfe8de6ec6920ff4d779b0d950605fb53 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0xc3248a1bd9d72fa3da6e6ba701e58cbf818354eb - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x6fd9d7ad17242c41f7131d257212c54a0e816691 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x14778860e937f509e651192a90589de711fb88a9 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0xdfa46478f9e5ea86d57387849598dbfb2e964b02 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x9b88d293b7a791e40d36a39765ffd5a1b9b5c349 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x3eb398fec5f7327c6b15099a9681d9568ded2e82 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x217d47011b23bb961eb6d93ca9945b7501a5bb11 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0xbfd5206962267c7b4b4a8b3d76ac2e1b2a5c4d5e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x1cef2d62af4cd26673c7416957cc4ec619a696a7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x9fd22a17b4a96da3f83797d122172c450381fb88 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0xaddb6a0412de1ba0f936dcaeb8aaa24578dcf3b2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x2791bca1f2de4661ed88a30c99a7a9449aa84174 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x7ceb23fd6bc0add59e62ac25578270cff1b9f619 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x3c499c542cef5e3811e1192ce70d8cc03d5c3359 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x1bfd67037b42cf73acf2047067bd4f2c47d9bfd6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xc2132d05d31c914a87c6611c10748aeb04b58e8f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x53e0bca35ec356bd5dddfebbd1fc0fd03fabad39 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x61299774020da444af134c82fa83e3810b309991 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xd6df932a45c0f255f85145f286ea0b292b21c90b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x2ad2934d5bfb7912304754479dd1f096d5c807da - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xc3c7d422809852031b44ab29eec9f1eff2a58756 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x8f3cf7ad23cd3cadbd9735aff958023239c6a063 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x750e4c4984a9e0f12978ea6742bc1c5d248f40ed - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x111111517e4929d3dcbdfa7cce55d30d4b6bc4d6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xd0258a3fd00f38aa8090dfee343f10a9d4d30d3f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x430ef9263e76dae63c84292c3409d61c598e9682 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xb33eaad8d922b1083446dc23f610c2567fb5180f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xdc3326e71d45186f113a2f448984ca0e8d201995 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x311434160d7537be358930def317afb606c0d737 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x0b3f868e0be5597d5db7feb59e1cadbb0fdda50a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xe3f2b1b2229c0333ad17d03f179b87500e7c5e01 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xac0f66379a6d7801d7726d5a943356a172549adb - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xf88332547c680f755481bf489d890426248bb275 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xe5417af564e4bfda1c483642db72007871397896 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xe261d618a959afffd53168cd07d12e37b26761db - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xe0b52e49357fd4daf2c15e02058dce6bc0057db4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xbbba073c31bf03b8acf7c28ef0738decf3695683 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xe238ecb42c424e877652ad82d8a939183a04c35f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x3b56a704c01d650147ade2b8cee594066b3f9421 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x5fe2b58c013d7601147dcdd68c143a77499f5531 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x172370d5cd63279efa6d502dab29171933a610af - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x53df32548214f51821cf1fe4368109ac5ddea1ff - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xff76c0b48363a7c7307868a81548d340049b0023 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x6f8a06447ff6fcf75d803135a7de15ce88c1d4ec - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x50b728d8d964fd00c2d0aad81718b71311fef68a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x3a58a54c066fdc0f2d55fc9c89f0415c92ebf3c4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x03b54a6e9a984069379fae1a4fc4dbae93b3bccd - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xd93f7e271cb87c23aaa73edc008a79646d1f9912 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x200c234721b5e549c3693ccc93cf191f90dc2af9 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x11cd37bb86f65419713f30673a480ea33c826872 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x8a16d4bf8a0a716017e8d2262c4ac32927797a2f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x9a71012b13ca4d3d0cdc72a177df3ef03b0e76a3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xa1c57f48f0deb89f569dfbe6e2b7f46d33606fd4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x190eb8a183d22a4bdf278c6791b152228857c033 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x2f6f07cdcf3588944bf4c42ac74ff24bf56e7590 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x235737dbb56e8517391473f7c964db31fa6ef280 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x0b220b82f3ea3b7f6d9a1d8ab58930c064a2b5bf - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x8bff1bd27e2789fe390acabc379c380a83b68e84 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xb58458c52b6511dc723d7d6f3be8c36d7383b4a8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x323665443cef804a3b5206103304bd4872ea4253 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x2760e46d9bb43dafcbecaad1f64b93207f9f0ed7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x18ec0a6e18e5bc3784fdd3a3634b31245ab704f6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x431d5dff03120afa4bdf332c61a6e1766ef37bdb - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x6f7c932e7684666c9fd1d44527765433e01ff61d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xeee3371b89fc43ea970e908536fcddd975135d8a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xe5b49820e5a1063f6f4ddf851327b5e8b2301048 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xaa3717090cddc9b227e49d0d84a28ac0a996e6ff - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x62a872d9977db171d9e213a5dc2b782e72ca0033 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x381caf412b45dac0f62fbeec89de306d3eabe384 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xe0bceef36f3a6efdd5eebfacd591423f8549b9d5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x23d29d30e35c5e8d321e1dc9a8a61bfd846d4c5c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x282d8efce846a88b159800bd4130ad77443fa1a1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x74dd45dd579cad749f9381d6227e7e02277c944b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x714db550b574b3e927af3d93e26127d15721d4c2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xfa68fb4628dff1028cfec22b4162fccd0d45efb6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xe631dabef60c37a37d70d3b4f812871df663226f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xdb725f82818de83e99f1dac22a9b5b51d3d04dd4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x3c59798620e5fec0ae6df1a19c6454094572ab92 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x0d0b8488222f7f83b23e365320a4021b12ead608 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xa380c0b01ad15c8cf6b46890bddab5f0868e87f3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x8a953cfe442c5e8855cc6c61b1293fa648bae472 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x45c32fa6df82ead1e2ef74d17b76547eddfaff89 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x11cd72f7a4b699c67f225ca8abb20bc9f8db90c7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x0c9c7712c83b3c70e7c5e11100d33d9401bdf9dd - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x77a6f2e9a9e44fd5d5c3f9be9e52831fc1c3c0a0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xbfc70507384047aa74c29cdc8c5cb88d0f7213ac - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xfcb54da3f4193435184f3f647467e12b50754575 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x9a6a40cdf21a0af417f1b815223fd92c85636c58 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xe111178a87a3bff0c8d18decba5798827539ae99 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x82617aa52dddf5ed9bb7b370ed777b3182a30fd1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x2ab0e9e4ee70fff1fb9d67031e44f6410170d00e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xa486c6bc102f409180ccb8a94ba045d39f8fc7cb - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xc4a206a306f0db88f98a3591419bc14832536862 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xf0059cc2b3e980065a906940fbce5f9db7ae40a7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x16eccfdbb4ee1a85a33f3a9b21175cd7ae753db4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x553d3d295e0f695b9228246232edf400ed3560b5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x14af1f2f02dccb1e43402339099a05a5e363b83c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x7bdf330f423ea880ff95fc41a280fd5ecfd3d09f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x8505b9d2254a7ae468c0e9dd10ccea3a837aef5c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xe2aa7db6da1dae97c5f5c6914d285fbfcc32a128 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xb7b31a6bc18e48888545ce79e83e06003be70930 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x1631244689ec1fecbdd22fb5916e920dfc9b8d30 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xf6372cdb9c1d3674e83842e3800f2a62ac9f3c66 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x692ac1e363ae34b6b489148152b12e2785a3d8d6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x0266f4f08d82372cf0fcbccc0ff74309089c74d1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x7fbc10850cae055b27039af31bd258430e714c62 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xa3fa99a148fa48d14ed51d610c367c61876997f1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x9dbfc1cbf7a1e711503a29b4b5f9130ebeccac96 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x236aa50979d5f3de3bd1eeb40e81137f22ab794b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xf86df9b91f002cfeb2aed0e6d05c4c4eaef7cf02 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x4200000000000000000000000000000000000006 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xd9aaec86b65d86f6a7b5b1b0c42ffa531710b6ca - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x6921b130d297cc43754afba22e5eac0fbf8db75b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x5babfc2f240bc5de90eb7e19d789412db1dec402 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x532f27101965dd16442e59d40670faf5ebb142e4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x833589fcd6edb6e08f4c7c32d4f71b54bda02913 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x4ed4e862860bed51a9570b96d89af5e1b0efefed - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xc1cba3fcea344f92d9239c08c0568f6f2f0ee452 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xac1bd2486aaf3b5c0fc3fd868558b082a531b2b4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x0d97f261b1e88845184f678e2d1e7a98d9fd38de - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x8129b94753f22ec4e62e2c4d099ffe6773969ebc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x3f14920c99beb920afa163031c4e47a3e03b3e4a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x940181a94a35a4569e4529a3cdfb74e38fd98631 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x3419875b4d3bca7f3fdda2db7a476a79fd31b4fe - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xa067436db77ab18b1a315095e4b816791609897c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xafb89a09d82fbde58f18ac6437b3fc81724e4df6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x489fe42c267fe0366b16b0c39e7aeef977e841ef - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x2ae3f1ec7f1f5012cfeab0185bfc7aa3cf0dec22 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xdc46c1e93b71ff9209a0f8076a9951569dc35855 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x91f45aa2bde7393e0af1cc674ffe75d746b93567 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x236aa50979d5f3de3bd1eeb40e81137f22ab794b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xf6e932ca12afa26665dc4dde7e27be02a7c02e50 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x524d524b4c9366be706d3a90dcf70076ca037ae3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x5b5dee44552546ecea05edea01dcd7be7aa6144a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x2598c30330d5771ae9f983979209486ae26de875 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xfa980ced6895ac314e7de34ef1bfae90a5add21b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x469fda1fb46fcb4befc0d8b994b516bd28c87003 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x4e496c0256fb9d4cc7ba2fdf931bc9cbb7731660 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x27d2decb4bfc9c76f0309b8e88dec3a601fe25a8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xbfd5206962267c7b4b4a8b3d76ac2e1b2a5c4d5e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x9e1028f5f1d5ede59748ffcee5532509976840e0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x3c3aa127e6ee3d2f2e432d0184dd36f2d2076b52 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xba5e6fa2f33f3955f0cef50c63dcc84861eab663 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x97c806e7665d3afd84a8fe1837921403d59f3dcc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x8ee73c484a26e0a5df2ee2a4960b789967dd0415 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x00e57ec29ef2ba7df07ad10573011647b2366f6d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x8f019931375454fe4ee353427eb94e2e0c9e0a8c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x93e6407554b2f02640ab806cd57bd83e848ec65d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x55d398326f99059ff775485246999027b3197955 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x2170ed0880ac9a755fd29b2688956bd959f933f8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xfdc66a08b0d0dc44c17bbd471b88f49f50cdd20f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x7130d2a12b9bcbfae4f2634d864a1ee1ce3ead9c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x1d2f0da169ceb9fc7b3144628db156f3f6c60dbe - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xe9e7cea3dedca5984780bafc599bd69add087d56 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xfa54ff1a158b5189ebba6ae130ced6bbd3aea76e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x570a5d26f7765ecb712c0924e4de545b89fd43df - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x47c454ca6be2f6def6f32b638c80f91c9c3c5949 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xad86d0e9764ba90ddd68747d64bffbd79879a238 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xf8a0bf9cf54bb92f17374d9e9a321e6a111a51bd - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xd691d9a68c887bdf34da8c36f63487333acfd103 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x1af3f329e8be154074d8769d1ffa4ee058b1dbc3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x1294f4183763743c7c9519bec51773fb3acd78fd - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xb04906e95ab5d797ada81508115611fee694c2b3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x111111111117dc0aa78b770fa6a738034120c302 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xcc42724c6683b7e57334c4e856f4c9965ed682bd - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x90c97f71e18723b0cf0dfa30ee176ab653e89f40 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x2b72867c32cf673f7b02d208b26889fed353b1f8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x031b41e504677879370e9dbcf937283a8691fa7f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x1ce0c2827e2ef14d5c4f29a091d735a204794041 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xcf3bb6ac0f6d987a5727e2d15e39c2d6061d5bec - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x8ff795a6f4d97e7887c79bea79aba5cc76444adf - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x2dff88a56767223a5529ea5960da7a3f5f766406 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x003d87d02a2a01e9e8a20f507c83e15dd83a33d1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x4b0f1812e5df2a09796481ff14017e6005508003 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xbf5140a22578168fd562dccf235e5d43a02ce9b1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xca1c644704febf4ab81f85daca488d1623c28e63 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x51e72dd1f2628295cc2ef931cb64fdbdc3a0c599 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xbbca42c60b5290f2c48871a596492f93ff0ddc82 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x555296de6a86e72752e5c5dc091fe49713aa145c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x0808bf94d57c905f1236212654268ef82e1e594e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x8457ca5040ad67fdebbcc8edce889a335bc0fbfb - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xcebef3df1f3c5bfd90fde603e71f31a53b11944d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x90ed8f1dc86388f14b64ba8fb4bbd23099f18240 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x9840652dc04fb9db2c43853633f0f62be6f00f98 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xba2ae424d960c26247dd6c32edc70b295c744c43 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x0782b6d8c4551b9760e74c0545a9bcd90bdc41e5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xbe2b6c5e31f292009f495ddbda88e28391c9815e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x8f0528ce5ef7b51152a59745befdd91d97091d2f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xffeecbf8d7267757c2dc3d13d730e97e15bfdf7f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x0eb3a705fc54725037cc9e008bdede697f62f335 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xf21768ccbc73ea5b6fd3c687208a7c2def2d966e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x0000028a2eb8346cd5c0267856ab7594b7a55308 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x76a797a59ba2c17726896976b7b3747bfd1d220f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xc79d1fd14f514cd713b5ca43d288a782ae53eab2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xad29abb318791d579433d831ed122afeaf29dcfe - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x3203c9e46ca618c8c1ce5dc67e7e9d75f5da2377 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xdb021b1b247fe2f1fa57e0a87c748cc1e321f07f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x7083609fce4d1d8dc0c979aab8c869ea2c873402 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xc5f0f7b66764f6ec8c8dff7ba683102295e16409 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xe29142e14e52bdfbb8108076f66f49661f10ec10 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xb0d502e938ed5f4df2e681fe6e419ff29631d62b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x6730f7a6bbb7b9c8e60843948f7feb4b6a17b7f7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x1613957159e9b0ac6c80e824f7eea748a32a0ae2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/celo/0x471ece3750da237f93b8e339c536989b8978a438 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/celo/0x765de816845861e75a25fca122bb6898b8b1282a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/celo/0x66803fb87abd4aac3cbb3fad7c3aa01f6f3fb207 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/celo/0xd8763cba276a3738e6de85b4b3bf5fded6d6ca73 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/celo/0x37f750b7cc259a2f741af45294f6a16572cf5cad - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/celo/0xd71ffd0940c920786ec4dbb5a12306669b5b81ef - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/celo/0xe8537a3d056da446677b9e9d6c5db704eaab4787 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/celo/0x4f604735c1cf31399c6e711d5962b2b3e0225ad3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/celo/0x02de4766c272abc10bc88c220d214a26960a7e92 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/celo/0xceba9300f2b948710d2653dd7b07f33a8b32118c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/celo/0xc16b81af351ba9e64c1a069e3ab18c244a1e3049 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x728f30fa2f100742c7949d1961804fa8e0b1387d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x41ea5d41eeacc2d5c4072260945118a13bb7ebce - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xf21661d0d1d76d3ecb8e1b9f1c923dbfffae4097 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xb0ecc6ac0073c063dcfc026ccdc9039cae2998e1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x00f932f0fe257456b32deda4758922e56a4f4b42 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xa4af354d466e8a68090dd9eb2cb7caf162f4c8c2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xba50933c268f567bdc86e1ac131be072c6b0b71a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xd29da236dd4aac627346e1bba06a619e8c22d7c5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x1bfce574deff725a3f483c334b790e25c8fa9779 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x9e18d5bab2fa94a6a95f509ecb38f8f68322abd3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xcd5fe23c85820f7b72d0926fc9b05b43e359b7ee - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xbf5495efe5db9ce00f80364c8b423567e58d2110 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x065b4e5dfd50ac12a81722fd0a0de81d78ddf7fb - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x57e114b691db790c35207b2e685d4a43181e6061 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x0b7f0e51cd1739d6c96982d55ad8fa634dd43a9c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xc56c7a0eaa804f854b536a5f3d5f49d2ec4b12b8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x594daad7d77592a2b97b725a7ad59d7e188b5bfa - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x8355dbe8b0e275abad27eb843f3eaf3fc855e525 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x2a961d752eaa791cbff05991e4613290aec0d9ac - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x38e68a37e401f7271568cecaac63c6b1e19130b4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x1131d427ecd794714ed00733ac0f851e904c8398 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x1495bc9e44af1f8bcb62278d2bec4540cf0c05ea - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x808507121b80c02388fad14726482e061b8da827 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x44971abf0251958492fee97da3e5c5ada88b9185 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x320623b8e4ff03373931769a31fc52a4e78b5d70 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x6e5970dbd6fc7eb1f29c6d2edf2bc4c36124c0c1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xd40c688da9df74e03566eaf0a7c754ed98fbb8cc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x8afe4055ebc86bd2afb3940c0095c9aca511d852 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x9ce84f6a69986a83d92c324df10bc8e64771030f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xbe4d9c8c638b5f0864017d7f6a04b66c42953847 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x68bbed6a47194eff1cf514b50ea91895597fc91e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x69420e3a3aa9e17dea102bb3a9b3b73dcddb9528 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x7420b4b9a0110cdc71fb720908340c03f9bc03ec - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x03aa6298f1370642642415edc0db8b957783e8d6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xd533a949740bb3306d119cc777fa900ba034cd52 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xf14dd7b286ce197019cba54b189d2b883e70f761 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xa35923162c49cf95e6bf26623385eb431ad920d3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x8cefbeb2172a9382753de431a493e21ba9694004 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x120a3879da835a5af037bb2d1456bebd6b54d4ba - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x69457a1c9ec492419344da01daf0df0e0369d5d0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xf6ce4be313ead51511215f1874c898239a331e37 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x73d7c860998ca3c01ce8c808f5577d94d545d1b4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xeff49b0f56a97c7fd3b51f0ecd2ce999a7861420 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x236501327e701692a281934230af0b6be8df3353 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x5026f006b85729a8b14553fae6af249ad16c9aab - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x66761fa41377003622aee3c7675fc7b5c1c2fac5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x9f9c8ec3534c3ce16f928381372bfbfbfb9f4d24 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xd8c978de79e12728e38aa952a6cb4166f891790f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x7122985656e38bdc0302db86685bb972b145bd3c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x582d872a1b094fc48f5de31d3b73f2d9be47def1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x504624040e0642921c2c266a9ac37cafbd8cda4e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xc548e90589b166e1364de744e6d35d8748996fe8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x4c11249814f11b9346808179cf06e71ac328c1b5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x423f4e6138e475d85cf7ea071ac92097ed631eea - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0x8390a1da07e376ef7add4be859ba74fb83aa02d5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xf94e7d0710709388bce3161c32b4eea56d3f91cc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/ethereum/0xaa95f26e30001251fb905d264aa7b00ee9df6c18 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x2416092f143378750bb29b79ed961ab195cceea5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x6c84a8f1c29108f47a79964b5fe888d4f4d0de40 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x71eeba415a523f5c952cc2f06361d5443545ad28 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x88a269df8fe7f53e590c561954c52fccc8ec0cfb - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x429fed88f10285e61b12bdf00848315fbdfcc341 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xb299751b088336e165da313c33e3195b8c6663a6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xf0a479c9c3378638ec603b8b6b0d75903902550b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xb59c8912c83157a955f9d715e556257f432c35d7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xba0dda8762c24da9487f5fa026a9b64b695a07ea - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xc24a365a870821eb83fd216c9596edd89479d8d7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xa586b3b80d7e3e8d439e25fbc16bc5bcee3e2c85 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xef04804e1e474d3f9b73184d7ef5d786f3fce930 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x2e9a6df78e42a30712c10a9dc4b1c8656f8f2879 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x13a7dedb7169a17be92b0e3c7c2315b46f4772b3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0x1dd6b5f9281c6b4f043c02a83a46c2772024636c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xc5102fe9359fd9a28f877a67e36b0f050d81a3cc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xf525e73bdeb4ac1b0e741af3ed8a8cbb43ab0756 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xe4177c1400a8eee1799835dcde2489c6f0d5d616 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xed5740209fcf6974d6f3a5f11e295b5e468ac27c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/arbitrum/0xe10d4a4255d2d35c9e23e2c4790e073046fbaf5c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x10398abc267496e49106b07dd6be13364d10dc71 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x2218a117083f5b482b0bb821d27056ba9c04b1d3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x395ae52bb17aef68c2888d941736a71dc6d4e125 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/optimism/0x9a601c5bb360811d96a23689066af316a30c3027 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xbac3368b5110f3a3dda8b5a0f7b66edb37c47afe - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x1d3c629ca5c1d0ab3bdf74600e81b4145615df8e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xe9c21de62c5c5d0ceacce2762bf655afdceb7ab3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x658cda444ac43b0a7da13d638700931319b64014 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x3d2bd0e15829aa5c362a4144fdf4a1112fa29b5c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x3fb83a9a2c4408909c058b0bfe5b4823f54fafe2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x00e5646f60ac6fb446f621d146b6e1886f002905 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x12a4cebf81f8671faf1ab0acea4e3429e42869e7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x9ff62d1fc52a907b6dcba8077c2ddca6e6a9d3e1 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0xc61f39418cd27820b5d4e9ba4a7197eefaeb8b05 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x15b7c0c907e4c6b9adaaaabc300c08991d6cea05 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x7f67639ffc8c93dd558d452b8920b28815638c44 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/polygon/0x276c9cbaa4bdf57d7109a41e67bd09699536fa3d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x041fdf3f472d2c8a7ecc458fc3b7f543e6c57ef7 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x3c281a39944a2319aa653d81cfd93ca10983d234 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x96419929d7949d6a801a6909c145c8eef6a40431 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xfea9dcdc9e23a9068bf557ad5b186675c61d33ea - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xdb6e0e5094a25a052ab6845a9f1e486b9a9b3dde - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xcde172dc5ffc46d228838446c57c1227e0b82049 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xff0c532fdb8cd566ae169c1cb157ff2bdc83e105 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x9a26f5433671751c3276a065f57e5a02d2817973 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x3636a7734b669ce352e97780df361ce1f809c58c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x50c5725949a6f0c72e6c4a641f24049a917db0cb - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xe3086852a4b125803c815a158249ae468a3254ca - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xbeb0fd48c2ba0f1aacad2814605f09e08a96b94e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xbc45647ea894030a4e9801ec03479739fa2485f0 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x768be13e1680b5ebe0024c42c896e3db59ec0149 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x928a6a9fc62b2c94baf2992a6fba4715f5bb0066 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xbf4db8b7a679f89ef38125d5f84dd1446af2ea3b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xed899bfdb28c8ad65307fa40f4acab113ae2e14c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x1b6a569dd61edce3c383f6d565e2f79ec3a12980 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x76734b57dfe834f102fb61e1ebf844adf8dd931e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x4621b7a9c75199271f773ebd9a499dbd165c3191 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xaf07d812d1dcec20bf741075bc18660738d226dd - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x7f12d13b34f5f4f0a9449c16bcd42f0da47af200 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x55a6f6cb50db03259f6ab17979a4891313be2f45 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x968d6a288d7b024d5012c0b25d67a889e4e3ec19 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x7a8a5012022bccbf3ea4b03cd2bb5583d915fb1a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xcde90558fc317c69580deeaf3efc509428df9080 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x0028e1e60167b48a938b785aa5292917e7eaca8b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x76e7447bafa3f0acafc9692629b1d1bc937ca15d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x15ac90165f8b45a80534228bdcb124a011f62fee - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x4045b33f339a3027af80013fb5451fdbb01a4492 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xddf98aad8180c3e368467782cd07ae2e3e8d36a5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x698dc45e4f10966f6d1d98e3bfd7071d8144c233 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x3c8665472ec5af30981b06b4e0143663ebedcc1e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x18a8bd1fe17a1bb9ffb39ecd83e9489cfd17a022 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xba0dda8762c24da9487f5fa026a9b64b695a07ea - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x13741c5df9ab03e7aa9fb3bf1f714551dd5a5f8a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xebff2db643cf955247339c8c6bcd8406308ca437 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xfadb26be94c1f959f900bf88cd396b3e803481d6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x52c2b317eb0bb61e650683d2f287f56c413e4cf6 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x38d513ec43dda20f323f26c7bef74c5cf80b6477 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x33ad778e6c76237d843c52d7cafc972bb7cf8729 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x290814ad0fbd2b935f34d7b40306102313d4c63e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x5e432eecd01c12ee7071ee9219c2477a347da192 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xbdf5bafee1291eec45ae3aadac89be8152d4e673 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xff62ddfa80e513114c3a0bf4d6ffff1c1d17aadf - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x8c81b4c816d66d36c4bf348bdec01dbcbc70e987 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x6b82297c6f1f9c3b1f501450d2ee7c37667ab70d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x42069babe14fb1802c5cb0f50bb9d2ad6fef55e2 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x72499bddb67f4ca150e1f522ca82c87bc9fb18c8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x0578d8a44db98b23bf096a382e016e29a5ce0ffe - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x8fe815417913a93ea99049fc0718ee1647a2a07c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x7d12aeb5d96d221071d176980d23c213d88d9998 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xb166e8b140d35d9d8226e40c09f757bac5a4d87d - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x8853f0c059c27527d33d02378e5e4f6d5afb574a - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xf3c052f2baab885c610a748eb01dfbb643ba835b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xcd1cffa8ebc66f1a2cf7675b48ba955ffcb82d8e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xde7a416ac821c77478340eebaa21b68297025ef3 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x2da56acb9ea78330f947bd57c54119debda7af71 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x8972ab69d499b5537a31576725f0af8f67203d38 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x88faea256f789f8dd50de54f9c807eef24f71b16 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x42069de48741db40aef864f8764432bbccbd0b69 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x9a27c6759a6de0f26ac41264f0856617dec6bc3f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xfaa4f3bcfc87d791e9305951275e0f62a98bcb10 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xfd9fa4f785331ce88b5af8994a047ba087c705d8 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x21eceaf3bf88ef0797e3927d855ca5bb569a47fc - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x7d9ce55d54ff3feddb611fc63ff63ec01f26d15f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x4229c271c19ca5f319fb67b4bc8a40761a6d6299 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x80f45eacf6537498ecc660e4e4a2d2f99e195cf4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x1a475d06d967aeb686c98de80d079d72097aeacf - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x4fb9b20dafe45d91ae287f2e07b2e79709308178 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xd3741ac9b3f280b0819191e4b30be4ecd990771e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x09579452bc3872727a5d105f342645792bb8a82b - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x8a24d7260cd02d3dfd8eefb66bc17ad4b17d494c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xd88611a629265c9af294ffdd2e7fa4546612273e - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x9a86980d3625b4a6e69d8a4606d51cbc019e2002 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x1c7a460413dd4e964f96d8dfc56e7223ce88cd85 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x776aaef8d8760129a0398cf8674ee28cefc0eab9 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x28e29ec91db66733a94ee8e3b86a6199117baf99 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xb9898511bd2bad8bfc23eba641ef97a08f27e730 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x76baa16ff15d61d32e6b3576c3a8c83a25c2f180 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x2816a491dd0b7a88d84cbded842a618e59016888 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0xa7ea9d5d4d4c7cf7dbde5871e6d108603c6942a5 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/base/0x586e10db93630a4d2da6c6a34ba715305b556f04 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xf486ad071f3bee968384d2e39e2d8af0fcf6fd46 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x76d36d44dc4595e8d2eb3ad745f175eda134284f - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x1fa4a73a3f0133f0025378af00236f3abdee5d63 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xb3ed0a426155b79b898849803e3b36552f7ed507 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x0ef4a107b48163ab4b57fca36e1352151a587be4 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x62694d43ccb9b64e76e38385d15e325c7712a735 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xa2b726b1145a4773f68593cf171187d8ebe4d495 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0xf275e1ac303a4c9d987a2c48b8e555a77fec3f1c - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/bnb/0x11a31b833d43853f8869c9eec17f60e3b4d2a753 - 2024-09-20T21:06:11.923Z + 2024-05-20T17:20:52.753Z 0.8 https://app.uniswap.org/explore/tokens/celo/0x48065fbbe25f71c9282ddf5e1cd6d6a887483d5e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xbadff0ef41d2a68f22de21eabca8a59aaf495cf0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x1fdd61ef9a5c31b9a2abc7d39c139c779e8412af - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x4ade2b180f65ed752b6f1296d0418ad21eb578c0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x0c5cb676e38d6973837b9496f6524835208145a2 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xb69753c06bb5c366be51e73bfc0cc2e3dc07e371 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x8143182a775c54578c8b7b3ef77982498866945d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x76e222b07c53d28b89b0bac18602810fc22b49a8 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x18aaa7115705e8be94bffebde57af9bfc265b998 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x7d8146cf21e8d7cbe46054e01588207b51198729 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xfe0c30065b384f05761f15d0cc899d4f9f9cc0eb - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x1ce270557c1f68cfb577b856766310bf8b47fd9c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x793a5d8b30aab326f83d20a9370c827fea8fdc51 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xff836a5821e69066c87e268bc51b849fab94240c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xf4d2888d29d722226fafa5d9b24f9164c092421e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x8ed97a637a790be1feff5e888d43629dc05408f6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x31c8eacbffdd875c74b94b077895bd78cf1e64a3 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xc55126051b22ebb829d00368f4b12bde432de5da - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xe0f63a424a4439cbe457d80e4f4b51ad25b2c56c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x8881562783028f5c1bcb985d2283d5e170d88888 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x67466be17df832165f8c80a5a120ccc652bd7e69 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xd939212f16560447ed82ce46ca40a63db62419b5 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x88417754ff7062c10f4e3a4ab7e9f9d9cbda6023 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x5afe3855358e112b5647b952709e6165e1c1eeee - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x02e7f808990638e9e67e1f00313037ede2362361 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xd2bdaaf2b9cc6981fd273dcb7c04023bfbe0a7fe - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x112b08621e27e10773ec95d250604a041f36c582 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x32b053f2cba79f80ada5078cb6b305da92bde6e1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x5ac34c53a04b9aaa0bf047e7291fb4e8a48f2a18 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x26ebb8213fb8d66156f1af8908d43f7e3e367c1d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xe3b9cfb8ea8a4f1279fbc28d3e15b4d2d86f18a0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x8207c1ffc5b6804f6024322ccf34f29c3541ae26 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x255f1b39172f65dc6406b8bee8b08155c45fe1b6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x092baadb7def4c3981454dd9c0a0d7ff07bcfc86 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x53bcf6698c911b2a7409a740eacddb901fc2a2c6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x2ac2b254bc18cd4999f64773a966e4f4869c34ee - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x17fc002b466eec40dae837fc4be5c67993ddbd6f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xc8a4eea31e9b6b61c406df013dd4fec76f21e279 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x498bf2b1e120fed3ad3d42ea2165e9b73f99c1e5 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xe4dddfe67e7164b0fe14e218d80dc4c08edc01cb - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x7c8a1a80fdd00c9cccd6ebd573e9ecb49bfa2a59 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x1debd73e752beaf79865fd6446b0c970eae7732f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xaf5db6e1cc585ca312e8c8f7c499033590cf5c98 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/optimism/0x65559aa14915a70190438ef90104769e5e890a00 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/optimism/0x7fb688ccf682d58f86d7e38e03f9d22e7705448b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/optimism/0x73cb180bf0521828d8849bc8cf2b920918e23032 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/optimism/0x2e3d870790dc77a83dd1d18184acc7439a53f475 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/optimism/0xa00e3a3511aac35ca78530c85007afcd31753819 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/optimism/0x528cdc92eab044e1e39fe43b9514bfdab4412b98 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/optimism/0x4f604735c1cf31399c6e711d5962b2b3e0225ad3 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x1c954e8fe737f99f68fa1ccda3e51ebdb291948c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xf50d05a1402d0adafa880d36050736f9f6ee7dee - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xab0b2ddb9c7e440fac8e140a89c0dbcbf2d7bbff - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x8bc3ec2e7973e64be582a90b08cadd13457160fe - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x64060ab139feaae7f06ca4e63189d86adeb51691 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x5ec03c1f7fa7ff05ec476d19e34a22eddb48acdc - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x9627a3d6872be48410fcece9b1ddd344bf08c53e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x1ed02954d60ba14e26c230eec40cbac55fa3aeea - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x8d3419b9a18651f3926a205ee0b1acea1e7192de - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xb56d0839998fd79efcd15c27cf966250aa58d6d3 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x81f91fe59ee415735d59bd5be5cca91a0ea4fa69 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x87c211144b1d9bdaa5a791b8099ea4123dc31d21 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xf4210f93bc68d63df3286c73eba08c6414f40c0d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xece7b98bd817ee5b1f2f536daf34d0b6af8bb542 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x4c96a67b0577358894407af7bc3158fc1dffbeb5 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x70737489dfdf1a29b7584d40500d3561bd4fe196 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x39353a32eceafe4979a8606512c046c3b6398cc4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x92fb1b7d9730b2f1bd4e2e91368c1eb6fdd2a009 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x174e33ef2effa0a4893d97dda5db4044cc7993a3 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xfdc944fb59201fb163596ee5e209ebc8fa4dcdc5 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x388e543a5a491e7b42e3fbcd127dd6812ea02d0d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x56a38e7216304108e841579041249feb236c887b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x1804e3db872eed4141e482ff74c56862f2791103 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x9de16c805a3227b9b92e39a446f9d56cf59fe640 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xb8d98a102b0079b69ffbc760c8d857a31653e56e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x5d6812722c3693078e4a0dbe3e9affc27a0b2768 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x255f1b39172f65dc6406b8bee8b08155c45fe1b6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xc2fe011c3885277c7f0e7ffd45ff90cadc8ecd12 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xc1ffaef4e7d553bbaf13926e258a1a555a363a07 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x4e73420dcc85702ea134d91a262c8ffc0a72aa70 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xecaf81eb42cd30014eb44130b89bcd6d4ad98b92 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x4eae52907dba9c370e9ee99f0ce810602a4f2c63 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x25d887ce7a35172c62febfd67a1856f20faebb00 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x382ea807a61a418479318efd96f1efbc5c1f2c21 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x6468e79a80c0eab0f9a2b574c8d5bc374af59414 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x3106a0a076bedae847652f42ef07fd58589e001f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xd015422879a1308ba557510345e944b912b9ab73 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x5de8ab7e27f6e7a1fff3e5b337584aa43961beef - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xcf078da6e85389de507ceede0e3d217e457b9d49 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x1bbf25e71ec48b84d773809b4ba55b6f4be946fb - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x7039cd6d7966672f194e8139074c3d5c4e6dcf65 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x943af17c37207c9d7a27d12cb5055542a0b7afa8 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x6d68015171eaa7af9a5a0a103664cf1e506ff699 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x6942806d1b2d5886d95ce2f04314ece8eb825833 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x949d48eca67b17269629c7194f4b727d4ef9e5d6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x9361adf2b72f413d96f81ff40d794b47ce13b331 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x3bb1be077f3f96722ae92ec985ab37fd0a0c4c51 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xdbb7a34bf10169d6d2d0d02a6cbb436cf4381bfa - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x66bff695f3b16a824869a8018a3a6e3685241269 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x85d19fb57ca7da715695fcf347ca2169144523a7 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x069d89974f4edabde69450f9cf5cf7d8cbd2568d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x0fe13ffe64b28a172c58505e24c0c111d149bd47 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x111111111117dc0aa78b770fa6a738034120c302 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xdc7ac5d5d4a9c3b5d8f3183058a92776dc12f4f3 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x482702745260ffd69fc19943f70cffe2cacd70e9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xc555d625828c4527d477e595ff1dd5801b4a600e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x9eec1a4814323a7396c938bc86aec46b97f1bd82 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x87d73e916d7057945c9bcd8cdd94e42a6f47f776 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x067def80d66fb69c276e53b641f37ff7525162f6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xdd157bd06c1840fa886da18a138c983a7d74c1d7 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xe80772eaf6e2e18b651f160bc9158b2a5cafca65 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xb6093b61544572ab42a0e43af08abafd41bf25a6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x35ca1e5a9b1c09fa542fa18d1ba4d61c8edff852 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x83e60b9f7f4db5cdb0877659b1740e73c662c55b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x4d01397994aa636bdcc65c9e8024bc497498c3bb - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xc3abc47863524ced8daf3ef98d74dd881e131c38 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x4d15a3a2286d883af0aa1b3f21367843fac63e07 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xfb7f8a2c0526d01bfb00192781b7a7761841b16c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x3809dcdd5dde24b37abe64a5a339784c3323c44f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x85955046df4668e1dd369d2de9f3aeb98dd2a369 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x554cd6bdd03214b10aafa3e0d4d42de0c5d2937b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x4318cb63a2b8edf2de971e2f17f77097e499459d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xab9cb20a28f97e189ca0b666b8087803ad636b3c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x6a8ec2d9bfbdd20a7f5a4e89d640f7e7ceba4499 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x385eeac5cb85a38a9a07a70c73e0a3271cfb54a7 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x0169ec1f8f639b32eec6d923e24c2a2ff45b9dd6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xe161be4a74ab8fa8706a2d03e67c02318d0a0ad6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x4d58608eff50b691a3b76189af2a7a123df1e9ba - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x420b0fa3de2efcf2b2fd04152eb1df36a09717cd - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x1cd38856ee0fdfd65c757e530e3b1de3061008d3 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xfad8cb754230dbfd249db0e8eccb5142dd675a0d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xda761a290e01c69325d12d82ac402e5a73d62e81 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xafb5d4d474693e68df500c9c682e6a2841f9661a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x0b3e328455c4059eeb9e3f84b5543f74e24e7e1b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xfc5462143a3178cf044e97c491f6bcb5e38f173e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xed1978d01d4a8a9d6a43ac79403d5b8dfbed739b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xba71cb8ef2d59de7399745793657838829e0b147 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x10c1b6f768e13c624a4a23337f1a5ba5c9be0e4b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x1b1514c76c54ce8807d7fdedf85c664eee734ece - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x58cd93c4a91c3940109fa27d700f5013b18b5dc2 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xea6f7e7e0f46a9e0f4e2048eb129d879f609d632 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x30d19fb77c3ee5cfa97f73d72c6a1e509fa06aef - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0xe2dca969624795985f2f083bcd0b674337ba130a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0xbb7d61d2511fd2e63f02178ca9b663458af9fc63 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x59f4f336bf3d0c49dbfba4a74ebd2a6ace40539a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x62d0a8458ed7719fdaf978fe5929c6d342b0bfce - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xb8fda5aee55120247f16225feff266dfdb381d4c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xca530408c3e552b020a2300debc7bd18820fb42f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x3ffeea07a27fab7ad1df5297fa75e77a43cb5790 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xcfeb09c3c5f0f78ad72166d55f9e6e9a60e96eec - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x467bccd9d29f223bce8043b84e8c8b282827790f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x2077d81d0c5258230d5a195233941547cb5f0989 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xa0bbbe391b0d0957f1d013381b643041d2ca4022 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xd1b89856d82f978d049116eba8b7f9df2f342ff3 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x62f03b52c377fea3eb71d451a95ad86c818755d1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x3927fb89f34bbee63351a6340558eebf51a19fb8 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xacd2c239012d17beb128b0944d49015104113650 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x86b69f38bea3e02f68ff88534bc61ec60e772b19 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x6873c95307e13beb58fb8fcddf9a99667655c9e4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x18084fba666a33d37592fa2633fd49a74dd93a88 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x6e79b51959cf968d87826592f46f819f92466615 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x80ee5c641a8ffc607545219a3856562f56427fe9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x0414d8c87b271266a5864329fb4932bbe19c0c49 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xf57e7e7c23978c3caec3c3548e3d615c346e79ff - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xb0ffa8000886e57f86dd5264b9582b2ad87b2b91 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x1c986661170c1834db49c3830130d4038eeeb866 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x9ed7e4b1bff939ad473da5e7a218c771d1569456 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x7f9a7db853ca816b9a138aee3380ef34c437dee0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x371c7ec6d8039ff7933a2aa28eb827ffe1f52f07 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xb1bc21f748ae2be95674876710bc6d78235480e0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xadf5dd3e51bf28ab4f07e684ecf5d00691818790 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/optimism/0x1eba7a6a72c894026cd654ac5cdcf83a46445b08 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x38022a157b95c52d43abcac9bd09f028a1079105 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xd2507e7b5794179380673870d88b22f94da6abe0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xc708d6f2153933daa50b2d0758955be0a93a8fec - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x0052074d3eb1429f39e5ea529b54a650c21f5aa4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x4e78011ce80ee02d2c3e649fb657e45898257815 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x7583feddbcefa813dc18259940f76a02710a8905 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xe78aee6ccb05471a69677fb74da80f5d251c042b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x04f177fcacf6fb4d2f95d41d7d3fee8e565ca1d0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xa6da8c8999c094432c77e7d318951d34019af24b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x6d3b8c76c5396642960243febf736c6be8b60562 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x7cf7132ede0ca592a236b6198a681bb7b42dd5ae - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x3afeae00a594fbf2e4049f924e3c6ac93296b6e8 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x0a93a7be7e7e426fc046e204c44d6b03a302b631 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xc9b6ef062fab19d3f1eabc36b1f2e852af1acd18 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x1754e5aadce9567a95f545b146a616ce34eead53 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xdb173587d459ddb1b9b0f2d6d88febef039304a2 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x10a7a84c91988138f8dbbc82a23b02c8639e2552 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x92af6f53febd6b4c6f5293840b6076a1b82c4bc2 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xeb9e49fb4c33d9f6aefb1b03f9133435e24c0ec6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x1b2c141479757b8643a519be4692904088d860b2 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x4d25e94291fe8dcfbfa572cbb2aaa7b755087c91 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x8e0e798966382e53bfb145d474254cbe065c17dc - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x4b6f82a4ed0b9e3767f53309b87819a78d041a7f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x004aa1586011f3454f487eac8d0d5c647d646c69 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x741777f6b6d8145041f73a0bddd35ae81f55a40f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0xc6c58f600917de512cd02d2b6ed595ab54b4c30f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x03aa6298f1370642642415edc0db8b957783e8d6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x3ee2200efb3400fabb9aacf31297cbdd1d435d47 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x0d8ce2a99bb6e3b7db580ed848240e4a0f9ae153 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0xa697e272a73744b343528c3bc4702f2565b2f422 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x301af3eff0c904dc5ddd06faa808f653474f7fcc - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x776f9987d9deed90eed791cbd824d971fd5ccf09 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0xf7de7e8a6bd59ed41a4b5fe50278b3b7f31384df - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x19e6bfc1a6e4b042fb20531244d47e252445df01 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x4338665cbb7b2485a8855a139b75d5e34ab0db94 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x2940566eb50f15129238f4dc599adc4f742d7d8e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0xbb73bb2505ac4643d5c0a99c2a1f34b3dfd09d11 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x4ea98c1999575aaadfb38237dd015c5e773f75a2 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/celo/0x1d18d0386f51ab03e7e84e71bda1681eba865f1f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x57b96d4af698605563a4653d882635da59bf11af - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xd33526068d116ce69f19a9ee46f0bd304f21a51f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x2a5fa016ffb20c70e2ef36058c08547f344677aa - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xbe0ed4138121ecfc5c0e56b40517da27e6c5226b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x9fd9278f04f01c6a39a9d1c1cd79f7782c6ade08 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x054c9d4c6f4ea4e14391addd1812106c97d05690 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x7613c48e0cd50e42dd9bf0f6c235063145f6f8dc - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x614da3b37b6f66f7ce69b4bbbcf9a55ce6168707 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x069e4aa272d17d9625aa3b6f863c7ef6cfb96713 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x24da31e7bb182cb2cabfef1d88db19c2ae1f5572 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x7d4a23832fad83258b32ce4fd3109ceef4332af4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xb58e61c3098d85632df34eecfb899a1ed80921cb - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x67c4d14861f9c975d004cfb3ac305bee673e996e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x69babe9811cc86dcfc3b8f9a14de6470dd18eda4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x32f0d04b48427a14fb3cbc73db869e691a9fec6f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x4cff49d0a19ed6ff845a9122fa912abcfb1f68a6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x51cb253744189f11241becb29bedd3f1b5384fdb - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xcf4c91ecafc43c9f382db723ba20b82efa852821 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x6968676661ac9851c38907bdfcc22d5dd77b564d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x0d438f3b5175bebc262bf23753c1e53d03432bde - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xb98d4c97425d9908e66e53a6fdf673acca0be986 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x68a47fe1cf42eba4a030a10cd4d6a1031ca3ca0a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x8a370c951f34e295b2655b47bb0985dd08d8f718 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x525574c899a7c877a11865339e57376092168258 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xd9a442856c234a39a81a089c06451ebaa4306a72 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x1c43d05be7e5b54d506e3ddb6f0305e8a66cd04e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xb766039cc6db368759c1e56b79affe831d0cc507 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x18c14c2d707b2212e17d1579789fc06010cfca23 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xe0ee18eacafddaeb38f8907c74347c44385578ab - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x56659245931cb6920e39c189d2a0e7dd0da2d57b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xb6a5ae40e79891e4deadad06c8a7ca47396df21c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x04565fe9aa3ae571ada8e1bebf8282c4e5247b2a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xf8a99f2bf2ce5bb6ce4aafcf070d8723bc904aa2 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x3b9728bd65ca2c11a817ce39a6e91808cceef6fd - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x6797b6244fa75f2e78cdffc3a4eb169332b730cc - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xe2c86869216ac578bd62a4b8313770d9ee359a05 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x47b464edb8dc9bc67b5cd4c9310bb87b773845bd - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x28a730de97dc62a8c88363e0b1049056f1274a70 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xba5ede8d98ab88cea9f0d69918dde28dc23c2553 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x8319767a7b602f88e376368dca1b92d38869b9b4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x461ee40928677644b8195662ab91bcdaae6ef105 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x24569d33653c404f90af10a2b98d6e0030d3d267 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x22222bd682745cf032006394750739684e45a5f8 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x9124577428c5bd73ad7636cbc5014081384f29d6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xaa6cccdce193698d33deb9ffd4be74eaa74c4898 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xe095780ba2a64a4efa7a74830f0b71656f0b0ad4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xb59c8912c83157a955f9d715e556257f432c35d7 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x7771450ece9c61430953d2646f995e33a06c91f5 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xc48823ec67720a04a9dfd8c7d109b2c3d6622094 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x9ec02756a559700d8d9e79ece56809f7bcc5dc27 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x3593d125a4f7849a1b059e64f4517a86dd60c95d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xb0ffa8000886e57f86dd5264b9582b2ad87b2b91 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x6985884c4392d348587b19cb9eaaf157f13271cd - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xa045fe936e26e1e1e1fb27c1f2ae3643acde0171 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xbeef698bd78139829e540622d5863e723e8715f1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x426a688ee72811773eb64f5717a32981b56f10c1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x873259322be8e50d80a4b868d186cc5ab148543a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x661c70333aa1850ccdbae82776bb436a0fcfeefb - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x0a2c375553e6965b42c135bb8b15a8914b08de0c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x6fba952443be1de22232c824eb8d976b426b3c38 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x1abaea1f7c830bd89acc67ec4af516284b1bc33c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xb62132e35a6c13ee1ee0f84dc5d40bad8d815206 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xb60fdf036f2ad584f79525b5da76c5c531283a1b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x5a3e6a77ba2f983ec0d371ea3b475f8bc0811ad5 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x55296f69f40ea6d20e478533c15a6b08b654e758 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x1a7e4e63778b4f12a199c062f3efdd288afcbce8 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x45804880de22913dafe09f4980848ece6ecbaf78 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xe5018913f2fdf33971864804ddb5fca25c539032 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x6985884c4392d348587b19cb9eaaf157f13271cd - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x2c650dab03a59332e2e0c0c4a7f726913e5028c1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x9aee3c99934c88832399d6c6e08ad802112ebeab - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x439c0cf1038f8002a4cad489b427e217ba4b42ad - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/optimism/0x6985884c4392d348587b19cb9eaaf157f13271cd - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x6985884c4392d348587b19cb9eaaf157f13271cd - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x6985884c4392d348587b19cb9eaaf157f13271cd - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xb79dd08ea68a908a97220c76d19a6aa9cbde4376 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x4b61e2f1bbdee6d746209a693156952936f1702c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x7480527815ccae421400da01e052b120cc4255e9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x7466de7bb8b5e41ee572f4167de6be782a7fa75d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x298d411511a05dc1b559ed8f79c56bee06687b14 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x8e16d46cb2da01cdd49601ec73d7b0344969ae33 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x18dd5b087bca9920562aff7a0199b96b9230438b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x37f0c2915cecc7e977183b8543fc0864d03e064c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x37f24b26bcefbfac7f261b97f8036da98f81a299 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xacb5b33ce55ba7729e38b2b59677e71c0112f0d9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x6985884c4392d348587b19cb9eaaf157f13271cd - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0xc71b5f631354be6853efe9c3ab6b9590f8302e81 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x7e744bbb1a49a44dfcc795014a4ba618e418fbbe - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x4e3fbd56cd56c3e72c1403e103b45db9da5b9d2b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x0c04ff41b11065eed8c9eda4d461ba6611591395 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x636bd98fc13908e475f56d8a38a6e03616ec5563 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x590246bfbf89b113d8ac36faeea12b7589f7fe5b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x80034f803afb1c6864e3ca481ef1362c54d094b9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x73fbd93bfda83b111ddc092aa3a4ca77fd30d380 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xff33a6b3dc0127862eedd3978609404b22298a54 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xc770eefad204b5180df6a14ee197d99d808ee52d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xa0385e7283c83e2871e9af49eec0966088421ddd - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xb2617246d0c6c0087f18703d576831899ca94f01 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xba386a4ca26b85fd057ab1ef86e3dc7bdeb5ce70 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x9ebb0895bd9c7c9dfab0d8d877c66ba613ac98ea - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xd12a99dbc40036cec6f1b776dccd2d36f5953b94 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x8ab2ff0116a279a99950c66a12298962d152b83c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x420698cfdeddea6bc78d59bc17798113ad278f9d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xa8c8cfb141a3bb59fea1e2ea6b79b5ecbcd7b6ca - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xd8e8438cf7beed13cfabc82f300fb6573962c9e3 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xb1c9d42fa4ba691efe21656a7e6953d999b990c4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xdadeca1167fe47499e53eb50f261103630974905 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xa05245ade25cc1063ee50cf7c083b4524c1c4302 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x4fafad147c8cd0e52f83830484d164e960bdc6c3 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x4dd9077269dd08899f2a9e73507125962b5bc87f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x8931ee05ec111325c1700b68e5ef7b887e00661d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x26f1bb40ea88b46ceb21557dc0ffac7b7c0ad40f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x642e993fa91ffe9fb24d39a8eb0e0663145f8e92 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x0c41f1fc9022feb69af6dc666abfe73c9ffda7ce - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xf7ccb8a6e3400eb8eb0c47619134f7516e025215 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x2416092f143378750bb29b79ed961ab195cceea5 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xf0268c5f9aa95baf5c25d646aabb900ac12f0800 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x0c067fc190cde145b0c537765a78d4e19873a5cc - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xbe5614875952b1683cb0a2c20e6509be46d353a4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x87a0233a8cb4392ec3eb8fa467817fc0b6a326dd - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xdfbea88c4842d30c26669602888d746d30f9d60d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xb6fe221fe9eef5aba221c348ba20a1bf5e73624c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x80b3455e1db60b4cba46aba12e8b1e256dd64979 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x747747e47a48c669be384e0dfb248eee6ba04039 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/celo/0x50e85c754929840b58614f48e29c64bc78c58345 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x02f92800f57bcd74066f5709f1daa1a4302df875 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x967da4048cd07ab37855c090aaf366e4ce1b9f48 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x729031b3995538ddf6b6bce6e68d5d6fdeb3ccb5 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x6dea81c8171d0ba574754ef6f8b412f2ed88c54d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x97a9a15168c22b3c137e6381037e1499c8ad0978 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x5faa989af96af85384b8a938c2ede4a7378d9875 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x4691937a7508860f876c9c0a2a617e7d9e945d4b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xb50721bcf8d664c30412cfbc6cf7a15145234ad1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x037a54aab062628c9bbae1fdb1583c195585fe41 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xcb8b5cd20bdcaea9a010ac1f8d835824f5c87a04 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xdfb8be6f8c87f74295a87de951974362cedcfa30 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x354a6da3fcde098f8389cad84b0182725c6c91de - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x3f56e0c36d275367b8c502090edf38289b3dea0d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x6f9590958ce2beaf9c92a3a8fca6d1ddf310e052 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/optimism/0x3e5d9d8a63cc8a88748f229999cf59487e90721e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/optimism/0xecc68d0451e20292406967fe7c04280e5238ac7d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xf1c1a3c2481a3a8a3f173a9ab5ade275292a6fa3 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xb5e0cfe1b4db501ac003b740665bf43192cc7853 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xffa188493c15dfaf2c206c97d8633377847b6a52 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xb5c064f955d8e7f38fe0460c556a72987494ee17 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x4f604735c1cf31399c6e711d5962b2b3e0225ad3 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xf0949dd87d2531d665010d6274f06a357669457a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x14e5386f47466a463f85d151653e1736c0c50fc3 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xadac33f543267c4d59a8c299cf804c303bc3e4ac - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xcfa3ef56d303ae4faaba0592388f19d7c3399fb4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x67ce18961c3269ca03c2e5632f1938cc53e614a1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x48164ea5df090e80a0eaee1147e466ea28669221 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x3054e8f8fba3055a42e5f5228a2a4e2ab1326933 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x42069d11a2cc72388a2e06210921e839cfbd3280 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x74ff3cbf86f95fea386f79633d7bc4460d415f34 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x2d6a3893966dda77749cc7e4003ab15f5cfa3cc1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x51b75da3da2e413ea1b8ed3eb078dc712304761c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x8ad5b9007556749de59e088c88801a3aaa87134b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xbd97693278f1948c59f65f130fd87e7ff7c61d11 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x3992b27da26848c2b19cea6fd25ad5568b68ab98 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x34980c35353a8d7b1a1ba02e02e387a8383e004a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0xdebd6e2da378784a69dc6ec99fe254223b312287 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/celo/0x456a3d042c0dbd3db53d5489e98dfb038553b0d0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/celo/0x9995cc8f20db5896943afc8ee0ba463259c931ed - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x30d20208d987713f46dfd34ef128bb16c404d10f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x19848077f45356b21164c412eff3d3e4ff6ebc31 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x53206bf5b6b8872c1bb0b3c533e06fde2f7e22e4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x07ddacf367f0d40bd68b4b80b4709a37bdc9f847 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xbdbe9f26918918bd3f43a0219d54e5fda9ce1bb3 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xb9d09bc374577dac1ab853de412a903408204ea8 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xe72b141df173b999ae7c1adcbf60cc9833ce56a8 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x214549b0317564de15770561221433fb3e8c995c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xc82e3db60a52cf7529253b4ec688f631aad9e7c2 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xf3dcbc6d72a4e1892f7917b7c43b74131df8480e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x62e3b3c557c792c4a70765b3cdb5b56b1879f82d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x2598c30330d5771ae9f983979209486ae26de875 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xd4f4d0a10bcae123bb6655e8fe93a30d01eebd04 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xa0995d43901551601060447f9abf93ebc277cec2 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x40379a439d4f6795b6fc9aa5687db461677a2dba - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x433cde5a82b5e0658da3543b47a375dffd126eb6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x619c4bbbd65f836b78b36cbe781513861d57f39d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x1e0bb24ed6c806c01ef2f880a4b91adb90099ea7 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x0dd7913197bfb6d2b1f03f9772ced06298f1a644 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xfbb75a59193a3525a8825bebe7d4b56899e2f7e1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xc3de830ea07524a0761646a6a4e4be0e114a3c83 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x3792dbdd07e87413247df995e692806aa13d3299 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x527856315a4bcd2f428ea7fa05ea251f7e96a50a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x292fcdd1b104de5a00250febba9bc6a5092a0076 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xd749b369d361396286f8cc28a99dd3425ac05619 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xfe3e6a25e6b192a42a44ecddcd13796471735acf - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xa1faa113cbe53436df28ff0aee54275c13b40975 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x8802269d1283cdb2a5a329649e5cb4cdcee91ab6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x0000bdaa645097ef80f9d475f341d0d107a45b3a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x683a4ac99e65200921f556a19dadf4b0214b5938 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x36c7188d64c44301272db3293899507eabb8ed43 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x8a2279d4a90b6fe1c4b30fa660cc9f926797baa2 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xf418588522d5dd018b425e472991e52ebbeeeeee - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x6135177a17e02658df99a07a2841464deb5b8589 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xcf91b70017eabde82c9671e30e5502d312ea6eb2 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x45080a6531d671ddff20db42f93792a489685e32 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x790814cd782983fab4d7b92cf155187a865d9f18 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x9e6be44cc1236eef7e1f197418592d363bedcd5a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xaa7a9ca87d3694b5755f213b5d04094b8d0f0a6f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x69ee720c120ec7c9c52a625c04414459b3185f23 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x408e41876cccdc0f92210600ef50372656052a38 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x5cf04716ba20127f1e2297addcf4b5035000c9eb - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x8290333cef9e6d528dd5618fb97a76f268f3edd4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x1929761e87667283f087ea9ab8370c174681b4e9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x888888848b652b3e3a0f34c96e00eec0f3a23f72 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xf944e35f95e819e752f3ccb5faf40957d311e8c5 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x1f70300bce8c2302780bd0a153ebb75b8ca7efcb - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x3de81ce90f5a27c5e6a5adb04b54aba488a6d14e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xc87b37a581ec3257b734886d9d3a581f5a9d056c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x1a6b3a62391eccaaa992ade44cd4afe6bec8cff1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x65c936f008bc34fe819bce9fa5afd9dc2d49977f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x07d65c18cecba423298c0aeb5d2beded4dfd5736 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x51fc0f6660482ea73330e414efd7808811a57fa2 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xcbe94d75ec713b7ead84f55620dc3174beeb1cfe - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xd3144ff5f388d36c0a445686c08540296d8b209b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x433e39ce74aef8f409182541269e417ad9b56011 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xb1a03eda10342529bbf8eb700a06c60441fef25d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x6b9bb36519538e0c073894e964e90172e1c0b41f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x689644b86075ed61c647596862c7403e1c474dbf - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x9a6d24c02ec35ad970287ee8296d4d6552a31dbe - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x506beb7965fc7053059006c7ab4c62c02c2d989f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x31b28012f61fc3600e1c076bafc9fd997fb2da90 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xd7d919ea0c33a97ad6e7bd4f510498e2ec98cb78 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xef553b6914dbd17567393f7e55fbd773fff7d0cb - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xe642657e4f43e6dcf0bd73ef24008394574dee28 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xf8b1b47aa748f5c7b5d0e80c726a843913eb573a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xd064c53f043d5aee2ac9503b13ee012bf2def1d0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xfc60aa1ffca50ce08b3cdec9626c0bb9e9b09bec - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x82c8f48ac694841360de84d649a0d48d239b61f8 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x7d89e05c0b93b24b5cb23a073e60d008fed1acf9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x7546e0d4d947a15f914e33de6616ffed826f45ef - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x9a5350edf28c1f93bb36d6e94b5c425fde8e222d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0xaa076b62efc6f357882e07665157a271ab46a063 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x6a6aa13393b7d1100c00a57c76c39e8b6c835041 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x07040971246a73ebda9cf29ea1306bb47c7c4e76 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x6df0e641fc9847c0c6fde39be6253045440c14d3 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x2b640a99991dea2916205ecdc9f9c58f80017ed8 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x38e4adb44ef08f22f5b5b76a8f0c2d0dcbe7dca1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x42069cc15f5befb510430d22ff1c9a1b3ae22cfe - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x40d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x89fd2d8fd8d937f55c89b7da3ceed44fa27e4a81 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x76bc677d444f1e9d57daf5187ee2b7dc852745ae - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xa0084063ea01d5f09e56ef3ff6232a9e18b0bacd - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x4abd5745f326932b1b673bfa592a20d7bb6bc455 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xe53ec727dbdeb9e2d5456c3be40cff031ab40a55 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xf43f21384d03b5cbbddd58d2de64071e4ce76ab0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x33349b282065b0284d756f0577fb39c158f935e6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x33c88d4cac6ac34f77020915a2a88cd0417dc069 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xdce765f021410b3266aa0053c93cb4535f1e12e0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xb50a8e92cb9782c9b8f3c88e4ee8a1d0aa2221d7 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x0a84edf70f30325151631ce7a61307d1f4d619a3 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xc11158c5da9db1d553ed28f0c2ba1cbedd42cfcb - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/optimism/0xb0b195aefa3650a6908f15cdac7d92f8a5791b0b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xdc4f4ed9872571d5ec8986a502a0d88f3a175f1e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x9beec80e62aa257ced8b0edd8692f79ee8783777 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xf95e1c0a67492720ca22842122fe7fa63d5519e5 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xca8e8d244f0d219a6fc9e4793c635cea98d0399c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x6a4f69da1e2fb2a9b11d1aad60d03163fe567732 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x0718f45bbf4781ce891e4e18182f025725f0fc95 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x132bbda4a40d4d6288be49b637ec2c113b5d7600 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x9aaae745cf2830fb8ddc6248b17436dc3a5e701c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x24fcfc492c1393274b6bcd568ac9e225bec93584 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x21fd16cd0ef24a49d28429921e335bb0c1bfadb3 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xa469b7ee9ee773642b3e93e842e5d9b5baa10067 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x8c19f7854b27758ddffdcdc8908f22bf55e00736 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xf2ae0038696774d65e67892c9d301c5f2cbbda58 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x6bc40d4099f9057b23af309c08d935b890d7adc0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xee2a03aa6dacf51c18679c516ad5283d8e7c2637 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x7f911119435d8ded9f018194b4b6661331379a3d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x777be1c6075c20184c4fd76344b7b0b7c858fe6b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x812ba41e071c7b7fa4ebcfb62df5f45f6fa853ee - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x881d4c8618d68872fa404518b2460ea839a02a6a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xba2ae4e0a9c6ecaf172015aa2cdd70a21f5a290b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x1caf237d7a2d103e3e9b1855988c01ac10344600 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x7d4a7be025652995364e0e232063abd9e8d65e6e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x620aa20875ec1144126ea47fb27ecfe6e10d0c56 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xfae103dc9cf190ed75350761e95403b7b8afa6c0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xae7ab96520de3a18e5e111b5eaab095312d7fe84 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x04c154b66cb340f3ae24111cc767e0184ed00cc6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x70e8de73ce538da2beed35d14187f6959a8eca96 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xfb7b4564402e5500db5bb6d63ae671302777c75a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x6810e776880c02933d47db1b9fc05908e5386b96 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x11e969e9b3f89cb16d686a03cd8508c9fc0361af - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x8b5d1d8b3466ec21f8ee33ce63f319642c026142 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x3ed03e95dd894235090b3d4a49e0c3239edce59e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xb3f13b0c61d65d67d7d6215d70c89533ee567a91 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xfea31d704deb0975da8e77bf13e04239e70d7c28 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/optimism/0x66e535e8d2ebf13f49f3d49e5c50395a97c137b1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x9a06db14d639796b25a6cec6a1bf614fd98815ec - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x7fdd7419428955dbf36d4176af5a8f09ad29d1f3 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x8c9037d1ef5c6d1f6816278c7aaf5491d24cd527 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xa9f5031b54c44c3603b4300fde9b8f5cd18ad06f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x57f5fbd3de65dfc0bd3630f732969e5fb97e6d37 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x9ef1139e6b420cc929dd912a5a7adeced6f12e91 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x120edc8e391ba4c94cb98bb65d8856ae6ec1525f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xd7ea82d19f1f59ff1ae95f1945ee6e6d86a25b96 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x2c9ab600d71967ff259c491ad51f517886740cbc - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0xf4c8e32eadec4bfe97e0f595add0f4450a863a11 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x8c49a510756224e887b3d99d00d959f2d86dda1c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x7777cec341e7434126864195adef9b05dcc3489c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x19af07b52e5faa0c2b1e11721c52aa23172fe2f5 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xb7109df1a93f8fe2b8162c6207c9b846c1c68090 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xbbc2ae13b23d715c30720f079fcd9b4a74093505 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x595832f8fc6bf59c85c527fec3740a1b7a361269 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x7316d973b0269863bbfed87302e11334e25ea565 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xa0b73e1ff0b80914ab6fe0444e65848c4c34450b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x2be8e422cb4a5a7f217a8f1b0658952a79132f28 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x83e6f1e41cdd28eaceb20cb649155049fac3d5aa - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xbabe3ce7835665464228df00b03246115c30730a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x2e6a60492fb5b58f5b5d08c7cafc75e740e6dc8e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xc08e7e23c235073c6807c2efe7021304cb7c2815 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x955d5c14c8d4944da1ea7836bd44d54a8ec35ba1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x3540abe4f288b280a0740ad5121aec337c404d15 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xfe8526a77a2c3590e5973ba81308b90bea21fbff - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xd807f7e2818db8eda0d28b5be74866338eaedb86 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x4186bfc76e2e237523cbc30fd220fe055156b41f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xd5d3aa404d7562d09a848f96a8a8d5d65977bf90 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xa3f751662e282e83ec3cbc387d225ca56dd63d3a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xd24157aa1097486dc9d7cf094a7e15026e566b5d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xbed0b9240bdbcc8e33f66d2ca650a5ef60a5bab0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x5d559ea7bb2dae4b694a079cb8328a2145fd32f6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x97b959385dfdcaf252223838746beb232ac601aa - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x18e692c03de43972fe81058f322fa542ae1a5e2c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x38029c62dfa30d9fd3cadf4c64e9b2ab21dbda17 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x4507cef57c46789ef8d1a19ea45f4216bae2b528 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/celo/0x73f93dcc49cb8a239e2032663e9475dd5ef29a08 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x9e523234d36973f9e38642886197d023c88e307e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x5de758bba013e58dae2693aea3f0b12b31a3023d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x1001271083c249bd771e1bb76c22d935809a61ee - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x9d39a5de30e57443bff2a8307a4256c8797a3497 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xf3768d6e78e65fc64b8f12ffc824452130bd5394 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xf2ec4a773ef90c58d98ea734c0ebdb538519b988 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x0f2d719407fdbeff09d87557abb7232601fd9f29 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x180000dda70eb7fb7f3e10e52e88ce88f46e3b3a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xed89fc0f41d8be2c98b13b7e3cd3e876d73f1d30 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x17c50d62e6e8d20d2dc18e9ad79c43263d0720d9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x3b50805453023a91a8bf641e279401a0b23fa6f9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xfd03723a9a3abe0562451496a9a394d2c4bad4ab - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xfe67a4450907459c3e1fff623aa927dd4e28c67a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xc5fb36dd2fb59d3b98deff88425a3f425ee469ed - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x6b021b3f68491974be6d4009fee61a4e3c708fd6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x7ae9ab13fc8945323b778b3f8678145e80ec2efb - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xbc4c97fb9befaa8b41448e1dfcc5236da543217f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/optimism/0x93919784c523f39cacaa98ee0a9d96c3f32b593e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xd55fce7cdab84d84f2ef3f99816d765a2a94a509 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x32e0f9d26d1e33625742a52620cc76c1130efde6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x9b700b043e9587dde9a0c29a9483e2f8fa450d54 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x0b1594b0e896bf165d925956e0df733b8443af6a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x891502ba08132653151f822a3a430198f1844115 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xc702b80a1bebac118cab22ce6f2978ef59563b3f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x1287a235474e0331c0975e373bdd066444d1bd35 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xab36452dbac151be02b16ca17d8919826072f64a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xcc7ff230365bd730ee4b352cc2492cedac49383e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0xa9b038285f43cd6fe9e16b4c80b4b9bccd3c161b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x77be1ba1cd2d7a63bffc772d361168cc327dd8bc - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x00000000efe302beaa2b3e6e1b18d08d69a9012a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xd101dcc414f310268c37eeb4cd376ccfa507f571 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xd09eb9099fac55edcbf4965e0a866779ca365a0c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x7b0df1cd724ec34ec9bc4bd19749b01afb490761 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x71297312753ea7a2570a5a3278ed70d9a75f4f44 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x9e32b13ce7f2e80a01932b42553652e053d6ed8e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x6942040b6d25d6207e98f8e26c6101755d67ac89 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x3301ee63fb29f863f2333bd4466acb46cd8323e6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xfefe157c9d0ae025213092ff9a5cb56ab492bab8 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x44108f0223a3c3028f5fe7aec7f9bb2e66bef82f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x1121acc14c63f3c872bfca497d10926a6098aac5 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xf1376bcef0f78459c0ed0ba5ddce976f1ddf51f4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xce722f60f35c37ab295adc4e6ba45bcc7ca89dd6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x614577036f0a024dbc1c88ba616b394dd65d105a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x93fa0b88c0c78e45980fa74cdd87469311b7b3e4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0xe22c452bd2ade15dfc8ad98286bc6bdf0c9219b7 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x00000000000451f49c692bfc24971cacea2db678 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x00000000702749f73e5210b08b0a3d440078f888 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x86f65121804d2cdbef79f9f072d4e0c2eebabc08 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x127e47aba094a9a87d084a3a93732909ff031419 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x52b492a33e447cdb854c7fc19f1e57e8bfa1777d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x55027a5b06f4340cc4c82dcc74c90ca93dcb173e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x32b133add6d99d085ff23f522662b546b70d54a1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x2ad3d80c917ddbf08acc04277f379e00e4d75395 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xc73dc7ae7a4fa40517aafa941ae1ee436b91a12c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x9f235d23354857efe6c541db92a9ef1877689bcb - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x0c90c756350fb803a7d5d9f9ee5ac29e77369973 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xac12f930318be4f9d37f602cbf89cd33e99aa9d4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x1c45366641014069114c78962bdc371f534bc81c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xc328a59e7321747aebbc49fd28d1b32c1af8d3b2 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x90edf25b14393350f0c1b5b12b6cb3cd3781fb4a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x590f820444fa3638e022776752c5eef34e2f89a6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x1fdb29ad49330b07ae5a87483f598aa6b292039e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x4a220e6096b25eadb88358cb44068a3248254675 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xabd4c63d2616a5201454168269031355f4764337 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x4c1b1302220d7de5c22b495e78b72f2dd2457d45 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x050c24dbf1eec17babe5fc585f06116a259cc77a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x57211299bc356319ba5ca36873eb06896173f8bc - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xfde4c96c8593536e31f229ea8f37b2ada2699bb2 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xf9b738c2e7adc4f299c57afd0890b925a5efea6f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x04c0599ae5a44757c0af6f9ec3b93da8976c150a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x99b2b1a2adb02b38222adcd057783d7e5d1fcc7d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xf9569cfb8fd265e91aa478d86ae8c78b8af55df4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xa3d1a8deb97b111454b294e2324efad13a9d8396 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xd85eff20288ca72ea9eecffb428f89ee5066ca5c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x13f4196cc779275888440b3000ae533bbbbc3166 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x160452f95612699d1a561a70eeeeede67c6812af - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x5ce12f6d9f2fcaf0b11494a1c39e09eeb16ca7e8 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x6894cde390a3f51155ea41ed24a33a4827d3063d - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x6db6fdb5182053eecec778afec95e0814172a474 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xc0cfbe1602dd586349f60e4681bf4badca584ec9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x289ff00235d2b98b0145ff5d4435d3e92f9540a6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xcb76314c2540199f4b844d4ebbc7998c604880ca - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xd7cfdb3cdc33dbeb9e9a4c95b61953cf12a008b3 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xce176825afc335d9759cb4e323ee8b31891de747 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x8f2bf2f59cdf7be4aee71500b9419623202b8636 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x744d70fdbe2ba4cf95131626614a1763df805b9e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x52e6654aee5d59e13ae30b48f8f5dbeb97f708cd - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x38f9bf9dce51833ec7f03c9dc218197999999999 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x7189fb5b6504bbff6a852b13b7b82a3c118fdc27 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/optimism/0x38f9bf9dce51833ec7f03c9dc218197999999999 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x8349314651ede274f8c5fef01aa65ff8da75e57c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x38f9bf9dce51833ec7f03c9dc218197999999999 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x1adcef5c780d8895ac77e6ee9239b4b3ecb76da2 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x38f9bf9dce51833ec7f03c9dc218197999999999 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x917f39bb33b2483dd19546b1e8d2f09ce481ee44 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x60a3e35cc302bfa44cb288bc5a4f316fdb1adb42 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x8b67f2e56139ca052a7ec49cbcd1aa9c83f2752a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x029c58a909fbe3d4be85a24f414dda923a3fde0f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x655a51e6803faf50d4ace80fa501af2f29c856cf - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x9ca5dfa3b0b187d7f53f4ef83ca435a2ec2e4070 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0xb68a20b9e9b06fde873897e12ab3372ce48f1a8a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x0203d275d2a65030889af45ed91d472be3948b92 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xa00453052a36d43a99ac1ca145dfe4a952ca33b8 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x8236a87084f8b84306f72007f36f2618a5634494 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xcbb7c0000ab88b473b1f5afd9ef808440eed33bf - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xbc5ca3c518c8a2930947661237b1b562e34f22b7 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xfd0205066521550d7d7ab19da8f72bb004b4c341 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x880226cbcce551eeafd18c9a9e883c85811b82fc - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xfc21540d6b89667d167d42086e1feb04da3e9b21 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x41d06390b935356b46ad6750bda30148ad2044a4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x8149745670881d99700078ede5903a1a7bebe262 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xcf01a5c02c9b9dd5bf73a5a56bcdbc9dca483d43 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xae0fe8474cf5b1b412b3e4327a1c535ea12b77b7 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xc98d64da73a6616c42117b582e832812e7b8d57f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x70c0b83501a3989d4f8a8693581bb7010194abb5 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x80122c6a83c8202ea365233363d3f4837d13e888 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x455e53cbb86018ac2b8092fdcd39d8444affc3f6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x58aea10748a00d1781d6651f9d78a414ea32ca46 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x406d59819bc2aef682f4ff2769085c98a264f97b - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xc4ce1d6f5d98d65ee25cf85e9f2e9dcfee6cb5d6 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x94025780a1ab58868d9b2dbbb775f44b32e8e6e5 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0xf33687811f3ad0cd6b48dd4b39f9f977bd7165a2 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xcbb7c0000ab88b473b1f5afd9ef808440eed33bf - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xa88594d404727625a9437c3f886c7643872296ae - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x7e72d6410803c40e73806f2a72e3eade5d075cc0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x31ea904a7eca45122890deb8da3473a2081bc9d1 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x48c6740bcf807d6c47c864faeea15ed4da3910ab - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xc5fecc3a29fb57b5024eec8a2239d4621e111cbe - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x184cff0e719826b966025f93e05d8c8b0a79b3f9 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x0c2e08e459fc43ddd1e2718c122f566473f59665 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x1a3a8cf347b2bf5890d3d6a1b981c4f4432c8661 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x8baf5d75cae25c7df6d1e0d26c52d19ee848301a - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x28561b8a2360f463011c16b6cc0b0cbef8dbbcad - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x0fd10b9899882a6f2fcb5c371e17e70fdee00c38 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x7a58c0be72be218b41c608b7fe7c5bb630736c71 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xddaf27167929cd045a7d97d09a4fa1046ece3d89 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x375e104af98872e5b4fe951919e504a47db1757c - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x5408d3883ec28c2de205064ae9690142b035fed2 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x1bb4afbf2ce0c9ec86e6414ad4ba4d9aab1c0de4 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x7391425ca7cee3ee03e09794b819291a572af83e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x38e382f74dfb84608f3c1f10187f6bef5951de93 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xbea269038eb75bdab47a9c04d0f5c572d94b93d5 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xf41a7b7c79840775f70a085c1fc5a762bbc6b180 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x13654df31871b5d01e5fba8e6c21a5d0344820f5 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x4d840b741bc05fde325d4ec0b4cfcd0cea237e4e - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x49b1be61a8ca3f9a9f178d6550e41e00d9162159 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xf5bc3439f53a45607ccad667abc7daf5a583633f - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x0a953dd9fc813fefaf6015b804c9dfa0624690c0 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x44ec807ce2f4a6f2737a92e985f318d035883e47 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0xfb6115445bff7b52feb98650c87f44907e58f802 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x117a123ded97cd125837d9ac19592b77d806fa88 - 2024-09-20T21:06:11.923Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xd9fcd98c322942075a5c3860693e9f4f03aae07b - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x240cd7b53d364a208ed41f8ced4965d11f571b7a - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xb8d6196d71cdd7d90a053a7769a077772aaac464 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xcbde0453d4e7d748077c1b0ac2216c011dd2f406 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x786f112c9a6bc840cdc07cfd840105efd6ef2d4b - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x0bffdd787c83235f6f0afa0faed42061a4619b7a - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x1c43cd666f22878ee902769fccda61f401814efb - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x1b54a6fa1360bd71a0f28f77a1d6fba215d498c3 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xb528edbef013aff855ac3c50b381f253af13b997 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x888888ae2c4a298efd66d162ffc53b3f2a869888 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x4cd27e18757baa3a4fe7b0ab7db083002637a6c5 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x240d6faf8c3b1a7394e371792a3bf9d28dd65515 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x41b1f9dcd5923c9542b6957b9b72169595acbc5c - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xd1f2586790a5bd6da1e443441df53af6ec213d83 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x8de5b80a0c1b02fe4976851d030b36122dbb8624 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x391cf4b21f557c935c7f670218ef42c21bd8d686 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0x8bd35250918ed056304fa8641e083be2c42308bb - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/ethereum/0xc3960227e41c3f54e9b399ce216149dea5315c34 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x59062301fb510f4ea2417b67404cb16d31e604ba - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x75ec618a817eb0a4a7e44ac3dfc64c963daf921a - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x7e7a7c916c19a45769f6bdaf91087f93c6c12f78 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/arbitrum/0x21ccbc5e7f353ec43b2f5b1fb12c3e9d89d30dca - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/optimism/0x87eee96d50fb761ad85b1c982d28a042169d61b1 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x3c720206bfacb2d16fa3ac0ed87d2048dbc401fc - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/polygon/0x8d60fb5886497851aac8c5195006ecf07647ba0d - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xcb327b99ff831bf8223cced12b1338ff3aa322ff - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xf544251d25f3d243a36b07e7e7962a678f952691 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xa7296cefae8477a81e23230ca5d3a3d6f49d3764 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x051fb509e4a775fabd257611eea1efaed8f91359 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xae2bddbcc932c2d2cf286bad0028c6f5074c77b5 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x1dd2d631c92b1acdfcdd51a0f7145a50130050c4 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0xd3c68968137317a57a9babeacc7707ec433548b4 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/base/0x7f6f6720a73c0f54f95ab343d7efeb1fa991f4f7 - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0xf3527ef8de265eaa3716fb312c12847bfba66cef - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0x8888888888f004100c0353d657be6300587a6ccd - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0xe2a59d5e33c6540e18aaa46bf98917ac3158db0d - 2024-09-27T19:51:14.628Z - 0.8 - - - https://app.uniswap.org/explore/tokens/bnb/0xfa2ad87e35fc8d3c9f57d73c4667a4651ce6ad2f - 2024-09-27T19:51:14.628Z + 2024-05-20T17:20:52.753Z 0.8 \ No newline at end of file diff --git a/apps/web/src/components/AccountDrawer/AuthenticatedHeader.tsx b/apps/web/src/components/AccountDrawer/AuthenticatedHeader.tsx index 9f941292461..7b9bd1accd7 100644 --- a/apps/web/src/components/AccountDrawer/AuthenticatedHeader.tsx +++ b/apps/web/src/components/AccountDrawer/AuthenticatedHeader.tsx @@ -17,7 +17,7 @@ import { DeltaArrow } from 'components/Tokens/TokenDetails/Delta' import { LoadingBubble } from 'components/Tokens/loading' import Column from 'components/deprecated/Column' import Row, { AutoRow } from 'components/deprecated/Row' -import { useTokenBalancesQuery } from 'graphql/data/apollo/AdaptiveTokenBalancesProvider' +import { useTokenBalancesQuery } from 'graphql/data/apollo/TokenBalancesProvider' import { useDisableNFTRoutes } from 'hooks/useDisableNFTRoutes' import { useDisconnect } from 'hooks/useDisconnect' import useENSName from 'hooks/useENSName' diff --git a/apps/web/src/components/AccountDrawer/DefaultMenu.tsx b/apps/web/src/components/AccountDrawer/DefaultMenu.tsx index 7294b36719e..ba3389d290a 100644 --- a/apps/web/src/components/AccountDrawer/DefaultMenu.tsx +++ b/apps/web/src/components/AccountDrawer/DefaultMenu.tsx @@ -47,7 +47,7 @@ function DefaultMenu({ drawerOpen }: { drawerOpen: boolean }) { }, 250) return () => clearTimeout(timer) } - return undefined + return }, [drawerOpen, menu, closeSettings]) useEffect(() => { @@ -58,7 +58,6 @@ function DefaultMenu({ drawerOpen }: { drawerOpen: boolean }) { sendAnalyticsEvent(InterfaceEventNameLocal.PortfolioMenuOpened, { name: menu }) }, [menu]) - // eslint-disable-next-line consistent-return const SubMenu = useMemo(() => { switch (menu) { case MenuState.DEFAULT: diff --git a/apps/web/src/components/AccountDrawer/IconButton.tsx b/apps/web/src/components/AccountDrawer/IconButton.tsx index df135ca3770..766ce926491 100644 --- a/apps/web/src/components/AccountDrawer/IconButton.tsx +++ b/apps/web/src/components/AccountDrawer/IconButton.tsx @@ -168,10 +168,10 @@ export const IconWithConfirmTextButton = ({ // keyboard action to cancel useEffect(() => { if (typeof window === 'undefined') { - return undefined + return } if (!showText || !frame) { - return undefined + return } const closeAndPrevent = (e: Event) => { diff --git a/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/OffchainActivityModal.tsx b/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/OffchainActivityModal.tsx index 6aad380de6d..55364fe4d9d 100644 --- a/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/OffchainActivityModal.tsx +++ b/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/OffchainActivityModal.tsx @@ -19,6 +19,7 @@ import Column, { AutoColumn } from 'components/deprecated/Column' import Row from 'components/deprecated/Row' import { LimitDisclaimer } from 'components/swap/LimitDisclaimer' import { SwapModalHeaderAmount } from 'components/swap/SwapModalHeaderAmount' +import { Field } from 'components/swap/constants' import { useCurrency } from 'hooks/Tokens' import { useUSDPrice } from 'hooks/useUSDPrice' import { atom } from 'jotai' @@ -34,7 +35,6 @@ import { InterfaceEventNameLocal } from 'uniswap/src/features/telemetry/constant import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { Trans } from 'uniswap/src/i18n' import { UniverseChainId } from 'uniswap/src/types/chains' -import { CurrencyField } from 'uniswap/src/types/currency' import { ExplorerDataType, getExplorerLink } from 'uniswap/src/utils/linking' import { logger } from 'utilities/src/logger/logger' @@ -238,7 +238,7 @@ export function OrderContent({
252.074 @@ -442,7 +442,7 @@ exports[`OrderContent should render without error, filled order 1`] = ` >
0.10684 @@ -878,7 +878,7 @@ exports[`OrderContent should render without error, limit order 1`] = ` } .c4 img { - width: 19px; + width: 20px; height: 40px; object-fit: cover; } @@ -1019,7 +1019,7 @@ exports[`OrderContent should render without error, limit order 1`] = ` >
252.074 @@ -1089,7 +1089,7 @@ exports[`OrderContent should render without error, limit order 1`] = ` >
0.10684 @@ -1534,7 +1534,7 @@ exports[`OrderContent should render without error, open order 1`] = ` } .c4 img { - width: 19px; + width: 20px; height: 40px; object-fit: cover; } @@ -1664,7 +1664,7 @@ exports[`OrderContent should render without error, open order 1`] = ` >
252.074 @@ -1734,7 +1734,7 @@ exports[`OrderContent should render without error, open order 1`] = ` >
0.10684 diff --git a/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/parseLocal.ts b/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/parseLocal.ts index 531962bd233..4d6c7387ab1 100644 --- a/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/parseLocal.ts +++ b/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/parseLocal.ts @@ -317,7 +317,6 @@ export async function signatureToActivity( switch (signature.type) { case SignatureType.SIGN_UNISWAPX_ORDER: case SignatureType.SIGN_UNISWAPX_V2_ORDER: - case SignatureType.SIGN_PRIORITY_ORDER: case SignatureType.SIGN_LIMIT: { // Only returns Activity items for orders that don't have an on-chain counterpart if (isOnChainOrder(signature.status)) { diff --git a/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/parseRemote.tsx b/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/parseRemote.tsx index 16e3443e527..41bc895888f 100644 --- a/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/parseRemote.tsx +++ b/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/parseRemote.tsx @@ -495,7 +495,7 @@ function parseUniswapXOrder(activity: OrderActivity): Activity | undefined { // If the order is open, do not render it. if (signature.status === UniswapXOrderStatus.OPEN) { - return undefined + return } const { inputToken, inputTokenQuantity, outputToken, outputTokenQuantity } = activity.details diff --git a/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/utils.ts b/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/utils.ts index a953f6bd2c0..85073f7bf82 100644 --- a/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/utils.ts +++ b/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/utils.ts @@ -1,7 +1,7 @@ import { TransactionRequest } from '@ethersproject/abstract-provider' import { Web3Provider } from '@ethersproject/providers' import { permit2Address } from '@uniswap/permit2-sdk' -import { CosignedPriorityOrder, CosignedV2DutchOrder, DutchOrder, getCancelMultipleParams } from '@uniswap/uniswapx-sdk' +import { CosignedV2DutchOrder, DutchOrder, getCancelMultipleParams } from '@uniswap/uniswapx-sdk' import { Activity } from 'components/AccountDrawer/MiniPortfolio/Activity/types' import { getYear, isSameDay, isSameMonth, isSameWeek, isSameYear } from 'date-fns' import { ContractTransaction } from 'ethers/lib/ethers' @@ -100,9 +100,7 @@ function getCancelMultipleUniswapXOrdersParams( .map(({ encodedOrder, type }) => type === SignatureType.SIGN_UNISWAPX_V2_ORDER ? CosignedV2DutchOrder.parse(encodedOrder, chainId) - : type === SignatureType.SIGN_PRIORITY_ORDER - ? CosignedPriorityOrder.parse(encodedOrder, chainId) - : DutchOrder.parse(encodedOrder, chainId), + : DutchOrder.parse(encodedOrder, chainId), ) .map((order) => order.info.nonce) return getCancelMultipleParams(nonces) @@ -155,7 +153,7 @@ async function cancelMultipleUniswapXOrders({ }) { const cancelParams = getCancelMultipleUniswapXOrdersParams(orders, chainId) if (!permit2 || !provider) { - return undefined + return } try { const transactions: ContractTransaction[] = [] @@ -179,7 +177,7 @@ async function getCancelMultipleUniswapXOrdersTransaction( ): Promise { const cancelParams = getCancelMultipleUniswapXOrdersParams(orders, chainId) if (!permit2 || cancelParams.length === 0) { - return undefined + return } try { const tx = await permit2.populateTransaction.invalidateUnorderedNonces(cancelParams[0].word, cancelParams[0].mask) @@ -213,7 +211,7 @@ export function useCreateCancelTransactionRequest( params.orders.filter(({ encodedOrder }) => Boolean(encodedOrder)).length === 0 || !permit2 ) { - return undefined + return } return getCancelMultipleUniswapXOrdersTransaction(params.orders, params.chainId, permit2) }, [params, permit2]) diff --git a/apps/web/src/components/AccountDrawer/MiniPortfolio/Pools/useMultiChainPositions.tsx b/apps/web/src/components/AccountDrawer/MiniPortfolio/Pools/useMultiChainPositions.tsx index 3ca93e7d6da..a3e35f8aa86 100644 --- a/apps/web/src/components/AccountDrawer/MiniPortfolio/Pools/useMultiChainPositions.tsx +++ b/apps/web/src/components/AccountDrawer/MiniPortfolio/Pools/useMultiChainPositions.tsx @@ -212,7 +212,7 @@ export default function useMultiChainPositions( // Fetches positions when existing positions are stale and the document has focus useEffect(() => { if (positionsFetching.current || cachedPositions?.stale === false) { - return undefined + return } else if (document.hasFocus()) { fetchAllPositions() } else { @@ -226,7 +226,7 @@ export default function useMultiChainPositions( window.removeEventListener('focus', onFocus) } } - return undefined + return }, [fetchAllPositions, positionsFetching, cachedPositions?.stale]) const positionsWithFeesAndPrices: PositionInfo[] | undefined = useMemo( diff --git a/apps/web/src/components/AccountDrawer/MiniPortfolio/Tokens/TokensTab.tsx b/apps/web/src/components/AccountDrawer/MiniPortfolio/Tokens/TokensTab.tsx index 24bd3116b7b..f02737c0958 100644 --- a/apps/web/src/components/AccountDrawer/MiniPortfolio/Tokens/TokensTab.tsx +++ b/apps/web/src/components/AccountDrawer/MiniPortfolio/Tokens/TokensTab.tsx @@ -8,7 +8,7 @@ import PortfolioRow, { import { useAccountDrawer } from 'components/AccountDrawer/MiniPortfolio/hooks' import { DeltaArrow } from 'components/Tokens/TokenDetails/Delta' import Row from 'components/deprecated/Row' -import { useTokenBalancesQuery } from 'graphql/data/apollo/AdaptiveTokenBalancesProvider' +import { useTokenBalancesQuery } from 'graphql/data/apollo/TokenBalancesProvider' import { PortfolioBalance, PortfolioToken } from 'graphql/data/portfolios' import { getTokenDetailsURL, gqlToCurrency } from 'graphql/data/util' import styled from 'lib/styled-components' @@ -106,13 +106,13 @@ function TokenRow({ element={InterfaceElementName.MINI_PORTFOLIO_TOKEN_ROW} properties={{ chain_id: currency.chainId, - token_name: token?.name ?? token?.project?.name, + token_name: token?.project?.name ?? token?.name, address: token?.address, }} > } - title={{token?.name ?? token?.project?.name}} + title={{token?.project?.name ?? token?.name}} descriptor={ {formatNumber({ diff --git a/apps/web/src/components/AccountDrawer/MiniPortfolio/__snapshots__/PortfolioLogo.test.tsx.snap b/apps/web/src/components/AccountDrawer/MiniPortfolio/__snapshots__/PortfolioLogo.test.tsx.snap index b1b6c9715ba..9e514fdd053 100644 --- a/apps/web/src/components/AccountDrawer/MiniPortfolio/__snapshots__/PortfolioLogo.test.tsx.snap +++ b/apps/web/src/components/AccountDrawer/MiniPortfolio/__snapshots__/PortfolioLogo.test.tsx.snap @@ -13,7 +13,7 @@ exports[`PortfolioLogo renders with L2 icon 1`] = ` } .c1 img { - width: 19px; + width: 20px; height: 40px; object-fit: cover; } @@ -136,7 +136,7 @@ exports[`PortfolioLogo renders without L2 icon 1`] = ` } .c1 img { - width: 19px; + width: 20px; height: 40px; object-fit: cover; } diff --git a/apps/web/src/components/AccountDrawer/index.tsx b/apps/web/src/components/AccountDrawer/index.tsx index a1aeb5a9adf..c2640b5406b 100644 --- a/apps/web/src/components/AccountDrawer/index.tsx +++ b/apps/web/src/components/AccountDrawer/index.tsx @@ -13,11 +13,10 @@ 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 { INTERFACE_NAV_HEIGHT } from 'uniswap/src/theme/heights' import { isMobileWeb } from 'utilities/src/platform' const DRAWER_WIDTH_XL = '390px' @@ -100,9 +99,9 @@ const Container = styled.div<{ isUniExtensionAvailable?: boolean; $open?: boolea const ExtensionContainerStyles = css` height: auto; - max-height: calc(100% - ${INTERFACE_NAV_HEIGHT + 16}px); + max-height: calc(100% - ${NAV_HEIGHT + 16}px); right: 12px; - top: ${INTERFACE_NAV_HEIGHT}px; + top: ${NAV_HEIGHT}px; ${ScrollBarStyles} ` @@ -116,8 +115,8 @@ const AccountDrawerWrapper = styled.div<{ open: boolean; isUniExtensionAvailable z-index: ${Z_INDEX.modal}; position: absolute; margin-right: 0; - top: ${({ open }) => (open ? `calc(-1 * (100% - ${INTERFACE_NAV_HEIGHT}px))` : 0)}; - height: calc(100% - ${INTERFACE_NAV_HEIGHT}px); + top: ${({ open }) => (open ? `calc(-1 * (100% - ${NAV_HEIGHT}px))` : 0)}; + height: calc(100% - ${NAV_HEIGHT}px); width: 100%; max-width: 100%; diff --git a/apps/web/src/components/AddressQRModal.tsx b/apps/web/src/components/AddressQRModal.tsx index 9a9be9ee7fd..513011f5ed0 100644 --- a/apps/web/src/components/AddressQRModal.tsx +++ b/apps/web/src/components/AddressQRModal.tsx @@ -58,11 +58,9 @@ export function AddressQRModal({ accountAddress }: { accountAddress: Address }) { } } -// eslint-disable-next-line consistent-return export function formatHistoryDuration(duration: HistoryDuration): string { switch (duration) { case HistoryDuration.FiveMinute: diff --git a/apps/web/src/components/Charts/VolumeChart/utils.ts b/apps/web/src/components/Charts/VolumeChart/utils.ts index b09ee580dae..b247b2666e6 100644 --- a/apps/web/src/components/Charts/VolumeChart/utils.ts +++ b/apps/web/src/components/Charts/VolumeChart/utils.ts @@ -205,7 +205,7 @@ export function calculateColumnPositionsInPlace( if (common.spacing > 0 && minColumnWidth < alignToMinimalWidthLimit) { ;(items as ColumnPositionItem[]).forEach((item: ColumnPositionItem, index: number) => { if (!item.column || index < startIndex || index > endIndex) { - return undefined + return } const width = item.column.right - item.column.left + 1 if (width <= minColumnWidth) { diff --git a/apps/web/src/components/Charts/utils.tsx b/apps/web/src/components/Charts/utils.tsx index 96d07f82b79..e52e0b7a773 100644 --- a/apps/web/src/components/Charts/utils.tsx +++ b/apps/web/src/components/Charts/utils.tsx @@ -27,7 +27,6 @@ export const CHART_TYPE_LABELS: Record * Custom time formatter used to customize tick mark labels on the time scale. * Follows the function signature of lightweight-charts' TickMarkFormatter. */ -// eslint-disable-next-line consistent-return export function formatTickMarks(time: UTCTimestamp, tickMarkType: TickMarkType, locale: string): string { const date = new Date(time.valueOf() * 1000) switch (tickMarkType) { diff --git a/apps/web/src/components/ConfirmSwapModal/Pending.tsx b/apps/web/src/components/ConfirmSwapModal/Pending.tsx index 596117e17c8..0f8bf41bb75 100644 --- a/apps/web/src/components/ConfirmSwapModal/Pending.tsx +++ b/apps/web/src/components/ConfirmSwapModal/Pending.tsx @@ -137,7 +137,7 @@ export function Pending({ } else if (uniswapXOrder && uniswapXOrder.status === UniswapXOrderStatus.FILLED) { txHash = uniswapXOrder.txHash } else { - return undefined + return } return getExplorerLink(chainId || UniverseChainId.Mainnet, txHash, ExplorerDataType.TRANSACTION) }, [chainId, swapResult, uniswapXOrder]) diff --git a/apps/web/src/components/ConfirmSwapModal/ProgressIndicator.tsx b/apps/web/src/components/ConfirmSwapModal/ProgressIndicator.tsx index e3849bc781d..c3b892873c6 100644 --- a/apps/web/src/components/ConfirmSwapModal/ProgressIndicator.tsx +++ b/apps/web/src/components/ConfirmSwapModal/ProgressIndicator.tsx @@ -1,5 +1,5 @@ import { ConfirmModalState } from 'components/ConfirmSwapModal' -import { Step, StepDetails } from 'components/ConfirmSwapModal/Step' +import { Step } from 'components/ConfirmSwapModal/Step' import { Sign } from 'components/Icons/Sign' import { Swap } from 'components/Icons/Swap' import CurrencyLogo from 'components/Logo/CurrencyLogo' @@ -18,7 +18,7 @@ import { useIsTransactionConfirmed, useSwapTransactionStatus } from 'state/trans import { colors } from 'theme/colors' import { Divider } from 'theme/components' import { UniswapXOrderStatus } from 'types/uniswapx' -import { StepStatus } from 'uniswap/src/components/ConfirmSwapModal/types' +import { StepDetails, StepStatus } from 'uniswap/src/components/ConfirmSwapModal/Step' import { uniswapUrls } from 'uniswap/src/constants/urls' import { TransactionStatus } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { t } from 'uniswap/src/i18n' diff --git a/apps/web/src/components/ConfirmSwapModal/Step.tsx b/apps/web/src/components/ConfirmSwapModal/Step.tsx index 483bca8c887..23b5129b5ff 100644 --- a/apps/web/src/components/ConfirmSwapModal/Step.tsx +++ b/apps/web/src/components/ConfirmSwapModal/Step.tsx @@ -5,28 +5,7 @@ import Row, { RowBetween } from 'components/deprecated/Row' import styled, { Keyframes, keyframes } from 'lib/styled-components' import { ReactElement, useEffect, useState } from 'react' import { ExternalLink, ThemedText } from 'theme/components' -import { StepStatus } from 'uniswap/src/components/ConfirmSwapModal/types' - -export interface StepDetails { - // Left-justified icon representing the step and grayed out when step is not active - icon: ReactElement - // Ripple animation around the icon of the currently active step (use color extraction to select) - rippleColor?: string - // Text shown before the step becomes active - previewTitle: string - // Text shown when the step is active and awaiting user input - actionRequiredTitle: string | ReactElement - // Text shown when user input has been accepted and step has yet to complete - inProgressTitle?: string - // Amount of time in seconds the user has to take action on a step (e.g. UniswapX exclusivity window) - timeToStart?: number - // Text shown when timeToStart is exceeded (countdown reaches zero) - delayedStartTitle?: string - // Anchor text displayed for the Learn-More link - learnMoreLinkText?: string - // URL for Learn-More link (opened in new tab) - learnMoreLinkHref?: string -} +import { StepDetails, StepStatus } from 'uniswap/src/components/ConfirmSwapModal/Step' const ringAnimation = keyframes` 0% { @@ -135,7 +114,7 @@ export function Step({ stepStatus, stepDetails }: { stepStatus: StepStatus; step setSecondsRemaining(stepDetails.timeToStart) } else { setSecondsRemaining(null) - return undefined + return } const timer = setInterval(() => { diff --git a/apps/web/src/components/ConfirmSwapModal/index.tsx b/apps/web/src/components/ConfirmSwapModal/index.tsx index 3d731feb9e3..57055b11742 100644 --- a/apps/web/src/components/ConfirmSwapModal/index.tsx +++ b/apps/web/src/components/ConfirmSwapModal/index.tsx @@ -9,6 +9,7 @@ import { MODAL_TRANSITION_DURATION } from 'components/Modal' import { AutoColumn } from 'components/deprecated/Column' import { SwapDetails } from 'components/swap/SwapDetails' import { SwapPreview } from 'components/swap/SwapPreview' +import { Field } from 'components/swap/constants' import { useConfirmModalState } from 'hooks/useConfirmModalState' import { Allowance, AllowanceState } from 'hooks/usePermit2Allowance' import { SwapResult } from 'hooks/useSwapCallback' @@ -25,7 +26,6 @@ import { FadePresence } from 'theme/components/FadePresence' import { UniswapXOrderStatus } from 'types/uniswapx' import { TransactionStatus } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' -import { CurrencyField } from 'uniswap/src/types/currency' import { SignatureExpiredError, UniswapXv2HardQuoteError } from 'utils/errors' import { formatSwapPriceUpdatedEventProperties } from 'utils/loggingFormatters' import { didUserReject } from 'utils/swapErrorToUserReadableMessage' @@ -75,7 +75,7 @@ export function ConfirmSwapModal({ clearSwapState: () => void onAcceptChanges?: () => void onConfirm: () => void - onCurrencySelection: (field: CurrencyField, currency: Currency) => void + onCurrencySelection: (field: Field, currency: Currency) => void onDismiss: () => void onXV2RetryWithClassic?: () => void }) { @@ -121,7 +121,7 @@ export function ConfirmSwapModal({ return approvalError } if (swapError instanceof SignatureExpiredError) { - return undefined + return } if (swapError instanceof UniswapXv2HardQuoteError) { return PendingModalError.XV2_HARD_QUOTE_ERROR @@ -129,7 +129,7 @@ export function ConfirmSwapModal({ if (swapError && !didUserReject(swapError)) { return PendingModalError.CONFIRMATION_ERROR } - return undefined + return }, [approvalError, swapError]) // Determine which view to show based on confirm modal state and other conditions diff --git a/apps/web/src/components/CurrencyInputPanel/LimitPriceInputPanel/LimitPriceInputLabel.tsx b/apps/web/src/components/CurrencyInputPanel/LimitPriceInputPanel/LimitPriceInputLabel.tsx index 325d07eeb99..13bdb191137 100644 --- a/apps/web/src/components/CurrencyInputPanel/LimitPriceInputPanel/LimitPriceInputLabel.tsx +++ b/apps/web/src/components/CurrencyInputPanel/LimitPriceInputPanel/LimitPriceInputLabel.tsx @@ -1,7 +1,7 @@ import { Currency } from '@uniswap/sdk-core' import CurrencyLogo from 'components/Logo/CurrencyLogo' import Row from 'components/deprecated/Row' -import { PrefetchBalancesWrapper } from 'graphql/data/apollo/AdaptiveTokenBalancesProvider' +import { PrefetchBalancesWrapper } from 'graphql/data/apollo/TokenBalancesProvider' import styled from 'lib/styled-components' import { ClickableStyle, ThemedText } from 'theme/components' import { Text } from 'ui/src' diff --git a/apps/web/src/components/CurrencyInputPanel/LimitPriceInputPanel/LimitPriceInputPanel.tsx b/apps/web/src/components/CurrencyInputPanel/LimitPriceInputPanel/LimitPriceInputPanel.tsx index 82d4c46fe63..473e3750233 100644 --- a/apps/web/src/components/CurrencyInputPanel/LimitPriceInputPanel/LimitPriceInputPanel.tsx +++ b/apps/web/src/components/CurrencyInputPanel/LimitPriceInputPanel/LimitPriceInputPanel.tsx @@ -12,7 +12,7 @@ import { StyledNumericalInput } from 'components/NumericalInput' import CurrencySearchModal from 'components/SearchModal/CurrencySearchModal' import Row from 'components/deprecated/Row' import { parseUnits } from 'ethers/lib/utils' -import { PrefetchBalancesWrapper } from 'graphql/data/apollo/AdaptiveTokenBalancesProvider' +import { PrefetchBalancesWrapper } from 'graphql/data/apollo/TokenBalancesProvider' import JSBI from 'jsbi' import styled from 'lib/styled-components' import { ReversedArrowsIcon } from 'nft/components/icons' diff --git a/apps/web/src/components/CurrencyInputPanel/SwapCurrencyInputPanel.tsx b/apps/web/src/components/CurrencyInputPanel/SwapCurrencyInputPanel.tsx index 6f2f903d893..5deac4befab 100644 --- a/apps/web/src/components/CurrencyInputPanel/SwapCurrencyInputPanel.tsx +++ b/apps/web/src/components/CurrencyInputPanel/SwapCurrencyInputPanel.tsx @@ -14,7 +14,7 @@ import Tooltip from 'components/Tooltip' import { AutoColumn } from 'components/deprecated/Column' import { RowBetween, RowFixed } from 'components/deprecated/Row' import { useIsSupportedChainId } from 'constants/chains' -import { PrefetchBalancesWrapper } from 'graphql/data/apollo/AdaptiveTokenBalancesProvider' +import { PrefetchBalancesWrapper } from 'graphql/data/apollo/TokenBalancesProvider' import { useAccount } from 'hooks/useAccount' import styled, { useTheme } from 'lib/styled-components' import ms from 'ms' diff --git a/apps/web/src/components/CurrencyInputPanel/index.tsx b/apps/web/src/components/CurrencyInputPanel/index.tsx index 6f2f7b090d7..abbf11eefcb 100644 --- a/apps/web/src/components/CurrencyInputPanel/index.tsx +++ b/apps/web/src/components/CurrencyInputPanel/index.tsx @@ -11,7 +11,7 @@ import { Input as NumericalInput } from 'components/NumericalInput' import CurrencySearchModal from 'components/SearchModal/CurrencySearchModal' import { RowBetween, RowFixed } from 'components/deprecated/Row' import { useIsSupportedChainId } from 'constants/chains' -import { PrefetchBalancesWrapper } from 'graphql/data/apollo/AdaptiveTokenBalancesProvider' +import { PrefetchBalancesWrapper } from 'graphql/data/apollo/TokenBalancesProvider' import { useAccount } from 'hooks/useAccount' import styled, { useTheme } from 'lib/styled-components' import { darken } from 'polished' diff --git a/apps/web/src/components/DropdownSelector/index.tsx b/apps/web/src/components/DropdownSelector/index.tsx index fe2392c953c..4b872c9ec22 100644 --- a/apps/web/src/components/DropdownSelector/index.tsx +++ b/apps/web/src/components/DropdownSelector/index.tsx @@ -2,6 +2,7 @@ import FilterButton from 'components/DropdownSelector/FilterButton' import { MouseoverTooltip, TooltipSize } from 'components/Tooltip' import { useOnClickOutside } from 'hooks/useOnClickOutside' import { useRef } from 'react' +import { NAV_HEIGHT } from 'theme' import { AnimatePresence, Flex, @@ -16,7 +17,6 @@ import { import { RotatableChevron } from 'ui/src/components/icons/RotatableChevron' import { zIndices } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme/iconSizes' -import { INTERFACE_NAV_HEIGHT } from 'uniswap/src/theme/heights' export const InternalMenuItem = styled(Text, { display: 'flex', @@ -156,7 +156,7 @@ export function DropdownSelector({ isOpen={isOpen && isSheet} onClose={() => toggleOpen(false)} {...dropdownStyle} - maxHeight={`calc(100dvh - ${INTERFACE_NAV_HEIGHT}px)`} + 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 88facb1ce2d..4588dc6e72a 100644 --- a/apps/web/src/components/FeatureFlagModal/FeatureFlagModal.tsx +++ b/apps/web/src/components/FeatureFlagModal/FeatureFlagModal.tsx @@ -223,10 +223,6 @@ export default function FeatureFlagModal() { flag={FeatureFlags.IndicativeSwapQuotes} label="[Universal Swap Flow Only] Enable Quick Routes" /> - { - setCreateFeeValue('') - setCreateModeEnabled(false) - setFeeTierSearchModalOpen(false) - } - const { t } = useTranslation() - const [searchValue, setSearchValue] = useState('') - const [createFeeValue, setCreateFeeValue] = useState('') - const [createModeEnabled, setCreateModeEnabled] = useState(false) - const { formatPercent } = useFormatter() - const [autoDecrementing, setAutoDecrementing] = useState(false) - const [autoIncrementing, setAutoIncrementing] = useState(false) - const [holdDuration, setHoldDuration] = useState(0) - const hiddenObserver = useResizeObserver() - - useEffect(() => { - let interval: NodeJS.Timeout - let holdTimeout: NodeJS.Timeout - const baseInterval = 100 - let currentInterval = baseInterval - - if (autoDecrementing || autoIncrementing) { - holdTimeout = setTimeout(() => { - setHoldDuration((prev) => prev + 1) - }, ms('1s')) - - if (holdDuration >= 2) { - currentInterval = baseInterval / 2 - } - if (holdDuration >= 4) { - currentInterval = baseInterval / 4 - } - if (holdDuration >= 6) { - currentInterval = baseInterval / 8 - } - - interval = setInterval(() => { - setCreateFeeValue((prev) => { - let newValue = parseFloat(prev) - if (autoDecrementing) { - newValue -= 0.01 - if (newValue < 0) { - return '0' - } - } else if (autoIncrementing) { - newValue += 0.01 - if (newValue > 100) { - return '100' - } - } - return newValue.toFixed(2) - }) - }, currentInterval) - - return () => { - clearInterval(interval) - clearTimeout(holdTimeout) - } - } - - return () => { - clearInterval(interval) - clearTimeout(holdTimeout) - setHoldDuration(0) // Reset hold duration on release - } - }, [autoDecrementing, autoIncrementing, holdDuration]) - - // TODO(WEB-4920): use tiers from Positions API for this specific pool, not presets. - const feeTiers = [FeeAmount.LOWEST, FeeAmount.LOW, FeeAmount.MEDIUM, FeeAmount.HIGH] - - return ( - - - - {createModeEnabled && ( - setCreateModeEnabled(false)}> - - - )} - - {createModeEnabled ? t('fee.tier.create') : t('fee.tier.select')} - - - - - {createModeEnabled ? ( - - - {t('fee.tier.create.description')} - - - { - setAutoDecrementing(true) - }} - onPressOut={() => { - setAutoDecrementing(false) - }} - onPress={() => { - setCreateFeeValue((prev) => { - if (!prev || prev === '') { - return '0' - } - const newValue = parseFloat(prev) - 0.01 - if (newValue < 0) { - return '0' - } - return newValue.toFixed(2) - }) - }} - {...ClickableTamaguiStyle} - > - - - - - - { - if (parseInt(input) > 100) { - setCreateFeeValue('100') - } else { - setCreateFeeValue(input) - } - }} - placeholder="0" - maxDecimals={2} - maxLength={4} - $width={createFeeValue && hiddenObserver.width ? hiddenObserver.width + 1 : undefined} - /> - % - {createFeeValue} - - - { - setAutoIncrementing(true) - }} - onPressOut={() => { - setAutoIncrementing(false) - }} - onPress={() => { - setCreateFeeValue((prev) => { - if (!prev || prev === '') { - return '0.01' - } - const newValue = parseFloat(prev) + 0.01 - if (newValue > 100) { - return '100' - } - return newValue.toFixed(2) - }) - }} - {...ClickableTamaguiStyle} - > - + - - - {/* TODO(WEB-4920): search existing fee tiers for a match and optionally show this, with real TVL value */} - {/* - {t('fee.tier.alreadyExists', { formattedTVL: '$289.6K' })} - */} - {/* TODO(WEB-4920): search existing fee tiers for close matches and optionally similar list */} - - - - ) : ( - <> - - - { - setSearchValue(event.target.value) - }} - value={searchValue} - /> - - - {/* TODO(WEB-4920): filter fee tiers based on search term */} - {feeTiers.map((feeTier) => ( - { - setPositionState((prevState) => ({ ...prevState, fee: feeTier })) - onClose() - }} - > - - {formatPercent(new Percent(feeTier, 1000000))} - - {/* TODO(WEB-4920): use real data from positions API */} - - $289.6K TVL - - - {t('fee.tier.percent.select', { percentage: 4 })} - - - - {feeTier === selectedFee && } - - ))} - - - - {t('fee.tier.missing.description')} - - - - - )} - - - ) -} diff --git a/apps/web/src/components/Liquidity/LiquidityPositionAmountsTile.tsx b/apps/web/src/components/Liquidity/LiquidityPositionAmountsTile.tsx deleted file mode 100644 index ea07a8e2aed..00000000000 --- a/apps/web/src/components/Liquidity/LiquidityPositionAmountsTile.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { Currency, CurrencyAmount } from '@uniswap/sdk-core' -import { useCurrencyInfo } from 'hooks/Tokens' -import { Flex, Text } from 'ui/src' -import { CurrencyLogo } from 'uniswap/src/components/CurrencyLogo/CurrencyLogo' - -export function LiquidityPositionAmountsTile({ - currency0Amount, - currency1Amount, -}: { - currency0Amount: CurrencyAmount - currency1Amount: CurrencyAmount -}) { - // TODO(WEB-4920): skip GraphQL call once backend provides image URLs - const currencyInfo0 = useCurrencyInfo(currency0Amount.currency) - const currencyInfo1 = useCurrencyInfo(currency1Amount.currency) - // TODO(WEB-4920): calculate real values for USD amounts and percentages - return ( - - - - - - {currency0Amount.currency.symbol} - - - - - {currency0Amount.toFixed()} - - - ($0) - - - - 45% - - - - - - - - - {currency1Amount.currency.symbol} - - - - - {currency1Amount.toFixed()} - - - ($0) - - - - 55% - - - - - - ) -} diff --git a/apps/web/src/components/Liquidity/LiquidityPositionCard.tsx b/apps/web/src/components/Liquidity/LiquidityPositionCard.tsx index 69fb51c4b2e..f847a9396aa 100644 --- a/apps/web/src/components/Liquidity/LiquidityPositionCard.tsx +++ b/apps/web/src/components/Liquidity/LiquidityPositionCard.tsx @@ -21,7 +21,6 @@ export function LiquidityPositionCard({ liquidityPosition, ...rest }: { liquidit borderRadius="$rounded20" borderColor="$surface3" width="100%" - overflow="hidden" {...rest} > diff --git a/apps/web/src/components/Liquidity/LiquidityPositionInfo.tsx b/apps/web/src/components/Liquidity/LiquidityPositionInfo.tsx index 4a25637dea7..0c65d5ec3cd 100644 --- a/apps/web/src/components/Liquidity/LiquidityPositionInfo.tsx +++ b/apps/web/src/components/Liquidity/LiquidityPositionInfo.tsx @@ -1,11 +1,10 @@ // eslint-disable-next-line no-restricted-imports import { Position } from '@uniswap/client-pools/dist/pools/v1/types_pb' -import { BadgeData, LiquidityPositionInfoBadges } from 'components/Liquidity/LiquidityPositionInfoBadges' +import { LiquidityPositionInfoBadges } from 'components/Liquidity/LiquidityPositionInfoBadges' import { LiquidityPositionStatusIndicator } from 'components/Liquidity/LiquidityPositionStatusIndicator' import { getProtocolVersionLabel, usePositionInfo } from 'components/Liquidity/utils' import { DoubleCurrencyAndChainLogo } from 'components/Logo/DoubleLogo' import { Flex, Text } from 'ui/src' -import { DocumentList } from 'ui/src/components/icons/DocumentList' interface LiquidityPositionInfoProps { position: Position @@ -33,15 +32,7 @@ export function LiquidityPositionInfo({ position }: LiquidityPositionInfoProps) } - : undefined, - feeTier ? { label: `${Number(feeTier) / 10000}%` } : undefined, - ].filter(Boolean) as BadgeData[] - } + labels={[versionLabel, v4hook, feeTier].filter(Boolean) as string[]} /> diff --git a/apps/web/src/components/Liquidity/LiquidityPositionInfoBadges.test.tsx b/apps/web/src/components/Liquidity/LiquidityPositionInfoBadges.test.tsx index 178b9c00a05..7a37d352316 100644 --- a/apps/web/src/components/Liquidity/LiquidityPositionInfoBadges.test.tsx +++ b/apps/web/src/components/Liquidity/LiquidityPositionInfoBadges.test.tsx @@ -1,21 +1,19 @@ import { LiquidityPositionInfoBadges } from 'components/Liquidity/LiquidityPositionInfoBadges' import { render } from 'test-utils/render' -const testBadgeData = [{ label: 'test', copyable: true }, { label: 'test2' }] - describe('LiquidityPositionInfoBadges', () => { it('should render with default size', () => { - const { getByText } = render() + const { getByText } = render() expect(getByText('test')).toBeInTheDocument() }) it('should render with small size', () => { - const { getByText } = render() + const { getByText } = render() expect(getByText('test')).toBeInTheDocument() }) - it('should render with multiple badges', () => { - const { getByText } = render() + it('should render with multiple labels', () => { + const { getByText } = render() expect(getByText('test')).toBeInTheDocument() expect(getByText('test2')).toBeInTheDocument() }) diff --git a/apps/web/src/components/Liquidity/LiquidityPositionInfoBadges.tsx b/apps/web/src/components/Liquidity/LiquidityPositionInfoBadges.tsx index 7e9b18eba9e..d00db7ea315 100644 --- a/apps/web/src/components/Liquidity/LiquidityPositionInfoBadges.tsx +++ b/apps/web/src/components/Liquidity/LiquidityPositionInfoBadges.tsx @@ -1,11 +1,6 @@ -import { CopyHelper } from 'theme/components' import { styled, Text } from 'ui/src' -import { isAddress, shortenAddress } from 'utilities/src/addresses' -export const PositionInfoBadge = styled(Text, { - display: 'flex', - flexDirection: 'row', - gap: '$spacing2', +const PositionInfoBadge = styled(Text, { variant: 'body3', color: '$neutral2', backgroundColor: '$surface3', @@ -41,41 +36,20 @@ function getPlacement(index: number, length: number): 'start' | 'middle' | 'end' return length === 1 ? 'only' : index === 0 ? 'start' : index === length - 1 ? 'end' : 'middle' } -export interface BadgeData { - label: string - copyable?: boolean - icon?: JSX.Element -} - export function LiquidityPositionInfoBadges({ - badges, + labels, size = 'default', }: { - badges: BadgeData[] + labels: string[] size: 'small' | 'default' }): JSX.Element { return ( <> - {badges.map(({ label, copyable, icon }, index) => { - const displayLabel = isAddress(label) ? shortenAddress(label) : label - return ( - - {icon} - {copyable ? ( - - {displayLabel} - - ) : ( - displayLabel - )} - - ) - })} + {labels.map((label, index) => ( + + {label} + + ))} ) } diff --git a/apps/web/src/components/Liquidity/LiquidityPositionPriceRangeTile.tsx b/apps/web/src/components/Liquidity/LiquidityPositionPriceRangeTile.tsx deleted file mode 100644 index 52a19a4a9d5..00000000000 --- a/apps/web/src/components/Liquidity/LiquidityPositionPriceRangeTile.tsx +++ /dev/null @@ -1,130 +0,0 @@ -// eslint-disable-next-line no-restricted-imports -import { PositionStatus } from '@uniswap/client-pools/dist/pools/v1/types_pb' -import { Currency, Price } from '@uniswap/sdk-core' -import { LiquidityPositionStatusIndicator } from 'components/Liquidity/LiquidityPositionStatusIndicator' -import { useMemo, useState } from 'react' -import { Flex, SegmentedControl, SegmentedControlOption, Text, styled } from 'ui/src' -import { Trans } from 'uniswap/src/i18n' - -const InnerTile = styled(Flex, { - grow: true, - alignItems: 'center', - gap: '$gap8', - borderRadius: '$rounded12', - backgroundColor: '$surface3', - p: '$padding16', -}) - -interface LiquidityPositionPriceRangeTileProps { - status: PositionStatus - minPrice: Price - maxPrice: Price - currentPrice: Price -} - -export function LiquidityPositionPriceRangeTile({ - status, - minPrice, - maxPrice, - currentPrice, -}: LiquidityPositionPriceRangeTileProps) { - const [pricesInverted, setPricesInverted] = useState(false) - const currencyASymbol = currentPrice.baseCurrency.symbol - const currencyBSymbol = currentPrice.quoteCurrency.symbol - - const controlOptions: SegmentedControlOption[] = useMemo(() => { - return [ - { - value: currencyASymbol ?? '', - display: {currencyASymbol}, - }, - { - value: currencyBSymbol ?? '', - display: {currencyBSymbol}, - }, - ] - }, [currencyASymbol, currencyBSymbol]) - - if (!currencyASymbol || !currencyBSymbol) { - throw new Error('LiquidityPositionPriceRangeTile: Currency symbols are required') - } - - const displayMinPrice = pricesInverted ? minPrice.invert() : minPrice - const displayMaxPrice = pricesInverted ? maxPrice.invert() : maxPrice - const displayCurrentPrice = pricesInverted ? currentPrice.invert() : currentPrice - const displayASymbol = pricesInverted ? currencyBSymbol : currencyASymbol - const displayBSymbol = pricesInverted ? currencyASymbol : currencyBSymbol - - return ( - - - - - - - - - { - setPricesInverted(selected !== currencyASymbol) - }} - /> - - - - - - - - {displayMinPrice.toFixed()} - - - - - - - - - - - {displayMaxPrice.toFixed()} - - - - - - - - - - - - {displayCurrentPrice.toFixed()} - - - - - - - ) -} diff --git a/apps/web/src/components/Liquidity/PositionNFT.tsx b/apps/web/src/components/Liquidity/PositionNFT.tsx deleted file mode 100644 index ebde1e1aa34..00000000000 --- a/apps/web/src/components/Liquidity/PositionNFT.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { useRef, useState } from 'react' -// eslint-disable-next-line @typescript-eslint/no-restricted-imports -import styled from 'styled-components' - -// snapshots a src img into a canvas -function getSnapshot(src: HTMLImageElement, canvas: HTMLCanvasElement, targetHeight: number) { - const context = canvas.getContext('2d') - - if (context) { - let { width, height } = src - - // src may be hidden and not have the target dimensions - const ratio = width / height - height = targetHeight - width = Math.round(ratio * targetHeight) - - // Ensure crispness at high DPIs - canvas.width = width * devicePixelRatio - canvas.height = height * devicePixelRatio - canvas.style.width = width + 'px' - canvas.style.height = height + 'px' - context.scale(devicePixelRatio, devicePixelRatio) - - context.clearRect(0, 0, width, height) - context.drawImage(src, 0, 0, width, height) - } -} - -const NFTGrid = styled.div` - display: grid; - grid-template: 'overlap'; - min-height: 400px; -` - -const NFTCanvas = styled.canvas` - grid-area: overlap; -` - -const NFTImage = styled.img` - grid-area: overlap; - height: 400px; - /* Ensures SVG appears on top of canvas. */ - z-index: 1; -` - -export function PositionNFT({ image, height: targetHeight }: { image: string; height: number }) { - const [animate, setAnimate] = useState(false) - - const canvasRef = useRef(null) - const imageRef = useRef(null) - - return ( - { - setAnimate(true) - }} - onMouseLeave={() => { - // snapshot the current frame so the transition to the canvas is smooth - if (imageRef.current && canvasRef.current) { - getSnapshot(imageRef.current, canvasRef.current, targetHeight) - } - setAnimate(false) - }} - > - - - ) -} diff --git a/apps/web/src/components/Liquidity/utils.tsx b/apps/web/src/components/Liquidity/utils.tsx index 44b94557871..2cb1c8cfcdb 100644 --- a/apps/web/src/components/Liquidity/utils.tsx +++ b/apps/web/src/components/Liquidity/utils.tsx @@ -6,9 +6,12 @@ import { Token as RestToken, } from '@uniswap/client-pools/dist/pools/v1/types_pb' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' +import { Position as V3PositionSDK } from '@uniswap/v3-sdk' +import { usePool } from 'hooks/usePools' import { useMemo } from 'react' import { useAppSelector } from 'state/hooks' import { AppTFunction } from 'ui/src/i18n/types' +import { shortenAddress } from 'utilities/src/addresses' export function getProtocolVersionLabel(version: ProtocolVersion): string | undefined { switch (version) { @@ -22,23 +25,6 @@ export function getProtocolVersionLabel(version: ProtocolVersion): string | unde return undefined } -export function getProtocolVersionFromString(version?: string): ProtocolVersion { - if (!version) { - return ProtocolVersion.V4 - } - - switch (version.toLowerCase()) { - case 'v2': - return ProtocolVersion.V2 - case 'v3': - return ProtocolVersion.V3 - case 'v4': - return ProtocolVersion.V4 - } - - return ProtocolVersion.V4 -} - export function getProtocolStatusLabel(status: PositionStatus, t: AppTFunction): string | undefined { switch (status) { case PositionStatus.IN_RANGE: @@ -51,10 +37,7 @@ export function getProtocolStatusLabel(status: PositionStatus, t: AppTFunction): return undefined } -function parseRestToken(token?: RestToken): Token | undefined { - if (!token) { - return undefined - } +function parseRestToken(token: RestToken): Currency { return new Token(token.chainId, token.address, token.decimals, token.symbol) } @@ -66,60 +49,58 @@ export type PositionInfo = { currency1Amount: CurrencyAmount feeTier?: string v4hook?: string - liquidityToken?: Token } export function usePositionInfo(position?: Position): PositionInfo | undefined { // TODO(WEB-4920): remove this as the API should return the needed information - make this function a synchronous non-hook. // Optimistically fetch the v3Pool, which should be undefined for non-v3 positions - // const [, v3Pool] = usePool( - // (position as any)?.v3Position?.token0 ? parseRestToken((position as any).v3Position.token0) : undefined, - // (position as any)?.v3Position?.token1 ? parseRestToken((position as any).v3Position.token1) : undefined, - // parseInt((position as any)?.v3Position?.feeTier), - // ) + const [, v3Pool] = usePool( + (position as any)?.v3Position?.token0 ? parseRestToken((position as any).v3Position.token0) : undefined, + (position as any)?.v3Position?.token1 ? parseRestToken((position as any).v3Position.token1) : undefined, + parseInt((position as any)?.v3Position?.feeTier), + ) return useMemo(() => { - if (!position?.position) { + if (!position) { return undefined - } else if (position.position.case === 'v2Pair') { - const v2Pair = position.position.value - const token0 = parseRestToken(v2Pair.token0) - const token1 = parseRestToken(v2Pair.token1) - if (!token0 || !token1) { + } else if ((position as any).v2Pair) { + const v2Pair = (position as any).v2Pair + if (!v2Pair.token0 || !v2Pair.token1) { return undefined } + const token0 = parseRestToken(v2Pair.token0) + const token1 = parseRestToken(v2Pair.token1) + return { status: position.status, feeTier: undefined, v4hook: undefined, version: position.protocolVersion, restPosition: position, - liquidityToken: parseRestToken(v2Pair.liquidityToken), // TODO(WEB-4920): test this with a real position and verify the decimals are correct here currency0Amount: CurrencyAmount.fromRawAmount(token0, v2Pair.reserve0.toString()), currency1Amount: CurrencyAmount.fromRawAmount(token1, v2Pair.reserve1.toString()), } - } else if (position.position.case === 'v3Position') { - const v3Position = position.position.value - const token0 = parseRestToken(v3Position.token0) - const token1 = parseRestToken(v3Position.token1) - if (!token0 || !token1) { + } else if ((position as any).v3Position) { + const v3Position = (position as any).v3Position + if (!v3Position.token0 || !v3Position.token1 || !v3Pool) { return undefined } + const token0 = parseRestToken(v3Position.token0) + const token1 = parseRestToken(v3Position.token1) // eslint-disable-next-line @typescript-eslint/no-unused-vars - // const v3PositionSDK = new V3PositionSDK({ - // pool: v3Pool, - // liquidity: v3Position.liquidity, - // tickLower: parseInt(v3Position.tickLower), - // tickUpper: parseInt(v3Position.tickUpper), - // }) + const v3PositionSDK = new V3PositionSDK({ + pool: v3Pool, + liquidity: v3Position.liquidity, + tickLower: v3Position.tickLower, + tickUpper: v3Position.tickUpper, + }) return { status: position.status, feeTier: v3Position.feeTier, version: position.protocolVersion, v4hook: undefined, - liquidityToken: undefined, restPosition: position, // TODO(WEB-4920): test this with a real position and use instead of the hardcoded amounts // currency0Amount: v3PositionSDK.amount0, @@ -128,19 +109,19 @@ export function usePositionInfo(position?: Position): PositionInfo | undefined { currency1Amount: CurrencyAmount.fromRawAmount(token1, '1'), } } else { - const v4Position = position.position.value - const token0 = parseRestToken(v4Position?.poolPosition?.token0) - const token1 = parseRestToken(v4Position?.poolPosition?.token1) - if (!token0 || !token1) { + const v4Position = (position as any).v4Position + if (!v4Position.poolPosition?.token0 || !v4Position.poolPosition?.token1) { return undefined } + const token0 = parseRestToken(v4Position.poolPosition.token0) + const token1 = parseRestToken(v4Position.poolPosition.token1) + return { status: position.status, feeTier: undefined, version: position.protocolVersion, - v4hook: v4Position?.hooks[0]?.address, - liquidityToken: undefined, + v4hook: v4Position.hooks[0]?.address ? shortenAddress(v4Position.hooks[0].address) : undefined, restPosition: position, currency0Amount: CurrencyAmount.fromRawAmount( token0, @@ -152,7 +133,7 @@ export function usePositionInfo(position?: Position): PositionInfo | undefined { ), } } - }, [position]) + }, [position, v3Pool]) } /** diff --git a/apps/web/src/components/Logo/DoubleLogo.tsx b/apps/web/src/components/Logo/DoubleLogo.tsx index c4200ff040e..b909a86b025 100644 --- a/apps/web/src/components/Logo/DoubleLogo.tsx +++ b/apps/web/src/components/Logo/DoubleLogo.tsx @@ -89,7 +89,7 @@ export const SingleLogoContainer = styled.div<{ size: number }>` const DoubleLogoContainer = styled.div<{ size: number }>` ${logoContainerCss} img { - width: ${({ size }) => size / 2 - 1}px; + width: ${({ size }) => size / 2}px; height: ${({ size }) => size}px; object-fit: cover; } diff --git a/apps/web/src/components/NavBar/NavDropdown/NavDropdown.tsx b/apps/web/src/components/NavBar/NavDropdown/NavDropdown.tsx index d3a028896c0..89f91ad3ce2 100644 --- a/apps/web/src/components/NavBar/NavDropdown/NavDropdown.tsx +++ b/apps/web/src/components/NavBar/NavDropdown/NavDropdown.tsx @@ -1,6 +1,6 @@ import { ReactNode, RefObject } from 'react' +import { NAV_HEIGHT } from 'theme' import { Flex, Popover, WebBottomSheet, styled, useScrollbarStyles, useShadowPropsMedium } from 'ui/src' -import { INTERFACE_NAV_HEIGHT } from 'uniswap/src/theme/heights' const NavDropdownContent = styled(Flex, { borderRadius: '$rounded16', @@ -8,17 +8,14 @@ const NavDropdownContent = styled(Flex, { borderStyle: 'solid', borderColor: '$surface2', backgroundColor: '$surface1', - maxHeight: `calc(100dvh - ${INTERFACE_NAV_HEIGHT * 2}px)`, + overflow: 'scroll', + maxHeight: `calc(100dvh - ${NAV_HEIGHT * 2}px)`, $sm: { width: '100%', borderRadius: '$none', borderWidth: 0, shadowColor: '$transparent', - maxHeight: `calc(100dvh - ${INTERFACE_NAV_HEIGHT}px)`, - }, - '$platform-web': { - overflowY: 'auto', - overflowX: 'hidden', + maxHeight: `calc(100dvh - ${NAV_HEIGHT}px)`, }, }) diff --git a/apps/web/src/components/NavBar/SearchBar/SuggestionRow.tsx b/apps/web/src/components/NavBar/SearchBar/SuggestionRow.tsx index c268316741c..209c654a7c8 100644 --- a/apps/web/src/components/NavBar/SearchBar/SuggestionRow.tsx +++ b/apps/web/src/components/NavBar/SearchBar/SuggestionRow.tsx @@ -11,7 +11,7 @@ import { getTokenDetailsURL, supportedChainIdFromGQLChain } from 'graphql/data/u import styled, { css } from 'lib/styled-components' import { searchGenieCollectionToTokenSearchResult, searchTokenToTokenSearchResult } from 'lib/utils/searchBar' import { GenieCollection } from 'nft/types' -import { useCallback, useEffect, useMemo, useState } from 'react' +import { useCallback, useEffect, useState } from 'react' import { useDispatch } from 'react-redux' import { Link, useNavigate } from 'react-router-dom' import { EllipsisStyle, ThemedText } from 'theme/components' @@ -23,7 +23,6 @@ import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { InterfaceSearchResultSelectionProperties } from 'uniswap/src/features/telemetry/types' import { Trans, useTranslation } from 'uniswap/src/i18n' import { UniverseChainId } from 'uniswap/src/types/chains' -import { shortenAddress } from 'uniswap/src/utils/addresses' import { NumberType, useFormatter } from 'utils/formatNumbers' const PriceChangeContainer = styled.div` @@ -50,13 +49,16 @@ const SuggestionRowStyles = css<{ $isFocused: boolean }>` background: ${theme.surface2}; `} ` - const StyledLink = styled(Link)` ${SuggestionRowStyles} ` const SkeletonSuggestionRow = styled.div` ${SuggestionRowStyles} ` +const PrimaryContainer = styled(Column)` + align-items: flex-start; + width: 90%; +` const CollectionImageStyles = css` width: 36px; height: 36px; @@ -145,14 +147,6 @@ export function SuggestionRow({ } }, [toggleOpen, isHovered, suggestion, navigate, handleClick, path]) - const shortenedAddress = useMemo(() => { - if (isToken && suggestion.address && suggestion.address !== NATIVE_CHAIN_ID) { - return shortenAddress(suggestion.address) - } - - return null - }, [suggestion, isToken]) - return ( isHovered && setHoveredIndex(undefined)} data-testid={isToken ? `searchbar-token-row-${suggestion.chain}-${suggestion.address ?? NATIVE_CHAIN_ID}` : ''} > - + {isToken ? ( setBrokenCollectionImage(true)} /> )} - - + + {suggestion.name} {isToken ? : suggestion.isVerified && } - - - {isToken - ? suggestion.symbol - : t('search.results.count', { - count: suggestion?.stats?.total_supply ?? 0, - })} - - {shortenedAddress && ( - - {shortenedAddress} - - )} - - + + {isToken + ? suggestion.symbol + : t('search.results.count', { + count: suggestion?.stats?.total_supply ?? 0, + })} + + 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 f0ff210e469..993bca0ec32 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 @@ -228,7 +228,7 @@ exports[`disable nft on searchbar dropdown should not render popular nft collect - ) : isLogIn ? ( - - ) : ( - - ) -} diff --git a/apps/web/src/components/NavBar/index.tsx b/apps/web/src/components/NavBar/index.tsx index 6541a17b945..4451f9a43cd 100644 --- a/apps/web/src/components/NavBar/index.tsx +++ b/apps/web/src/components/NavBar/index.tsx @@ -20,16 +20,15 @@ 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' -import { INTERFACE_NAV_HEIGHT } from 'uniswap/src/theme/heights' const Nav = styled.nav` padding: 0px 12px; width: 100%; - height: ${INTERFACE_NAV_HEIGHT}px; + height: ${NAV_HEIGHT}px; z-index: ${Z_INDEX.sticky}; display: flex; align-items: center; diff --git a/apps/web/src/components/PercentInput.tsx b/apps/web/src/components/PercentInput.tsx index 0fcb8716092..41208a1b646 100644 --- a/apps/web/src/components/PercentInput.tsx +++ b/apps/web/src/components/PercentInput.tsx @@ -3,18 +3,18 @@ import { NumericalInputFontStyle } from 'pages/Swap/common/shared' import React, { forwardRef } from 'react' // eslint-disable-next-line @typescript-eslint/no-restricted-imports import styled from 'styled-components' +import { escapeRegExp } from 'utilities/src/primitives/string' import { useFormatterLocales } from 'utils/formatNumbers' -const inputRegex = RegExp(`^\\d*(\\.\\d{0,2})?$`) +const inputRegex = RegExp(`^\\d*$`) const PercentInput = forwardRef( ({ value, onUserInput, placeholder, testId, ...rest }: InputProps, ref) => { const { formatterLocale } = useFormatterLocales() const enforcer = (nextUserInput: string) => { - const sanitizedInput = nextUserInput.replace(/,/g, '.') // Normalize the input - if (sanitizedInput === '' || inputRegex.test(sanitizedInput)) { - onUserInput(sanitizedInput) + if (nextUserInput === '' || inputRegex.test(escapeRegExp(nextUserInput))) { + onUserInput(nextUserInput) } } @@ -27,14 +27,12 @@ const PercentInput = forwardRef( return ( { - enforcer(event.target.value) + enforcer(event.target.value.replace(/,/g, '.')) }} // universal input options inputMode="numeric" @@ -42,8 +40,10 @@ const PercentInput = forwardRef( autoCorrect="off" // text-specific options type="text" - pattern="^\\d*(\\.\\d{0,2})?$" + pattern="^[0-9]*$" placeholder={placeholder || '0'} + minLength={1} + maxLength={2} spellCheck="false" /> ) diff --git a/apps/web/src/components/Pools/PoolDetails/ChartSection/index.tsx b/apps/web/src/components/Pools/PoolDetails/ChartSection/index.tsx index 6c5f5084078..853132593ca 100644 --- a/apps/web/src/components/Pools/PoolDetails/ChartSection/index.tsx +++ b/apps/web/src/components/Pools/PoolDetails/ChartSection/index.tsx @@ -118,7 +118,6 @@ function usePDPChartState( const volumeQuery = usePDPVolumeChartData(variables) return useMemo(() => { - // eslint-disable-next-line consistent-return const activeQuery = (() => { switch (chartType) { case ChartType.PRICE: @@ -164,7 +163,6 @@ export default function ChartSection(props: ChartSectionProps) { // TODO(WEB-3740): Integrate BE tick query, remove special casing for liquidity chart const loading = props.loading || (activeQuery.chartType !== ChartType.LIQUIDITY ? activeQuery?.loading : false) - // eslint-disable-next-line consistent-return const ChartBody = (() => { if (!currencyA || !currencyB || !props.poolData || !props.chain) { return diff --git a/apps/web/src/components/Pools/PoolDetails/PoolDetailsStatsButtons.tsx b/apps/web/src/components/Pools/PoolDetails/PoolDetailsStatsButtons.tsx index 5c50c73a8ca..f5ea57787f5 100644 --- a/apps/web/src/components/Pools/PoolDetails/PoolDetailsStatsButtons.tsx +++ b/apps/web/src/components/Pools/PoolDetails/PoolDetailsStatsButtons.tsx @@ -10,7 +10,7 @@ import { LoadingBubble } from 'components/Tokens/loading' import TokenSafetyMessage from 'components/TokenSafety/TokenSafetyMessage' import { chainIdToBackendChain, SupportedInterfaceChainId } from 'constants/chains' import { getPriorityWarning, StrongWarning, useTokenWarning } from 'constants/deprecatedTokenSafety' -import { useTokenBalancesQuery } from 'graphql/data/apollo/AdaptiveTokenBalancesProvider' +import { useTokenBalancesQuery } from 'graphql/data/apollo/TokenBalancesProvider' import { gqlToCurrency } from 'graphql/data/util' import { useScreenSize } from 'hooks/screenSize/useScreenSize' import { useAccount } from 'hooks/useAccount' 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 7240e786740..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 @@ -364,7 +364,7 @@ exports[`PoolDetailsHeader renders header text correctly 1`] = ` } .c4 img { - width: 15px; + width: 16px; height: 32px; object-fit: cover; } diff --git a/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsLink.test.tsx.snap b/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsLink.test.tsx.snap index 7c29c102b4f..b8b22d91c8a 100644 --- a/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsLink.test.tsx.snap +++ b/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsLink.test.tsx.snap @@ -14,7 +14,7 @@ exports[`PoolDetailsHeader renders link for pool address 1`] = ` } .c5 img { - width: 9px; + width: 10px; height: 20px; object-fit: cover; } diff --git a/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsPositionTable.test.tsx.snap b/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsPositionTable.test.tsx.snap index 5187f3bf461..081653ca11b 100644 --- a/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsPositionTable.test.tsx.snap +++ b/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsPositionTable.test.tsx.snap @@ -14,7 +14,7 @@ exports[`PoolDetailsPositionsTable renders with PositionStatus Closed 1`] = ` } .c5 img { - width: 7px; + width: 8px; height: 16px; object-fit: cover; } @@ -325,7 +325,7 @@ exports[`PoolDetailsPositionsTable renders with PositionStatus In Range 1`] = ` } .c5 img { - width: 7px; + width: 8px; height: 16px; object-fit: cover; } @@ -611,7 +611,7 @@ exports[`PoolDetailsPositionsTable renders with PositionStatus Out Of Range 1`] } .c5 img { - width: 7px; + width: 8px; height: 16px; object-fit: cover; } 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 cf80be53796..8383d1c1eda 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 @@ -14,7 +14,7 @@ exports[`PoolTable renders data filled state 1`] = ` } .c4 img { - width: 13px; + width: 14px; height: 28px; object-fit: cover; } diff --git a/apps/web/src/components/Popups/PopupContent.tsx b/apps/web/src/components/Popups/PopupContent.tsx index 9d5f11c2e21..7f22480dea0 100644 --- a/apps/web/src/components/Popups/PopupContent.tsx +++ b/apps/web/src/components/Popups/PopupContent.tsx @@ -8,7 +8,6 @@ import { Activity } from 'components/AccountDrawer/MiniPortfolio/Activity/types' import { PortfolioLogo } from 'components/AccountDrawer/MiniPortfolio/PortfolioLogo' import PortfolioRow from 'components/AccountDrawer/MiniPortfolio/PortfolioRow' import AlertTriangleFilled from 'components/Icons/AlertTriangleFilled' -import { LoaderV3 } from 'components/Icons/LoadingSpinner' import Column, { AutoColumn } from 'components/deprecated/Column' import { AutoRow } from 'components/deprecated/Row' import { SupportedInterfaceChainId, useIsSupportedChainId } from 'constants/chains' @@ -17,7 +16,6 @@ import { X } from 'react-feather' import { useOrder } from 'state/signatures/hooks' import { useTransaction } from 'state/transactions/hooks' import { EllipsisStyle, ThemedText } from 'theme/components' -import { Flex, useSporeColors } from 'ui/src' import { UNIVERSE_CHAIN_INFO } from 'uniswap/src/constants/chains' import { TransactionStatus } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { Trans } from 'uniswap/src/i18n' @@ -104,16 +102,13 @@ const Descriptor = styled(ThemedText.BodySmall)` type ActivityPopupContentProps = { activity: Activity; onClick: () => void; onClose: () => void } function ActivityPopupContent({ activity, onClick, onClose }: ActivityPopupContentProps) { const success = activity.status === TransactionStatus.Confirmed && !activity.cancelled - const pending = activity.status === TransactionStatus.Pending - - const showPortfolioLogo = success || pending || !!activity.offchainOrderDetails - const colors = useSporeColors() return ( + {activity.descriptor}} onClick={onClick} /> - {pending ? ( - - - - ) : ( - - )} ) } diff --git a/apps/web/src/components/SearchModal/CurrencySearchModal.tsx b/apps/web/src/components/SearchModal/CurrencySearchModal.tsx index 06963564612..b245a930055 100644 --- a/apps/web/src/components/SearchModal/CurrencySearchModal.tsx +++ b/apps/web/src/components/SearchModal/CurrencySearchModal.tsx @@ -4,9 +4,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 { INTERFACE_NAV_HEIGHT } from 'uniswap/src/theme/heights' import { CurrencyField } from 'uniswap/src/types/currency' interface CurrencySearchModalProps { @@ -72,8 +72,8 @@ export default memo(function CurrencySearchModal({ content = ( handleCurrencySelect(warningToken)} - closeModalOnly={() => setModalView(CurrencyModalView.search)} + onContinue={() => handleCurrencySelect(warningToken)} + onCancel={() => setModalView(CurrencyModalView.search)} showCancel={true} /> ) @@ -89,7 +89,7 @@ export default memo(function CurrencySearchModal({ px={0} py={0} flex={1} - $sm={{ height: `calc(100dvh - ${INTERFACE_NAV_HEIGHT}px)` }} + $sm={{ height: `calc(100dvh - ${NAV_HEIGHT}px)` }} > {content} diff --git a/apps/web/src/components/Settings/MultipleRoutingOptions.tsx b/apps/web/src/components/Settings/MultipleRoutingOptions.tsx index 4f891e5c113..0ff035bc227 100644 --- a/apps/web/src/components/Settings/MultipleRoutingOptions.tsx +++ b/apps/web/src/components/Settings/MultipleRoutingOptions.tsx @@ -3,7 +3,7 @@ import UniswapXBrandMark from 'components/Logo/UniswapXBrandMark' import QuestionHelper from 'components/QuestionHelper' import Column from 'components/deprecated/Column' import Row, { RowBetween } from 'components/deprecated/Row' -import { useIsUniswapXSupportedChain } from 'constants/chains' +import { isUniswapXSupportedChain } from 'constants/chains' import { atom, useAtom } from 'jotai' import styled from 'lib/styled-components' import { ReactNode, useCallback } from 'react' @@ -122,7 +122,7 @@ export default function MultipleRoutingOptions({ chainId }: { chainId?: number } const [, setRoutingPreferences] = useAtom(routingPreferencesAtom) const shouldDisableProtocolOptionToggle = !routePreferenceOptions[RoutePreferenceOption.v2] || !routePreferenceOptions[RoutePreferenceOption.v3] - const uniswapXSupportedChain = useIsUniswapXSupportedChain(chainId) + const uniswapXSupportedChain = chainId && isUniswapXSupportedChain(chainId) const handleSetRoutePreferenceOptions = useCallback( (options: RoutePreferenceOptionsType) => { if (options[RoutePreferenceOption.Optimal]) { diff --git a/apps/web/src/components/Settings/index.test.tsx b/apps/web/src/components/Settings/index.test.tsx index 76b938ec24e..5f52e320bed 100644 --- a/apps/web/src/components/Settings/index.test.tsx +++ b/apps/web/src/components/Settings/index.test.tsx @@ -1,6 +1,6 @@ import { Percent } from '@uniswap/sdk-core' import SettingsTab from 'components/Settings/index' -import { useIsSupportedChainId, useIsUniswapXSupportedChain } from 'constants/chains' +import { isUniswapXSupportedChain, useIsSupportedChainId } from 'constants/chains' import { useAccount } from 'hooks/useAccount' import { mocked } from 'test-utils/mocked' import { fireEvent, render, screen, waitFor } from 'test-utils/render' @@ -20,7 +20,7 @@ describe('Settings Tab', () => { }) it('renders routing settings when hideRoutingSettings is false', async () => { - mocked(useIsUniswapXSupportedChain).mockReturnValue(true) + mocked(isUniswapXSupportedChain).mockReturnValue(true) render() const settingsButton = screen.getByTestId('open-settings-dialog-button') @@ -43,7 +43,7 @@ describe('Settings Tab', () => { }) it('does not render routing settings when uniswapx is not enabled', async () => { - mocked(useIsUniswapXSupportedChain).mockReturnValue(false) + mocked(isUniswapXSupportedChain).mockReturnValue(false) render() const settingsButton = screen.getByTestId('open-settings-dialog-button') diff --git a/apps/web/src/components/Settings/index.tsx b/apps/web/src/components/Settings/index.tsx index 5acb587d56a..50b23347d8c 100644 --- a/apps/web/src/components/Settings/index.tsx +++ b/apps/web/src/components/Settings/index.tsx @@ -8,7 +8,7 @@ import MenuButton from 'components/Settings/MenuButton' import MultipleRoutingOptions from 'components/Settings/MultipleRoutingOptions' import RouterPreferenceSettings from 'components/Settings/RouterPreferenceSettings' import TransactionDeadlineSettings from 'components/Settings/TransactionDeadlineSettings' -import { useIsSupportedChainId, useIsUniswapXSupportedChain } from 'constants/chains' +import { isUniswapXSupportedChain, useIsSupportedChainId } from 'constants/chains' import { useIsMobile } from 'hooks/screenSize/useIsMobile' import useDisableScrolling from 'hooks/useDisableScrolling' import { useOnClickOutside } from 'hooks/useOnClickOutside' @@ -136,7 +136,7 @@ export default function SettingsTab({ useDisableScrolling(isOpen) const multipleRoutingOptionsEnabled = useFeatureFlag(FeatureFlags.MultipleRoutingOptions) - const uniswapXEnabled = useIsUniswapXSupportedChain(chainId) + const uniswapXEnabled = chainId && isUniswapXSupportedChain(chainId) const showRoutingSettings = Boolean(uniswapXEnabled && !hideRoutingSettings && !multipleRoutingOptionsEnabled) const isChainSupported = useIsSupportedChainId(chainId) diff --git a/apps/web/src/components/Table/index.tsx b/apps/web/src/components/Table/index.tsx index 1479dfdf423..6638d31b4fc 100644 --- a/apps/web/src/components/Table/index.tsx +++ b/apps/web/src/components/Table/index.tsx @@ -30,12 +30,12 @@ import { import useDebounce from 'hooks/useDebounce' 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' import Trace from 'uniswap/src/features/telemetry/Trace' import { Trans } from 'uniswap/src/i18n' -import { INTERFACE_NAV_HEIGHT } from 'uniswap/src/theme/heights' import { useTrace } from 'utilities/src/telemetry/trace/TraceContext' function TableBody({ @@ -154,7 +154,7 @@ export function Table({ useEffect(() => { const scrollableElement = maxHeight ? tableBodyRef.current : window if (scrollableElement === null) { - return undefined + return } const updateScrollPosition = () => { if (scrollableElement instanceof HTMLDivElement) { @@ -203,7 +203,7 @@ export function Table({ }) const headerHeight = useMemo(() => { const header = document.getElementById('AppHeader') - return header?.clientHeight || INTERFACE_NAV_HEIGHT + return header?.clientHeight || NAV_HEIGHT }, []) return ( diff --git a/apps/web/src/components/TokenSafety/TokenSafetyModal.tsx b/apps/web/src/components/TokenSafety/TokenSafetyModal.tsx index ca2f37091c4..e8d4a8d193f 100644 --- a/apps/web/src/components/TokenSafety/TokenSafetyModal.tsx +++ b/apps/web/src/components/TokenSafety/TokenSafetyModal.tsx @@ -8,9 +8,6 @@ import TokenSafety, { TokenSafetyProps } from '.' interface TokenSafetyModalProps extends TokenSafetyProps { isOpen: boolean - onReject?: () => void - onToken0BlockAcknowledged: () => void - onToken1BlockAcknowledged?: () => void } /* TODO(WALL-4625): Clean up and remove this file; is duplicate of packages/uniswap TokenWarningModal.tsx */ @@ -18,11 +15,9 @@ export default function TokenSafetyModal({ isOpen, token0, token1, - onAcknowledge, - closeModalOnly, - onReject, - onToken0BlockAcknowledged, - onToken1BlockAcknowledged, + onContinue, + onCancel, + onBlocked, showCancel, }: TokenSafetyModalProps) { const tokenProtectionEnabled = useFeatureFlag(FeatureFlags.TokenProtection) @@ -40,24 +35,17 @@ export default function TokenSafetyModal({ isVisible={isOpen} currencyInfo0={currencyInfo0} currencyInfo1={currencyInfo1 ?? undefined} - onReject={onReject} - onAcknowledge={onAcknowledge} - closeModalOnly={closeModalOnly} - onToken0BlockAcknowledged={onToken0BlockAcknowledged} - onToken1BlockAcknowledged={onToken1BlockAcknowledged} + onClose={onBlocked ?? onCancel} + onAccept={onContinue} /> ) : ( - + { - onToken0BlockAcknowledged() - onToken1BlockAcknowledged?.() - closeModalOnly() - }} - closeModalOnly={closeModalOnly} + onContinue={onContinue} + onBlocked={onBlocked} + onCancel={onCancel} showCancel={showCancel} /> diff --git a/apps/web/src/components/TokenSafety/index.tsx b/apps/web/src/components/TokenSafety/index.tsx index 68cd68f3241..0c438186613 100644 --- a/apps/web/src/components/TokenSafety/index.tsx +++ b/apps/web/src/components/TokenSafety/index.tsx @@ -130,20 +130,13 @@ const StyledExternalLink = styled(ExternalLink)` export interface TokenSafetyProps { token0: Token token1?: Token - onAcknowledge: () => void - closeModalOnly: () => void + onContinue: () => void + onCancel: () => void onBlocked?: () => void showCancel?: boolean } -export default function TokenSafety({ - token0, - token1, - onAcknowledge, - closeModalOnly: onClose, - onBlocked, - showCancel, -}: TokenSafetyProps) { +export default function TokenSafety({ token0, token1, onContinue, onCancel, onBlocked, showCancel }: TokenSafetyProps) { const logos = [] const urls = [] @@ -176,7 +169,7 @@ export default function TokenSafety({ const acknowledge = () => { onDismissToken0() onDismissToken1() - onAcknowledge() + onContinue() } const { heading, description } = getWarningCopy(displayWarning, plural) @@ -206,7 +199,7 @@ export default function TokenSafety({ @@ -223,7 +216,7 @@ export default function TokenSafety({ {heading} {description} {learnMoreUrl} - + ) diff --git a/apps/web/src/components/Tokens/TokenDetails/ChartSection/index.tsx b/apps/web/src/components/Tokens/TokenDetails/ChartSection/index.tsx index efde7f2bf80..b8356e75cde 100644 --- a/apps/web/src/components/Tokens/TokenDetails/ChartSection/index.tsx +++ b/apps/web/src/components/Tokens/TokenDetails/ChartSection/index.tsx @@ -84,7 +84,6 @@ export function useCreateTDPChartState(tokenDBAddress: string | undefined, curre return useMemo(() => { const { disableCandlestickUI } = priceQuery - // eslint-disable-next-line consistent-return const activeQuery = (() => { switch (chartType) { case ChartType.PRICE: @@ -111,36 +110,38 @@ export function useCreateTDPChartState(tokenDBAddress: string | undefined, curre export default function ChartSection() { const { activeQuery, timePeriod, priceChartType } = useTDPContext().chartState - // eslint-disable-next-line consistent-return - const getSection = () => { - if (activeQuery.dataQuality === DataQuality.INVALID) { - return ( - } - /> - ) - } - - const stale = activeQuery.dataQuality === DataQuality.STALE - switch (activeQuery.chartType) { - case ChartType.PRICE: - return ( - - ) - case ChartType.VOLUME: - return ( - - ) - case ChartType.TVL: - return - } - } - return (
- {getSection()} + {(() => { + if (activeQuery.dataQuality === DataQuality.INVALID) { + return ( + } + /> + ) + } + + const stale = activeQuery.dataQuality === DataQuality.STALE + switch (activeQuery.chartType) { + case ChartType.PRICE: + return ( + + ) + case ChartType.VOLUME: + return ( + + ) + case ChartType.TVL: + return + } + })()}
) diff --git a/apps/web/src/components/Tokens/TokenDetails/index.tsx b/apps/web/src/components/Tokens/TokenDetails/index.tsx index 87faf407af1..e1e02432c50 100644 --- a/apps/web/src/components/Tokens/TokenDetails/index.tsx +++ b/apps/web/src/components/Tokens/TokenDetails/index.tsx @@ -3,6 +3,7 @@ import { Currency } from '@uniswap/sdk-core' import { BreadcrumbNavContainer, BreadcrumbNavLink, CurrentPageBreadcrumb } from 'components/BreadcrumbNav' import { MobileBottomBar, TDPActionTabs } from 'components/NavBar/MobileBottomBar' import TokenSafetyMessage from 'components/TokenSafety/TokenSafetyMessage' +import TokenSafetyModal from 'components/TokenSafety/TokenSafetyModal' import { ActivitySection } from 'components/Tokens/TokenDetails/ActivitySection' import BalanceSummary, { PageChainBalanceSummary } from 'components/Tokens/TokenDetails/BalanceSummary' import ChartSection from 'components/Tokens/TokenDetails/ChartSection' @@ -22,7 +23,7 @@ import { ScrollDirection, useScroll } from 'hooks/useScroll' import deprecatedStyled from 'lib/styled-components' import { Swap } from 'pages/Swap' import { useTDPContext } from 'pages/TokenDetails/TDPContext' -import { PropsWithChildren, useCallback, useMemo } from 'react' +import { PropsWithChildren, useCallback, useMemo, useState } from 'react' import { ChevronRight } from 'react-feather' import { useNavigate } from 'react-router-dom' import { CurrencyState } from 'state/swap/types' @@ -126,18 +127,47 @@ function TDPSwapComponent() { // Other token to prefill the swap form with const initialInputCurrency = useSwapInitialInputCurrency() + const [openTokenSafetyModal, setOpenTokenSafetyModal] = useState(false) + const [continueSwap, setContinueSwap] = useState<{ resolve: (value: boolean | PromiseLike) => void }>() + + const onResolveSwap = useCallback( + (value: boolean) => { + continueSwap?.resolve(value) + setContinueSwap(undefined) + }, + [continueSwap, setContinueSwap], + ) + const isBlockedToken = warning?.canProceed === false + return ( <> - +
isBlockedToken && setOpenTokenSafetyModal(true)} + > + +
{warning && } + {currency.isToken && ( + onResolveSwap(true)} + onBlocked={() => { + setOpenTokenSafetyModal(false) + }} + onCancel={() => onResolveSwap(false)} + showCancel={true} + /> + )} ) } 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 3e948723b69..7e357ebf395 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 @@ -14,7 +14,7 @@ exports[`TDPPoolTable renders data filled state 1`] = ` } .c4 img { - width: 13px; + width: 14px; height: 28px; object-fit: cover; } diff --git a/apps/web/src/components/Tokens/TokenTable/VolumeTimeFrameSelector.tsx b/apps/web/src/components/Tokens/TokenTable/VolumeTimeFrameSelector.tsx index e1dad3c24c5..15bfd7e1ad9 100644 --- a/apps/web/src/components/Tokens/TokenTable/VolumeTimeFrameSelector.tsx +++ b/apps/web/src/components/Tokens/TokenTable/VolumeTimeFrameSelector.tsx @@ -25,7 +25,6 @@ export const DISPLAYS: Record = { [TimePeriod.YEAR]: TimePeriodDisplay.YEAR, } -// eslint-disable-next-line consistent-return export function getTimePeriodFromDisplay(display: TimePeriodDisplay): TimePeriod { switch (display) { case TimePeriodDisplay.HOUR: diff --git a/apps/web/src/components/Tokens/TokenTable/index.tsx b/apps/web/src/components/Tokens/TokenTable/index.tsx index d046b73f08b..770ea2c42f2 100644 --- a/apps/web/src/components/Tokens/TokenTable/index.tsx +++ b/apps/web/src/components/Tokens/TokenTable/index.tsx @@ -76,7 +76,7 @@ function TokenDescription({ token }: { token: TopToken | TokenStat }) { return ( - {token?.name ?? token?.project?.name} + {token?.project?.name ?? token?.name} { switch (size) { case TooltipSize.ExtraSmall: @@ -103,7 +102,7 @@ export const MouseoverTooltip = memo(function MouseoverTooltip(props: MouseoverT clearTimeout(tooltipTimer) } } - return undefined + return }, [timeout, show]) return ( diff --git a/apps/web/src/components/Web3Provider/index.tsx b/apps/web/src/components/Web3Provider/index.tsx index 0c6a75c4b33..95a3560ae42 100644 --- a/apps/web/src/components/Web3Provider/index.tsx +++ b/apps/web/src/components/Web3Provider/index.tsx @@ -1,7 +1,7 @@ import { QueryClientProvider } from '@tanstack/react-query' import { CustomUserProperties, InterfaceEventName, WalletConnectionResult } from '@uniswap/analytics-events' import { recentConnectorIdAtom } from 'components/Web3Provider/constants' -import { queryClient, wagmiConfig } from 'components/Web3Provider/wagmiConfig' +import { queryClient, wagmiConfig } from 'components/Web3Provider/wagmi' import { walletTypeToAmplitudeWalletType } from 'components/Web3Provider/walletConnect' import { useIsSupportedChainId } from 'constants/chains' import { RPC_PROVIDERS } from 'constants/providers' diff --git a/apps/web/src/components/Web3Provider/wagmiConfig.ts b/apps/web/src/components/Web3Provider/wagmi.ts similarity index 100% rename from apps/web/src/components/Web3Provider/wagmiConfig.ts rename to apps/web/src/components/Web3Provider/wagmi.ts diff --git a/apps/web/src/components/Web3Status/index.tsx b/apps/web/src/components/Web3Status/index.tsx index 3ba8cd0793c..9e21825fa04 100644 --- a/apps/web/src/components/Web3Status/index.tsx +++ b/apps/web/src/components/Web3Status/index.tsx @@ -7,7 +7,7 @@ import Loader, { LoaderV3 } from 'components/Icons/LoadingSpinner' import StatusIcon, { IconWrapper } from 'components/Identicon/StatusIcon' import { useAccountIdentifier } from 'components/Web3Status/useAccountIdentifier' import { RowBetween } from 'components/deprecated/Row' -import { PrefetchBalancesWrapper } from 'graphql/data/apollo/AdaptiveTokenBalancesProvider' +import { PrefetchBalancesWrapper } from 'graphql/data/apollo/TokenBalancesProvider' import { navSearchInputVisibleSize } from 'hooks/screenSize/useScreenSize' import { useAccount } from 'hooks/useAccount' import { atom, useAtom } from 'jotai' diff --git a/apps/web/src/components/addLiquidity/AddLiquidityContext.tsx b/apps/web/src/components/addLiquidity/AddLiquidityContext.tsx index c5018cfcd4a..8309a84b455 100644 --- a/apps/web/src/components/addLiquidity/AddLiquidityContext.tsx +++ b/apps/web/src/components/addLiquidity/AddLiquidityContext.tsx @@ -1,23 +1,23 @@ import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { PositionInfo, useModalLiquidityPositionInfo } from 'components/Liquidity/utils' +import { Field } from 'components/addLiquidity/InputForm' import { useDerivedAddLiquidityInfo } from 'components/addLiquidity/hooks' import { Dispatch, PropsWithChildren, SetStateAction, createContext, useContext, useMemo, useState } from 'react' -import { PositionField } from 'types/position' export interface AddLiquidityState { position?: PositionInfo - exactField: PositionField + exactField: Field exactAmount?: string } const DEFAULT_ADD_LIQUIDITY_STATE = { - exactField: PositionField.TOKEN0, + exactField: Field.TOKEN0, } export interface AddLiquidityInfo { - formattedAmounts?: { [field in PositionField]?: string } - currencyBalances?: { [field in PositionField]?: CurrencyAmount } - currencyAmounts?: { [field in PositionField]?: CurrencyAmount } - currencyAmountsUSDValue?: { [field in PositionField]?: CurrencyAmount } + formattedAmounts?: { [field in Field]?: string } + currencyBalances?: { [field in Field]?: CurrencyAmount } + currencyAmounts?: { [field in Field]?: CurrencyAmount } + currencyAmountsUSDValue?: { [field in Field]?: CurrencyAmount } } interface AddLiquidityContextType { diff --git a/apps/web/src/components/addLiquidity/InputForm.tsx b/apps/web/src/components/addLiquidity/InputForm.tsx index d5f7a0e3814..aec154ceee5 100644 --- a/apps/web/src/components/addLiquidity/InputForm.tsx +++ b/apps/web/src/components/addLiquidity/InputForm.tsx @@ -2,16 +2,20 @@ import { Currency } from '@uniswap/sdk-core' import { AddLiquidityInfo } from 'components/addLiquidity/AddLiquidityContext' import { useCurrencyInfo } from 'hooks/Tokens' import { useState } from 'react' -import { PositionField } from 'types/position' import { Flex } from 'ui/src' import { CurrencyInputPanel } from 'uniswap/src/components/CurrencyInputPanel/CurrencyInputPanel' import { CurrencyField } from 'uniswap/src/types/currency' +export enum Field { + TOKEN0 = 'TOKEN0', + TOKEN1 = 'TOKEN1', +} + type InputFormProps = { token0: Currency token1: Currency - onUserInput: (field: PositionField, newValue: string) => void - onSetMax: (field: PositionField, amount: string) => void + onUserInput: (field: Field, newValue: string) => void + onSetMax: (field: Field, amount: string) => void } & AddLiquidityInfo export function InputForm({ @@ -24,19 +28,19 @@ export function InputForm({ onUserInput, onSetMax, }: InputFormProps) { - const [focusedInputField, setFocusedInputField] = useState(PositionField.TOKEN0) + const [focusedInputField, setFocusedInputField] = useState(Field.TOKEN0) // TODO(WEB-4920): when the backend returns the logo info make sure that there is no call being made // to graphql to retrieve it const token0CurrencyInfo = useCurrencyInfo(token0) const token1CurrencyInfo = useCurrencyInfo(token1) - const handleUserInput = (field: PositionField) => { + const handleUserInput = (field: Field) => { return (newValue: string) => { onUserInput(field, newValue) } } - const handleOnSetMax = (field: PositionField) => { + const handleOnSetMax = (field: Field) => { return (amount: string) => { setFocusedInputField(field) onSetMax(field, amount) @@ -46,37 +50,37 @@ export function InputForm({ undefined} - usdValue={currencyAmountsUSDValue?.[PositionField.TOKEN0]} - onSetMax={handleOnSetMax(PositionField.TOKEN0)} - value={formattedAmounts?.[PositionField.TOKEN0]} - onPressIn={() => setFocusedInputField(PositionField.TOKEN0)} + usdValue={currencyAmountsUSDValue?.[Field.TOKEN0]} + onSetMax={handleOnSetMax(Field.TOKEN0)} + value={formattedAmounts?.[Field.TOKEN0]} + onPressIn={() => setFocusedInputField(Field.TOKEN0)} /> undefined} - usdValue={currencyAmountsUSDValue?.[PositionField.TOKEN1]} - onSetMax={handleOnSetMax(PositionField.TOKEN1)} - value={formattedAmounts?.[PositionField.TOKEN1]} - onPressIn={() => setFocusedInputField(PositionField.TOKEN1)} + usdValue={currencyAmountsUSDValue?.[Field.TOKEN1]} + onSetMax={handleOnSetMax(Field.TOKEN1)} + value={formattedAmounts?.[Field.TOKEN1]} + onPressIn={() => setFocusedInputField(Field.TOKEN1)} /> ) diff --git a/apps/web/src/components/addLiquidity/hooks.tsx b/apps/web/src/components/addLiquidity/hooks.tsx index 0a02128fe2a..c57ac513ae7 100644 --- a/apps/web/src/components/addLiquidity/hooks.tsx +++ b/apps/web/src/components/addLiquidity/hooks.tsx @@ -1,123 +1,31 @@ -// eslint-disable-next-line no-restricted-imports -import { PoolPosition } from '@uniswap/client-pools/dist/pools/v1/types_pb' -import { Currency, CurrencyAmount } from '@uniswap/sdk-core' -import { FeeAmount, Position } from '@uniswap/v3-sdk' import { AddLiquidityInfo, AddLiquidityState } from 'components/addLiquidity/AddLiquidityContext' +import { Field } from 'components/addLiquidity/InputForm' import { useAccount } from 'hooks/useAccount' -import { usePool } from 'hooks/usePools' -import { useV2Pair } from 'hooks/useV2Pairs' import { useCurrencyBalances } from 'lib/hooks/useCurrencyBalance' import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount' -import { useMemo } from 'react' -import { PositionField } from 'types/position' import { useUSDCValue } from 'uniswap/src/features/transactions/swap/hooks/useUSDCPrice' -function parseV3FeeTier(feeTier: string | undefined): FeeAmount | undefined { - const parsedFee = parseInt(feeTier || '') - - return parsedFee in FeeAmount ? parsedFee : undefined -} - export function useDerivedAddLiquidityInfo(state: AddLiquidityState): AddLiquidityInfo { const account = useAccount() - const { position: positionInfo, exactAmount, exactField } = state + const { position, exactAmount } = state - if (!positionInfo) { + if (!position) { throw new Error('no position available') } - const token0 = positionInfo.currency0Amount.currency - const token1 = positionInfo.currency1Amount.currency + const token0 = position.currency0Amount.currency + const token1 = position.currency1Amount.currency const [token0Balance, token1Balance] = useCurrencyBalances(account.address, [token0, token1]) + const token0CurrencyAmount = tryParseCurrencyAmount(exactAmount, token0) + const token0USDValue = useUSDCValue(token0CurrencyAmount) || undefined - const [independentToken, dependentToken] = exactField === PositionField.TOKEN0 ? [token0, token1] : [token1, token0] - const independentAmount = tryParseCurrencyAmount(exactAmount, independentToken) - - const [, pool] = usePool(token0, token1, parseV3FeeTier(positionInfo.feeTier)) - const [, pair] = useV2Pair(token0, token1) - - const dependentAmount: CurrencyAmount | undefined = useMemo(() => { - // we wrap the currencies just to get the price in terms of the other token - const wrappedIndependentAmount = independentAmount?.wrapped - - if (positionInfo.restPosition.position.case === 'v2Pair') { - const [token0Wrapped, token1Wrapped] = [token0?.wrapped, token1?.wrapped] - - if (token0Wrapped && token1Wrapped && wrappedIndependentAmount && pair) { - const dependentTokenAmount = - exactField === PositionField.TOKEN0 - ? pair.priceOf(token0Wrapped).quote(wrappedIndependentAmount) - : pair.priceOf(token1Wrapped).quote(wrappedIndependentAmount) - return dependentToken?.isNative - ? CurrencyAmount.fromRawAmount(dependentToken, dependentTokenAmount.quotient) - : dependentTokenAmount - } - return undefined - } - - if (positionInfo.restPosition.position.case === 'v3Position') { - const position: PoolPosition = positionInfo.restPosition.position.value - const { tickLower: tickLowerStr, tickUpper: tickUpperStr } = position - const tickLower = parseInt(tickLowerStr) - const tickUpper = parseInt(tickUpperStr) - - if ( - independentAmount && - wrappedIndependentAmount && - typeof tickLower === 'number' && - typeof tickUpper === 'number' && - pool - ) { - const position: Position | undefined = wrappedIndependentAmount.currency.equals(pool.token0) - ? Position.fromAmount0({ - pool, - tickLower, - tickUpper, - amount0: independentAmount.quotient, - useFullPrecision: true, // we want full precision for the theoretical position - }) - : Position.fromAmount1({ - pool, - tickLower, - tickUpper, - amount1: independentAmount.quotient, - }) - - const dependentTokenAmount = wrappedIndependentAmount.currency.equals(pool.token0) - ? position.amount1 - : position.amount0 - return dependentToken && CurrencyAmount.fromRawAmount(dependentToken, dependentTokenAmount.quotient) - } - - return undefined - } - - if (positionInfo.restPosition.position.case === 'v4Position') { - // TODO: calculate for v4 - return undefined - } - - return undefined - }, [ - dependentToken, - independentAmount, - pool, - positionInfo.restPosition.position, - exactField, - pair, - token0.wrapped, - token1.wrapped, - ]) - - const independentTokenUSDValue = useUSDCValue(independentAmount) || undefined - const dependentTokenUSDValue = useUSDCValue(dependentAmount) || undefined + // TODO: compute the dependent value - const dependentField = exactField === PositionField.TOKEN0 ? PositionField.TOKEN1 : PositionField.TOKEN0 return { - currencyBalances: { [PositionField.TOKEN0]: token0Balance, [PositionField.TOKEN1]: token1Balance }, - formattedAmounts: { [exactField]: exactAmount, [dependentField]: dependentAmount?.toExact() }, - currencyAmounts: { [exactField]: independentAmount, [dependentField]: dependentAmount }, - currencyAmountsUSDValue: { [exactField]: independentTokenUSDValue, [dependentField]: dependentTokenUSDValue }, + formattedAmounts: { [Field.TOKEN0]: exactAmount }, + currencyBalances: { [Field.TOKEN0]: token0Balance, [Field.TOKEN1]: token1Balance }, + currencyAmounts: { [Field.TOKEN0]: token0CurrencyAmount }, + currencyAmountsUSDValue: { [Field.TOKEN0]: token0USDValue }, } } diff --git a/apps/web/src/components/swap/SwapHeader.test.tsx b/apps/web/src/components/swap/SwapHeader.test.tsx index 2a7d8eb2bc1..956593df5a0 100644 --- a/apps/web/src/components/swap/SwapHeader.test.tsx +++ b/apps/web/src/components/swap/SwapHeader.test.tsx @@ -1,9 +1,9 @@ import SwapHeader from 'components/swap/SwapHeader' +import { Field } from 'components/swap/constants' import { Dispatch, PropsWithChildren, SetStateAction } from 'react' import { CurrencyState, EMPTY_DERIVED_SWAP_INFO, SwapAndLimitContext, SwapContext } from 'state/swap/types' import { act, render, screen } from 'test-utils/render' import { InterfaceChainId, UniverseChainId } from 'uniswap/src/types/chains' -import { CurrencyField } from 'uniswap/src/types/currency' import { SwapTab } from 'uniswap/src/types/screens/interface' interface WrapperProps { @@ -37,7 +37,7 @@ function Wrapper(props: PropsWithChildren) { derivedSwapInfo: EMPTY_DERIVED_SWAP_INFO, setSwapState: jest.fn(), swapState: { - independentField: CurrencyField.INPUT, + independentField: Field.INPUT, typedValue: '', }, }} diff --git a/apps/web/src/components/swap/SwapLineItem.tsx b/apps/web/src/components/swap/SwapLineItem.tsx index 3691bef360c..3f8a44e2241 100644 --- a/apps/web/src/components/swap/SwapLineItem.tsx +++ b/apps/web/src/components/swap/SwapLineItem.tsx @@ -130,7 +130,6 @@ function FeeRow({ trade: { swapFee, outputAmount } }: { trade: SubmittableTrade return <>{formatNumber({ input: outputFeeFiatValue, type: NumberType.FiatGasPrice })} } -// eslint-disable-next-line consistent-return function useLineItem(props: SwapLineItemProps): LineItemData | undefined { const { trade, syncing, allowedSlippage, type, priceImpact } = props const { formatPercent } = useFormatter() @@ -158,7 +157,7 @@ function useLineItem(props: SwapLineItemProps): LineItemData | undefined { } case SwapLineItemType.NETWORK_COST: if (!SUPPORTED_GAS_ESTIMATE_CHAIN_IDS.includes(chainId)) { - return undefined + return } return { Label: () => , @@ -173,7 +172,7 @@ function useLineItem(props: SwapLineItemProps): LineItemData | undefined { case SwapLineItemType.PRICE_IMPACT: // Hides price impact row if the current trade is UniswapX or we're expecting a preview trade to result in UniswapX if (isUniswapX || !priceImpact || (isPreview && isUniswapXTradeType(lastSubmittableFillType))) { - return undefined + return } return { Label: () => , @@ -206,7 +205,7 @@ function useLineItem(props: SwapLineItemProps): LineItemData | undefined { } case SwapLineItemType.MAXIMUM_INPUT: if (trade.tradeType === TradeType.EXACT_INPUT) { - return undefined + return } return { Label: () => , @@ -243,7 +242,7 @@ function useLineItem(props: SwapLineItemProps): LineItemData | undefined { return getFOTLineItem(props) case SwapLineItemType.EXPIRY: if (!isLimitTrade(trade)) { - return undefined + return } return { Label: () => , @@ -257,7 +256,7 @@ function getFOTLineItem({ type, trade }: SwapLineItemProps): LineItemData | unde const currency = isInput ? trade.inputAmount.currency : trade.outputAmount.currency const tax = isInput ? trade.inputTax : trade.outputTax if (tax.equalTo(0)) { - return undefined + return } const tokenSymbol = currency.symbol ?? currency.name diff --git a/apps/web/src/components/swap/SwapModalHeaderAmount.tsx b/apps/web/src/components/swap/SwapModalHeaderAmount.tsx index c0fa4e1c30b..c9cebdd241c 100644 --- a/apps/web/src/components/swap/SwapModalHeaderAmount.tsx +++ b/apps/web/src/components/swap/SwapModalHeaderAmount.tsx @@ -3,13 +3,13 @@ import CurrencyLogo from 'components/Logo/CurrencyLogo' import { MouseoverTooltip } from 'components/Tooltip' import Column from 'components/deprecated/Column' import Row from 'components/deprecated/Row' +import { Field } from 'components/swap/constants' import { useWindowSize } from 'hooks/screenSize/useWindowSize' import styled from 'lib/styled-components' import { PropsWithChildren, ReactNode } from 'react' import { TextProps } from 'rebass' import { BREAKPOINTS } from 'theme' import { ThemedText } from 'theme/components' -import { CurrencyField } from 'uniswap/src/types/currency' import { NumberType, useFormatter } from 'utils/formatNumbers' const Label = styled(ThemedText.BodySmall)<{ cursor?: string }>` @@ -30,7 +30,7 @@ const ResponsiveHeadline = ({ children, ...textProps }: PropsWithChildren diff --git a/apps/web/src/components/swap/SwapPreview.test.tsx b/apps/web/src/components/swap/SwapPreview.test.tsx index 6f9627dc97d..fc524d5688d 100644 --- a/apps/web/src/components/swap/SwapPreview.test.tsx +++ b/apps/web/src/components/swap/SwapPreview.test.tsx @@ -20,8 +20,8 @@ describe('SwapPreview.tsx', () => { ) expect(asFragment()).toMatchSnapshot() expect(screen.getByText(/Output is estimated. You will receive at least /i)).toBeInTheDocument() - expect(screen.getByTestId('input-amount')).toHaveTextContent(`<0.00001 ABC`) - expect(screen.getByTestId('output-amount')).toHaveTextContent(`<0.00001 DEF`) + expect(screen.getByTestId('INPUT-amount')).toHaveTextContent(`<0.00001 ABC`) + expect(screen.getByTestId('OUTPUT-amount')).toHaveTextContent(`<0.00001 DEF`) }) it('renders ETH input token for an ETH input UniswapX swap', () => { @@ -34,8 +34,8 @@ describe('SwapPreview.tsx', () => { ) expect(asFragment()).toMatchSnapshot() expect(screen.getByText(/Output is estimated. You will receive at least /i)).toBeInTheDocument() - expect(screen.getByTestId('input-amount')).toHaveTextContent(`<0.00001 ETH`) - expect(screen.getByTestId('output-amount')).toHaveTextContent(`<0.00001 DEF`) + expect(screen.getByTestId('INPUT-amount')).toHaveTextContent(`<0.00001 ETH`) + expect(screen.getByTestId('OUTPUT-amount')).toHaveTextContent(`<0.00001 DEF`) }) it('renders ETH input token for an ETH input UniswapX v2 swap', () => { @@ -48,8 +48,8 @@ describe('SwapPreview.tsx', () => { ) expect(asFragment()).toMatchSnapshot() expect(screen.getByText(/Output is estimated. You will receive at least /i)).toBeInTheDocument() - expect(screen.getByTestId('input-amount')).toHaveTextContent(`<0.00001 ETH`) - expect(screen.getByTestId('output-amount')).toHaveTextContent(`<0.00001 DEF`) + expect(screen.getByTestId('INPUT-amount')).toHaveTextContent(`<0.00001 ETH`) + expect(screen.getByTestId('OUTPUT-amount')).toHaveTextContent(`<0.00001 DEF`) }) it('test trade exact output, no recipient', () => { @@ -59,8 +59,8 @@ describe('SwapPreview.tsx', () => { expect(asFragment()).toMatchSnapshot() expect(screen.getByText(/Input is estimated. You will sell at most/i)).toBeInTheDocument() - expect(screen.getByTestId('input-amount')).toHaveTextContent(`<0.00001 ABC`) - expect(screen.getByTestId('output-amount')).toHaveTextContent(`<0.00001 GHI`) + expect(screen.getByTestId('INPUT-amount')).toHaveTextContent(`<0.00001 ABC`) + expect(screen.getByTestId('OUTPUT-amount')).toHaveTextContent(`<0.00001 GHI`) }) it('renders preview trades with loading states', () => { diff --git a/apps/web/src/components/swap/SwapPreview.tsx b/apps/web/src/components/swap/SwapPreview.tsx index 6ff18513e0f..21073e466b8 100644 --- a/apps/web/src/components/swap/SwapPreview.tsx +++ b/apps/web/src/components/swap/SwapPreview.tsx @@ -1,13 +1,13 @@ import { Currency, Percent, TradeType } from '@uniswap/sdk-core' import Column, { AutoColumn } from 'components/deprecated/Column' import { SwapModalHeaderAmount } from 'components/swap/SwapModalHeaderAmount' +import { Field } from 'components/swap/constants' import { useUSDPrice } from 'hooks/useUSDPrice' import styled from 'lib/styled-components' import { InterfaceTrade } from 'state/routing/types' import { isPreviewTrade } from 'state/routing/utils' import { ThemedText } from 'theme/components' import { Trans } from 'uniswap/src/i18n' -import { CurrencyField } from 'uniswap/src/types/currency' const HeaderContainer = styled(AutoColumn)` margin-top: 0px; @@ -29,7 +29,7 @@ export function SwapPreview({ } amount={trade.inputAmount} currency={inputCurrency ?? trade.inputAmount.currency} @@ -37,7 +37,7 @@ export function SwapPreview({ isLoading={isPreviewTrade(trade) && trade.tradeType === TradeType.EXACT_OUTPUT} /> } amount={trade.outputAmount} currency={trade.outputAmount.currency} diff --git a/apps/web/src/components/swap/__snapshots__/SwapLineItem.test.tsx.snap b/apps/web/src/components/swap/__snapshots__/SwapLineItem.test.tsx.snap index 33b7d62604f..e905125f95b 100644 --- a/apps/web/src/components/swap/__snapshots__/SwapLineItem.test.tsx.snap +++ b/apps/web/src/components/swap/__snapshots__/SwapLineItem.test.tsx.snap @@ -1780,7 +1780,7 @@ exports[`SwapLineItem.tsx exact input 1`] = ` } .c38 img { - width: 9px; + width: 10px; height: 20px; object-fit: cover; } @@ -2779,7 +2779,7 @@ exports[`SwapLineItem.tsx exact input api 1`] = ` } .c38 img { - width: 9px; + width: 10px; height: 20px; object-fit: cover; } @@ -3778,7 +3778,7 @@ exports[`SwapLineItem.tsx exact output 1`] = ` } .c38 img { - width: 9px; + width: 10px; height: 20px; object-fit: cover; } @@ -4818,7 +4818,7 @@ exports[`SwapLineItem.tsx fee on buy 1`] = ` } .c38 img { - width: 9px; + width: 10px; height: 20px; object-fit: cover; } @@ -5871,7 +5871,7 @@ exports[`SwapLineItem.tsx fee on sell 1`] = ` } .c38 img { - width: 9px; + width: 10px; height: 20px; object-fit: cover; } diff --git a/apps/web/src/components/swap/__snapshots__/SwapPreview.test.tsx.snap b/apps/web/src/components/swap/__snapshots__/SwapPreview.test.tsx.snap index 52834c5e8b4..c44ebc10b4f 100644 --- a/apps/web/src/components/swap/__snapshots__/SwapPreview.test.tsx.snap +++ b/apps/web/src/components/swap/__snapshots__/SwapPreview.test.tsx.snap @@ -192,7 +192,7 @@ exports[`SwapPreview.tsx matches base snapshot, test trade exact input 1`] = ` >
<0.00001 ABC
@@ -255,7 +255,7 @@ exports[`SwapPreview.tsx matches base snapshot, test trade exact input 1`] = ` >
<0.00001 DEF
@@ -491,7 +491,7 @@ exports[`SwapPreview.tsx renders ETH input token for an ETH input UniswapX swap >
<0.00001 ETH
@@ -554,7 +554,7 @@ exports[`SwapPreview.tsx renders ETH input token for an ETH input UniswapX swap >
<0.00001 DEF
@@ -790,7 +790,7 @@ exports[`SwapPreview.tsx renders ETH input token for an ETH input UniswapX v2 sw >
<0.00001 ETH
@@ -853,7 +853,7 @@ exports[`SwapPreview.tsx renders ETH input token for an ETH input UniswapX v2 sw >
<0.00001 DEF
@@ -1089,7 +1089,7 @@ exports[`SwapPreview.tsx renders preview trades with loading states 1`] = ` >
<0.00001 DEF
@@ -1152,7 +1152,7 @@ exports[`SwapPreview.tsx renders preview trades with loading states 1`] = ` >
<0.00001 DEF
@@ -1388,7 +1388,7 @@ exports[`SwapPreview.tsx test trade exact output, no recipient 1`] = ` >
<0.00001 ABC
@@ -1451,7 +1451,7 @@ exports[`SwapPreview.tsx test trade exact output, no recipient 1`] = ` >
<0.00001 GHI
diff --git a/apps/web/src/components/swap/constants.ts b/apps/web/src/components/swap/constants.ts index 1d70d7969ff..8a5c722cc6f 100644 --- a/apps/web/src/components/swap/constants.ts +++ b/apps/web/src/components/swap/constants.ts @@ -3,3 +3,8 @@ import { LDO, MNW, NMR, USDT as USDT_MAINNET } from 'uniswap/src/constants/token // List of tokens that require existing allowance to be reset before approving the new amount (mainnet only). // See the `approve` function here: https://etherscan.io/address/0xdAC17F958D2ee523a2206206994597C13D831ec7#code export const RESET_APPROVAL_TOKENS = [USDT_MAINNET, LDO, NMR, MNW] + +export enum Field { + INPUT = 'INPUT', + OUTPUT = 'OUTPUT', +} diff --git a/apps/web/src/constants/chains.ts b/apps/web/src/constants/chains.ts index b3318d2fe27..855b466d07a 100644 --- a/apps/web/src/constants/chains.ts +++ b/apps/web/src/constants/chains.ts @@ -5,9 +5,8 @@ import { useCallback, useMemo } from 'react' import { useParams } from 'react-router-dom' import { GQL_MAINNET_CHAINS, UNIVERSE_CHAIN_INFO } from 'uniswap/src/constants/chains' import { Chain as BackendChainId } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' -import { ArbitrumXV2ExperimentGroup, Experiments } from 'uniswap/src/features/gating/experiments' import { FeatureFlags } from 'uniswap/src/features/gating/flags' -import { useExperimentGroupName, useFeatureFlag } from 'uniswap/src/features/gating/hooks' +import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' import { InterfaceChainId, UniverseChainId, UniverseChainInfo, WEB_SUPPORTED_CHAIN_IDS } from 'uniswap/src/types/chains' export const AVERAGE_L1_BLOCK_TIME = ms(`12s`) @@ -53,7 +52,7 @@ export function useIsSupportedChainIdCallback() { export function useSupportedChainId(chainId?: number): SupportedInterfaceChainId | undefined { const featureFlaggedChains = useFeatureFlaggedChainIds() if (!chainId || WEB_SUPPORTED_CHAIN_IDS.indexOf(chainId) === -1) { - return undefined + return } const chainDisabled = featureFlaggedChains[chainId as SupportedInterfaceChainId] === false @@ -180,16 +179,8 @@ export function getChainPriority(chainId: InterfaceChainId): number { return Infinity } -export function useIsUniswapXSupportedChain(chainId?: number) { - const xv2ArbitrumEnabled = - useExperimentGroupName(Experiments.ArbitrumXV2OpenOrders) === ArbitrumXV2ExperimentGroup.Test - const isPriorityOrdersEnabled = useFeatureFlag(FeatureFlags.UniswapXPriorityOrders) - - return ( - chainId === UniverseChainId.Mainnet || - (xv2ArbitrumEnabled && chainId === UniverseChainId.ArbitrumOne) || - (isPriorityOrdersEnabled && chainId === UniverseChainId.Base) // UniswapX priority orders are only available on Base for now - ) +export function isUniswapXSupportedChain(chainId?: number) { + return chainId === UniverseChainId.Mainnet } export function isStablecoin(currency?: Currency): boolean { diff --git a/apps/web/src/constants/routing.test.ts b/apps/web/src/constants/routing.test.ts index 44d686c6142..cd4bae70530 100644 --- a/apps/web/src/constants/routing.test.ts +++ b/apps/web/src/constants/routing.test.ts @@ -17,7 +17,7 @@ describe('Routing', () => { }) it('contains all coins for polygon', () => { const symbols = COMMON_BASES[UniverseChainId.Polygon].map((coin) => coin.currency.symbol) - expect(symbols).toEqual(['POL', 'WETH', 'USDC', 'DAI', 'USDT', 'WBTC']) + expect(symbols).toEqual(['MATIC', 'WETH', 'USDC', 'DAI', 'USDT', 'WBTC']) }) it('contains all coins for celo', () => { const symbols = COMMON_BASES[UniverseChainId.Celo].map((coin) => coin.currency.symbol) diff --git a/apps/web/src/featureFlags/useFeatureFlagUrlOverrides.tsx b/apps/web/src/featureFlags/useFeatureFlagUrlOverrides.tsx index 1e54108df99..425c620505c 100644 --- a/apps/web/src/featureFlags/useFeatureFlagUrlOverrides.tsx +++ b/apps/web/src/featureFlags/useFeatureFlagUrlOverrides.tsx @@ -1,12 +1,10 @@ import useParsedQueryString from 'hooks/useParsedQueryString' import { useContext, useEffect } from 'react' import { Statsig, StatsigContext } from 'uniswap/src/features/gating/sdk/statsig' -import { isProdEnv } from 'utilities/src/environment/env' export function useFeatureFlagUrlOverrides() { const parsedQs = useParsedQueryString() const statsigContext = useContext(StatsigContext) - const isProduction = isProdEnv() useEffect(() => { // Override on @@ -16,9 +14,9 @@ export function useFeatureFlagUrlOverrides() { const featureFlagOverridesOff = typeof parsedQs.featureFlagOverrideOff === 'string' ? parsedQs.featureFlagOverrideOff.split(',') : [] - if (statsigContext.initialized && !isProduction) { + if (statsigContext.initialized) { featureFlagOverrides.forEach((gate) => Statsig.overrideGate(gate, true)) featureFlagOverridesOff.forEach((gate) => Statsig.overrideGate(gate, false)) } - }, [statsigContext.initialized, parsedQs.featureFlagOverride, parsedQs.featureFlagOverrideOff, isProduction]) + }, [statsigContext.initialized, parsedQs.featureFlagOverride, parsedQs.featureFlagOverrideOff]) } diff --git a/apps/web/src/graphql/data/ConversionRate.ts b/apps/web/src/graphql/data/ConversionRate.ts new file mode 100644 index 00000000000..66e67cddaea --- /dev/null +++ b/apps/web/src/graphql/data/ConversionRate.ts @@ -0,0 +1,19 @@ +import ms from 'ms' +import { useConvertWebQuery } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' +import { FiatCurrency } from 'uniswap/src/features/fiatCurrency/constants' +import { mapFiatCurrencyToServerCurrency } from 'uniswap/src/features/fiatCurrency/conversion' +import { getFetchPolicyForKey } from 'utils/getFetchPolicyForKey' + +// TODO(WALL-4578): converge conversion rate code to use the shared localization context +export function useLocalCurrencyConversionRate(localCurrency: FiatCurrency, skip?: boolean) { + const { data, loading } = useConvertWebQuery({ + variables: { toCurrency: mapFiatCurrencyToServerCurrency[localCurrency] }, + fetchPolicy: getFetchPolicyForKey(`convert-${localCurrency}`, ms('5m')), + skip, + }) + + return { + data: data?.convert?.value, + isLoading: loading, + } +} diff --git a/apps/web/src/graphql/data/apollo/AdaptiveRefetch.tsx b/apps/web/src/graphql/data/apollo/AdaptiveRefetch.tsx index ea387a82397..6ee88817ab8 100644 --- a/apps/web/src/graphql/data/apollo/AdaptiveRefetch.tsx +++ b/apps/web/src/graphql/data/apollo/AdaptiveRefetch.tsx @@ -80,7 +80,7 @@ export function createAdaptiveRefetchContext() { // Subscribing/unsubscribing allows AdaptiveRefetchProvider to track whether components are currently using the query or not, impacting whether or not to re-fetch when stale. useEffect(() => { if (options?.cacheOnly === true) { - return undefined + return } return subscribe() }, [options?.cacheOnly, subscribe]) diff --git a/apps/web/src/graphql/data/apollo/AdaptiveTokenBalancesProvider.tsx b/apps/web/src/graphql/data/apollo/AdaptiveTokenBalancesProvider.tsx deleted file mode 100644 index 5eeb6b1064f..00000000000 --- a/apps/web/src/graphql/data/apollo/AdaptiveTokenBalancesProvider.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { createAdaptiveRefetchContext } from 'graphql/data/apollo/AdaptiveRefetch' -import { PortfolioBalancesQueryResult } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' - -const { - Provider: AdaptiveTokenBalancesProvider, - useQuery: useTokenBalancesQuery, - PrefetchWrapper: PrefetchBalancesWrapper, -} = createAdaptiveRefetchContext() - -export { AdaptiveTokenBalancesProvider, PrefetchBalancesWrapper, useTokenBalancesQuery } diff --git a/apps/web/src/graphql/data/apollo/TokenBalancesProvider.test.tsx b/apps/web/src/graphql/data/apollo/TokenBalancesProvider.test.tsx index b4f02e14ec4..b3aeaad2a7e 100644 --- a/apps/web/src/graphql/data/apollo/TokenBalancesProvider.test.tsx +++ b/apps/web/src/graphql/data/apollo/TokenBalancesProvider.test.tsx @@ -1,5 +1,5 @@ import { fireEvent, screen } from '@testing-library/react' -import { PrefetchBalancesWrapper, useTokenBalancesQuery } from 'graphql/data/apollo/AdaptiveTokenBalancesProvider' +import { PrefetchBalancesWrapper, useTokenBalancesQuery } from 'graphql/data/apollo/TokenBalancesProvider' import { useAccount } from 'hooks/useAccount' import { mocked } from 'test-utils/mocked' import { render, renderHook } from 'test-utils/render' diff --git a/apps/web/src/graphql/data/apollo/TokenBalancesProvider.tsx b/apps/web/src/graphql/data/apollo/TokenBalancesProvider.tsx index 985f22a63a3..7fb0b26aa46 100644 --- a/apps/web/src/graphql/data/apollo/TokenBalancesProvider.tsx +++ b/apps/web/src/graphql/data/apollo/TokenBalancesProvider.tsx @@ -1,21 +1,31 @@ import { usePendingActivity } from 'components/AccountDrawer/MiniPortfolio/Activity/hooks' -import { AdaptiveTokenBalancesProvider } from 'graphql/data/apollo/AdaptiveTokenBalancesProvider' +import { createAdaptiveRefetchContext } from 'graphql/data/apollo/AdaptiveRefetch' import { useAssetActivitySubscription } from 'graphql/data/apollo/AssetActivityProvider' import { useAccount } from 'hooks/useAccount' -import { PropsWithChildren, useCallback, useMemo } from 'react' +import { PropsWithChildren, useCallback, useEffect, useMemo } from 'react' import { GQL_MAINNET_CHAINS_MUTABLE } from 'uniswap/src/constants/chains' +import { useTotalBalancesUsdPerChain } from 'uniswap/src/data/balances/utils' import { OnAssetActivitySubscription, + PortfolioBalancesQueryResult, SwapOrderStatus, usePortfolioBalancesLazyQuery, } 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' +const { + Provider: AdaptiveTokenBalancesProvider, + useQuery: useTokenBalancesQuery, + PrefetchWrapper: PrefetchBalancesWrapper, +} = createAdaptiveRefetchContext() + /** Returns whether an update may affect token balances. */ function mayAffectTokenBalances(data?: OnAssetActivitySubscription) { // Special case: non-filled order status updates do not affect balances. @@ -112,3 +122,42 @@ export function TokenBalancesProvider({ children }: PropsWithChildren) { ) } + +/** + * Retrieves cached token balances, avoiding new fetches to reduce backend load. + * Analytics should use balances from transaction flows instead of initiating fetches at pageload. + */ +export function useTotalBalancesUsdForAnalytics(): number | undefined { + return useTokenBalancesQuery({ cacheOnly: true }).data?.portfolios?.[0]?.tokensTotalDenominatedValue?.value +} + +export function useReportTotalBalancesUsdForAnalytics() { + const account = useAccount() + const portfolioBalanceUsd = useTotalBalancesUsdForAnalytics() + const totalBalancesUsdPerChain = useTotalBalancesUsdPerChain(useTokenBalancesQuery({ cacheOnly: true })) + + const sendBalancesReport = useCallback(async () => { + if (!portfolioBalanceUsd || !totalBalancesUsdPerChain || !account.address) { + return + } + + sendAnalyticsEvent(UniswapEventName.BalancesReport, { + total_balances_usd: portfolioBalanceUsd, + wallets: [account.address], + balances: [portfolioBalanceUsd], + }) + + sendAnalyticsEvent(UniswapEventName.BalancesReportPerChain, { + total_balances_usd_per_chain: totalBalancesUsdPerChain, + wallet: account.address, + }) + }, [portfolioBalanceUsd, totalBalancesUsdPerChain, account.address]) + + useEffect(() => { + if (portfolioBalanceUsd !== undefined && totalBalancesUsdPerChain !== undefined) { + sendBalancesReport() + } + }, [portfolioBalanceUsd, totalBalancesUsdPerChain, sendBalancesReport]) +} + +export { PrefetchBalancesWrapper, useTokenBalancesQuery } diff --git a/apps/web/src/graphql/data/apollo/useReportTotalBalancesUsdForAnalytics.ts b/apps/web/src/graphql/data/apollo/useReportTotalBalancesUsdForAnalytics.ts deleted file mode 100644 index 6dd098a6f2c..00000000000 --- a/apps/web/src/graphql/data/apollo/useReportTotalBalancesUsdForAnalytics.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { useTokenBalancesQuery } from 'graphql/data/apollo/AdaptiveTokenBalancesProvider' -import { useTotalBalancesUsdForAnalytics } from 'graphql/data/apollo/useTotalBalancesUsdForAnalytics' -import { useAccount } from 'hooks/useAccount' -import { useCallback, useEffect } from 'react' -import { useTotalBalancesUsdPerChain } from 'uniswap/src/data/balances/utils' -import { UniswapEventName } from 'uniswap/src/features/telemetry/constants' -import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' - -export function useReportTotalBalancesUsdForAnalytics() { - const account = useAccount() - const portfolioBalanceUsd = useTotalBalancesUsdForAnalytics() - const totalBalancesUsdPerChain = useTotalBalancesUsdPerChain(useTokenBalancesQuery({ cacheOnly: true })) - - const sendBalancesReport = useCallback(async () => { - if (!portfolioBalanceUsd || !totalBalancesUsdPerChain || !account.address) { - return - } - - sendAnalyticsEvent(UniswapEventName.BalancesReport, { - total_balances_usd: portfolioBalanceUsd, - wallets: [account.address], - balances: [portfolioBalanceUsd], - }) - - sendAnalyticsEvent(UniswapEventName.BalancesReportPerChain, { - total_balances_usd_per_chain: totalBalancesUsdPerChain, - wallet: account.address, - }) - }, [portfolioBalanceUsd, totalBalancesUsdPerChain, account.address]) - - useEffect(() => { - if (portfolioBalanceUsd !== undefined && totalBalancesUsdPerChain !== undefined) { - sendBalancesReport() - } - }, [portfolioBalanceUsd, totalBalancesUsdPerChain, sendBalancesReport]) -} diff --git a/apps/web/src/graphql/data/apollo/useTotalBalancesUsdForAnalytics.ts b/apps/web/src/graphql/data/apollo/useTotalBalancesUsdForAnalytics.ts deleted file mode 100644 index d9409036e32..00000000000 --- a/apps/web/src/graphql/data/apollo/useTotalBalancesUsdForAnalytics.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { useTokenBalancesQuery } from 'graphql/data/apollo/AdaptiveTokenBalancesProvider' - -/** - * Retrieves cached token balances, avoiding new fetches to reduce backend load. - * Analytics should use balances from transaction flows instead of initiating fetches at pageload. - */ -export function useTotalBalancesUsdForAnalytics(): number | undefined { - return useTokenBalancesQuery({ cacheOnly: true }).data?.portfolios?.[0]?.tokensTotalDenominatedValue?.value -} diff --git a/apps/web/src/graphql/data/types.ts b/apps/web/src/graphql/data/types.ts index 388a32f6bf5..7d44a6e9c00 100644 --- a/apps/web/src/graphql/data/types.ts +++ b/apps/web/src/graphql/data/types.ts @@ -40,7 +40,7 @@ export function gqlTokenToCurrencyInfo(token?: GqlToken): CurrencyInfo | undefin export function meldSupportedCurrencyToCurrencyInfo(forCurrency: FORSupportedToken): CurrencyInfo | undefined { if (!isSupportedChainId(Number(forCurrency.chainId))) { - return undefined + return } const supportedChainId = Number(forCurrency.chainId) as SupportedInterfaceChainId @@ -67,7 +67,7 @@ export function meldSupportedCurrencyToCurrencyInfo(forCurrency: FORSupportedTok const currency = fiatOnRampToCurrency(forCurrency) if (!currency) { - return undefined + return } return { currency, diff --git a/apps/web/src/graphql/data/util.tsx b/apps/web/src/graphql/data/util.tsx index 82f6823178b..32f32470621 100644 --- a/apps/web/src/graphql/data/util.tsx +++ b/apps/web/src/graphql/data/util.tsx @@ -65,7 +65,6 @@ export enum TimePeriod { YEAR = 'Y', } -// eslint-disable-next-line consistent-return export function toHistoryDuration(timePeriod: TimePeriod): HistoryDuration { switch (timePeriod) { case TimePeriod.HOUR: @@ -112,14 +111,14 @@ export function gqlToCurrency(token: DeepPartial): Currenc token.address, token.decimals ?? 18, token.symbol ?? undefined, - token.name ?? token.project?.name ?? undefined, + token.project?.name ?? token.name ?? undefined, ) } } export function fiatOnRampToCurrency(forCurrency: FORSupportedToken): Currency | undefined { if (!isSupportedChainId(Number(forCurrency.chainId))) { - return undefined + return } const supportedChainId = Number(forCurrency.chainId) as SupportedInterfaceChainId diff --git a/apps/web/src/hooks/useConfirmModalState.ts b/apps/web/src/hooks/useConfirmModalState.ts index d23c61985a6..9e0355f2de4 100644 --- a/apps/web/src/hooks/useConfirmModalState.ts +++ b/apps/web/src/hooks/useConfirmModalState.ts @@ -2,7 +2,7 @@ import { InterfaceEventName } from '@uniswap/analytics-events' import { Currency, Percent } from '@uniswap/sdk-core' import { ConfirmModalState } from 'components/ConfirmSwapModal' import { PendingModalError } from 'components/ConfirmSwapModal/Error' -import { RESET_APPROVAL_TOKENS } from 'components/swap/constants' +import { Field, RESET_APPROVAL_TOKENS } from 'components/swap/constants' import { useAccount } from 'hooks/useAccount' import { useMaxAmountIn } from 'hooks/useMaxAmountIn' import { Allowance, AllowanceState } from 'hooks/usePermit2Allowance' @@ -18,7 +18,6 @@ import { useSwapAndLimitContext } from 'state/swap/useSwapContext' import { useIsTransactionConfirmed } from 'state/transactions/hooks' import invariant from 'tiny-invariant' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' -import { CurrencyField } from 'uniswap/src/types/currency' import { logger } from 'utilities/src/logger/logger' import { useTrace } from 'utilities/src/telemetry/trace/TraceContext' import { NumberType, useFormatter } from 'utils/formatNumbers' @@ -47,7 +46,7 @@ export function useConfirmModalState({ allowedSlippage: Percent onSwap: () => void allowance: Allowance - onCurrencySelection: (field: CurrencyField, currency: Currency) => void + onCurrencySelection: (field: Field, currency: Currency) => void }) { const [confirmModalState, setConfirmModalState] = useState(ConfirmModalState.REVIEWING) const [approvalError, setApprovalError] = useState() @@ -122,7 +121,7 @@ export function useConfirmModalState({ setWrapTxHash(wrapTxHash) // After the wrap has succeeded, reset the input currency to be WETH // because the trade will be on WETH -> token - onCurrencySelection(CurrencyField.INPUT, trade.inputAmount.currency) + onCurrencySelection(Field.INPUT, trade.inputAmount.currency) sendAnalyticsEvent(InterfaceEventName.WRAP_TOKEN_TXN_SUBMITTED, { chain_id: chainId, token_symbol: maximumAmountIn?.currency.symbol, diff --git a/apps/web/src/hooks/useEthersProvider.ts b/apps/web/src/hooks/useEthersProvider.ts index 0fe25fa89ea..91a1b793f78 100644 --- a/apps/web/src/hooks/useEthersProvider.ts +++ b/apps/web/src/hooks/useEthersProvider.ts @@ -7,7 +7,7 @@ import { useClient, useConnectorClient } from 'wagmi' const providers = new WeakMap() -export function clientToProvider(client?: Client, chainId?: number) { +function clientToProvider(client?: Client, chainId?: number) { if (!client) { return undefined } diff --git a/apps/web/src/hooks/useKeyPress.ts b/apps/web/src/hooks/useKeyPress.ts index 44c91d4fc78..33badc6078f 100644 --- a/apps/web/src/hooks/useKeyPress.ts +++ b/apps/web/src/hooks/useKeyPress.ts @@ -20,7 +20,7 @@ export const useKeyPress = ({ }) => { useEffect(() => { if (!keys || disabled) { - return undefined + return } const onKeyPress = (event: any) => { const wasAnyKeyPressed = keys.some((key) => event.key === key) diff --git a/apps/web/src/hooks/useSelectChain.ts b/apps/web/src/hooks/useSelectChain.ts index 3f97f2ad9b0..96b85147abf 100644 --- a/apps/web/src/hooks/useSelectChain.ts +++ b/apps/web/src/hooks/useSelectChain.ts @@ -1,13 +1,13 @@ import { useSwitchChain } from 'hooks/useSwitchChain' import { useCallback } from 'react' -import { useDispatch } from 'react-redux' import { PopupType, addPopup, removePopup } from 'state/application/reducer' +import { useAppDispatch } from 'state/hooks' import { InterfaceChainId } from 'uniswap/src/types/chains' import { logger } from 'utilities/src/logger/logger' import { UserRejectedRequestError } from 'viem' export default function useSelectChain() { - const dispatch = useDispatch() + const dispatch = useAppDispatch() const switchChain = useSwitchChain() return useCallback( diff --git a/apps/web/src/hooks/useSwapTaxes.ts b/apps/web/src/hooks/useSwapTaxes.ts index b1121c13ae8..2033271abe5 100644 --- a/apps/web/src/hooks/useSwapTaxes.ts +++ b/apps/web/src/hooks/useSwapTaxes.ts @@ -94,7 +94,6 @@ async function getSwapTaxes( return { inputTax, outputTax } } -// Use the buyFeeBps/sellFeeBps fields from Token GQL query where possible instead of this hook export function useSwapTaxes(inputTokenAddress?: string, outputTokenAddress?: string, tokenChainId?: InterfaceChainId) { const account = useAccount() const chainId = tokenChainId ?? account.chainId diff --git a/apps/web/src/hooks/useSwitchChain.ts b/apps/web/src/hooks/useSwitchChain.ts index 278a489bbeb..4bb9b35bcd4 100644 --- a/apps/web/src/hooks/useSwitchChain.ts +++ b/apps/web/src/hooks/useSwitchChain.ts @@ -1,14 +1,14 @@ import { useIsSupportedChainIdCallback } from 'constants/chains' import { useAccount } from 'hooks/useAccount' import { useCallback } from 'react' -import { useDispatch } from 'react-redux' +import { useAppDispatch } from 'state/hooks' import { endSwitchingChain, startSwitchingChain } from 'state/wallets/reducer' import { trace } from 'tracing/trace' import { InterfaceChainId } from 'uniswap/src/types/chains' import { useSwitchChain as useSwitchChainWagmi } from 'wagmi' export function useSwitchChain() { - const dispatch = useDispatch() + const dispatch = useAppDispatch() const isSupportedChainCallback = useIsSupportedChainIdCallback() const { switchChain } = useSwitchChainWagmi() const account = useAccount() @@ -21,7 +21,7 @@ export function useSwitchChain() { } 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 undefined + return } return trace( { name: 'Switch chain', op: 'wallet.switch_chain' }, diff --git a/apps/web/src/hooks/useTokenBalances.test.ts b/apps/web/src/hooks/useTokenBalances.test.ts index 5320afef5c9..39153a60194 100644 --- a/apps/web/src/hooks/useTokenBalances.test.ts +++ b/apps/web/src/hooks/useTokenBalances.test.ts @@ -1,6 +1,6 @@ import { useWeb3React } from '@web3-react/core' import { NATIVE_CHAIN_ID } from 'constants/tokens' -import { useTokenBalancesQuery } from 'graphql/data/apollo/AdaptiveTokenBalancesProvider' +import { useTokenBalancesQuery } from 'graphql/data/apollo/TokenBalancesProvider' import { useTokenBalances } from 'hooks/useTokenBalances' import { mocked } from 'test-utils/mocked' import { renderHook } from 'test-utils/render' @@ -13,8 +13,8 @@ jest.mock('@web3-react/core', () => ({ useWeb3React: jest.fn(() => ({ account: '0x123', chainId: 1 })), })) -jest.mock('graphql/data/apollo/AdaptiveTokenBalancesProvider', () => ({ - ...jest.requireActual('graphql/data/apollo/AdaptiveTokenBalancesProvider'), +jest.mock('graphql/data/apollo/TokenBalancesProvider', () => ({ + ...jest.requireActual('graphql/data/apollo/TokenBalancesProvider'), useTokenBalancesQuery: jest.fn(() => ({ data: {}, loading: false })), })) diff --git a/apps/web/src/hooks/useTokenBalances.ts b/apps/web/src/hooks/useTokenBalances.ts index bee4eed2761..758ce011377 100644 --- a/apps/web/src/hooks/useTokenBalances.ts +++ b/apps/web/src/hooks/useTokenBalances.ts @@ -1,4 +1,4 @@ -import { useTokenBalancesQuery } from 'graphql/data/apollo/AdaptiveTokenBalancesProvider' +import { useTokenBalancesQuery } from 'graphql/data/apollo/TokenBalancesProvider' import { PortfolioBalance } from 'graphql/data/portfolios' import { useAccount } from 'hooks/useAccount' import { TokenBalances } from 'lib/hooks/useTokenList/sorting' diff --git a/apps/web/src/hooks/useTransactionGasFee.ts b/apps/web/src/hooks/useTransactionGasFee.ts index 18189342a09..7bab1638618 100644 --- a/apps/web/src/hooks/useTransactionGasFee.ts +++ b/apps/web/src/hooks/useTransactionGasFee.ts @@ -108,7 +108,7 @@ const isErrorResponse = (res: Response, gasFee: GasFeeResponse): gasFee is GasFe function useGasFeeQuery(tx?: TransactionRequest, skip: boolean = !tx) { const gasFeeFetcher = useCallback(async () => { if (skip) { - return undefined + return } const res = await fetch(`${UNISWAP_API_URL}/v1/gas-fee`, { @@ -119,7 +119,7 @@ function useGasFeeQuery(tx?: TransactionRequest, skip: boolean = !tx) { const body = (await res.json()) as GasFeeResponse if (isErrorResponse(res, body)) { - return undefined + return } return body diff --git a/apps/web/src/hooks/useUSDTokenUpdater.ts b/apps/web/src/hooks/useUSDTokenUpdater.ts index afd86b8ad1f..d72b8a15ae7 100644 --- a/apps/web/src/hooks/useUSDTokenUpdater.ts +++ b/apps/web/src/hooks/useUSDTokenUpdater.ts @@ -19,7 +19,7 @@ export function useUSDTokenUpdater( } { const { price, state } = useStablecoinPrice(exactCurrency) const { convertToFiatAmount, formatCurrencyAmount } = useFormatter() - const conversionRate = convertToFiatAmount(1).amount + const conversionRate = convertToFiatAmount().amount const supportedChainId = useSupportedChainId(exactCurrency?.chainId) return useMemo(() => { diff --git a/apps/web/src/hooks/useUniswapXSwapCallback.ts b/apps/web/src/hooks/useUniswapXSwapCallback.ts index 39523146b20..22ecab6ce4b 100644 --- a/apps/web/src/hooks/useUniswapXSwapCallback.ts +++ b/apps/web/src/hooks/useUniswapXSwapCallback.ts @@ -3,15 +3,8 @@ import { BigNumber } from '@ethersproject/bignumber' import { CustomUserProperties, SwapEventName } from '@uniswap/analytics-events' import { PermitTransferFrom } from '@uniswap/permit2-sdk' import { Percent } from '@uniswap/sdk-core' -import { - DutchOrder, - DutchOrderBuilder, - PriorityOrderBuilder, - UnsignedPriorityOrder, - UnsignedV2DutchOrder, - V2DutchOrderBuilder, -} from '@uniswap/uniswapx-sdk' -import { useTotalBalancesUsdForAnalytics } from 'graphql/data/apollo/useTotalBalancesUsdForAnalytics' +import { DutchOrder, DutchOrderBuilder, UnsignedV2DutchOrder, V2DutchOrderBuilder } from '@uniswap/uniswapx-sdk' +import { useTotalBalancesUsdForAnalytics } from 'graphql/data/apollo/TokenBalancesProvider' import { useAccount } from 'hooks/useAccount' import { useEthersWeb3Provider } from 'hooks/useEthersProvider' import { formatSwapSignedAnalyticsEventProperties } from 'lib/utils/analytics' @@ -20,7 +13,6 @@ import { DutchOrderTrade, LimitOrderTrade, OffchainOrderType, - PriorityOrderTrade, TradeFillType, V2DutchOrderTrade, } from 'state/routing/types' @@ -85,7 +77,7 @@ export function useUniswapXSwapCallback({ allowedSlippage, fiatValues, }: { - trade?: DutchOrderTrade | V2DutchOrderTrade | LimitOrderTrade | PriorityOrderTrade + trade?: DutchOrderTrade | V2DutchOrderTrade | LimitOrderTrade fiatValues: { amountIn?: number; amountOut?: number; feeUsd?: number } allowedSlippage: Percent }) { @@ -139,7 +131,7 @@ export function useUniswapXSwapCallback({ let domain: TypedDataDomain let types: Record let values: PermitTransferFrom - let updatedOrder: DutchOrder | UnsignedV2DutchOrder | UnsignedPriorityOrder + let updatedOrder: DutchOrder | UnsignedV2DutchOrder if (trade instanceof V2DutchOrderTrade) { deadline = now + trade.deadlineBufferSecs @@ -152,17 +144,6 @@ export function useUniswapXSwapCallback({ .nonce(updatedNonce ?? order.info.nonce) .buildPartial() ;({ domain, types, values } = updatedOrder.permitData()) - } else if (trade instanceof PriorityOrderTrade) { - deadline = now + trade.deadlineBufferSecs - - const order = trade.order - updatedOrder = PriorityOrderBuilder.fromOrder(order) - .deadline(deadline) - .nonFeeRecipient(account.address, trade.swapFee?.recipient) - // if fetching the nonce fails for any reason, default to existing nonce from the Swap quote. - .nonce(updatedNonce ?? order.info.nonce) - .buildPartial() - ;({ domain, types, values } = updatedOrder.permitData()) } else { const startTime = now + trade.startTimeBufferSecs const endTime = startTime + trade.auctionPeriodSecs @@ -182,6 +163,7 @@ export function useUniswapXSwapCallback({ trace.setData('startTime', startTime) trace.setData('endTime', endTime) } + trace.setData('deadline', deadline) const signature = await trace.child({ name: 'Sign', op: 'wallet.sign' }, async (walletTrace) => { @@ -255,7 +237,6 @@ export function useUniswapXSwapCallback({ signature, chainId: updatedOrder.chainId, quoteId: trade.quoteId, - requestId: trade.requestId, } } diff --git a/apps/web/src/hooks/useUniversalRouter.ts b/apps/web/src/hooks/useUniversalRouter.ts index 95a141510c0..f5b5afab550 100644 --- a/apps/web/src/hooks/useUniversalRouter.ts +++ b/apps/web/src/hooks/useUniversalRouter.ts @@ -4,7 +4,7 @@ import { CustomUserProperties, SwapEventName } from '@uniswap/analytics-events' import { Percent } from '@uniswap/sdk-core' import { FlatFeeOptions, SwapRouter, UNIVERSAL_ROUTER_ADDRESS } from '@uniswap/universal-router-sdk' import { FeeOptions, toHex } from '@uniswap/v3-sdk' -import { useTotalBalancesUsdForAnalytics } from 'graphql/data/apollo/useTotalBalancesUsdForAnalytics' +import { useTotalBalancesUsdForAnalytics } from 'graphql/data/apollo/TokenBalancesProvider' import { useAccount } from 'hooks/useAccount' import { useEthersWeb3Provider } from 'hooks/useEthersProvider' import { PermitSignature } from 'hooks/usePermitAllowance' diff --git a/apps/web/src/hooks/useUnmountingAnimation.ts b/apps/web/src/hooks/useUnmountingAnimation.ts index 6de835a3194..325afb2b2ef 100644 --- a/apps/web/src/hooks/useUnmountingAnimation.ts +++ b/apps/web/src/hooks/useUnmountingAnimation.ts @@ -40,7 +40,7 @@ export function useUnmountingAnimation( // If we can't remove the child or skipping is requested, stop here. if (!(parent && removeChild) || skip) { - return undefined + return } // Override the parent's removeChild function to add our animation logic diff --git a/apps/web/src/lib/hooks/routing/useRoutingAPIArguments.ts b/apps/web/src/lib/hooks/routing/useRoutingAPIArguments.ts index 5a393c7fa8c..1b2232f4cf0 100644 --- a/apps/web/src/lib/hooks/routing/useRoutingAPIArguments.ts +++ b/apps/web/src/lib/hooks/routing/useRoutingAPIArguments.ts @@ -1,19 +1,19 @@ import { SkipToken, skipToken } from '@reduxjs/toolkit/query/react' import { Protocol } from '@uniswap/router-sdk' import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core' -import { useIsUniswapXSupportedChain } from 'constants/chains' import { useMemo } from 'react' import { GetQuoteArgs, INTERNAL_ROUTER_PREFERENCE_PRICE, RouterPreference } from 'state/routing/types' import { currencyAddressForSwapQuote } from 'state/routing/utils' -import { - ArbitrumXV2ExperimentGroup, - ArbitrumXV2OpenOrderProperties, - Experiments, -} from 'uniswap/src/features/gating/experiments' +import { ArbitrumXV2OpenOrderProperties, Experiments } from 'uniswap/src/features/gating/experiments' import { FeatureFlags } from 'uniswap/src/features/gating/flags' import { useExperimentGroupName, useExperimentValue, useFeatureFlag } from 'uniswap/src/features/gating/hooks' import { UniverseChainId } from 'uniswap/src/types/chains' +enum ArbitrumXV2ExperimentGroup { + Test = 'Test', + Control = 'Control', +} + /** * Returns query arguments for the Routing API query or undefined if the * query should be skipped. Input arguments do not need to be memoized, as they will @@ -37,7 +37,6 @@ export function useRoutingAPIArguments({ protocolPreferences?: Protocol[] }): GetQuoteArgs | SkipToken { const uniswapXForceSyntheticQuotes = useFeatureFlag(FeatureFlags.UniswapXSyntheticQuote) - const isPriorityOrdersEnabled = useFeatureFlag(FeatureFlags.UniswapXPriorityOrders) const isXv2 = useFeatureFlag(FeatureFlags.UniswapXv2) const xv2ArbitrumEnabled = useExperimentGroupName(Experiments.ArbitrumXV2OpenOrders) === ArbitrumXV2ExperimentGroup.Test @@ -65,11 +64,6 @@ export function useRoutingAPIArguments({ // Don't enable fee logic if this is a quote for pricing const sendPortionEnabled = routerPreference !== INTERNAL_ROUTER_PREFERENCE_PRICE - const chainId = tokenIn?.chainId - const isUniswapXSupportedChain = useIsUniswapXSupportedChain(chainId) - const isPriorityOrder = - routerPreference === RouterPreference.X && isPriorityOrdersEnabled && chainId === UniverseChainId.Base // UniswapX priority orders are only available on Base for now - return useMemo( () => !tokenIn || !tokenOut || !amount || tokenIn.equals(tokenOut) || tokenIn.wrapped.equals(tokenOut.wrapped) @@ -97,8 +91,6 @@ export function useRoutingAPIArguments({ forceOpenOrders, deadlineBufferSecs, arbitrumXV2SlippageTolerance, - isPriorityOrder, - isUniswapXSupportedChain, }, [ tokenIn, @@ -116,8 +108,6 @@ export function useRoutingAPIArguments({ forceOpenOrders, deadlineBufferSecs, arbitrumXV2SlippageTolerance, - isPriorityOrder, - isUniswapXSupportedChain, ], ) } diff --git a/apps/web/src/lib/hooks/useBlockNumber.tsx b/apps/web/src/lib/hooks/useBlockNumber.tsx index 1fc46e36d18..10d38e555a8 100644 --- a/apps/web/src/lib/hooks/useBlockNumber.tsx +++ b/apps/web/src/lib/hooks/useBlockNumber.tsx @@ -82,7 +82,7 @@ export function BlockNumberProvider({ children }: PropsWithChildren) { provider.removeListener('block', onBlock) } } - return undefined + return }, [provider, windowVisible, onChainBlock, multicallChainId]) // Poll once for the mainnet block number using the network provider. useEffect(() => { diff --git a/apps/web/src/lib/hooks/useInterval.ts b/apps/web/src/lib/hooks/useInterval.ts index 01b51237aac..11be822f5d6 100644 --- a/apps/web/src/lib/hooks/useInterval.ts +++ b/apps/web/src/lib/hooks/useInterval.ts @@ -11,7 +11,7 @@ import { useEffect } from 'react' export default function useInterval(callback: () => void | Promise, delay: null | number, leading = true) { useEffect(() => { if (delay === null) { - return undefined + return } let timeout: ReturnType diff --git a/apps/web/src/lib/hooks/useTokenList/sorting.ts b/apps/web/src/lib/hooks/useTokenList/sorting.ts index 772eb8abd55..bbaadb2c4e8 100644 --- a/apps/web/src/lib/hooks/useTokenList/sorting.ts +++ b/apps/web/src/lib/hooks/useTokenList/sorting.ts @@ -66,7 +66,7 @@ export function getSortedPortfolioTokens( address, tokenBalance.token?.decimals, tokenBalance.token?.symbol, - tokenBalance.token?.name ?? tokenBalance.token?.project?.name, + tokenBalance.token?.project?.name ?? tokenBalance.token?.name, ) return portfolioToken diff --git a/apps/web/src/lib/utils/analytics.ts b/apps/web/src/lib/utils/analytics.ts index 17f0f36e100..b718d21e2b0 100644 --- a/apps/web/src/lib/utils/analytics.ts +++ b/apps/web/src/lib/utils/analytics.ts @@ -1,10 +1,7 @@ import { Currency, CurrencyAmount, Percent, Price, Token } from '@uniswap/sdk-core' import { NATIVE_CHAIN_ID } from 'constants/tokens' -import { InterfaceTrade, OffchainOrderType, QuoteMethod, SubmittableTrade, TradeFillType } from 'state/routing/types' +import { InterfaceTrade, QuoteMethod, SubmittableTrade } from 'state/routing/types' import { isClassicTrade, isSubmittableTrade, isUniswapXTrade } from 'state/routing/utils' -import { Routing } from 'uniswap/src/data/tradingApi/__generated__' -import { ClassicTrade, UniswapXTrade } from 'uniswap/src/features/transactions/swap/types/trade' -import { isClassic } from 'uniswap/src/features/transactions/swap/utils/routing' import { TransactionOriginType } from 'uniswap/src/features/transactions/types/transactionDetails' import { computeRealizedPriceImpact } from 'utils/prices' @@ -45,95 +42,38 @@ function getEstimatedNetworkFee(trade: InterfaceTrade) { return undefined } -// eslint-disable-next-line consistent-return -function tradeRoutingToFillType({ - routing, - indicative, -}: { - routing: Routing - indicative: boolean -}): TradeFillType | 'bridge' { - if (indicative) { - return TradeFillType.None - } - - switch (routing) { - case Routing.DUTCH_V2: - case Routing.DUTCH_LIMIT: - case Routing.LIMIT_ORDER: - return TradeFillType.UniswapXv2 - case Routing.CLASSIC: - return TradeFillType.Classic - case Routing.BRIDGE: - return 'bridge' - } -} - -function tradeRoutingToOffchainOrderType(routing: Routing): OffchainOrderType | undefined { - switch (routing) { - case Routing.DUTCH_V2: - return OffchainOrderType.DUTCH_V2_AUCTION - case Routing.DUTCH_LIMIT: - case Routing.LIMIT_ORDER: - return OffchainOrderType.LIMIT_ORDER - default: - return undefined - } -} - export function formatCommonPropertiesForTrade( - trade: InterfaceTrade | ClassicTrade | UniswapXTrade, + trade: InterfaceTrade, allowedSlippage: Percent, outputFeeFiatValue?: number, ) { - const isUniversalSwapFlow = trade instanceof ClassicTrade || trade instanceof UniswapXTrade - return { - routing: isUniversalSwapFlow ? tradeRoutingToFillType(trade) : trade.fillType, + routing: trade.fillType, type: trade.tradeType, - ura_quote_id: isUniversalSwapFlow ? trade.quote?.quote.quoteId : isUniswapXTrade(trade) ? trade.quoteId : undefined, - ura_request_id: isUniversalSwapFlow - ? trade.quote?.requestId - : isSubmittableTrade(trade) - ? trade.requestId - : undefined, - ura_quote_block_number: isUniversalSwapFlow - ? isClassic(trade) - ? trade.quote?.quote.blockNumber - : undefined - : isClassicTrade(trade) - ? trade.blockNumber - : undefined, + ura_quote_id: isUniswapXTrade(trade) ? trade.quoteId : undefined, + ura_request_id: isSubmittableTrade(trade) ? trade.requestId : undefined, + ura_quote_block_number: isClassicTrade(trade) ? trade.blockNumber : undefined, token_in_address: getTokenAddress(trade.inputAmount.currency), token_out_address: getTokenAddress(trade.outputAmount.currency), token_in_symbol: trade.inputAmount.currency.symbol, token_out_symbol: trade.outputAmount.currency.symbol, token_in_amount: formatToDecimal(trade.inputAmount, trade.inputAmount.currency.decimals), token_out_amount: formatToDecimal(trade.outputAmount, trade.outputAmount.currency.decimals), - price_impact_basis_points: - trade instanceof ClassicTrade || (!isUniversalSwapFlow && isClassicTrade(trade)) - ? formatPercentInBasisPointsNumber(computeRealizedPriceImpact(trade)) - : undefined, + price_impact_basis_points: isClassicTrade(trade) + ? formatPercentInBasisPointsNumber(computeRealizedPriceImpact(trade)) + : undefined, chain_id: trade.inputAmount.currency.chainId === trade.outputAmount.currency.chainId ? trade.inputAmount.currency.chainId : undefined, - estimated_network_fee_usd: isUniversalSwapFlow - ? trade instanceof ClassicTrade - ? trade.quote?.quote.gasFeeUSD - : undefined - : getEstimatedNetworkFee(trade)?.toString(), + estimated_network_fee_usd: getEstimatedNetworkFee(trade)?.toString(), minimum_output_after_slippage: trade.minimumAmountOut(allowedSlippage).toSignificant(6), allowed_slippage: formatPercentNumber(allowedSlippage), - method: isUniversalSwapFlow ? undefined : getQuoteMethod(trade), + method: getQuoteMethod(trade), fee_usd: outputFeeFiatValue, token_out_detected_tax: formatPercentNumber(trade.outputTax), token_in_detected_tax: formatPercentNumber(trade.inputTax), - offchain_order_type: isUniversalSwapFlow - ? tradeRoutingToOffchainOrderType(trade.routing) - : isUniswapXTrade(trade) - ? trade.offchainOrderType - : undefined, + offchain_order_type: isUniswapXTrade(trade) ? trade.offchainOrderType : undefined, transactionOriginType: TransactionOriginType.Internal, } } @@ -146,7 +86,7 @@ export const formatSwapSignedAnalyticsEventProperties = ({ timeToSignSinceRequestMs, portfolioBalanceUsd, }: { - trade: SubmittableTrade | ClassicTrade | UniswapXTrade + trade: SubmittableTrade allowedSlippage: Percent fiatValues: { amountIn?: number; amountOut?: number; feeUsd?: number } txHash?: string diff --git a/apps/web/src/nft/components/bag/BagRow.tsx b/apps/web/src/nft/components/bag/BagRow.tsx index acf9d2bf7fa..56243fb4f53 100644 --- a/apps/web/src/nft/components/bag/BagRow.tsx +++ b/apps/web/src/nft/components/bag/BagRow.tsx @@ -280,7 +280,7 @@ export const UnavailableAssetsHeaderRow = ({ clearUnavailableAssets() setDidOpenUnavailableAssets(false) } - return undefined + return } const intervalId = setInterval(() => { diff --git a/apps/web/src/nft/components/bag/ButtonStates.tsx b/apps/web/src/nft/components/bag/ButtonStates.tsx index 5aab1a9cb66..447dc79d166 100644 --- a/apps/web/src/nft/components/bag/ButtonStates.tsx +++ b/apps/web/src/nft/components/bag/ButtonStates.tsx @@ -1,4 +1,3 @@ -import { ConnectWalletButtonText } from 'components/NavBar/accountCTAsExperimentUtils' import { DefaultTheme } from 'lib/styled-components' import { PriceImpact } from 'nft/hooks/usePriceImpact' import { ReactNode } from 'react' @@ -59,7 +58,7 @@ export function getBuyButtonStateData( ...defaultBuyButtonState, handleClick: handleClickOverride ?? (() => undefined), disabled: false, - buttonText: , + buttonText: , }, [BuyButtonStates.NOT_SUPPORTED_CHAIN]: { ...defaultBuyButtonState, diff --git a/apps/web/src/nft/components/card/utils.tsx b/apps/web/src/nft/components/card/utils.tsx index 2abf8fb7d04..6b39286f3e5 100644 --- a/apps/web/src/nft/components/card/utils.tsx +++ b/apps/web/src/nft/components/card/utils.tsx @@ -48,7 +48,6 @@ function getAssetMediaType(asset: GenieAsset | WalletAsset) { return assetMediaType } -// eslint-disable-next-line consistent-return export function getNftDisplayComponent( asset: GenieAsset | WalletAsset, mediaShouldBePlaying: boolean, @@ -128,11 +127,7 @@ export function useSelectAsset({ return } - if (isSelected) { - unselectAsset?.() - } else { - selectAsset?.() - } + return isSelected ? unselectAsset?.() : selectAsset?.() }, [selectAsset, isDisabled, onClick, unselectAsset, isSelected], ) diff --git a/apps/web/src/nft/components/collection/Sweep.tsx b/apps/web/src/nft/components/collection/Sweep.tsx index 6ef47f36f81..69871c08c5c 100644 --- a/apps/web/src/nft/components/collection/Sweep.tsx +++ b/apps/web/src/nft/components/collection/Sweep.tsx @@ -467,7 +467,6 @@ function useSweepFetcherParams( const isMarketFiltered = !!markets.length - // eslint-disable-next-line consistent-return return useMemo(() => { if (isMarketFiltered) { if (market === 'others') { diff --git a/apps/web/src/nft/components/details/AssetDetails.tsx b/apps/web/src/nft/components/details/AssetDetails.tsx index bce53ef0824..b637a4c1948 100644 --- a/apps/web/src/nft/components/details/AssetDetails.tsx +++ b/apps/web/src/nft/components/details/AssetDetails.tsx @@ -203,7 +203,6 @@ const AssetView = ({ mediaType: MediaType asset: GenieAsset dominantColor: [number, number, number] - // eslint-disable-next-line consistent-return }) => { const style = { ['--shadow' as string]: `rgba(${dominantColor.join(', ')}, 0.5)` } diff --git a/apps/web/src/nft/hooks/useSendTransaction.ts b/apps/web/src/nft/hooks/useSendTransaction.ts index c1ac8e3f883..558a025de70 100644 --- a/apps/web/src/nft/hooks/useSendTransaction.ts +++ b/apps/web/src/nft/hooks/useSendTransaction.ts @@ -88,7 +88,7 @@ export const useSendTransaction = create()( }) set({ state: TxStateType.Invalid }) } - return undefined + return } }, }), diff --git a/apps/web/src/nft/pages/profile/index.tsx b/apps/web/src/nft/pages/profile/index.tsx index b7a0a9c6edc..0a486f5600c 100644 --- a/apps/web/src/nft/pages/profile/index.tsx +++ b/apps/web/src/nft/pages/profile/index.tsx @@ -1,7 +1,6 @@ import { InterfacePageName } from '@uniswap/analytics-events' import { useAccountDrawer } from 'components/AccountDrawer/MiniPortfolio/hooks' import { ButtonPrimary } from 'components/Button/buttons' -import { ConnectWalletButtonText } from 'components/NavBar/accountCTAsExperimentUtils' import { useAccount } from 'hooks/useAccount' import useENSName from 'hooks/useENSName' import styled from 'lib/styled-components' @@ -118,7 +117,7 @@ export default function Profile() { - + diff --git a/apps/web/src/nft/utils/urlParams.ts b/apps/web/src/nft/utils/urlParams.ts index e6d6fa8baf5..a37ee3ad292 100644 --- a/apps/web/src/nft/utils/urlParams.ts +++ b/apps/web/src/nft/utils/urlParams.ts @@ -162,7 +162,7 @@ export const syncLocalFiltersWithURL = (state: CollectionFilters) => { export const applyFiltersFromURL = (location: Location, collectionStats: GenieCollection) => { if (!location.search) { - return undefined + return } const query = qs.parse(location.search, { diff --git a/apps/web/src/pages/AddLiquidity/AddLiquidityModal.tsx b/apps/web/src/pages/AddLiquidity/AddLiquidityModal.tsx index edfe0149a25..277b51862e2 100644 --- a/apps/web/src/pages/AddLiquidity/AddLiquidityModal.tsx +++ b/apps/web/src/pages/AddLiquidity/AddLiquidityModal.tsx @@ -2,9 +2,8 @@ import { LiquidityModalDetailRows } from 'components/Liquidity/LiquidityModalDet import { LiquidityModalHeader } from 'components/Liquidity/LiquidityModalHeader' import { LiquidityPositionInfo } from 'components/Liquidity/LiquidityPositionInfo' import { AddLiquidityContextProvider, useAddLiquidityContext } from 'components/addLiquidity/AddLiquidityContext' -import { InputForm } from 'components/addLiquidity/InputForm' +import { Field, InputForm } from 'components/addLiquidity/InputForm' import { useCloseModal } from 'state/application/hooks' -import { PositionField } from 'types/position' import { Button, Flex } from 'ui/src' import { Modal } from 'uniswap/src/components/modals/Modal' import { ModalName } from 'uniswap/src/features/telemetry/constants' @@ -26,7 +25,7 @@ function AddLiquidityModalInner() { const token0 = currency0Amount.currency const token1 = currency1Amount.currency - const handleUserInput = (field: PositionField, newValue: string) => { + const handleUserInput = (field: Field, newValue: string) => { setAddLiquidityState((prev) => ({ ...prev, exactField: field, @@ -34,7 +33,7 @@ function AddLiquidityModalInner() { })) } - const handleOnSetMax = (field: PositionField, amount: string) => { + const handleOnSetMax = (field: Field, amount: string) => { setAddLiquidityState((prev) => ({ ...prev, exactField: field, diff --git a/apps/web/src/pages/AddLiquidity/index.tsx b/apps/web/src/pages/AddLiquidity/index.tsx index 4d2e00c077c..20373915ec3 100644 --- a/apps/web/src/pages/AddLiquidity/index.tsx +++ b/apps/web/src/pages/AddLiquidity/index.tsx @@ -21,7 +21,6 @@ import CurrencyInputPanel from 'components/CurrencyInputPanel' import FeeSelector from 'components/FeeSelector' import HoverInlineText from 'components/HoverInlineText' import LiquidityChartRangeInput from 'components/LiquidityChartRangeInput' -import { ConnectWalletButtonText } from 'components/NavBar/accountCTAsExperimentUtils' import { AddRemoveTabs } from 'components/NavigationTabs' import { PositionPreview } from 'components/PositionPreview' import RangeSelector from 'components/RangeSelector' @@ -85,6 +84,8 @@ import { ThemedText } from 'theme/components' import { Text } from 'ui/src' import { UNIVERSE_CHAIN_INFO } from 'uniswap/src/constants/chains' import { WRAPPED_NATIVE_CURRENCY } from 'uniswap/src/constants/tokens' +import { AccountCTAsExperimentGroup, Experiments } from 'uniswap/src/features/gating/experiments' +import { useExperimentGroupName } from 'uniswap/src/features/gating/hooks' import Trace from 'uniswap/src/features/telemetry/Trace' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { Trans, t } from 'uniswap/src/i18n' @@ -542,6 +543,10 @@ function AddLiquidity() { }, [searchParams]) // END: sync values with query string + const accountsCTAExperimentGroup = useExperimentGroupName(Experiments.AccountCTAs) + const isSignIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.SignInSignUp + const isLogIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.LogInCreateAccount + const Buttons = () => addIsUnsupported ? ( @@ -557,7 +562,13 @@ function AddLiquidity() { element={InterfaceElementName.CONNECT_WALLET_BUTTON} > - + {isSignIn ? ( + + ) : isLogIn ? ( + + ) : ( + + )} ) : ( diff --git a/apps/web/src/pages/AddLiquidityV2/index.tsx b/apps/web/src/pages/AddLiquidityV2/index.tsx index dfcb2d1c01e..234eb7dcc1a 100644 --- a/apps/web/src/pages/AddLiquidityV2/index.tsx +++ b/apps/web/src/pages/AddLiquidityV2/index.tsx @@ -13,7 +13,6 @@ import { ButtonError, ButtonLight, ButtonPrimary } from 'components/Button/butto import { BlueCard, LightCard } from 'components/Card/cards' import CurrencyInputPanel from 'components/CurrencyInputPanel' import { DoubleCurrencyLogo } from 'components/Logo/DoubleLogo' -import { ConnectWalletButtonText } from 'components/NavBar/accountCTAsExperimentUtils' import { AddRemoveTabs } from 'components/NavigationTabs' import { MinimalPositionCard } from 'components/PositionCard' import { SwitchLocaleLink } from 'components/SwitchLocaleLink' @@ -48,6 +47,8 @@ import { useUserSlippageToleranceWithDefault } from 'state/user/hooks' import { ThemedText } from 'theme/components' import { Text } from 'ui/src' import { WRAPPED_NATIVE_CURRENCY } from 'uniswap/src/constants/tokens' +import { AccountCTAsExperimentGroup, Experiments } from 'uniswap/src/features/gating/experiments' +import { useExperimentGroupName } from 'uniswap/src/features/gating/hooks' import Trace from 'uniswap/src/features/telemetry/Trace' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { Trans } from 'uniswap/src/i18n' @@ -353,6 +354,10 @@ export default function AddLiquidity() { const addIsUnsupported = useIsSwapUnsupported(currencies?.CURRENCY_A, currencies?.CURRENCY_B) + const accountsCTAExperimentGroup = useExperimentGroupName(Experiments.AccountCTAs) + const isSignIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.SignInSignUp + const isLogIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.LogInCreateAccount + if (!networkSupportsV2) { return } @@ -469,7 +474,13 @@ export default function AddLiquidity() { element={InterfaceElementName.CONNECT_WALLET_BUTTON} > - + {isSignIn ? ( + + ) : isLogIn ? ( + + ) : ( + + )} ) : ( diff --git a/apps/web/src/pages/App/Header.tsx b/apps/web/src/pages/App/Header.tsx index 289d5c1a56f..ad58e6e7f8a 100644 --- a/apps/web/src/pages/App/Header.tsx +++ b/apps/web/src/pages/App/Header.tsx @@ -7,9 +7,9 @@ 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' -import { INTERFACE_NAV_HEIGHT } from 'uniswap/src/theme/heights' const AppHeader = styled.div` grid-area: ${GRID_AREAS.HEADER}; @@ -18,11 +18,6 @@ const AppHeader = styled.div` position: sticky; top: 0px; z-index: ${Z_INDEX.sticky}; - pointer-events: none; - - & > * { - pointer-events: auto; - } ` const Banners = styled.div` position: relative; @@ -33,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 }) => $hide && `transform: translateY(-${INTERFACE_NAV_HEIGHT}px);`} + ${({ $hide }) => $hide && `transform: translateY(-${NAV_HEIGHT}px);`} ` export const Header = memo(function Header() { diff --git a/apps/web/src/pages/Landing/LandingV2.tsx b/apps/web/src/pages/Landing/LandingV2.tsx index 69289f291e4..f3b0a7d7ddd 100644 --- a/apps/web/src/pages/Landing/LandingV2.tsx +++ b/apps/web/src/pages/Landing/LandingV2.tsx @@ -1,7 +1,7 @@ import { Hero } from 'pages/Landing/sections/Hero' import { Suspense, lazy, memo, useRef } from 'react' +import { NAV_HEIGHT } from 'theme' import { Flex, styled } from 'ui/src' -import { INTERFACE_NAV_HEIGHT } from 'uniswap/src/theme/heights' // The Fold is always loaded, but is lazy-loaded because it is not seen without user interaction. // Annotating it with webpackPreload allows it to be ready when requested. @@ -29,13 +29,7 @@ function LandingV2({ transition }: { transition?: boolean }) { } return ( - + diff --git a/apps/web/src/pages/Landing/sections/Hero.tsx b/apps/web/src/pages/Landing/sections/Hero.tsx index de2a698233d..5715750cef0 100644 --- a/apps/web/src/pages/Landing/sections/Hero.tsx +++ b/apps/web/src/pages/Landing/sections/Hero.tsx @@ -4,14 +4,11 @@ import { useScroll } from 'hooks/useScroll' import { TokenCloud } from 'pages/Landing/components/TokenCloud' import { Hover, RiseIn, RiseInText } from 'pages/Landing/components/animations' import { Swap } from 'pages/Swap' -import { Fragment, useCallback } from 'react' +import { Fragment } from 'react' import { ChevronDown } from 'react-feather' -import { useNavigate } from 'react-router-dom' -import { serializeSwapStateToURLParameters } from 'state/swap/hooks' +import { NAV_HEIGHT } from 'theme' import { Flex, Text } from 'ui/src' -import { SwapRedirectFn } from 'uniswap/src/features/transactions/TransactionModal/TransactionModalContext' import { Trans, useTranslation } from 'uniswap/src/i18n' -import { INTERFACE_NAV_HEIGHT } from 'uniswap/src/theme/heights' import { UniverseChainId } from 'uniswap/src/types/chains' interface HeroProps { @@ -22,27 +19,11 @@ interface HeroProps { export function Hero({ scrollToRef, transition }: HeroProps) { const { height: scrollPosition } = useScroll() const initialInputCurrency = useCurrency('ETH') - const navigate = useNavigate() const { t } = useTranslation() const translateY = -scrollPosition / 7 const opacityY = 1 - scrollPosition / 1000 - const swapRedirectCallback = useCallback( - ({ inputCurrency, outputCurrency, typedValue, independentField, chainId }: Parameters[0]) => { - navigate( - `/swap${serializeSwapStateToURLParameters({ - inputCurrency, - outputCurrency, - typedValue, - independentField, - chainId, - })}`, - ) - }, - [navigate], - ) - return ( @@ -108,13 +89,11 @@ export function Hero({ scrollToRef, transition }: HeroProps) { maxWidth="100%" > diff --git a/apps/web/src/pages/LegacyPool/NewPosition.tsx b/apps/web/src/pages/LegacyPool/NewPosition.tsx new file mode 100644 index 00000000000..d9cd754809c --- /dev/null +++ b/apps/web/src/pages/LegacyPool/NewPosition.tsx @@ -0,0 +1,21 @@ +import { Navigate } from 'react-router-dom' +import { FeatureFlags } from 'uniswap/src/features/gating/flags' +import { useFeatureFlagWithLoading } from 'uniswap/src/features/gating/hooks' + +export const NewPosition = () => { + const { value: v4Enabled, isLoading } = useFeatureFlagWithLoading(FeatureFlags.V4Everywhere) + + if (!isLoading && !v4Enabled) { + return + } + + if (isLoading) { + return null + } + + return ( +
+

New Position

+
+ ) +} diff --git a/apps/web/src/pages/LegacyPool/PositionPage.tsx b/apps/web/src/pages/LegacyPool/PositionPage.tsx index a903037588c..c4437e7a0b2 100644 --- a/apps/web/src/pages/LegacyPool/PositionPage.tsx +++ b/apps/web/src/pages/LegacyPool/PositionPage.tsx @@ -7,7 +7,6 @@ import Badge from 'components/Badge/Badge' import RangeBadge from 'components/Badge/RangeBadge' import { ButtonConfirmed, ButtonGray, ButtonPrimary, SmallButtonPrimary } from 'components/Button/buttons' import { DarkCard, LightCard } from 'components/Card/cards' -import { PositionNFT } from 'components/Liquidity/PositionNFT' import { LoadingFullscreen } from 'components/Loader/styled' import CurrencyLogo from 'components/Logo/CurrencyLogo' import { DoubleCurrencyLogo } from 'components/Logo/DoubleLogo' @@ -39,7 +38,7 @@ import { useSingleCallResult } from 'lib/hooks/multicall' import useNativeCurrency from 'lib/hooks/useNativeCurrency' import styled, { useTheme } from 'lib/styled-components' import { LoadingRows } from 'pages/LegacyPool/styled' -import { PropsWithChildren, useCallback, useMemo, useState } from 'react' +import { PropsWithChildren, useCallback, useMemo, useRef, useState } from 'react' import { Helmet } from 'react-helmet-async/lib/index' import { Link, useParams } from 'react-router-dom' import { Bound } from 'state/mint/v3/actions' @@ -158,6 +157,23 @@ const ResponsiveButtonConfirmed = styled(ButtonConfirmed)` } ` +const NFTGrid = styled.div` + display: grid; + grid-template: 'overlap'; + min-height: 400px; +` + +const NFTCanvas = styled.canvas` + grid-area: overlap; +` + +const NFTImage = styled.img` + grid-area: overlap; + height: 400px; + /* Ensures SVG appears on top of canvas. */ + z-index: 1; +` + const StyledPoolLink = styled(Link)` text-decoration: none; ${ClickableStyle} @@ -260,6 +276,65 @@ function getRatio( } } +// snapshots a src img into a canvas +function getSnapshot(src: HTMLImageElement, canvas: HTMLCanvasElement, targetHeight: number) { + const context = canvas.getContext('2d') + + if (context) { + let { width, height } = src + + // src may be hidden and not have the target dimensions + const ratio = width / height + height = targetHeight + width = Math.round(ratio * targetHeight) + + // Ensure crispness at high DPIs + canvas.width = width * devicePixelRatio + canvas.height = height * devicePixelRatio + canvas.style.width = width + 'px' + canvas.style.height = height + 'px' + context.scale(devicePixelRatio, devicePixelRatio) + + context.clearRect(0, 0, width, height) + context.drawImage(src, 0, 0, width, height) + } +} + +function NFT({ image, height: targetHeight }: { image: string; height: number }) { + const [animate, setAnimate] = useState(false) + + const canvasRef = useRef(null) + const imageRef = useRef(null) + + return ( + { + setAnimate(true) + }} + onMouseLeave={() => { + // snapshot the current frame so the transition to the canvas is smooth + if (imageRef.current && canvasRef.current) { + getSnapshot(imageRef.current, canvasRef.current, targetHeight) + } + setAnimate(false) + }} + > + + + ) +} + const useInverter = ({ priceLower, priceUpper, @@ -321,12 +396,12 @@ const PositionLabelRow = styled(RowFixed)({ function parseTokenId(tokenId: string | undefined): BigNumber | undefined { if (!tokenId) { - return undefined + return } try { return BigNumber.from(tokenId) } catch (error) { - return undefined + return } } @@ -722,7 +797,7 @@ function PositionPageContent() { minWidth: '340px', }} > - + {typeof account.chainId === 'number' && owner && !ownsNFT ? ( diff --git a/apps/web/src/pages/MigrateV3/index.tsx b/apps/web/src/pages/MigrateV3/index.tsx index e5f2a5a10e5..87e7718a3e2 100644 --- a/apps/web/src/pages/MigrateV3/index.tsx +++ b/apps/web/src/pages/MigrateV3/index.tsx @@ -1,17 +1,11 @@ import { BreadcrumbNavContainer, BreadcrumbNavLink } from 'components/BreadcrumbNav' import { LiquidityPositionCard } from 'components/Liquidity/LiquidityPositionCard' -import { PositionInfo, usePositionInfo } from 'components/Liquidity/utils' +import { usePositionInfo } from 'components/Liquidity/utils' import { PoolProgressIndicator } from 'components/PoolProgressIndicator/PoolProgressIndicator' -import { PriceRangeContextProvider, useCreatePositionContext } from 'pages/Pool/Positions/create/CreatePositionContext' -import { CreatePositionContextProvider } from 'pages/Pool/Positions/create/CreatePositionContextProvider' -import { EditSelectTokensStep } from 'pages/Pool/Positions/create/EditStep' -import { SelectPriceRangeStep } from 'pages/Pool/Positions/create/RangeSelectionStep' -import { SelectTokensStep } from 'pages/Pool/Positions/create/SelectTokenStep' -import { PositionFlowStep } from 'pages/Pool/Positions/create/types' +import { useState } from 'react' import { ChevronRight } from 'react-feather' import { Navigate, useParams } from 'react-router-dom' import { ClickableTamaguiStyle } from 'theme/components' -import { PositionField } from 'types/position' import { Flex, Main, Text, styled } from 'ui/src' import { ArrowDown } from 'ui/src/components/icons/ArrowDown' import { RotateLeft } from 'ui/src/components/icons/RotateLeft' @@ -32,13 +26,30 @@ const BodyWrapper = styled(Main, { p: 24, }) -function MigrateV3Inner({ positionInfo }: { positionInfo: PositionInfo }) { +enum MigrateStep { + SELECT_FEE_TIER, + SET_PRICE_RANGE, +} + +/** + * The page for migrating any v3 LP position to v4. + */ +export default function MigrateV3() { const { positionId } = useParams<{ positionId: string }>() const { t } = useTranslation() - - const { step, setStep } = useCreatePositionContext() + const [step, setStep] = useState(MigrateStep.SELECT_FEE_TIER) const { value: v4Enabled, isLoading: isV4GateLoading } = useFeatureFlagWithLoading(FeatureFlags.V4Everywhere) + // TODO(WEB-4920): replace this with real data fetching + const { data } = useGetPositionsQuery() + const position = data?.positions[2] + const positionInfo = usePositionInfo(position) + + if (!position || !positionInfo) { + // TODO(WEB-4920): handle loading/error states (including if the position is for v2) + return null + } + const { currency0Amount, currency1Amount } = positionInfo if (!isV4GateLoading && !v4Enabled) { @@ -69,8 +80,8 @@ function MigrateV3Inner({ positionInfo }: { positionInfo: PositionInfo }) {
@@ -88,7 +99,7 @@ function MigrateV3Inner({ positionInfo }: { positionInfo: PositionInfo }) { px="$padding12" {...ClickableTamaguiStyle} onPress={() => { - setStep(PositionFlowStep.SELECT_TOKENS_AND_FEE_TIER) + setStep(MigrateStep.SELECT_FEE_TIER) // reset any other state here. }} > @@ -98,65 +109,15 @@ function MigrateV3Inner({ positionInfo }: { positionInfo: PositionInfo }) {
- + - - {step === PositionFlowStep.SELECT_TOKENS_AND_FEE_TIER ? ( - { - setStep(PositionFlowStep.PRICE_RANGE) - }} - /> - ) : ( - - )} - {step === PositionFlowStep.PRICE_RANGE && ( - { - // TODO (WEB-4920): submit the migration transaction. - }} - /> - )}
+ {/* TODO: fee tier selection component. collapse if step === SET_PRICE_RANGE */} + {/* TODO: price range component. hide if step === SELECT_FEE_TIER */} ) } - -/** - * The page for migrating any v3 LP position to v4. - */ -export default function MigrateV3() { - // TODO(WEB-4920): replace this with real data fetching - const { data } = useGetPositionsQuery() - const position = data?.positions[1] - const positionInfo = usePositionInfo(position) - - if (!position || !positionInfo) { - // TODO(WEB-4920): handle loading/error states (including if the position is for v2) - return null - } - const { currency0Amount, currency1Amount } = positionInfo - return ( - - - - - - ) -} diff --git a/apps/web/src/pages/Pool/Positions/PositionPage.tsx b/apps/web/src/pages/Pool/Positions/PositionPage.tsx deleted file mode 100644 index 86e2e2fc34b..00000000000 --- a/apps/web/src/pages/Pool/Positions/PositionPage.tsx +++ /dev/null @@ -1,196 +0,0 @@ -import { Price } from '@uniswap/sdk-core' -import { BreadcrumbNavContainer, BreadcrumbNavLink } from 'components/BreadcrumbNav' -import { LiquidityPositionAmountsTile } from 'components/Liquidity/LiquidityPositionAmountsTile' -import { LiquidityPositionInfo } from 'components/Liquidity/LiquidityPositionInfo' -import { LiquidityPositionPriceRangeTile } from 'components/Liquidity/LiquidityPositionPriceRangeTile' -import { PositionNFT } from 'components/Liquidity/PositionNFT' -import { usePositionInfo } from 'components/Liquidity/utils' -import { LoadingFullscreen } from 'components/Loader/styled' -import { usePositionTokenURI } from 'hooks/usePositionTokenURI' -import { useState } from 'react' -import { ChevronRight } from 'react-feather' -import { Navigate, useParams } from 'react-router-dom' -import { setOpenModal } from 'state/application/reducer' -import { useAppDispatch } from 'state/hooks' -import { ClickableTamaguiStyle } from 'theme/components' -import { Flex, Main, Switch, Text, styled } from 'ui/src' -import { useGetPositionsQuery } from 'uniswap/src/data/rest/getPositions' -import { FeatureFlags } from 'uniswap/src/features/gating/flags' -import { useFeatureFlagWithLoading } from 'uniswap/src/features/gating/hooks' -import { ModalName } from 'uniswap/src/features/telemetry/constants' -import { Trans } from 'uniswap/src/i18n' - -const BodyWrapper = styled(Main, { - backgroundColor: '$surface1', - display: 'flex', - flexDirection: 'column', - gap: '$spacing32', - mx: 'auto', - width: '100%', - zIndex: '$default', - p: '$spacing24', -}) - -// TODO: replace with Spore button once available -export const HeaderButton = styled(Flex, { - row: true, - backgroundColor: '$surface2', - borderRadius: '$rounded12', - alignItems: 'center', - justifyContent: 'center', - gap: '$gap4', - py: '$padding8', - px: '$padding12', - ...ClickableTamaguiStyle, - variants: { - emphasis: { - primary: { - backgroundColor: '$accent3', - }, - secondary: { - backgroundColor: '$surface2', - }, - }, - } as const, -}) - -export default function PositionPage() { - const { positionId } = useParams<{ positionId: string }>() - // const { t } = useTranslation() - // TODO(WEB-4920): replace this with real query fetching the position by ID - const { data } = useGetPositionsQuery() - const position = data?.positions[1] - const positionInfo = usePositionInfo(position) - const metadata = usePositionTokenURI(positionId ? parseInt(positionId) : undefined) - - const dispatch = useAppDispatch() - const [collectAsWeth, setCollectAsWeth] = useState(false) - - const { value: v4Enabled, isLoading } = useFeatureFlagWithLoading(FeatureFlags.V4Everywhere) - - if (!isLoading && !v4Enabled) { - return - } - - if (!position || !positionInfo) { - // TODO(WEB-4920): handle loading/error states - return null - } - - const { currency0Amount, currency1Amount, status } = positionInfo - - return ( - - - - - - - - - - - - - { - dispatch(setOpenModal({ name: ModalName.AddLiquidity, initialState: position })) - }} - > - - - - - { - dispatch(setOpenModal({ name: ModalName.RemoveLiquidity, initialState: position })) - }} - > - - - - - - - - - - {'result' in metadata ? ( - - ) : ( - - )} - - - - - - - - {/* TODO(WEB-4920): get est. USD value of position */} - $5678.90 - - - - - - - - - { - // TODO(WEB-4920): open claim fees modal - }} - > - - - - - - - $1,084.61 - - - - - - - { - setCollectAsWeth((prev) => !prev) - }} - /> - - - - - - - ) -} diff --git a/apps/web/src/pages/Pool/Positions/V2PositionPage.tsx b/apps/web/src/pages/Pool/Positions/V2PositionPage.tsx deleted file mode 100644 index 1b77e08cea7..00000000000 --- a/apps/web/src/pages/Pool/Positions/V2PositionPage.tsx +++ /dev/null @@ -1,175 +0,0 @@ -import { Percent } from '@uniswap/sdk-core' -import { BreadcrumbNavContainer, BreadcrumbNavLink } from 'components/BreadcrumbNav' -import { LiquidityPositionInfo } from 'components/Liquidity/LiquidityPositionInfo' -import { usePositionInfo } from 'components/Liquidity/utils' -import { DoubleCurrencyAndChainLogo } from 'components/Logo/DoubleLogo' -import { useTotalSupply } from 'hooks/useTotalSupply' -import JSBI from 'jsbi' -import { useTokenBalance } from 'lib/hooks/useCurrencyBalance' -import { HeaderButton } from 'pages/Pool/Positions/PositionPage' -import { ChevronRight } from 'react-feather' -import { Navigate, useNavigate } from 'react-router-dom' -import { setOpenModal } from 'state/application/reducer' -import { useAppDispatch } from 'state/hooks' -import { Flex, Main, Text, styled } from 'ui/src' -import { useGetPositionsQuery } from 'uniswap/src/data/rest/getPositions' -import { FeatureFlags } from 'uniswap/src/features/gating/flags' -import { useFeatureFlagWithLoading } from 'uniswap/src/features/gating/hooks' -import { ModalName } from 'uniswap/src/features/telemetry/constants' -import { Trans } from 'uniswap/src/i18n' -import { useFormatter } from 'utils/formatNumbers' -import { useAccount } from 'wagmi' - -const BodyWrapper = styled(Main, { - backgroundColor: '$surface1', - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - mx: 'auto', - width: '100%', - zIndex: '$default', - p: '$spacing24', -}) - -export default function V2PositionPage() { - // const { currencyIdA, currencyIdB } = useParams<{ positionId: string }>() - // TODO(WEB-4920): replace this with real query fetching the position by the params above - const { data } = useGetPositionsQuery() - const position = data?.positions[0] - const positionInfo = usePositionInfo(position) - const dispatch = useAppDispatch() - const navigate = useNavigate() - const account = useAccount() - const { formatPercent } = useFormatter() - - const userDefaultPoolBalance = useTokenBalance(account.address, positionInfo?.liquidityToken) - const totalPoolTokens = useTotalSupply(positionInfo?.liquidityToken) - - const poolTokenPercentage = - !!userDefaultPoolBalance && - !!totalPoolTokens && - JSBI.greaterThanOrEqual(totalPoolTokens.quotient, userDefaultPoolBalance.quotient) - ? new Percent(userDefaultPoolBalance.quotient, totalPoolTokens.quotient) - : undefined - - const { value: v4Enabled, isLoading } = useFeatureFlagWithLoading(FeatureFlags.V4Everywhere) - - if (!isLoading && !v4Enabled) { - return - } - - if (!position || !positionInfo) { - // TODO(WEB-4920): handle loading/error states - return null - } - - const { currency0Amount, currency1Amount } = positionInfo - - return ( - - - - - - - - - - - - - { - navigate('/migrate/v2') - }} - > - - - - - { - dispatch(setOpenModal({ name: ModalName.AddLiquidity, initialState: position })) - }} - > - - - - - { - dispatch(setOpenModal({ name: ModalName.RemoveLiquidity, initialState: position })) - }} - > - - - - - - - - - - - {/* TODO(WEB-4920): get real USD position value */} - $1482.21 - - - - - - - {userDefaultPoolBalance ? userDefaultPoolBalance.toSignificant(4) : '-'} - - - - - - - - - {currency0Amount.toSignificant(4)} - - - - - - - - - {currency1Amount.toSignificant(4)} - - - - - - - - {formatPercent(poolTokenPercentage)} - - - - - ) -} diff --git a/apps/web/src/pages/Pool/Positions/create/AddHook.tsx b/apps/web/src/pages/Pool/Positions/create/AddHook.tsx deleted file mode 100644 index 426aff323d8..00000000000 --- a/apps/web/src/pages/Pool/Positions/create/AddHook.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { AdvancedButton } from 'pages/Pool/Positions/create/shared' -import { useState } from 'react' -import { Button } from 'ui/src' -import { DocumentList } from 'ui/src/components/icons/DocumentList' -import { X } from 'ui/src/components/icons/X' -import { Flex } from 'ui/src/components/layout/Flex' -import { fonts } from 'ui/src/theme' -import { TextInput } from 'uniswap/src/components/input/TextInput' -import { useTranslation } from 'uniswap/src/i18n' - -export function AddHook() { - const { t } = useTranslation() - - const [hookInputEnabled, setHookInputEnabled] = useState(false) - const [hookAddress, setHookAddress] = useState('') - - const handleToggleHookInput = () => { - setHookInputEnabled((prev) => !prev) - setHookAddress('') - } - - if (hookInputEnabled) { - return ( - - setHookAddress(text)} - /> - - - ) - } - - return -} diff --git a/apps/web/src/pages/Pool/Positions/create/CreatePosition.tsx b/apps/web/src/pages/Pool/Positions/create/CreatePosition.tsx deleted file mode 100644 index 5445f2a6c18..00000000000 --- a/apps/web/src/pages/Pool/Positions/create/CreatePosition.tsx +++ /dev/null @@ -1,242 +0,0 @@ -/* eslint-disable-next-line no-restricted-imports */ -import { ProtocolVersion } from '@uniswap/client-pools/dist/pools/v1/types_pb' -import { getProtocolVersionFromString, getProtocolVersionLabel } from 'components/Liquidity/utils' -import { PoolProgressIndicator } from 'components/PoolProgressIndicator/PoolProgressIndicator' -import { - DEFAULT_PRICE_RANGE_STATE, - PriceRangeContextProvider, - useCreatePositionContext, - usePriceRangeContext, -} from 'pages/Pool/Positions/create/CreatePositionContext' -import { CreatePositionContextProvider } from 'pages/Pool/Positions/create/CreatePositionContextProvider' -import { EditRangeSelectionStep, EditSelectTokensStep } from 'pages/Pool/Positions/create/EditStep' -import { SelectPriceRangeStep } from 'pages/Pool/Positions/create/RangeSelectionStep' -import { SelectTokensStep } from 'pages/Pool/Positions/create/SelectTokenStep' -import { DEFAULT_POSITION_STATE, PositionFlowStep } from 'pages/Pool/Positions/create/types' -import { useCallback, useMemo } from 'react' -import { Navigate, useParams } from 'react-router-dom' -import { Button, Flex, Text } from 'ui/src' -import { AngleRightSmall } from 'ui/src/components/icons/AngleRightSmall' -import { RotatableChevron } from 'ui/src/components/icons/RotatableChevron' -import { RotateLeft } from 'ui/src/components/icons/RotateLeft' -import { Settings } from 'ui/src/components/icons/Settings' -import { iconSizes } from 'ui/src/theme/iconSizes' -import { ActionSheetDropdown } from 'uniswap/src/components/dropdowns/ActionSheetDropdown' -import { FeatureFlags } from 'uniswap/src/features/gating/flags' -import { useFeatureFlagWithLoading } from 'uniswap/src/features/gating/hooks' -import { Trans, useTranslation } from 'uniswap/src/i18n' - -function CreatePositionInner() { - const { - positionState: { protocolVersion }, - step, - setStep, - } = useCreatePositionContext() - const v2Selected = protocolVersion === ProtocolVersion.V2 - - const handleContinue = useCallback(() => { - if (v2Selected) { - setStep(PositionFlowStep.DEPOSIT) - } else { - setStep((prevStep) => prevStep + 1) - } - }, [setStep, v2Selected]) - - return ( - - {step === PositionFlowStep.SELECT_TOKENS_AND_FEE_TIER ? ( - - ) : step === PositionFlowStep.PRICE_RANGE ? ( - <> - - - - ) : ( - <> - - {!v2Selected && } - - )} - - ) -} - -const Sidebar = () => { - const { t } = useTranslation() - const { - positionState: { protocolVersion }, - step, - } = useCreatePositionContext() - - const PoolProgressSteps = useMemo(() => { - if (protocolVersion === ProtocolVersion.V2) { - return [ - { label: t(`position.step.select`), active: step === PositionFlowStep.SELECT_TOKENS_AND_FEE_TIER }, - { label: t(`position.step.deposit`), active: step == PositionFlowStep.DEPOSIT }, - ] - } - - return [ - { label: t(`position.step.select`), active: step === PositionFlowStep.SELECT_TOKENS_AND_FEE_TIER }, - { label: t(`position.step.range`), active: step === PositionFlowStep.PRICE_RANGE }, - { label: t(`position.step.deposit`), active: step == PositionFlowStep.DEPOSIT }, - ] - }, [protocolVersion, step, t]) - - return ( - - - - - - - - - - - - - - - ) -} - -const Toolbar = () => { - const { - positionState: { protocolVersion }, - setPositionState, - setStep, - } = useCreatePositionContext() - const { setPriceRangeState } = usePriceRangeContext() - - const handleReset = useCallback(() => { - setPositionState(DEFAULT_POSITION_STATE) - setPriceRangeState(DEFAULT_PRICE_RANGE_STATE) - setStep(PositionFlowStep.SELECT_TOKENS_AND_FEE_TIER) - }, [setPositionState, setPriceRangeState, setStep]) - - const handleVersionChange = useCallback( - (version: ProtocolVersion) => { - setPositionState(() => ({ - ...DEFAULT_POSITION_STATE, - protocolVersion: version, - })) - setPriceRangeState(DEFAULT_PRICE_RANGE_STATE) - setStep(PositionFlowStep.SELECT_TOKENS_AND_FEE_TIER) - }, - [setPositionState, setPriceRangeState, setStep], - ) - - const versionOptions = useMemo( - () => - [ProtocolVersion.V2, ProtocolVersion.V3, ProtocolVersion.V4] - .filter((version) => version != protocolVersion) - .map((version) => ({ - key: `version-${version}`, - onPress: () => handleVersionChange(version), - render: () => ( - - - - - - ), - })), - [handleVersionChange, protocolVersion], - ) - - return ( - - - - - - - - ) -} - -export function CreatePosition() { - const { value: v4Enabled, isLoading } = useFeatureFlagWithLoading(FeatureFlags.V4Everywhere) - const { protocolVersion } = useParams<{ protocolVersion: string }>() - - if (!isLoading && !v4Enabled) { - return - } - - if (isLoading) { - return null - } - return ( - - - - - - - - - - - - ) -} diff --git a/apps/web/src/pages/Pool/Positions/create/CreatePositionContext.tsx b/apps/web/src/pages/Pool/Positions/create/CreatePositionContext.tsx deleted file mode 100644 index 45a3d9a681f..00000000000 --- a/apps/web/src/pages/Pool/Positions/create/CreatePositionContext.tsx +++ /dev/null @@ -1,49 +0,0 @@ -/* eslint-disable-next-line no-restricted-imports */ -import { - CreatePositionContextType, - DEFAULT_POSITION_STATE, - PositionFlowStep, - PriceRangeContextType, - PriceRangeState, -} from 'pages/Pool/Positions/create/types' -import React, { useContext, useState } from 'react' - -export const CreatePositionContext = React.createContext({ - step: PositionFlowStep.SELECT_TOKENS_AND_FEE_TIER, - setStep: () => undefined, - positionState: DEFAULT_POSITION_STATE, - setPositionState: () => undefined, - feeTierSearchModalOpen: false, - setFeeTierSearchModalOpen: () => undefined, - derivedPositionInfo: { - pool: undefined, - }, -}) - -export const useCreatePositionContext = () => { - return useContext(CreatePositionContext) -} - -export const DEFAULT_PRICE_RANGE_STATE: PriceRangeState = { - priceInverted: false, - fullRange: true, - minPrice: '0', - maxPrice: 'INF', -} - -const PriceRangeContext = React.createContext({ - priceRangeState: DEFAULT_PRICE_RANGE_STATE, - setPriceRangeState: () => undefined, -}) - -export const usePriceRangeContext = () => { - return useContext(PriceRangeContext) -} - -export function PriceRangeContextProvider({ children }: { children: React.ReactNode }) { - const [priceRangeState, setPriceRangeState] = useState(DEFAULT_PRICE_RANGE_STATE) - - return ( - {children} - ) -} diff --git a/apps/web/src/pages/Pool/Positions/create/CreatePositionContextProvider.tsx b/apps/web/src/pages/Pool/Positions/create/CreatePositionContextProvider.tsx deleted file mode 100644 index c0248087865..00000000000 --- a/apps/web/src/pages/Pool/Positions/create/CreatePositionContextProvider.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { FeeTierSearchModal } from 'components/Liquidity/FeeTierSearchModal' -import { CreatePositionContext } from 'pages/Pool/Positions/create/CreatePositionContext' -import { useDerivedPositionInfo } from 'pages/Pool/Positions/create/hooks' -import { DEFAULT_POSITION_STATE, PositionFlowStep, PositionState } from 'pages/Pool/Positions/create/types' -import { useState } from 'react' - -export function CreatePositionContextProvider({ - children, - initialState = {}, -}: { - children: React.ReactNode - initialState?: Partial -}) { - const [positionState, setPositionState] = useState({ ...DEFAULT_POSITION_STATE, ...initialState }) - const [step, setStep] = useState(PositionFlowStep.SELECT_TOKENS_AND_FEE_TIER) - const derivedPositionInfo = useDerivedPositionInfo(positionState) - const [feeTierSearchModalOpen, setFeeTierSearchModalOpen] = useState(false) - - return ( - - {children} - - - ) -} diff --git a/apps/web/src/pages/Pool/Positions/create/EditStep.tsx b/apps/web/src/pages/Pool/Positions/create/EditStep.tsx deleted file mode 100644 index 604f1efab00..00000000000 --- a/apps/web/src/pages/Pool/Positions/create/EditStep.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { DoubleCurrencyLogo } from 'components/Logo/DoubleLogo' -import { useCreatePositionContext, usePriceRangeContext } from 'pages/Pool/Positions/create/CreatePositionContext' -import { Container } from 'pages/Pool/Positions/create/shared' -import { PositionFlowStep } from 'pages/Pool/Positions/create/types' -import { useCallback } from 'react' -import { Button, Flex, FlexProps, Text } from 'ui/src' -import { Edit } from 'ui/src/components/icons/Edit' -import { iconSizes } from 'ui/src/theme' -import { Trans } from 'uniswap/src/i18n' - -const EditStep = ({ children, onClick, ...rest }: { children: JSX.Element; onClick: () => void } & FlexProps) => { - return ( - - {children} - - - ) -} - -export const EditSelectTokensStep = (props?: FlexProps) => { - const { - positionState: { - tokenInputs: { TOKEN0: token0, TOKEN1: token1 }, - }, - setStep, - } = useCreatePositionContext() - const currencies = [token0, token1] - - const handleEdit = useCallback(() => { - setStep(PositionFlowStep.SELECT_TOKENS_AND_FEE_TIER) - }, [setStep]) - - return ( - - - - - {token0?.symbol} - / - {token1?.symbol} - - - - ) -} - -export const EditRangeSelectionStep = (props?: FlexProps) => { - const { - positionState: { - tokenInputs: { TOKEN0: token0, TOKEN1: token1 }, - }, - setStep, - } = useCreatePositionContext() - const { - priceRangeState: { priceInverted }, - } = usePriceRangeContext() - - const baseCurrency = priceInverted ? token1 : token0 - const quoteCurrency = priceInverted ? token0 : token1 - - const handleEdit = useCallback(() => { - setStep(PositionFlowStep.PRICE_RANGE) - }, [setStep]) - - return ( - - - - - - - - - - - {`283,923,000 ${baseCurrency?.symbol + '/' + quoteCurrency?.symbol}`} - - - - - - {`481,848,481 ${baseCurrency?.symbol + '/' + quoteCurrency?.symbol}`} - - - - - ) -} diff --git a/apps/web/src/pages/Pool/Positions/create/RangeSelectionStep.tsx b/apps/web/src/pages/Pool/Positions/create/RangeSelectionStep.tsx deleted file mode 100644 index eda93cab403..00000000000 --- a/apps/web/src/pages/Pool/Positions/create/RangeSelectionStep.tsx +++ /dev/null @@ -1,234 +0,0 @@ -import { useCreatePositionContext, usePriceRangeContext } from 'pages/Pool/Positions/create/CreatePositionContext' -import { Container } from 'pages/Pool/Positions/create/shared' -import { useCallback, useMemo } from 'react' -import { Minus, Plus } from 'react-feather' -import { Button, Flex, FlexProps, SegmentedControl, Text, useSporeColors } from 'ui/src' -import { SwapActionButton } from 'ui/src/components/icons/SwapActionButton' -import { fonts } from 'ui/src/theme' -import { AmountInput } from 'uniswap/src/components/CurrencyInputPanel/AmountInput' -import { Trans, useTranslation } from 'uniswap/src/i18n' - -enum RangeSelectionInput { - MIN, - MAX, -} - -enum RangeSelection { - FULL = 'FULL', - CUSTOM = 'CUSTOM', -} - -function RangeControl({ value, active }: { value: string; active: boolean }) { - return ( - - {value} - - ) -} - -function RangeInput({ input }: { input: RangeSelectionInput }) { - const colors = useSporeColors() - const { t } = useTranslation() - - const { - positionState: { - tokenInputs: { TOKEN0: token0, TOKEN1: token1 }, - }, - } = useCreatePositionContext() - const { - priceRangeState: { minPrice, maxPrice, priceInverted }, - setPriceRangeState, - } = usePriceRangeContext() - - const baseCurrency = priceInverted ? token1 : token0 - const quoteCurrency = priceInverted ? token0 : token1 - - const handlePriceRangeInput = useCallback( - (input: RangeSelectionInput, value: string) => { - if (input === RangeSelectionInput.MIN) { - setPriceRangeState((prev) => ({ ...prev, minPrice: value })) - } else { - setPriceRangeState((prev) => ({ ...prev, maxPrice: value })) - } - }, - [setPriceRangeState], - ) - - return ( - - - - {input === RangeSelectionInput.MIN ? t(`pool.minPrice`) : t(`pool.maxPrice`)} - - handlePriceRangeInput(input, text)} - /> - - - - - - - - - - ) -} - -export const SelectPriceRangeStep = ({ onContinue, ...rest }: { onContinue: () => void } & FlexProps) => { - const { t } = useTranslation() - - const { - positionState: { - tokenInputs: { TOKEN0: token0, TOKEN1: token1 }, - }, - } = useCreatePositionContext() - const { - priceRangeState: { priceInverted, fullRange }, - setPriceRangeState, - } = usePriceRangeContext() - - const baseCurrency = priceInverted ? token1 : token0 - const quoteCurrency = priceInverted ? token0 : token1 - - const controlOptions = useMemo(() => { - return [{ value: token0?.symbol ?? '' }, { value: token1?.symbol ?? '' }] - }, [token0?.symbol, token1?.symbol]) - - const handleSelectToken = useCallback( - (option: string) => { - if (option === token0?.symbol) { - setPriceRangeState((prevState) => ({ ...prevState, priceInverted: false })) - } else { - setPriceRangeState((prevState) => ({ ...prevState, priceInverted: true })) - } - }, - [token0?.symbol, setPriceRangeState], - ) - - const handleSelectRange = useCallback( - (option: RangeSelection) => { - if (option === RangeSelection.FULL) { - setPriceRangeState((prevState) => ({ ...prevState, fullRange: true })) - } else { - setPriceRangeState((prevState) => ({ ...prevState, fullRange: false })) - } - }, - [setPriceRangeState], - ) - - const segmentedControlRangeOptions = [ - { display: , value: RangeSelection.FULL }, - { display: , value: RangeSelection.CUSTOM }, - ] - - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ) -} diff --git a/apps/web/src/pages/Pool/Positions/create/SelectTokenStep.tsx b/apps/web/src/pages/Pool/Positions/create/SelectTokenStep.tsx deleted file mode 100644 index fce536207e6..00000000000 --- a/apps/web/src/pages/Pool/Positions/create/SelectTokenStep.tsx +++ /dev/null @@ -1,301 +0,0 @@ -// eslint-disable-next-line no-restricted-imports -import { ProtocolVersion } from '@uniswap/client-pools/dist/pools/v1/types_pb' -import { Currency, Percent } from '@uniswap/sdk-core' -import { FeeAmount } from '@uniswap/v3-sdk' -import { PositionInfoBadge } from 'components/Liquidity/LiquidityPositionInfoBadges' -import { DoubleCurrencyAndChainLogo } from 'components/Logo/DoubleLogo' -import CurrencySearchModal from 'components/SearchModal/CurrencySearchModal' -import { useCurrencyInfo } from 'hooks/Tokens' -import { AddHook } from 'pages/Pool/Positions/create/AddHook' -import { useCreatePositionContext } from 'pages/Pool/Positions/create/CreatePositionContext' -import { AdvancedButton, Container } from 'pages/Pool/Positions/create/shared' -import { useCallback, useReducer, useState } from 'react' -import { TamaguiClickableStyle } from 'theme/components' -import { PositionField } from 'types/position' -import { Button, Flex, FlexProps, Text, styled } from 'ui/src' -import { CheckCircleFilled } from 'ui/src/components/icons/CheckCircleFilled' -import { Dollar } from 'ui/src/components/icons/Dollar' -import { RotatableChevron } from 'ui/src/components/icons/RotatableChevron' -import { iconSizes } from 'ui/src/theme' -import { TokenLogo } from 'uniswap/src/components/CurrencyLogo/TokenLogo' -import { Trans, useTranslation } from 'uniswap/src/i18n' -import { useFormatter } from 'utils/formatNumbers' - -const CurrencySelector = ({ currency, onPress }: { currency?: Currency; onPress: () => void }) => { - const { t } = useTranslation() - // TODO: remove when backend returns token logos in graphql response: WEB-4920 - const currencyInfo = useCurrencyInfo(currency) - - return ( - - ) -} - -interface FeeTier { - value: number - title: string - selectionPercent: number -} - -const FeeTierContainer = styled(Flex, { - flex: 1, - width: '100%', - p: '$spacing12', - gap: '$spacing8', - justifyContent: 'space-between', - borderRadius: '$rounded12', - borderWidth: 1, - borderColor: '$surface3', - ...TamaguiClickableStyle, -}) - -const FeeTier = ({ - feeTier, - selected, - onSelect, -}: { - feeTier: FeeTier - selected: boolean - onSelect: (value: number) => void -}) => { - return ( - onSelect(feeTier.value)} background={selected ? '$surface3' : '$surface1'}> - - {feeTier.value / 10000}% - {selected && } - - {feeTier.title} - - {feeTier.selectionPercent}% select - - - ) -} - -export function SelectTokensStep({ - onContinue, - tokensLocked, - ...rest -}: { tokensLocked?: boolean; onContinue: () => void } & FlexProps) { - const { formatPercent } = useFormatter() - const { t } = useTranslation() - - const { - positionState: { - tokenInputs: { TOKEN0: token0, TOKEN1: token1 }, - fee, - protocolVersion, - }, - setPositionState, - derivedPositionInfo, - setFeeTierSearchModalOpen, - } = useCreatePositionContext() - - const [currencySearchInputState, setCurrencySearchInputState] = useState(undefined) - const [isShowMoreFeeTiersEnabled, toggleShowMoreFeeTiersEnabled] = useReducer((state) => !state, false) - const continueButtonEnabled = !!derivedPositionInfo.pool - - const handleCurrencySelect = useCallback( - (currency: Currency) => { - switch (currencySearchInputState) { - case PositionField.TOKEN0: - case PositionField.TOKEN1: - setPositionState((prevState) => ({ - ...prevState, - tokenInputs: { ...prevState.tokenInputs, [currencySearchInputState]: currency }, - })) - break - default: - break - } - }, - [currencySearchInputState, setPositionState], - ) - - const handleFeeTierSelect = useCallback( - (feeTier: number) => { - setPositionState((prevState) => ({ ...prevState, fee: feeTier })) - }, - [setPositionState], - ) - - const feeTiers = [ - { value: FeeAmount.LOWEST, title: t(`fee.bestForVeryStable`), selectionPercent: 0 }, - { value: FeeAmount.LOW, title: t(`fee.bestForStablePairs`), selectionPercent: 0 }, - { value: FeeAmount.MEDIUM, title: t(`fee.bestForMost`), selectionPercent: 96 }, - { value: FeeAmount.HIGH, title: t(`fee.bestForExotic`), selectionPercent: 4 }, - ] - - return ( - <> - - - - - {tokensLocked ? t('pool.tokenPair') : t('pool.selectPair')} - - {tokensLocked ? t('position.migrate.liquidity') : t('position.provide.liquidity')} - - - {tokensLocked && token0 && token1 ? ( - - - - - {token0.symbol} / {token1.symbol} - - - - ) : ( - - setCurrencySearchInputState(PositionField.TOKEN0)} /> - setCurrencySearchInputState(PositionField.TOKEN1)} /> - - )} - {protocolVersion === ProtocolVersion.V4 && } - - - - - - - - - {protocolVersion === ProtocolVersion.V2 ? t('fee.tier.description.v2') : t('fee.tier.description')} - - - - {protocolVersion !== ProtocolVersion.V2 && ( - - - - - - - - - - - - {fee === FeeAmount.MEDIUM ? ( - - - - ) : feeTiers.find((tier) => tier.value === fee) ? null : ( - - - - )} - - - - {isShowMoreFeeTiersEnabled && ( - - {feeTiers.map((feeTier) => ( - - ))} - - )} - {protocolVersion === ProtocolVersion.V4 && ( - { - setFeeTierSearchModalOpen(true) - }} - /> - )} - - )} - - - - setCurrencySearchInputState(undefined)} - onCurrencySelect={handleCurrencySelect} - /> - - ) -} diff --git a/apps/web/src/pages/Pool/Positions/create/hooks.tsx b/apps/web/src/pages/Pool/Positions/create/hooks.tsx deleted file mode 100644 index c03b3d33ebb..00000000000 --- a/apps/web/src/pages/Pool/Positions/create/hooks.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { useAccount } from 'hooks/useAccount' -import { PositionInfo, PositionState } from 'pages/Pool/Positions/create/types' -import { useMemo } from 'react' -import { useGetPoolsByTokens } from 'uniswap/src/data/rest/getPools' -import { UniverseChainId } from 'uniswap/src/types/chains' - -export function useDerivedPositionInfo(state: PositionState): PositionInfo { - const { chainId } = useAccount() - const tokens = [ - state.tokenInputs.TOKEN0?.isNative ? state.tokenInputs.TOKEN0.wrapped : state.tokenInputs.TOKEN0, - state.tokenInputs.TOKEN1?.isNative ? state.tokenInputs.TOKEN1.wrapped : state.tokenInputs.TOKEN1, - ] - const sortedTokens = tokens.sort((a, b) => (!b ? -1 : a?.sortsBefore(b) ? -1 : 1)) - const { data } = useGetPoolsByTokens({ - fee: state.fee, - chainId: chainId ?? (UniverseChainId.Mainnet as number), - protocolVersions: [state.protocolVersion], - token0: sortedTokens[0]?.address, - token1: sortedTokens[1]?.address, - }) - - return useMemo( - () => ({ - pool: data?.pools?.[0], - }), - [data?.pools], - ) -} diff --git a/apps/web/src/pages/Pool/Positions/create/shared.tsx b/apps/web/src/pages/Pool/Positions/create/shared.tsx deleted file mode 100644 index a2ef7a86030..00000000000 --- a/apps/web/src/pages/Pool/Positions/create/shared.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { Flex, GeneratedIcon, Text, styled } from 'ui/src' -import { InfoCircleFilled } from 'ui/src/components/icons/InfoCircleFilled' -import { iconSizes } from 'ui/src/theme' -import { useTranslation } from 'uniswap/src/i18n' - -export const Container = styled(Flex, { - gap: 32, - p: '$spacing24', - borderRadius: '$rounded20', - borderWidth: '$spacing1', - borderColor: '$surface3', - maxWidth: 580, - overflow: 'hidden', -}) - -export function AdvancedButton({ - title, - tooltip = true, - Icon, - onPress, -}: { - title: string - tooltip?: boolean - Icon: GeneratedIcon - onPress: () => void -}) { - const { t } = useTranslation() - return ( - - - - - {title} - - - - ({t('common.advanced')}) - - {/* TODO(WEB-4920): implement tooltip text here */} - {tooltip && } - - ) -} diff --git a/apps/web/src/pages/Pool/Positions/create/types.ts b/apps/web/src/pages/Pool/Positions/create/types.ts deleted file mode 100644 index f38fc022522..00000000000 --- a/apps/web/src/pages/Pool/Positions/create/types.ts +++ /dev/null @@ -1,51 +0,0 @@ -// eslint-disable-next-line no-restricted-imports -import { Pool, ProtocolVersion } from '@uniswap/client-pools/dist/pools/v1/types_pb' -import { Currency } from '@uniswap/sdk-core' -import { Dispatch, SetStateAction } from 'react' -import { PositionField } from 'types/position' - -export enum PositionFlowStep { - SELECT_TOKENS_AND_FEE_TIER, - PRICE_RANGE, - DEPOSIT, -} - -export interface PositionState { - protocolVersion: ProtocolVersion - tokenInputs: { [field in PositionField]?: Currency } - fee: number - hook?: string -} - -export const DEFAULT_POSITION_STATE: PositionState = { - tokenInputs: {}, - fee: 3000, - hook: undefined, - protocolVersion: ProtocolVersion.UNSPECIFIED, -} - -export interface PositionInfo { - pool?: Pool -} - -export type CreatePositionContextType = { - step: PositionFlowStep - setStep: Dispatch> - positionState: PositionState - setPositionState: Dispatch> - derivedPositionInfo: PositionInfo - feeTierSearchModalOpen: boolean - setFeeTierSearchModalOpen: Dispatch> -} - -export interface PriceRangeState { - priceInverted: boolean - fullRange: boolean - minPrice: string - maxPrice: string -} - -export type PriceRangeContextType = { - priceRangeState: PriceRangeState - setPriceRangeState: Dispatch> -} diff --git a/apps/web/src/pages/Pool/Positions/index.tsx b/apps/web/src/pages/Pool/Positions/index.tsx index c3f2e4a3d21..a0fb4f53251 100644 --- a/apps/web/src/pages/Pool/Positions/index.tsx +++ b/apps/web/src/pages/Pool/Positions/index.tsx @@ -1,15 +1,13 @@ /* eslint-disable-next-line no-restricted-imports */ -import { Position, PositionStatus, ProtocolVersion } from '@uniswap/client-pools/dist/pools/v1/types_pb' +import { PositionStatus, ProtocolVersion } from '@uniswap/client-pools/dist/pools/v1/types_pb' import { LiquidityPositionCard } from 'components/Liquidity/LiquidityPositionCard' import { useAccount } from 'hooks/useAccount' import { PositionsHeader } from 'pages/Pool/Positions/PositionsHeader' -import { useCallback, useState } from 'react' -import { useNavigate } from 'react-router-dom' +import { useState } from 'react' import { ClickableTamaguiStyle } from 'theme/components' import { Flex } from 'ui/src' import { useGetPositionsQuery } from 'uniswap/src/data/rest/getPositions' import { UniverseChainId } from 'uniswap/src/types/chains' -import { logger } from 'utilities/src/logger/logger' export default function Positions() { const [chainFilter, setChainFilter] = useState(null) @@ -24,31 +22,16 @@ export default function Positions() { PositionStatus.CLOSED, ]) - const navigate = useNavigate() const account = useAccount() const { address } = account const { data } = useGetPositionsQuery({ + chainIds: chainFilter ? [chainFilter] : undefined, + protocolVersions: versionFilter, + positionStatuses: statusFilter, address, }) - const onNavigateToPosition = useCallback( - (position: Position) => { - if (position.position.case === 'v2Pair' && position.position.value.token0 && position.position.value.token1) { - navigate(`/positions/v2/${position.position.value.token0.address}/${position.position.value.token1.address}`) - } else if (position.position.case === 'v3Position') { - navigate(`/positions/v3/${position.position.value.tokenId}`) - } else if (position.position.case === 'v4Position') { - navigate(`/positions/v4/${position.position.value.poolPosition?.tokenId}`) - } else { - logger.error('Invalid position', { - tags: { file: 'Positions/index.tsx', function: 'onPress' }, - }) - } - }, - [navigate], - ) - // TODO(WEB-4920): implement pagination w/ max 8 positions per page. return ( @@ -82,7 +65,9 @@ export default function Positions() { key={index} liquidityPosition={position} {...ClickableTamaguiStyle} - onPress={() => onNavigateToPosition(position)} + onPress={() => { + // TODO(WEB-4920): navigate to the PosDP for this position + }} /> ) })} diff --git a/apps/web/src/pages/RemoveLiquidity/index.tsx b/apps/web/src/pages/RemoveLiquidity/index.tsx index f1f91aeec0e..72a51b10496 100644 --- a/apps/web/src/pages/RemoveLiquidity/index.tsx +++ b/apps/web/src/pages/RemoveLiquidity/index.tsx @@ -15,7 +15,6 @@ import { BlueCard, LightCard } from 'components/Card/cards' import CurrencyInputPanel from 'components/CurrencyInputPanel' import CurrencyLogo from 'components/Logo/CurrencyLogo' import { DoubleCurrencyLogo } from 'components/Logo/DoubleLogo' -import { ConnectWalletButtonText } from 'components/NavBar/accountCTAsExperimentUtils' import { AddRemoveTabs } from 'components/NavigationTabs' import { MinimalPositionCard } from 'components/PositionCard' import Slider from 'components/Slider' @@ -49,6 +48,8 @@ import { useUserSlippageToleranceWithDefault } from 'state/user/hooks' import { StyledInternalLink, ThemedText } from 'theme/components' import { Text } from 'ui/src' import { WRAPPED_NATIVE_CURRENCY } from 'uniswap/src/constants/tokens' +import { AccountCTAsExperimentGroup, Experiments } from 'uniswap/src/features/gating/experiments' +import { useExperimentGroupName } from 'uniswap/src/features/gating/hooks' import Trace from 'uniswap/src/features/telemetry/Trace' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { Trans } from 'uniswap/src/i18n' @@ -502,6 +503,10 @@ function RemoveLiquidity() { liquidityPercentChangeCallback, ) + const accountsCTAExperimentGroup = useExperimentGroupName(Experiments.AccountCTAs) + const isSignIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.SignInSignUp + const isLogIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.LogInCreateAccount + if (!networkSupportsV2) { return } @@ -710,7 +715,13 @@ function RemoveLiquidity() { element={InterfaceElementName.CONNECT_WALLET_BUTTON} > - + {isSignIn ? ( + + ) : isLogIn ? ( + + ) : ( + + )} ) : ( diff --git a/apps/web/src/pages/RouteDefinitions.tsx b/apps/web/src/pages/RouteDefinitions.tsx index 43eeb2f5dd2..0b11a79b5da 100644 --- a/apps/web/src/pages/RouteDefinitions.tsx +++ b/apps/web/src/pages/RouteDefinitions.tsx @@ -8,7 +8,7 @@ import { t } from 'uniswap/src/i18n' import { isBrowserRouterEnabled } from 'utils/env' // High-traffic pages (index and /swap) should not be lazy-loaded. import Landing from 'pages/Landing' -import { CreatePosition } from 'pages/Pool/Positions/create/CreatePosition' +import { NewPosition } from 'pages/LegacyPool/NewPosition' import Swap from 'pages/Swap' const NftExplore = lazy(() => import('nft/pages/explore')) @@ -25,8 +25,6 @@ const NotFound = lazy(() => import('pages/NotFound')) const Pool = lazy(() => import('pages/Pool')) const LegacyPool = lazy(() => import('pages/LegacyPool')) const LegacyPositionPage = lazy(() => import('pages/LegacyPool/PositionPage')) -const PositionPage = lazy(() => import('pages/Pool/Positions/PositionPage')) -const V2PositionPage = lazy(() => import('pages/Pool/Positions/V2PositionPage')) const LegacyPoolV2 = lazy(() => import('pages/LegacyPool/v2')) const PoolDetails = lazy(() => import('pages/PoolDetails')) const PoolFinder = lazy(() => import('pages/PoolFinder')) @@ -204,14 +202,8 @@ export const routes: RouteDefinition[] = [ }), // Refreshed pool routes createRouteDefinition({ - path: '/positions/create', - getElement: () => , - getTitle: getPositionPageTitle, - getDescription: getPositionPageDescription, - }), - createRouteDefinition({ - path: '/positions/create/:protocolVersion', - getElement: () => , + path: '/positions/new', + getElement: () => , getTitle: getPositionPageTitle, getDescription: getPositionPageDescription, }), @@ -221,24 +213,6 @@ export const routes: RouteDefinition[] = [ getTitle: getPositionPageTitle, getDescription: getPositionPageDescription, }), - createRouteDefinition({ - path: '/positions/v2/:currencyIdA/:currencyIdB', - getElement: () => , - getTitle: getPositionPageTitle, - getDescription: getPositionPageDescription, - }), - createRouteDefinition({ - path: '/positions/v3/:tokenId', - getElement: () => , - getTitle: getPositionPageTitle, - getDescription: getPositionPageDescription, - }), - createRouteDefinition({ - path: '/positions/v4/:tokenId', - getElement: () => , - getTitle: getPositionPageTitle, - getDescription: getPositionPageDescription, - }), createRouteDefinition({ path: '/migrate/v3/:positionId', // Position token ID (v3) getElement: () => , diff --git a/apps/web/src/pages/Swap/Buy/BuyFormButton.tsx b/apps/web/src/pages/Swap/Buy/BuyFormButton.tsx index 02a3140b983..a28788d2860 100644 --- a/apps/web/src/pages/Swap/Buy/BuyFormButton.tsx +++ b/apps/web/src/pages/Swap/Buy/BuyFormButton.tsx @@ -1,10 +1,11 @@ import { useAccountDrawer } from 'components/AccountDrawer/MiniPortfolio/hooks' import { ButtonLight } from 'components/Button/buttons' -import { ConnectWalletButtonText } from 'components/NavBar/accountCTAsExperimentUtils' import { useBuyFormContext } from 'pages/Swap/Buy/BuyFormContext' import { Button, Flex, SpinningLoader, Text, WidthAnimator } from 'ui/src' import { iconSizes } from 'ui/src/theme' -import { useTranslation } from 'uniswap/src/i18n' +import { AccountCTAsExperimentGroup, Experiments } from 'uniswap/src/features/gating/experiments' +import { useExperimentGroupName } from 'uniswap/src/features/gating/hooks' +import { Trans, useTranslation } from 'uniswap/src/i18n' import { useAccount } from 'wagmi' interface BuyFormButtonProps { @@ -20,10 +21,20 @@ export function BuyFormButton({ forceDisabled }: BuyFormButtonProps) { const { inputAmount } = buyFormState const { notAvailableInThisRegion, quotes, fetchingQuotes, error } = derivedBuyFormInfo + const accountsCTAExperimentGroup = useExperimentGroupName(Experiments.AccountCTAs) + const isSignIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.SignInSignUp + const isLogIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.LogInCreateAccount + if (!account.isConnected) { return ( - + {isSignIn ? ( + + ) : isLogIn ? ( + + ) : ( + + )} ) } diff --git a/apps/web/src/pages/Swap/Buy/CountryListModal.tsx b/apps/web/src/pages/Swap/Buy/CountryListModal.tsx index c43160e22d3..6401f678ef6 100644 --- a/apps/web/src/pages/Swap/Buy/CountryListModal.tsx +++ b/apps/web/src/pages/Swap/Buy/CountryListModal.tsx @@ -5,12 +5,12 @@ import { ContentWrapper } from 'pages/Swap/Buy/shared' import { ChangeEvent, useCallback, useMemo, useRef, useState } from 'react' import AutoSizer from 'react-virtualized-auto-sizer' import { FixedSizeList } from 'react-window' +import { NAV_HEIGHT } from 'theme' import { CloseIcon } from 'theme/components' import { AdaptiveWebModal, Flex, styled } from 'ui/src' import { Text } from 'ui/src/components/text/Text' import { FORCountry } from 'uniswap/src/features/fiatOnRamp/types' import { useTranslation } from 'uniswap/src/i18n' -import { INTERFACE_NAV_HEIGHT } from 'uniswap/src/theme/heights' import { bubbleToTop } from 'utilities/src/primitives/array' const ROW_ITEM_SIZE = 56 @@ -67,7 +67,7 @@ export function CountryListModal({ flex={1} onClose={closeModal} maxHeight={700} - $sm={{ height: `calc(100dvh - ${INTERFACE_NAV_HEIGHT}px)` }} + $sm={{ height: `calc(100dvh - ${NAV_HEIGHT}px)` }} > diff --git a/apps/web/src/pages/Swap/Buy/__snapshots__/PredefinedAmount.test.tsx.snap b/apps/web/src/pages/Swap/Buy/__snapshots__/PredefinedAmount.test.tsx.snap index ae19017a0d8..d5abc5106c7 100644 --- a/apps/web/src/pages/Swap/Buy/__snapshots__/PredefinedAmount.test.tsx.snap +++ b/apps/web/src/pages/Swap/Buy/__snapshots__/PredefinedAmount.test.tsx.snap @@ -69,7 +69,7 @@ exports[`PredefinedAmount renders correctly with amount= 300 , currentAmount= "1 $300 @@ -148,7 +148,7 @@ exports[`PredefinedAmount renders correctly with amount= 1000 , currentAmount= " $1000 diff --git a/apps/web/src/pages/Swap/Limit/LimitExpirySection.tsx b/apps/web/src/pages/Swap/Limit/LimitExpirySection.tsx index d701f65c822..b055200e1ab 100644 --- a/apps/web/src/pages/Swap/Limit/LimitExpirySection.tsx +++ b/apps/web/src/pages/Swap/Limit/LimitExpirySection.tsx @@ -29,8 +29,7 @@ const LimitExpiryButton = styled.button<{ $selected: boolean }>` const EXPIRY_OPTIONS = [LimitsExpiry.Day, LimitsExpiry.Week, LimitsExpiry.Month, LimitsExpiry.Year] -// eslint-disable-next-line consistent-return -function getExpiryLabelText(expiry: LimitsExpiry): string { +function getExpiryLabelText(expiry: LimitsExpiry) { switch (expiry) { case LimitsExpiry.Day: return t('common.oneDay') diff --git a/apps/web/src/pages/Swap/Limit/LimitForm.tsx b/apps/web/src/pages/Swap/Limit/LimitForm.tsx index c3a7fc40cb2..473c9bdb4a8 100644 --- a/apps/web/src/pages/Swap/Limit/LimitForm.tsx +++ b/apps/web/src/pages/Swap/Limit/LimitForm.tsx @@ -12,11 +12,11 @@ import { useCurrentPriceAdjustment, } from 'components/CurrencyInputPanel/LimitPriceInputPanel/useCurrentPriceAdjustment' import SwapCurrencyInputPanel from 'components/CurrencyInputPanel/SwapCurrencyInputPanel' -import { ConnectWalletButtonText } from 'components/NavBar/accountCTAsExperimentUtils' import Column from 'components/deprecated/Column' import Row from 'components/deprecated/Row' +import { Field } from 'components/swap/constants' import { ArrowContainer, ArrowWrapper, SwapSection } from 'components/swap/styled' -import { getChain, useIsSupportedChainId, useIsUniswapXSupportedChain } from 'constants/chains' +import { getChain, isUniswapXSupportedChain, useIsSupportedChainId } from 'constants/chains' import { ZERO_PERCENT } from 'constants/misc' import { useAccount } from 'hooks/useAccount' import usePermit2Allowance, { AllowanceState } from 'hooks/usePermit2Allowance' @@ -37,8 +37,11 @@ import { CurrencyState } from 'state/swap/types' import { useSwapAndLimitContext } from 'state/swap/useSwapContext' import { Anchor, Text, styled as tamaguiStyled } from 'ui/src' import { AlertTriangleFilled } from 'ui/src/components/icons/AlertTriangleFilled' +import { colors, validColor } from 'ui/src/theme' import { nativeOnChain } from 'uniswap/src/constants/tokens' import { uniswapUrls } from 'uniswap/src/constants/urls' +import { AccountCTAsExperimentGroup, Experiments } from 'uniswap/src/features/gating/experiments' +import { useExperimentGroupName } from 'uniswap/src/features/gating/hooks' import { Locale } from 'uniswap/src/features/language/constants' import Trace from 'uniswap/src/features/telemetry/Trace' import { ElementName, InterfacePageNameLocal } from 'uniswap/src/features/telemetry/constants' @@ -97,7 +100,6 @@ function LimitForm({ onCurrencyChange }: LimitFormProps) { setCurrencyState, } = useSwapAndLimitContext() const isSupportedChain = useIsSupportedChainId(chainId) - const isUniswapXSupportedChain = useIsUniswapXSupportedChain(chainId) const { limitState, setLimitState, derivedLimitInfo } = useLimitContext() const { currencyBalances, parsedAmounts, parsedLimitPrice, limitOrderTrade, marketPrice } = derivedLimitInfo @@ -171,8 +173,7 @@ function LimitForm({ onCurrencyChange }: LimitFormProps) { const onSelectCurrency = useCallback( (type: keyof CurrencyState, newCurrency: Currency) => { if ((type === 'inputCurrency' ? outputCurrency : inputCurrency)?.equals(newCurrency)) { - switchTokens() - return + return switchTokens() } const [newInput, newOutput] = type === 'inputCurrency' ? [newCurrency, outputCurrency] : [inputCurrency, newCurrency] @@ -227,56 +228,54 @@ function LimitForm({ onCurrencyChange }: LimitFormProps) { }, []) const maxInputAmount: CurrencyAmount | undefined = useMemo( - () => maxAmountSpend(currencyBalances[CurrencyField.INPUT]), + () => maxAmountSpend(currencyBalances[Field.INPUT]), [currencyBalances], ) - const showMaxButton = Boolean( - maxInputAmount?.greaterThan(0) && !parsedAmounts[CurrencyField.INPUT]?.equalTo(maxInputAmount), - ) + const showMaxButton = Boolean(maxInputAmount?.greaterThan(0) && !parsedAmounts[Field.INPUT]?.equalTo(maxInputAmount)) const handleMaxInput = useCallback(() => { maxInputAmount && onTypeInput('inputAmount')(maxInputAmount.toExact()) }, [maxInputAmount, onTypeInput]) const hasInsufficientFunds = - parsedAmounts.input && currencyBalances.input ? currencyBalances.input.lessThan(parsedAmounts.input) : false + parsedAmounts.INPUT && currencyBalances.INPUT ? currencyBalances.INPUT.lessThan(parsedAmounts.INPUT) : false const allowance = usePermit2Allowance( - parsedAmounts.input?.currency?.isNative ? undefined : (parsedAmounts.input as CurrencyAmount), + parsedAmounts.INPUT?.currency?.isNative ? undefined : (parsedAmounts.INPUT as CurrencyAmount), isSupportedChain ? UNIVERSAL_ROUTER_ADDRESS(chainId) : undefined, TradeFillType.UniswapX, ) - const fiatValueTradeInput = useUSDPrice(parsedAmounts.input) - const fiatValueTradeOutput = useUSDPrice(parsedAmounts.output) + const fiatValueTradeInput = useUSDPrice(parsedAmounts.INPUT) + const fiatValueTradeOutput = useUSDPrice(parsedAmounts.OUTPUT) const formattedAmounts = useMemo(() => { // if there is no Price field, then just default to user-typed amounts if (!limitState.limitPrice) { return { - [CurrencyField.INPUT]: limitState.inputAmount, - [CurrencyField.OUTPUT]: limitState.outputAmount, + [Field.INPUT]: limitState.inputAmount, + [Field.OUTPUT]: limitState.outputAmount, } } const formattedInput = limitState.isInputAmountFixed ? limitState.inputAmount : formatCurrencyAmount({ - amount: derivedLimitInfo.parsedAmounts[CurrencyField.INPUT], + amount: derivedLimitInfo.parsedAmounts[Field.INPUT], type: NumberType.SwapTradeAmount, placeholder: '', }) const formattedOutput = limitState.isInputAmountFixed ? formatCurrencyAmount({ - amount: derivedLimitInfo.parsedAmounts[CurrencyField.OUTPUT], + amount: derivedLimitInfo.parsedAmounts[Field.OUTPUT], type: NumberType.SwapTradeAmount, placeholder: '', }) : limitState.outputAmount return { - [CurrencyField.INPUT]: formattedInput, - [CurrencyField.OUTPUT]: formattedOutput, + [Field.INPUT]: formattedInput, + [Field.OUTPUT]: formattedOutput, } }, [ limitState.limitPrice, @@ -319,7 +318,7 @@ function LimitForm({ onCurrencyChange }: LimitFormProps) { } - value={formattedAmounts[CurrencyField.INPUT]} + value={formattedAmounts[Field.INPUT]} showMaxButton={showMaxButton} currency={inputCurrency ?? null} currencyField={CurrencyField.INPUT} @@ -346,7 +345,7 @@ function LimitForm({ onCurrencyChange }: LimitFormProps) { } - value={formattedAmounts[CurrencyField.OUTPUT]} + value={formattedAmounts[Field.OUTPUT]} showMaxButton={false} currency={outputCurrency ?? null} currencyField={CurrencyField.OUTPUT} @@ -367,7 +366,7 @@ function LimitForm({ onCurrencyChange }: LimitFormProps) { hasInsufficientFunds={hasInsufficientFunds} limitPriceError={priceError} /> - {isUniswapXSupportedChain && !!priceError && inputCurrency && outputCurrency && limitOrderTrade && ( + {isUniswapXSupportedChain(chainId) && !!priceError && inputCurrency && outputCurrency && limitOrderTrade && ( )} - + - {!isUniswapXSupportedChain ? ( + {!isUniswapXSupportedChain(chainId) ? ( { - onSelectCurrency(field === CurrencyField.INPUT ? 'inputCurrency' : 'outputCurrency', currency) + onCurrencySelection={(field: Field, currency) => { + onSelectCurrency(field === Field.INPUT ? 'inputCurrency' : 'outputCurrency', currency) }} onConfirm={handleSubmit} onDismiss={() => { @@ -466,7 +465,11 @@ function SubmitOrderButton({ const account = useAccount() const { chainId } = useSwapAndLimitContext() - if (!useIsUniswapXSupportedChain(chainId)) { + const accountsCTAExperimentGroup = useExperimentGroupName(Experiments.AccountCTAs) + const isSignIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.SignInSignUp + const isLogIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.LogInCreateAccount + + if (!isUniswapXSupportedChain(chainId)) { return ( @@ -477,7 +480,13 @@ function SubmitOrderButton({ if (!account.isConnected) { return ( - + {isSignIn ? ( + + ) : isLogIn ? ( + + ) : ( + + )} ) } @@ -504,7 +513,7 @@ function SubmitOrderButton({ data-testid="submit-order-button" disabled={!trade || !!limitPriceError} > - + diff --git a/apps/web/src/pages/Swap/Send/SendCurrencyInputForm.tsx b/apps/web/src/pages/Swap/Send/SendCurrencyInputForm.tsx index 03659cd04c3..b99403d0a3b 100644 --- a/apps/web/src/pages/Swap/Send/SendCurrencyInputForm.tsx +++ b/apps/web/src/pages/Swap/Send/SendCurrencyInputForm.tsx @@ -10,7 +10,7 @@ import CurrencySearchModal from 'components/SearchModal/CurrencySearchModal' import Column from 'components/deprecated/Column' import Row, { RowBetween } from 'components/deprecated/Row' import { getChain, useSupportedChainId } from 'constants/chains' -import { PrefetchBalancesWrapper } from 'graphql/data/apollo/AdaptiveTokenBalancesProvider' +import { PrefetchBalancesWrapper } from 'graphql/data/apollo/TokenBalancesProvider' import { useActiveLocalCurrency, useActiveLocalCurrencyComponents } from 'hooks/useActiveLocalCurrency' import { useUSDPrice } from 'hooks/useUSDPrice' import styled, { css } from 'lib/styled-components' diff --git a/apps/web/src/pages/Swap/Send/SendForm.tsx b/apps/web/src/pages/Swap/Send/SendForm.tsx index 17a3e7ec3f0..11f1f39ccc5 100644 --- a/apps/web/src/pages/Swap/Send/SendForm.tsx +++ b/apps/web/src/pages/Swap/Send/SendForm.tsx @@ -1,7 +1,6 @@ import { InterfaceElementName, InterfaceEventName } from '@uniswap/analytics-events' import { useAccountDrawer } from 'components/AccountDrawer/MiniPortfolio/hooks' import { ButtonLight, ButtonPrimary } from 'components/Button/buttons' -import { ConnectWalletButtonText } from 'components/NavBar/accountCTAsExperimentUtils' import Column from 'components/deprecated/Column' import { useIsSupportedChainId } from 'constants/chains' import { useAccount } from 'hooks/useAccount' @@ -18,6 +17,8 @@ import { SendContextProvider, useSendContext } from 'state/send/SendContext' import { CurrencyState } from 'state/swap/types' import { useSwapAndLimitContext } from 'state/swap/useSwapContext' import { UNIVERSE_CHAIN_INFO } from 'uniswap/src/constants/chains' +import { AccountCTAsExperimentGroup, Experiments } from 'uniswap/src/features/gating/experiments' +import { useExperimentGroupName } from 'uniswap/src/features/gating/hooks' import Trace from 'uniswap/src/features/telemetry/Trace' import { InterfacePageNameLocal } from 'uniswap/src/features/telemetry/constants' import { Trans } from 'uniswap/src/i18n' @@ -186,6 +187,10 @@ function SendFormInner({ disableTokenInputs = false, onCurrencyChange }: SendFor .catch(() => undefined) }, [handleModalState, sendCallback, setSendState]) + const accountsCTAExperimentGroup = useExperimentGroupName(Experiments.AccountCTAs) + const isSignIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.SignInSignUp + const isLogIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.LogInCreateAccount + return ( <> @@ -198,7 +203,13 @@ function SendFormInner({ disableTokenInputs = false, onCurrencyChange }: SendFor element={InterfaceElementName.CONNECT_WALLET_BUTTON} > - + {isSignIn ? ( + + ) : isLogIn ? ( + + ) : ( + + )} ) : !multichainUXEnabled && initialChainId && initialChainId !== account.chainId ? ( diff --git a/apps/web/src/pages/Swap/Send/__snapshots__/SendCurrencyInputForm.test.tsx.snap b/apps/web/src/pages/Swap/Send/__snapshots__/SendCurrencyInputForm.test.tsx.snap index 019b8f55a53..62f8e2aa521 100644 --- a/apps/web/src/pages/Swap/Send/__snapshots__/SendCurrencyInputForm.test.tsx.snap +++ b/apps/web/src/pages/Swap/Send/__snapshots__/SendCurrencyInputForm.test.tsx.snap @@ -13,7 +13,7 @@ exports[`SendCurrencyInputform renders input in fiat correctly 1`] = ` } .c23 img { - width: 17px; + width: 18px; height: 36px; object-fit: cover; } @@ -584,7 +584,7 @@ exports[`SendCurrencyInputform renders input in token amount correctly 1`] = ` } .c22 img { - width: 17px; + width: 18px; height: 36px; object-fit: cover; } @@ -1139,7 +1139,7 @@ exports[`SendCurrencyInputform should render placeholder values 1`] = ` } .c23 img { - width: 17px; + width: 18px; height: 36px; object-fit: cover; } diff --git a/apps/web/src/pages/Swap/Send/__snapshots__/SendRecipientForm.test.tsx.snap b/apps/web/src/pages/Swap/Send/__snapshots__/SendRecipientForm.test.tsx.snap index 845168c55f2..83fa766cead 100644 --- a/apps/web/src/pages/Swap/Send/__snapshots__/SendRecipientForm.test.tsx.snap +++ b/apps/web/src/pages/Swap/Send/__snapshots__/SendRecipientForm.test.tsx.snap @@ -351,7 +351,7 @@ exports[`SendCurrencyInputform should render correctly with unitag 1`] = `
diff --git a/apps/web/src/pages/Swap/SwapForm.tsx b/apps/web/src/pages/Swap/SwapForm.tsx index 63077f938d9..5d7dc92fca1 100644 --- a/apps/web/src/pages/Swap/SwapForm.tsx +++ b/apps/web/src/pages/Swap/SwapForm.tsx @@ -3,7 +3,6 @@ import { InterfaceEventName, InterfaceSectionName, SwapEventName, - SwapPriceImpactUserResponse, } from '@uniswap/analytics-events' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' import { UNIVERSAL_ROUTER_ADDRESS } from '@uniswap/universal-router-sdk' @@ -13,13 +12,13 @@ import { GrayCard } from 'components/Card/cards' import { ConfirmSwapModal } from 'components/ConfirmSwapModal' import SwapCurrencyInputPanel from 'components/CurrencyInputPanel/SwapCurrencyInputPanel' import ErrorIcon from 'components/Icons/Error' -import { ConnectWalletButtonText } from 'components/NavBar/accountCTAsExperimentUtils' import TokenSafetyModal from 'components/TokenSafety/TokenSafetyModal' import Column, { AutoColumn } from 'components/deprecated/Column' import Row from 'components/deprecated/Row' import PriceImpactModal from 'components/swap/PriceImpactModal' import SwapDetailsDropdown from 'components/swap/SwapDetailsDropdown' import confirmPriceImpactWithoutFee from 'components/swap/confirmPriceImpactWithoutFee' +import { Field } from 'components/swap/constants' import { ArrowContainer, ArrowWrapper, OutputSwapSection, SwapSection } from 'components/swap/styled' import { useIsSupportedChainId, useSupportedChainId } from 'constants/chains' import { useCurrencyInfo } from 'hooks/Tokens' @@ -53,6 +52,8 @@ import { Text } from 'ui/src' import { UNIVERSE_CHAIN_INFO } from 'uniswap/src/constants/chains' import { SafetyLevel } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { CurrencyInfo } from 'uniswap/src/features/dataApi/types' +import { AccountCTAsExperimentGroup, Experiments } from 'uniswap/src/features/gating/experiments' +import { useExperimentGroupName } from 'uniswap/src/features/gating/hooks' import Trace from 'uniswap/src/features/telemetry/Trace' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { WrapType } from 'uniswap/src/features/transactions/types/wrap' @@ -136,10 +137,10 @@ export function SwapForm({ useEffect(() => { // Force exact input if the user switches to an output token with tax - if (outputTokenHasTax && independentField === CurrencyField.OUTPUT) { + if (outputTokenHasTax && independentField === Field.OUTPUT) { setSwapState((state) => ({ ...state, - independentField: CurrencyField.INPUT, + independentField: Field.INPUT, typedValue: '', })) } @@ -149,39 +150,39 @@ export function SwapForm({ wrapType, execute: onWrap, inputError: wrapInputError, - } = useWrapCallback(currencies[CurrencyField.INPUT], currencies[CurrencyField.OUTPUT], typedValue) + } = useWrapCallback(currencies[Field.INPUT], currencies[Field.OUTPUT], typedValue) const showWrap: boolean = wrapType !== WrapType.NotApplicable const parsedAmounts = useMemo( () => showWrap ? { - [CurrencyField.INPUT]: parsedAmount, - [CurrencyField.OUTPUT]: parsedAmount, + [Field.INPUT]: parsedAmount, + [Field.OUTPUT]: parsedAmount, } : { - [CurrencyField.INPUT]: independentField === CurrencyField.INPUT ? parsedAmount : trade?.inputAmount, - [CurrencyField.OUTPUT]: independentField === CurrencyField.OUTPUT ? parsedAmount : trade?.outputAmount, + [Field.INPUT]: independentField === Field.INPUT ? parsedAmount : trade?.inputAmount, + [Field.OUTPUT]: independentField === Field.OUTPUT ? parsedAmount : trade?.outputAmount, }, [independentField, parsedAmount, showWrap, trade], ) - const showFiatValueInput = Boolean(parsedAmounts[CurrencyField.INPUT]) - const showFiatValueOutput = Boolean(parsedAmounts[CurrencyField.OUTPUT]) + const showFiatValueInput = Boolean(parsedAmounts[Field.INPUT]) + const showFiatValueOutput = Boolean(parsedAmounts[Field.OUTPUT]) const getSingleUnitAmount = (currency?: Currency) => { if (!currency) { - return undefined + return } return CurrencyAmount.fromRawAmount(currency, JSBI.BigInt(10 ** currency.decimals)) } const fiatValueInput = useUSDPrice( - parsedAmounts[CurrencyField.INPUT] ?? getSingleUnitAmount(currencies[CurrencyField.INPUT]), - currencies[CurrencyField.INPUT], + parsedAmounts[Field.INPUT] ?? getSingleUnitAmount(currencies[Field.INPUT]), + currencies[Field.INPUT], ) const fiatValueOutput = useUSDPrice( - parsedAmounts[CurrencyField.OUTPUT] ?? getSingleUnitAmount(currencies[CurrencyField.OUTPUT]), - currencies[CurrencyField.OUTPUT], + parsedAmounts[Field.OUTPUT] ?? getSingleUnitAmount(currencies[Field.OUTPUT]), + currencies[Field.OUTPUT], ) const [routeNotFound, routeIsLoading, routeIsSyncing] = useMemo( @@ -208,26 +209,25 @@ export function SwapForm({ ) const { onSwitchTokens, onCurrencySelection, onUserInput } = useSwapActionHandlers() - const dependentField: CurrencyField = - independentField === CurrencyField.INPUT ? CurrencyField.OUTPUT : CurrencyField.INPUT + const dependentField: Field = independentField === Field.INPUT ? Field.OUTPUT : Field.INPUT const handleTypeInput = useCallback( (value: string) => { - onUserInput(CurrencyField.INPUT, value) + onUserInput(Field.INPUT, value) maybeLogFirstSwapAction(trace) }, [onUserInput, trace], ) const handleTypeOutput = useCallback( (value: string) => { - onUserInput(CurrencyField.OUTPUT, value) + onUserInput(Field.OUTPUT, value) maybeLogFirstSwapAction(trace) }, [onUserInput, trace], ) const navigate = useNavigate() - const swapIsUnsupported = useIsSwapUnsupported(currencies[CurrencyField.INPUT], currencies[CurrencyField.OUTPUT]) + const swapIsUnsupported = useIsSwapUnsupported(currencies[Field.INPUT], currencies[Field.OUTPUT]) const isLandingPage = useIsLandingPage() const navigateToSwapWithParams = useCallback(() => { @@ -248,6 +248,12 @@ export function SwapForm({ swapState.typedValue, ]) + // reset if they close warning without tokens in params + const handleDismissTokenWarning = useCallback(() => { + setDismissTokenWarning(true) + navigate('/swap') + }, [navigate]) + // modal and loading const [{ showConfirm, tradeToConfirm, swapError, swapResult }, setSwapFormState] = useState<{ showConfirm: boolean @@ -310,28 +316,24 @@ export function SwapForm({ const selectChain = useSelectChain() const userHasSpecifiedInputOutput = Boolean( - currencies[CurrencyField.INPUT] && - currencies[CurrencyField.OUTPUT] && - parsedAmounts[independentField]?.greaterThan(JSBI.BigInt(0)), + currencies[Field.INPUT] && currencies[Field.OUTPUT] && parsedAmounts[independentField]?.greaterThan(JSBI.BigInt(0)), ) const maximumAmountIn = useMaxAmountIn(trade, allowedSlippage) const allowance = usePermit2Allowance( maximumAmountIn ?? - (parsedAmounts[CurrencyField.INPUT]?.currency.isToken - ? (parsedAmounts[CurrencyField.INPUT] as CurrencyAmount) + (parsedAmounts[Field.INPUT]?.currency.isToken + ? (parsedAmounts[Field.INPUT] as CurrencyAmount) : undefined), supportedChainId ? UNIVERSAL_ROUTER_ADDRESS(supportedChainId) : undefined, trade?.fillType, ) const maxInputAmount: CurrencyAmount | undefined = useMemo( - () => maxAmountSpend(currencyBalances[CurrencyField.INPUT]), + () => maxAmountSpend(currencyBalances[Field.INPUT]), [currencyBalances], ) - const showMaxButton = Boolean( - maxInputAmount?.greaterThan(0) && !parsedAmounts[CurrencyField.INPUT]?.equalTo(maxInputAmount), - ) + const showMaxButton = Boolean(maxInputAmount?.greaterThan(0) && !parsedAmounts[Field.INPUT]?.equalTo(maxInputAmount)) const swapFiatValues = useMemo(() => { return { amountIn: fiatValueTradeInput.data, amountOut: fiatValueTradeOutput.data, feeUsd: outputFeeFiatValue } }, [fiatValueTradeInput.data, fiatValueTradeOutput.data, outputFeeFiatValue]) @@ -403,13 +405,13 @@ export function SwapForm({ swapError: undefined, txHash, })) - onUserInput(CurrencyField.INPUT, '') + onUserInput(Field.INPUT, '') } catch (error) { if (!didUserReject(error)) { sendAnalyticsEvent(SwapEventName.SWAP_ERROR, { wrapType, - input: currencies[CurrencyField.INPUT], - output: currencies[CurrencyField.OUTPUT], + input: currencies[Field.INPUT], + output: currencies[Field.OUTPUT], }) } else { logger.debug('SwapForm', 'handleOnWrap', 'rejected wrap/unwrap') @@ -442,7 +444,7 @@ export function SwapForm({ setSwapState((state) => ({ ...state, routerPreferenceOverride: undefined })) // If there was a swap, we want to clear the input if (swapResult) { - onUserInput(CurrencyField.INPUT, '') + onUserInput(Field.INPUT, '') } }, [onUserInput, setSwapState, swapResult]) @@ -452,7 +454,7 @@ export function SwapForm({ const handleInputSelect = useCallback( (inputCurrency: Currency) => { - onCurrencySelection(CurrencyField.INPUT, inputCurrency) + onCurrencySelection(Field.INPUT, inputCurrency) onCurrencyChange?.({ inputCurrency, outputCurrency: currencyState.outputCurrency, @@ -464,13 +466,13 @@ export function SwapForm({ const inputCurrencyNumericalInputRef = useRef(null) const handleMaxInput = useCallback(() => { - maxInputAmount && onUserInput(CurrencyField.INPUT, maxInputAmount.toExact()) + maxInputAmount && onUserInput(Field.INPUT, maxInputAmount.toExact()) maybeLogFirstSwapAction(trace) }, [maxInputAmount, onUserInput, trace]) const handleOutputSelect = useCallback( (outputCurrency: Currency) => { - onCurrencySelection(CurrencyField.OUTPUT, outputCurrency) + onCurrencySelection(Field.OUTPUT, outputCurrency) onCurrencyChange?.({ inputCurrency: currencyState.inputCurrency, outputCurrency, @@ -498,7 +500,7 @@ export function SwapForm({ !isLandingPage && !showWrap && userHasSpecifiedInputOutput && (trade || routeIsLoading || routeIsSyncing), ) - const inputCurrency = currencies[CurrencyField.INPUT] ?? undefined + const inputCurrency = currencies[Field.INPUT] ?? undefined const switchingChain = useAppSelector((state) => state.wallets.switchingChain) const targetChain = switchingChain ? switchingChain : undefined @@ -506,23 +508,18 @@ export function SwapForm({ // @ts-ignore const isUsingBlockedExtension = window.ethereum?.['isPocketUniverseZ'] + const accountsCTAExperimentGroup = useExperimentGroupName(Experiments.AccountCTAs) + const isSignIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.SignInSignUp + const isLogIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.LogInCreateAccount + return ( <> 0 && !dismissTokenWarning} token0={urlTokensNotInDefault[0]} token1={urlTokensNotInDefault[1]} - onAcknowledge={handleConfirmTokenWarning} - onReject={() => { - setDismissTokenWarning(true) - onCurrencySelection(CurrencyField.INPUT, undefined) - onCurrencySelection(CurrencyField.OUTPUT, undefined) - }} - closeModalOnly={() => { - setDismissTokenWarning(true) - }} - onToken0BlockAcknowledged={() => onCurrencySelection(CurrencyField.INPUT, undefined)} - onToken1BlockAcknowledged={() => onCurrencySelection(CurrencyField.OUTPUT, undefined)} + onContinue={handleConfirmTokenWarning} + onCancel={handleDismissTokenWarning} showCancel={true} /> {trade && showConfirm && ( @@ -555,16 +552,8 @@ export function SwapForm({ {showPriceImpactModal && showPriceImpactWarning && ( { - sendAnalyticsEvent(SwapEventName.SWAP_PRICE_IMPACT_ACKNOWLEDGED, { - response: SwapPriceImpactUserResponse.REJECTED, - }) - setShowPriceImpactModal(false) - }} + onDismiss={() => setShowPriceImpactModal(false)} onContinue={() => { - sendAnalyticsEvent(SwapEventName.SWAP_PRICE_IMPACT_ACKNOWLEDGED, { - response: SwapPriceImpactUserResponse.ACCEPTED, - }) setShowPriceImpactModal(false) handleContinueToReview() }} @@ -576,17 +565,17 @@ export function SwapForm({ } disabled={disableTokenInputs} - value={formattedAmounts[CurrencyField.INPUT]} + value={formattedAmounts[Field.INPUT]} showMaxButton={showMaxButton} - currency={currencies[CurrencyField.INPUT] ?? null} + currency={currencies[Field.INPUT] ?? null} currencyField={CurrencyField.INPUT} onUserInput={handleTypeInput} onMax={handleMaxInput} fiatValue={showFiatValueInput ? fiatValueInput : undefined} onCurrencySelect={handleInputSelect} - otherCurrency={currencies[CurrencyField.OUTPUT]} + otherCurrency={currencies[Field.OUTPUT]} id={InterfaceSectionName.CURRENCY_INPUT_PANEL} - loading={independentField === CurrencyField.OUTPUT && routeIsSyncing} + loading={independentField === Field.OUTPUT && routeIsSyncing} initialCurrencyLoading={initialCurrencyLoading} ref={inputCurrencyNumericalInputRef} /> @@ -622,7 +611,7 @@ export function SwapForm({ } @@ -630,12 +619,12 @@ export function SwapForm({ hideBalance={false} fiatValue={showFiatValueOutput ? fiatValueOutput : undefined} priceImpact={stablecoinPriceImpact} - currency={currencies[CurrencyField.OUTPUT] ?? null} + currency={currencies[Field.OUTPUT] ?? null} currencyField={CurrencyField.OUTPUT} onCurrencySelect={handleOutputSelect} - otherCurrency={currencies[CurrencyField.INPUT]} + otherCurrency={currencies[Field.INPUT]} id={InterfaceSectionName.CURRENCY_OUTPUT_PANEL} - loading={independentField === CurrencyField.INPUT && routeIsSyncing} + loading={independentField === Field.INPUT && routeIsSyncing} numericalInputSettings={{ // We disable numerical input here if the selected token has tax, since we cannot guarantee exact_outputs for FOT tokens disabled: inputTokenHasTax || outputTokenHasTax, @@ -643,7 +632,7 @@ export function SwapForm({ onDisabledClick: () => inputCurrencyNumericalInputRef.current?.focus(), disabledTooltipBody: ( ), }} @@ -687,7 +676,13 @@ export function SwapForm({ element={InterfaceElementName.CONNECT_WALLET_BUTTON} > - + {isSignIn ? ( + + ) : isLogIn ? ( + + ) : ( + + )} ) : !multichainUXEnabled && initialChainId && initialChainId !== connectedChainId ? ( diff --git a/apps/web/src/pages/Swap/index.tsx b/apps/web/src/pages/Swap/index.tsx index e6e015c103b..fc3a402259b 100644 --- a/apps/web/src/pages/Swap/index.tsx +++ b/apps/web/src/pages/Swap/index.tsx @@ -3,8 +3,8 @@ import { Currency } from '@uniswap/sdk-core' import { NetworkAlert } from 'components/NetworkAlert' import { SwitchLocaleLink } from 'components/SwitchLocaleLink' import SwapHeader from 'components/swap/SwapHeader' +import { Field } from 'components/swap/constants' import { PageWrapper, SwapWrapper } from 'components/swap/styled' -import { PrefetchBalancesWrapper } from 'graphql/data/apollo/AdaptiveTokenBalancesProvider' import { useScreenSize } from 'hooks/screenSize/useScreenSize' import { BuyForm } from 'pages/Swap/Buy/BuyForm' import { LimitFormWrapper } from 'pages/Swap/Limit/LimitForm' @@ -14,8 +14,6 @@ import { ReactNode, useState } from 'react' import { useLocation } from 'react-router-dom' import { InterfaceTrade, TradeState } from 'state/routing/types' import { isPreviewTrade } from 'state/routing/utils' -import { useSwapCallback } from 'state/sagas/transactions/swapSaga' -import { useWrapCallback } from 'state/sagas/transactions/wrapSaga' import { SwapAndLimitContextProvider, SwapContextProvider } from 'state/swap/SwapContext' import { useInitialCurrencyState } from 'state/swap/hooks' import { CurrencyState, SwapAndLimitContext } from 'state/swap/types' @@ -25,19 +23,13 @@ import { AppTFunction } from 'ui/src/i18n/types' 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 { SwapRedirectFn } from 'uniswap/src/features/transactions/TransactionModal/TransactionModalContext' import { SwapFlow } from 'uniswap/src/features/transactions/swap/SwapFlow' -import { useSwapPrefilledState } from 'uniswap/src/features/transactions/swap/hooks/useSwapPrefilledState' import { Deadline } from 'uniswap/src/features/transactions/swap/settings/configs/Deadline' -import { currencyToAsset } from 'uniswap/src/features/transactions/swap/utils/asset' import { useTranslation } from 'uniswap/src/i18n' import { InterfaceChainId } from 'uniswap/src/types/chains' -import { CurrencyField } from 'uniswap/src/types/currency' import { SwapTab } from 'uniswap/src/types/screens/interface' import noop from 'utilities/src/react/noop' -const WEB_CUSTOM_SWAP_SETTINGS = [Deadline] - export function getIsReviewableQuote( trade: InterfaceTrade | undefined, tradeState: TradeState, @@ -104,13 +96,11 @@ export function Swap({ initialCurrencyLoading = false, chainId, hideHeader = false, - hideFooter = false, onCurrencyChange, multichainUXEnabled = false, disableTokenInputs = false, compact = false, syncTabToUrl, - swapRedirectCallback, }: { className?: string chainId?: InterfaceChainId @@ -119,19 +109,16 @@ export function Swap({ initialInputCurrency?: Currency initialOutputCurrency?: Currency initialTypedValue?: string - initialIndependentField?: CurrencyField + initialIndependentField?: Field initialCurrencyLoading?: boolean compact?: boolean syncTabToUrl: boolean multichainUXEnabled?: boolean hideHeader?: boolean - hideFooter?: boolean - swapRedirectCallback?: SwapRedirectFn }) { const isDark = useIsDarkMode() const screenSize = useScreenSize() const forAggregatorEnabled = useFeatureFlag(FeatureFlags.ForAggregator) - const universalSwapFlow = useFeatureFlag(FeatureFlags.UniversalSwap) if (universalSwapFlow) { @@ -142,17 +129,7 @@ export function Swap({ initialOutputCurrency={initialOutputCurrency} multichainUXEnabled={multichainUXEnabled} > - - - + ) } @@ -206,72 +183,36 @@ const TAB_TYPE_TO_LABEL = { } function UniversalSwapFlow({ - hideHeader = false, - hideFooter = false, - disableTokenInputs = false, - initialInputCurrency, - initialOutputCurrency, - initialTypedValue, - initialIndependentField, onCurrencyChange, - swapRedirectCallback, + disableTokenInputs = false, }: { - hideHeader?: boolean - hideFooter?: boolean - disableTokenInputs?: boolean - initialInputCurrency?: Currency - initialOutputCurrency?: Currency - initialTypedValue?: string - initialIndependentField?: CurrencyField onCurrencyChange?: (selected: CurrencyState) => void - swapRedirectCallback?: SwapRedirectFn + disableTokenInputs?: boolean }) { const [currentTab, setCurrentTab] = useState(SwapTab.Swap) const { t } = useTranslation() const forAggregatorEnabled = useFeatureFlag(FeatureFlags.ForAggregator) - const swapCallback = useSwapCallback() - const wrapCallback = useWrapCallback() - - const input = currencyToAsset(initialInputCurrency) - const output = currencyToAsset(initialOutputCurrency) - - const prefilledState = useSwapPrefilledState({ - input, - output, - exactAmountToken: initialTypedValue ?? '', - exactCurrencyField: initialIndependentField ?? CurrencyField.INPUT, - }) return ( - + - {!hideHeader && - SWAP_TABS.map((tab) => ( - setCurrentTab(tab)} - > - - {TAB_TYPE_TO_LABEL[tab](t)} - - - ))} + {SWAP_TABS.map((tab) => ( + setCurrentTab(tab)} + > + + {TAB_TYPE_TO_LABEL[tab](t)} + + + ))} {currentTab === SwapTab.Swap && ( - + )} {currentTab === SwapTab.Limit && } {currentTab === SwapTab.Send && ( diff --git a/apps/web/src/pages/TokenDetails/index.tsx b/apps/web/src/pages/TokenDetails/index.tsx index 02dd545479c..b64a65cfd5d 100644 --- a/apps/web/src/pages/TokenDetails/index.tsx +++ b/apps/web/src/pages/TokenDetails/index.tsx @@ -5,7 +5,7 @@ import { TokenDetailsPageSkeleton } from 'components/Tokens/TokenDetails/Skeleto import { useChainFromUrlParam } from 'constants/chains' import { useTokenWarning } from 'constants/deprecatedTokenSafety' import { NATIVE_CHAIN_ID, UNKNOWN_TOKEN_SYMBOL } from 'constants/tokens' -import { useTokenBalancesQuery } from 'graphql/data/apollo/AdaptiveTokenBalancesProvider' +import { useTokenBalancesQuery } from 'graphql/data/apollo/TokenBalancesProvider' import { getSupportedGraphQlChain, gqlToCurrency } from 'graphql/data/util' import { useCurrency } from 'hooks/Tokens' import { useAccount } from 'hooks/useAccount' @@ -123,7 +123,7 @@ function useCreateTDPContext(): PendingTDPContext | LoadedTDPContext { const tokenColor = useSrcColor( extractedColorSrc, - tokenQuery.data?.token?.name ?? tokenQuery.data?.token?.project?.name, + tokenQuery.data?.token?.project?.name ?? tokenQuery.data?.token?.name, theme.surface2, ).tokenColor ?? undefined diff --git a/apps/web/src/pages/__snapshots__/routes.test.ts.snap b/apps/web/src/pages/__snapshots__/routes.test.ts.snap index 18907c51030..553d131803d 100644 --- a/apps/web/src/pages/__snapshots__/routes.test.ts.snap +++ b/apps/web/src/pages/__snapshots__/routes.test.ts.snap @@ -132,15 +132,7 @@ Array [ "getElement": [Function], "getTitle": [Function], "nestedPaths": Array [], - "path": "/positions/create", - }, - Object { - "enabled": [Function], - "getDescription": [Function], - "getElement": [Function], - "getTitle": [Function], - "nestedPaths": Array [], - "path": "/positions/create/:protocolVersion", + "path": "/positions/new", }, Object { "enabled": [Function], @@ -150,30 +142,6 @@ Array [ "nestedPaths": Array [], "path": "/positions", }, - Object { - "enabled": [Function], - "getDescription": [Function], - "getElement": [Function], - "getTitle": [Function], - "nestedPaths": Array [], - "path": "/positions/v2/:currencyIdA/:currencyIdB", - }, - Object { - "enabled": [Function], - "getDescription": [Function], - "getElement": [Function], - "getTitle": [Function], - "nestedPaths": Array [], - "path": "/positions/v3/:tokenId", - }, - Object { - "enabled": [Function], - "getDescription": [Function], - "getElement": [Function], - "getTitle": [Function], - "nestedPaths": Array [], - "path": "/positions/v4/:tokenId", - }, Object { "enabled": [Function], "getDescription": [Function], diff --git a/apps/web/src/pages/paths.ts b/apps/web/src/pages/paths.ts index bb7eaed7fc7..1f825b1efa8 100644 --- a/apps/web/src/pages/paths.ts +++ b/apps/web/src/pages/paths.ts @@ -30,11 +30,7 @@ export const paths = [ '/pools', '/pools/:tokenId', '/positions', - '/positions/create', - '/positions/create/:protocolVersion', - '/positions/v2/:currencyIdA/:currencyIdB', - '/positions/v3/:tokenId', - '/positions/v4/:tokenId', + '/positions/new', '/add/v2', '/add', '/increase', diff --git a/apps/web/src/setupTests.ts b/apps/web/src/setupTests.ts index 06b21653492..09f764b041e 100644 --- a/apps/web/src/setupTests.ts +++ b/apps/web/src/setupTests.ts @@ -15,7 +15,6 @@ import { Readable } from 'stream' import { toBeVisible } from 'test-utils/matchers' import { mocked } from 'test-utils/mocked' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' -import { mockLocalizationContext } from 'uniswap/src/test/mocks/locale' import { TextDecoder, TextEncoder } from 'util' setupi18n() @@ -83,8 +82,6 @@ jest.mock('@popperjs/core', () => { } }) -jest.mock('uniswap/src/features/language/LocalizationContext', () => mockLocalizationContext({})) - jest.mock('@web3-react/core', () => { const web3React = jest.requireActual('@web3-react/core') const { Empty } = jest.requireActual('@web3-react/empty') diff --git a/apps/web/src/state/activity/polling/orders.ts b/apps/web/src/state/activity/polling/orders.ts index 06fde5c5823..48e23cc6a3b 100644 --- a/apps/web/src/state/activity/polling/orders.ts +++ b/apps/web/src/state/activity/polling/orders.ts @@ -41,14 +41,6 @@ async function fetchLimitStatuses(account: string, orders: UniswapXOrderDetails[ ) } -async function fetchPriorityStatuses(account: string, orders: UniswapXOrderDetails[]): Promise { - return fetchStatuses( - orders, - (order) => order.type === SignatureType.SIGN_PRIORITY_ORDER, - (hashes) => `/orders?swapper=${account}&orderHashes=${hashes}&orderType=${OffchainOrderType.PRIORITY_ORDER}`, - ) -} - async function fetchOrderStatuses(account: string, orders: UniswapXOrderDetails[]): Promise { return fetchStatuses( orders, @@ -85,7 +77,6 @@ export function usePollPendingOrders(onActivityUpdate: OnActivityUpdate) { await Promise.all([ fetchOrderStatuses(account.address, pendingOrders), fetchLimitStatuses(account.address, pendingOrders), - fetchPriorityStatuses(account.address, pendingOrders), ]) ).flat() @@ -135,7 +126,7 @@ export function usePollPendingOrders(onActivityUpdate: OnActivityUpdate) { timeout = setTimeout(getOrderStatuses, currentDelay) return () => clearTimeout(timeout) } - return undefined + return }, [account.address, currentDelay, onActivityUpdate, pendingOrders, provider, realtimeEnabled]) return null diff --git a/apps/web/src/state/activity/polling/transactions.ts b/apps/web/src/state/activity/polling/transactions.ts index f0ff95c01e4..684f191ca64 100644 --- a/apps/web/src/state/activity/polling/transactions.ts +++ b/apps/web/src/state/activity/polling/transactions.ts @@ -120,7 +120,7 @@ export function usePollPendingTransactions(onActivityUpdate: OnActivityUpdate) { useEffect(() => { if (!account.chainId || !provider || !lastBlockNumber || !hasPending) { - return undefined + return } const cancels = pendingTransactions diff --git a/apps/web/src/state/application/reducer.test.ts b/apps/web/src/state/application/reducer.test.ts index ea4f30b3afc..89f6cd1541d 100644 --- a/apps/web/src/state/application/reducer.test.ts +++ b/apps/web/src/state/application/reducer.test.ts @@ -3,7 +3,6 @@ import reducer, { addPopup, ApplicationModal, ApplicationState, - PopupType, removePopup, setCloseModal, setOpenModal, @@ -26,27 +25,27 @@ describe('application reducer', () => { describe('popupList', () => { describe('addPopup', () => { it('adds the popup to list with a generated id', () => { - store.dispatch(addPopup({ content: { type: PopupType.Transaction, hash: 'abc' } })) + store.dispatch(addPopup({ content: { txn: { hash: 'abc' } } })) const list = store.getState().popupList expect(list).toEqual([ { key: expect.any(String), show: true, - content: { type: PopupType.Transaction, hash: 'abc' }, + content: { txn: { hash: 'abc' } }, removeAfterMs: 10000, }, ]) }) it('replaces any existing popups with the same key', () => { - store.dispatch(addPopup({ key: 'abc', content: { type: PopupType.Transaction, hash: 'abc' } })) - store.dispatch(addPopup({ key: 'abc', content: { type: PopupType.Transaction, hash: 'abc' } })) + store.dispatch(addPopup({ key: 'abc', content: { txn: { hash: 'abc' } } })) + store.dispatch(addPopup({ key: 'abc', content: { txn: { hash: 'def' } } })) const list = store.getState().popupList expect(list).toEqual([ { key: 'abc', show: true, - content: { type: PopupType.Transaction, hash: 'abc' }, + content: { txn: { hash: 'def' } }, removeAfterMs: 10000, }, ]) @@ -55,7 +54,7 @@ describe('application reducer', () => { describe('removePopup', () => { beforeEach(() => { - store.dispatch(addPopup({ key: 'abc', content: { type: PopupType.Transaction, hash: 'abc' } })) + store.dispatch(addPopup({ key: 'abc', content: { txn: { hash: 'abc' } } })) }) it('hides the popup', () => { @@ -65,7 +64,7 @@ describe('application reducer', () => { { key: 'abc', show: false, - content: { type: PopupType.Transaction, hash: 'abc' }, + content: { txn: { hash: 'abc' } }, removeAfterMs: 10000, }, ]) diff --git a/apps/web/src/state/application/reducer.ts b/apps/web/src/state/application/reducer.ts index c7afb5ca341..ac901e294b4 100644 --- a/apps/web/src/state/application/reducer.ts +++ b/apps/web/src/state/application/reducer.ts @@ -60,7 +60,7 @@ type AddLiquidityModalParams = { type RemoveLiquidityModalParams = { name: typeof ModalName.RemoveLiquidity - initialState: Position + initialState?: Position } export type OpenModalParams = @@ -108,12 +108,7 @@ const applicationSlice = createSlice({ state.openModal = null } }, - addPopup( - state, - { - payload: { content, key, removeAfterMs = DEFAULT_TXN_DISMISS_MS }, - }: { payload: { content: PopupContent; key?: string; removeAfterMs?: number } }, - ) { + addPopup(state, { payload: { content, key, removeAfterMs = DEFAULT_TXN_DISMISS_MS } }) { key = key || nanoid() state.popupList = [ ...state.popupList.filter((popup) => popup.key !== key), diff --git a/apps/web/src/state/burn/hooks.tsx b/apps/web/src/state/burn/hooks.tsx index a72e01cb648..b5f56026488 100644 --- a/apps/web/src/state/burn/hooks.tsx +++ b/apps/web/src/state/burn/hooks.tsx @@ -1,6 +1,5 @@ import { Currency, CurrencyAmount, Percent, Token } from '@uniswap/sdk-core' import { Pair } from '@uniswap/v2-sdk' -import { ConnectWalletButtonText } from 'components/NavBar/accountCTAsExperimentUtils' import { useAccount } from 'hooks/useAccount' import { useTotalSupply } from 'hooks/useTotalSupply' import { useV2Pair } from 'hooks/useV2Pairs' @@ -11,6 +10,8 @@ import { ReactNode, useCallback } from 'react' import { Field, typeInput } from 'state/burn/actions' import { useAppDispatch, useAppSelector } from 'state/hooks' import { InterfaceState } from 'state/webReducer' +import { AccountCTAsExperimentGroup, Experiments } from 'uniswap/src/features/gating/experiments' +import { useExperimentGroupName } from 'uniswap/src/features/gating/hooks' import { Trans } from 'uniswap/src/i18n' export function useBurnState(): InterfaceState['burn'] { @@ -121,9 +122,19 @@ export function useDerivedBurnInfo( : undefined, } + const accountsCTAExperimentGroup = useExperimentGroupName(Experiments.AccountCTAs) + const isSignIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.SignInSignUp + const isLogIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.LogInCreateAccount + let error: ReactNode | undefined if (!account.isConnected) { - error = + error = isSignIn ? ( + + ) : isLogIn ? ( + + ) : ( + + ) } if (!parsedAmounts[Field.LIQUIDITY] || !parsedAmounts[Field.CURRENCY_A] || !parsedAmounts[Field.CURRENCY_B]) { diff --git a/apps/web/src/state/burn/v3/hooks.tsx b/apps/web/src/state/burn/v3/hooks.tsx index 981381d5039..f4d26353046 100644 --- a/apps/web/src/state/burn/v3/hooks.tsx +++ b/apps/web/src/state/burn/v3/hooks.tsx @@ -1,6 +1,5 @@ import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' import { Position } from '@uniswap/v3-sdk' -import { ConnectWalletButtonText } from 'components/NavBar/accountCTAsExperimentUtils' import { useToken } from 'hooks/Tokens' import { useAccount } from 'hooks/useAccount' import { usePool } from 'hooks/usePools' @@ -10,6 +9,8 @@ import { selectPercent } from 'state/burn/v3/actions' import { useAppDispatch, useAppSelector } from 'state/hooks' import { InterfaceState } from 'state/webReducer' import { PositionDetails } from 'types/position' +import { AccountCTAsExperimentGroup, Experiments } from 'uniswap/src/features/gating/experiments' +import { useExperimentGroupName } from 'uniswap/src/features/gating/hooks' import { Trans } from 'uniswap/src/i18n' import { unwrappedToken } from 'utils/unwrappedToken' @@ -74,9 +75,19 @@ export function useDerivedV3BurnInfo( const outOfRange = pool && position ? pool.tickCurrent < position.tickLower || pool.tickCurrent > position.tickUpper : false + const accountsCTAExperimentGroup = useExperimentGroupName(Experiments.AccountCTAs) + const isSignIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.SignInSignUp + const isLogIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.LogInCreateAccount + let error: ReactNode | undefined if (!account.isConnected) { - error = + error = isSignIn ? ( + + ) : isLogIn ? ( + + ) : ( + + ) } if (percent === 0) { error = error ?? diff --git a/apps/web/src/state/claim/hooks.ts b/apps/web/src/state/claim/hooks.ts index 04ac7f48049..38716dd5fb2 100644 --- a/apps/web/src/state/claim/hooks.ts +++ b/apps/web/src/state/claim/hooks.ts @@ -179,7 +179,7 @@ export function useClaimCallback(address: string | null | undefined): { const claimCallback = async function () { if (!claimData || !address || !provider || !account.chainId || !distributorContract) { - return undefined + return } const args = [claimData.index, address, claimData.amount, claimData.proof] diff --git a/apps/web/src/state/fiatOnRampTransactions/types.ts b/apps/web/src/state/fiatOnRampTransactions/types.ts index 5522d57ab06..fa36557bf9b 100644 --- a/apps/web/src/state/fiatOnRampTransactions/types.ts +++ b/apps/web/src/state/fiatOnRampTransactions/types.ts @@ -7,7 +7,6 @@ export enum FiatOnRampTransactionStatus { FAILED = 'FAILED', } -// eslint-disable-next-line consistent-return export function backendStatusToFiatOnRampStatus(status: TransactionStatus) { switch (status) { case TransactionStatus.Confirmed: diff --git a/apps/web/src/state/index.ts b/apps/web/src/state/index.ts index 4dfd196a592..b942e103050 100644 --- a/apps/web/src/state/index.ts +++ b/apps/web/src/state/index.ts @@ -8,7 +8,6 @@ import { sentryEnhancer } from 'state/logging' import { INDEXED_DB_REDUX_TABLE_NAME, PERSIST_VERSION, customCreateMigrate, migrations } from 'state/migrations' import { quickRouteApi } from 'state/routing/quickRouteSlice' import { routingApi } from 'state/routing/slice' -import { rootWebSaga } from 'state/sagas/root' import { InterfaceState, interfacePersistedStateList, interfaceReducer } from 'state/webReducer' import { fiatOnRampAggregatorApi } from 'uniswap/src/features/fiatOnRamp/api' import { isDevEnv, isTestEnv } from 'utilities/src/environment/env' @@ -33,10 +32,8 @@ const persistConfig: PersistConfig = { const persistedReducer = persistReducer(persistConfig, interfaceReducer) -const sagaMiddleware = createSagaMiddleware() - export function createDefaultStore() { - const store = configureStore({ + return configureStore({ reducer: persistedReducer, enhancers: (defaultEnhancers) => defaultEnhancers.concat(sentryEnhancer), middleware: (getDefaultMiddleware) => @@ -67,11 +64,8 @@ export function createDefaultStore() { .concat(routingApi.middleware) .concat(quickRouteApi.middleware) .concat(fiatOnRampAggregatorApi.middleware) - .concat(sagaMiddleware), + .concat(createSagaMiddleware()), }) - sagaMiddleware.run(rootWebSaga) - - return store } const store = createDefaultStore() diff --git a/apps/web/src/state/limit/expiryToDeadlineSeconds.ts b/apps/web/src/state/limit/expiryToDeadlineSeconds.ts index d970cb995ce..7ef50d99ab4 100644 --- a/apps/web/src/state/limit/expiryToDeadlineSeconds.ts +++ b/apps/web/src/state/limit/expiryToDeadlineSeconds.ts @@ -3,7 +3,6 @@ import { LimitsExpiry } from 'uniswap/src/types/limits' const DAY_SECS = ms('1d') / 1000 -// eslint-disable-next-line consistent-return export function expiryToDeadlineSeconds(expiry: LimitsExpiry): number { switch (expiry) { case LimitsExpiry.Day: diff --git a/apps/web/src/state/limit/hooks.ts b/apps/web/src/state/limit/hooks.ts index 492f31d31d3..e2b61034968 100644 --- a/apps/web/src/state/limit/hooks.ts +++ b/apps/web/src/state/limit/hooks.ts @@ -1,4 +1,5 @@ import { Currency, CurrencyAmount, Price, TradeType } from '@uniswap/sdk-core' +import { Field } from 'components/swap/constants' import { isStablecoin } from 'constants/chains' import { useAccount } from 'hooks/useAccount' import JSBI from 'jsbi' @@ -15,11 +16,10 @@ import { useSwapAndLimitContext } from 'state/swap/useSwapContext' import { nativeOnChain } from 'uniswap/src/constants/tokens' import { FeatureFlags } from 'uniswap/src/features/gating/flags' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' -import { CurrencyField } from 'uniswap/src/types/currency' export type LimitInfo = { - currencyBalances: { [field in CurrencyField]?: CurrencyAmount } - parsedAmounts: { [field in CurrencyField]?: CurrencyAmount } + currencyBalances: { [field in Field]?: CurrencyAmount } + parsedAmounts: { [field in Field]?: CurrencyAmount } parsedLimitPrice?: Price limitOrderTrade?: LimitOrderTrade marketPrice?: Price @@ -55,8 +55,8 @@ export function useDerivedLimitInfo(state: LimitState, setState: Dispatch ({ - [CurrencyField.INPUT]: relevantTokenBalances[0], - [CurrencyField.OUTPUT]: relevantTokenBalances[1], + [Field.INPUT]: relevantTokenBalances[0], + [Field.OUTPUT]: relevantTokenBalances[1], }), [relevantTokenBalances], ) @@ -100,8 +100,8 @@ export function useDerivedLimitInfo(state: LimitState, setState: Dispatch } + parsedAmounts: { [field in Field]?: CurrencyAmount } outputAmount?: CurrencyAmount swapFee?: SwapFeeInfo }) { @@ -185,10 +185,10 @@ function useLimitOrderTrade({ }, [account.address, inputCurrency, trade]) const limitOrderTrade = useMemo(() => { - if (!inputCurrency || !parsedAmounts?.[CurrencyField.INPUT] || !account.address || !outputAmount || !wrapInfo) { + if (!inputCurrency || !parsedAmounts?.[Field.INPUT] || !account.address || !outputAmount || !wrapInfo) { return undefined } - const amountIn = CurrencyAmount.fromRawAmount(inputCurrency.wrapped, parsedAmounts?.[CurrencyField.INPUT].quotient) + const amountIn = CurrencyAmount.fromRawAmount(inputCurrency.wrapped, parsedAmounts?.[Field.INPUT].quotient) return new LimitOrderTrade({ amountIn, amountOut: outputAmount, diff --git a/apps/web/src/state/migrations/14.ts b/apps/web/src/state/migrations/14.ts index 8e12ba6dd81..c5523feaf17 100644 --- a/apps/web/src/state/migrations/14.ts +++ b/apps/web/src/state/migrations/14.ts @@ -12,7 +12,7 @@ export const hideSpamBalancesAtomName = 'hideSpamBalances' */ export const migration14 = (state: PersistAppStateV14 | undefined) => { if (!state) { - return undefined + return } const newState: any = { ...state } diff --git a/apps/web/src/state/migrations/15.ts b/apps/web/src/state/migrations/15.ts index ebd9b8dab96..c0ae928266d 100644 --- a/apps/web/src/state/migrations/15.ts +++ b/apps/web/src/state/migrations/15.ts @@ -47,7 +47,7 @@ function webResultToUniswapResult(webItem: TokenSearchResultWeb): SearchResult | */ export const migration15 = (state: PersistAppStateV15 | undefined) => { if (!state) { - return undefined + return } const newState: any = { ...state } diff --git a/apps/web/src/state/migrations/16.ts b/apps/web/src/state/migrations/16.ts index f0ca60f7160..c12920a2e6f 100644 --- a/apps/web/src/state/migrations/16.ts +++ b/apps/web/src/state/migrations/16.ts @@ -15,7 +15,7 @@ export type PersistAppStateV16 = { */ export const migration16 = (state: PersistAppStateV16 | undefined) => { if (!state) { - return undefined + return } const newState: any = { ...state } diff --git a/apps/web/src/state/migrations/17.ts b/apps/web/src/state/migrations/17.ts index 8eb4760636c..640804ad58d 100644 --- a/apps/web/src/state/migrations/17.ts +++ b/apps/web/src/state/migrations/17.ts @@ -15,7 +15,7 @@ export type PersistAppStateV17 = { */ export const migration17 = (state: PersistAppStateV17 | undefined) => { if (!state) { - return undefined + return } const newState: any = { ...state } diff --git a/apps/web/src/state/migrations/18.ts b/apps/web/src/state/migrations/18.ts index e9e3cef0c5a..37bb861d2ef 100644 --- a/apps/web/src/state/migrations/18.ts +++ b/apps/web/src/state/migrations/18.ts @@ -13,7 +13,7 @@ export type PersistAppStateV18 = { */ export const migration18 = (state: PersistAppStateV18 | undefined) => { if (!state?.userSettings) { - return undefined + return } const newState: any = { ...state } diff --git a/apps/web/src/state/migrations/19.ts b/apps/web/src/state/migrations/19.ts index 3afe1a064a9..9d5a7f3ce98 100644 --- a/apps/web/src/state/migrations/19.ts +++ b/apps/web/src/state/migrations/19.ts @@ -16,7 +16,7 @@ export type PersistAppStateV19 = { */ export const migration19 = (state: PersistAppStateV19 | undefined) => { if (!state) { - return undefined + return } // Copy state diff --git a/apps/web/src/state/migrations/20.ts b/apps/web/src/state/migrations/20.ts index dcf248c40ea..4f82071b2b7 100644 --- a/apps/web/src/state/migrations/20.ts +++ b/apps/web/src/state/migrations/20.ts @@ -14,7 +14,7 @@ export const activeLocalCurrencyAtomName = 'activeLocalCurrency' */ export const migration20 = (state: PersistAppStateV20 | undefined) => { if (!state) { - return undefined + return } // Translate existing atom value const atomLocalCurrencyAtomValue = localStorage.getItem(activeLocalCurrencyAtomName) as FiatCurrency diff --git a/apps/web/src/state/mint/hooks.tsx b/apps/web/src/state/mint/hooks.tsx index 941b516031a..9bb1d08162d 100644 --- a/apps/web/src/state/mint/hooks.tsx +++ b/apps/web/src/state/mint/hooks.tsx @@ -1,6 +1,5 @@ import { Currency, CurrencyAmount, Percent, Price, Token } from '@uniswap/sdk-core' import { Pair } from '@uniswap/v2-sdk' -import { ConnectWalletButtonText } from 'components/NavBar/accountCTAsExperimentUtils' import { useAccount } from 'hooks/useAccount' import { useTotalSupply } from 'hooks/useTotalSupply' import { PairState, useV2Pair } from 'hooks/useV2Pairs' @@ -11,6 +10,8 @@ import { useCurrencyBalances } from 'state/connection/hooks' import { useAppDispatch, useAppSelector } from 'state/hooks' import { Field, typeInput } from 'state/mint/actions' import { InterfaceState } from 'state/webReducer' +import { AccountCTAsExperimentGroup, Experiments } from 'uniswap/src/features/gating/experiments' +import { useExperimentGroupName } from 'uniswap/src/features/gating/hooks' import { Trans } from 'uniswap/src/i18n' import { logger } from 'utilities/src/logger/logger' @@ -182,9 +183,19 @@ export function useDerivedMintInfo( } }, [liquidityMinted, totalSupply]) + const accountsCTAExperimentGroup = useExperimentGroupName(Experiments.AccountCTAs) + const isSignIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.SignInSignUp + const isLogIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.LogInCreateAccount + let error: ReactNode | undefined if (!account.isConnected) { - error = + error = isSignIn ? ( + + ) : isLogIn ? ( + + ) : ( + + ) } if (pairState === PairState.INVALID) { diff --git a/apps/web/src/state/mint/v3/hooks.tsx b/apps/web/src/state/mint/v3/hooks.tsx index 24e91a054c3..2f1c4da3a0e 100644 --- a/apps/web/src/state/mint/v3/hooks.tsx +++ b/apps/web/src/state/mint/v3/hooks.tsx @@ -10,7 +10,6 @@ import { priceToClosestTick, tickToPrice, } from '@uniswap/v3-sdk' -import { ConnectWalletButtonText } from 'components/NavBar/accountCTAsExperimentUtils' import { BIG_INT_ZERO } from 'constants/misc' import { useAccount } from 'hooks/useAccount' import { PoolState, usePool } from 'hooks/usePools' @@ -32,6 +31,8 @@ import { } from 'state/mint/v3/actions' import { tryParseTick } from 'state/mint/v3/utils' import { InterfaceState } from 'state/webReducer' +import { AccountCTAsExperimentGroup, Experiments } from 'uniswap/src/features/gating/experiments' +import { useExperimentGroupName } from 'uniswap/src/features/gating/hooks' import { Trans } from 'uniswap/src/i18n' import { getTickToPrice } from 'utils/getTickToPrice' @@ -449,9 +450,19 @@ export function useV3DerivedMintInfo( tickUpper, ]) + const accountsCTAExperimentGroup = useExperimentGroupName(Experiments.AccountCTAs) + const isSignIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.SignInSignUp + const isLogIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.LogInCreateAccount + let errorMessage: ReactNode | undefined if (!account.isConnected) { - errorMessage = + errorMessage = isSignIn ? ( + + ) : isLogIn ? ( + + ) : ( + + ) } if (poolState === PoolState.INVALID) { diff --git a/apps/web/src/state/routing/slice.ts b/apps/web/src/state/routing/slice.ts index e88e03e3746..f1e88045a54 100644 --- a/apps/web/src/state/routing/slice.ts +++ b/apps/web/src/state/routing/slice.ts @@ -1,5 +1,6 @@ import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' import { Protocol } from '@uniswap/router-sdk' +import { isUniswapXSupportedChain } from 'constants/chains' import ms from 'ms' import { ClassicAPIConfig, @@ -14,7 +15,6 @@ import { URAQuoteResponse, URAQuoteType, UniswapXConfig, - UniswapXPriorityOrdersConfig, UniswapXv2Config, } from 'state/routing/types' import { isExactInput, transformQuoteToTrade } from 'state/routing/utils' @@ -44,6 +44,7 @@ const DEFAULT_QUERY_PARAMS = { function getRoutingAPIConfig(args: GetQuoteArgs): RoutingConfig { const { account, + tokenInChainId, uniswapXForceSyntheticQuotes, routerPreference, protocolPreferences, @@ -52,8 +53,6 @@ function getRoutingAPIConfig(args: GetQuoteArgs): RoutingConfig { forceOpenOrders, deadlineBufferSecs, isXv2Arbitrum, - isPriorityOrder, - isUniswapXSupportedChain, } = args const uniswapX: UniswapXConfig = { @@ -62,11 +61,6 @@ function getRoutingAPIConfig(args: GetQuoteArgs): RoutingConfig { routingType: URAQuoteType.DUTCH_V1, } - const uniswapXPriorityOrders: UniswapXPriorityOrdersConfig = { - routingType: URAQuoteType.PRIORITY, - swapper: account, - } - const uniswapXv2: UniswapXv2Config = { useSyntheticQuotes: uniswapXForceSyntheticQuotes || isXv2Arbitrum, swapper: account, @@ -92,12 +86,12 @@ function getRoutingAPIConfig(args: GetQuoteArgs): RoutingConfig { // If the user has opted out of UniswapX during the opt-out transition period, we should respect that preference and only request classic quotes. routerPreference === RouterPreference.API || routerPreference === INTERNAL_ROUTER_PREFERENCE_PRICE || - !isUniswapXSupportedChain + (!isUniswapXSupportedChain(tokenInChainId) && !isXv2Arbitrum) ) { return [classic] } - return [isPriorityOrder ? uniswapXPriorityOrders : isXv2 || isXv2Arbitrum ? uniswapXv2 : uniswapX, classic] + return [isXv2 || isXv2Arbitrum ? uniswapXv2 : uniswapX, classic] } export const routingApi = createApi({ diff --git a/apps/web/src/state/routing/types.ts b/apps/web/src/state/routing/types.ts index df471da34b2..ee8c9e14e4b 100644 --- a/apps/web/src/state/routing/types.ts +++ b/apps/web/src/state/routing/types.ts @@ -6,10 +6,7 @@ import { DutchOrderInfo, DutchOrderInfoJSON, DutchOrderTrade as IDutchOrderTrade, - PriorityOrderTrade as IPriorityOrderTrade, V2DutchOrderTrade as IV2DutchOrderTrade, - UnsignedPriorityOrderInfo, - UnsignedPriorityOrderInfoJSON, UnsignedV2DutchOrderInfo, UnsignedV2DutchOrderInfoJSON, } from '@uniswap/uniswapx-sdk' @@ -74,8 +71,6 @@ export interface GetQuoteArgs { forceOpenOrders: boolean deadlineBufferSecs: number arbitrumXV2SlippageTolerance: string - isPriorityOrder: boolean - isUniswapXSupportedChain: boolean } export type GetQuickQuoteArgs = { @@ -192,24 +187,6 @@ export type URADutchOrderV2QuoteData = { portionRecipient?: string } -// from `PriorityQuoteDataJSON` in https://github.com/Uniswap/backend/blob/main/packages/services/unified-routing-api/lib/entities/quote/PriorityQuote.ts -export type URAPriorityOrderQuoteData = { - orderInfo: UnsignedPriorityOrderInfoJSON - startTimeBufferSecs: number // ignore for priority order - deadlineBufferSecs: number // ignore for priority order - amountInMpsPerPriorityFeeWei: number - amountOutMpsPerPriorityFeeWei: number - permitData: PermitTransferFromData - quoteId: string - requestId: string - encodedOrder: string - orderHash: string - slippageTolerance: string - portionBips?: number - portionAmount?: string - portionRecipient?: string -} - type URADutchOrderQuoteResponse = { routing: URAQuoteType.DUTCH_V1 quote: URADutchOrderQuoteData @@ -225,16 +202,7 @@ type URAClassicQuoteResponse = { quote: ClassicQuoteData allQuotes: Array } -type URAPriorityOrderQuoteResponse = { - routing: URAQuoteType.PRIORITY - quote: URAPriorityOrderQuoteData - allQuotes: Array -} -export type URAQuoteResponse = - | URAClassicQuoteResponse - | URADutchOrderQuoteResponse - | URADutchOrderV2QuoteResponse - | URAPriorityOrderQuoteResponse +export type URAQuoteResponse = URAClassicQuoteResponse | URADutchOrderQuoteResponse | URADutchOrderV2QuoteResponse export type QuickRouteResponse = { tokenIn: { @@ -365,7 +333,6 @@ export enum OffchainOrderType { DUTCH_V2_AUCTION = 'Dutch_V2', LIMIT_ORDER = 'Limit', DUTCH_V1_AND_V2 = 'Dutch_V1_V2', // Only used for GET /orders queries. Returns both Dutch V1 and V2 orders. - PRIORITY_ORDER = 'Priority', } export class DutchOrderTrade extends IDutchOrderTrade { @@ -530,81 +497,6 @@ export class V2DutchOrderTrade extends IV2DutchOrderTrade { - public readonly fillType = TradeFillType.UniswapX - public readonly offchainOrderType = OffchainOrderType.PRIORITY_ORDER - - quoteId?: string - requestId?: string - wrapInfo: WrapInfo - approveInfo: ApproveInfo - // The gas estimate of the reference classic trade, if there is one. - classicGasUseEstimateUSD?: number - startTimeBufferSecs: number - deadlineBufferSecs: number - slippageTolerance: Percent - - inputTax = ZERO_PERCENT - outputTax = ZERO_PERCENT - swapFee: SwapFeeInfo | undefined - - constructor({ - currencyIn, - currenciesOut, - orderInfo, - tradeType, - quoteId, - requestId, - wrapInfo, - approveInfo, - classicGasUseEstimateUSD, - startTimeBufferSecs, - deadlineBufferSecs, - slippageTolerance, - swapFee, - }: { - currencyIn: Currency - currenciesOut: Currency[] - orderInfo: UnsignedPriorityOrderInfo - tradeType: TradeType - quoteId?: string - requestId?: string - approveInfo: ApproveInfo - wrapInfo: WrapInfo - classicGasUseEstimateUSD?: number - startTimeBufferSecs: number - deadlineBufferSecs: number - slippageTolerance: Percent - swapFee?: SwapFeeInfo - }) { - super({ currencyIn, currenciesOut, orderInfo, tradeType }) - this.quoteId = quoteId - this.requestId = requestId - this.approveInfo = approveInfo - this.wrapInfo = wrapInfo - this.classicGasUseEstimateUSD = classicGasUseEstimateUSD - this.deadlineBufferSecs = deadlineBufferSecs - this.slippageTolerance = slippageTolerance - this.startTimeBufferSecs = startTimeBufferSecs - this.swapFee = swapFee - } - - public get totalGasUseEstimateUSD(): number { - if (this.wrapInfo.needsWrap && this.approveInfo.needsApprove) { - return this.wrapInfo.wrapGasEstimateUSD + this.approveInfo.approveGasEstimateUSD - } - - if (this.wrapInfo.needsWrap) { - return this.wrapInfo.wrapGasEstimateUSD - } - if (this.approveInfo.needsApprove) { - return this.approveInfo.approveGasEstimateUSD - } - - return 0 - } -} - export class PreviewTrade { public readonly fillType = TradeFillType.None public readonly quoteMethod = QuoteMethod.QUICK_ROUTE @@ -853,7 +745,7 @@ export class LimitOrderTrade { } } -export type SubmittableTrade = ClassicTrade | DutchOrderTrade | V2DutchOrderTrade | LimitOrderTrade | PriorityOrderTrade +export type SubmittableTrade = ClassicTrade | DutchOrderTrade | V2DutchOrderTrade | LimitOrderTrade export type InterfaceTrade = SubmittableTrade | PreviewTrade export enum QuoteState { @@ -914,10 +806,9 @@ export enum URAQuoteType { CLASSIC = 'CLASSIC', DUTCH_V1 = 'DUTCH_LIMIT', // "dutch limit" refers to dutch. Fully separate from "limit orders" DUTCH_V2 = 'DUTCH_V2', - PRIORITY = 'PRIORITY', } -/* Config types should match URA config schemas https://github.com/Uniswap/backend/blob/main/packages/services/unified-routing-api/lib/util/validator.ts */ +/* Config types should match URA config schemas `classicConfig`, `dutchLimitConfig`, and `dutchV2Config` at https://github.com/Uniswap/unified-routing-api/blob/main/lib/util/validator.ts */ export type ClassicAPIConfig = { routingType: URAQuoteType.CLASSIC @@ -962,13 +853,4 @@ export type UniswapXv2Config = { slippageTolerance?: string } -export type UniswapXPriorityOrdersConfig = { - routingType: URAQuoteType.PRIORITY - swapper?: string - mpsPerPriorityFeeWei?: number - baselinePriorityFeeWei?: number - startTimeBufferSecs?: number - deadlineBufferSecs?: number -} - -export type RoutingConfig = (UniswapXConfig | UniswapXv2Config | ClassicAPIConfig | UniswapXPriorityOrdersConfig)[] +export type RoutingConfig = (UniswapXConfig | UniswapXv2Config | ClassicAPIConfig)[] diff --git a/apps/web/src/state/routing/useRoutingAPITrade.test.ts b/apps/web/src/state/routing/useRoutingAPITrade.test.ts index 9bdd8566c05..d313b0913ba 100644 --- a/apps/web/src/state/routing/useRoutingAPITrade.test.ts +++ b/apps/web/src/state/routing/useRoutingAPITrade.test.ts @@ -81,8 +81,6 @@ const MOCK_ARGS: GetQuoteArgs = { deadlineBufferSecs: 0, arbitrumXV2SlippageTolerance: undefined as any, protocolPreferences: undefined, - isPriorityOrder: false, - isUniswapXSupportedChain: true, } describe('#useRoutingAPITrade ExactIn', () => { diff --git a/apps/web/src/state/routing/utils.test.ts b/apps/web/src/state/routing/utils.test.ts index 0c299c074f7..7ce882d9a02 100644 --- a/apps/web/src/state/routing/utils.test.ts +++ b/apps/web/src/state/routing/utils.test.ts @@ -43,8 +43,6 @@ function constructArgs(currencyIn: Currency, currencyOut: Currency, isXv2?: bool forceOpenOrders: false, deadlineBufferSecs: 30, arbitrumXV2SlippageTolerance: '0.5', - isPriorityOrder: false, - isUniswapXSupportedChain: true, } } diff --git a/apps/web/src/state/routing/utils.ts b/apps/web/src/state/routing/utils.ts index 1c6626f015a..a506f9e8e8d 100644 --- a/apps/web/src/state/routing/utils.ts +++ b/apps/web/src/state/routing/utils.ts @@ -5,9 +5,6 @@ import { DutchOrderInfo, DutchOrderInfoJSON, DutchOutputJSON, - PriorityOutputJSON, - UnsignedPriorityOrderInfo, - UnsignedPriorityOrderInfoJSON, UnsignedV2DutchOrderInfo, UnsignedV2DutchOrderInfoJSON, } from '@uniswap/uniswapx-sdk' @@ -26,7 +23,6 @@ import { OffchainOrderType, PoolType, PreviewTrade, - PriorityOrderTrade, QuickRouteResponse, QuoteMethod, QuoteState, @@ -39,7 +35,6 @@ import { TradeResult, URADutchOrderQuoteData, URADutchOrderV2QuoteData, - URAPriorityOrderQuoteData, URAQuoteResponse, URAQuoteType, V2DutchOrderTrade, @@ -95,7 +90,7 @@ export function computeRoutes(args: GetQuoteArgs, routes: ClassicQuoteData['rout }) } catch (e) { logger.warn('routing/utils', 'computeRoutes', 'Failed to compute routes', { error: e }) - return undefined + return } } @@ -147,28 +142,6 @@ function toUnsignedV2DutchOrderInfo(orderInfoJSON: UnsignedV2DutchOrderInfoJSON) } } -function toUnsignedPriorityOrderInfo(orderInfoJSON: UnsignedPriorityOrderInfoJSON): UnsignedPriorityOrderInfo { - const { nonce, auctionStartBlock, baselinePriorityFeeWei, input, outputs } = orderInfoJSON - - return { - ...orderInfoJSON, - nonce: BigNumber.from(nonce), - auctionStartBlock: BigNumber.from(auctionStartBlock), - baselinePriorityFeeWei: BigNumber.from(baselinePriorityFeeWei), - - input: { - ...input, - amount: BigNumber.from(input.amount), - mpsPerPriorityFeeWei: BigNumber.from(input.mpsPerPriorityFeeWei), - }, - outputs: outputs.map((output: PriorityOutputJSON) => ({ - ...output, - amount: BigNumber.from(output.amount), - mpsPerPriorityFeeWei: BigNumber.from(output.mpsPerPriorityFeeWei), - })), - } -} - // Prepares the currencies used for the actual Swap (either UniswapX or Universal Router) // May not match `currencyIn` that the user selected because for ETH inputs in UniswapX, the actual // swap will use WETH. @@ -223,7 +196,7 @@ function getTradeCurrencies( } function getSwapFee( - data: ClassicQuoteData | URADutchOrderQuoteData | URADutchOrderV2QuoteData | URAPriorityOrderQuoteData, + data: ClassicQuoteData | URADutchOrderQuoteData | URADutchOrderV2QuoteData, ): SwapFeeInfo | undefined { const { portionAmount, portionBips, portionRecipient } = data @@ -291,8 +264,7 @@ export async function transformQuoteToTrade( const { tradeType, needsWrapIfUniswapX, isXv2, routerPreference, account, amount } = args const showUniswapXTrade = - ((isXv2 ? data.routing === URAQuoteType.DUTCH_V2 : data.routing === URAQuoteType.DUTCH_V1) || - data.routing === URAQuoteType.PRIORITY) && + (isXv2 ? data.routing === URAQuoteType.DUTCH_V2 : data.routing === URAQuoteType.DUTCH_V1) && routerPreference === RouterPreference.X const [currencyIn, currencyOut] = getTradeCurrencies(args, showUniswapXTrade) @@ -341,11 +313,7 @@ export async function transformQuoteToTrade( }) // If the top-level URA quote type is DUTCH_V1 or DUTCH_V2, then UniswapX is better for the user - // Or if quote type is PRIORITY, we only use UniswapX - const isUniswapXBetter = - data.routing === URAQuoteType.DUTCH_V1 || - data.routing === URAQuoteType.DUTCH_V2 || - data.routing === URAQuoteType.PRIORITY + const isUniswapXBetter = data.routing === URAQuoteType.DUTCH_V1 || data.routing === URAQuoteType.DUTCH_V2 if (isUniswapXBetter) { const swapFee = getSwapFee(data.quote) const wrapInfo = await getWrapInfo(needsWrapIfUniswapX, account, currencyIn.chainId, amount, usdCostPerGas) @@ -395,26 +363,6 @@ export async function transformQuoteToTrade( state: QuoteState.SUCCESS, trade: uniswapXTrade, } - } else if (data.routing === URAQuoteType.PRIORITY) { - const orderInfo = toUnsignedPriorityOrderInfo(data.quote.orderInfo) - const priorityOrderTrade = new PriorityOrderTrade({ - currencyIn, - currenciesOut: [currencyOut], - orderInfo, - tradeType, - approveInfo, - wrapInfo, - startTimeBufferSecs: data.quote.startTimeBufferSecs, - deadlineBufferSecs: data.quote.deadlineBufferSecs, - slippageTolerance: toSlippagePercent(data.quote.slippageTolerance), - classicGasUseEstimateUSD: classicTrade.totalGasUseEstimateUSD, - swapFee, - }) - - return { - state: QuoteState.SUCCESS, - trade: priorityOrderTrade, - } } } @@ -487,19 +435,16 @@ export function isUniswapXTradeType( export function isUniswapXTrade( trade?: InterfaceTrade, -): trade is DutchOrderTrade | V2DutchOrderTrade | LimitOrderTrade | PriorityOrderTrade { +): trade is DutchOrderTrade | V2DutchOrderTrade | LimitOrderTrade { return isUniswapXTradeType(trade?.fillType) } /* Returns true if trade is a SWAP on UniswapX, not a limit order */ -export function isUniswapXSwapTrade( - trade?: InterfaceTrade, -): trade is DutchOrderTrade | V2DutchOrderTrade | PriorityOrderTrade { +export function isUniswapXSwapTrade(trade?: InterfaceTrade): trade is DutchOrderTrade | V2DutchOrderTrade { return ( isUniswapXTrade(trade) && (trade?.offchainOrderType === OffchainOrderType.DUTCH_AUCTION || - trade?.offchainOrderType === OffchainOrderType.DUTCH_V2_AUCTION || - trade?.offchainOrderType === OffchainOrderType.PRIORITY_ORDER) + trade?.offchainOrderType === OffchainOrderType.DUTCH_V2_AUCTION) ) } diff --git a/apps/web/src/state/sagas/root.ts b/apps/web/src/state/sagas/root.ts deleted file mode 100644 index c70f5bfbaf7..00000000000 --- a/apps/web/src/state/sagas/root.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { PersistState } from 'redux-persist' -import { swapSaga } from 'state/sagas/transactions/swapSaga' -import { wrapSaga } from 'state/sagas/transactions/wrapSaga' -import { delay, select, spawn } from 'typed-redux-saga' - -const sagas = [swapSaga.wrappedSaga, wrapSaga.wrappedSaga] - -export function* rootWebSaga() { - // wait until redux-persist has finished rehydration - while (true) { - if (yield* select((state: { _persist?: PersistState }): boolean | undefined => state._persist?.rehydrated)) { - break - } - yield* delay(/* REHYDRATION_STATUS_POLLING_INTERVAL */ 50) - } - - for (const wrappedSaga of sagas) { - yield* spawn(wrappedSaga) - } -} diff --git a/apps/web/src/state/sagas/transactions/swapSaga.ts b/apps/web/src/state/sagas/transactions/swapSaga.ts deleted file mode 100644 index 955fda5388b..00000000000 --- a/apps/web/src/state/sagas/transactions/swapSaga.ts +++ /dev/null @@ -1,319 +0,0 @@ -/* eslint-disable rulesdir/no-undefined-or */ -import { TransactionResponse } from '@ethersproject/providers' -import { SwapEventName } from '@uniswap/analytics-events' -import { useTotalBalancesUsdForAnalytics } from 'graphql/data/apollo/useTotalBalancesUsdForAnalytics' -import { useAccount } from 'hooks/useAccount' -import useSelectChain from 'hooks/useSelectChain' -import { formatSwapSignedAnalyticsEventProperties } from 'lib/utils/analytics' -import { useCallback } from 'react' -import { useDispatch, useSelector } from 'react-redux' -import { PopupType, addPopup } from 'state/application/reducer' -import { handleUniswapXSignatureStep } from 'state/sagas/transactions/uniswapx' -import { - HandleOnChainStepParams, - getSwapTransactionInfo, - handleApprovalTransactionStep, - handleOnChainStep, - handleSignatureStep, -} from 'state/sagas/transactions/utils' -import { handleWrapStep } from 'state/sagas/transactions/wrapSaga' -import invariant from 'tiny-invariant' -import { call, put } from 'typed-redux-saga' -import { Routing } from 'uniswap/src/data/tradingApi/__generated__/index' -import { SignerMnemonicAccountMeta } from 'uniswap/src/features/accounts/types' -import { useLocalizationContext } from 'uniswap/src/features/language/LocalizationContext' -import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' -import { selectSwapStartTimestamp } from 'uniswap/src/features/timing/selectors' -import { updateSwapStartTimestamp } from 'uniswap/src/features/timing/slice' -import { getBaseTradeAnalyticsProperties } from 'uniswap/src/features/transactions/swap/analytics' -import { - SetCurrentStepFn, - SwapCallback, - SwapCallbackParams, -} from 'uniswap/src/features/transactions/swap/types/swapCallback' -import { - ValidatedClassicSwapTxAndGasInfo, - ValidatedSwapTxContext, - ValidatedUniswapXSwapTxAndGasInfo, -} from 'uniswap/src/features/transactions/swap/types/swapTxAndGasInfo' -import { ClassicTrade } from 'uniswap/src/features/transactions/swap/types/trade' -import { - SwapTransactionStep, - SwapTransactionStepAsync, - TransactionStep, - TransactionStepType, - generateTransactionSteps, -} from 'uniswap/src/features/transactions/swap/utils/generateTransactionSteps' -import { isClassic } from 'uniswap/src/features/transactions/swap/utils/routing' -import { getClassicQuoteFromResponse } from 'uniswap/src/features/transactions/swap/utils/tradingApi' -import { createSaga } from 'uniswap/src/utils/saga' -import { percentFromFloat } from 'utilities/src/format/percent' -import { logger } from 'utilities/src/logger/logger' - -// TODO(WEB-4921): Move errors to uniswap package and handle them in UI -class UnexpectedSwapStateError extends Error { - constructor(message: string) { - super(message) - this.name = 'UnexpectedSwapStateError' - } -} - -interface HandleSwapStepParams extends Omit { - step: SwapTransactionStep | SwapTransactionStepAsync - signature: string | undefined - trade: ClassicTrade - analytics: ReturnType -} -function* handleSwapTransactionStep(params: HandleSwapStepParams) { - const { trade, step, signature, analytics } = params - const info = getSwapTransactionInfo(trade) - const txRequest = yield* call(getSwapTxRequest, step, signature) - - const onModification = (response: TransactionResponse) => { - sendAnalyticsEvent(SwapEventName.SWAP_MODIFIED_IN_WALLET, { - txHash: response.hash, - expected: txRequest.data?.toString() ?? '', - actual: response.data, - }) - } - - // Now that we have the txRequest, we can create a definitive SwapTransactionStep, incase we started with an async step. - const onChainStep = { ...step, txRequest } - const hash = yield* call(handleOnChainStep, { ...params, info, step: onChainStep, onModification }) - - sendAnalyticsEvent( - SwapEventName.SWAP_SIGNED, - formatSwapSignedAnalyticsEventProperties({ - trade, - allowedSlippage: percentFromFloat(trade.slippageTolerance), - fiatValues: { - amountIn: analytics.token_in_amount_usd, - amountOut: analytics.token_out_amount_usd, - feeUsd: analytics.fee_usd, - }, - txHash: hash, - portfolioBalanceUsd: analytics.total_balances_usd, - }), - ) - - yield* put(addPopup({ content: { type: PopupType.Transaction, hash }, key: hash })) - - return -} - -function* getSwapTxRequest(step: SwapTransactionStep | SwapTransactionStepAsync, signature: string | undefined) { - if (step.type === TransactionStepType.SwapTransaction) { - return step.txRequest - } - - if (!signature) { - throw new UnexpectedSwapStateError('Signature required for async swap transaction step') - } - - try { - const txRequest = yield* call(step.getTxRequest, signature) - invariant(txRequest !== undefined) - - return txRequest - } catch { - throw new UnexpectedSwapStateError('Failed to get transaction request') - } -} - -type SwapParams = { - selectChain: (chainId: number) => Promise - startChainId?: number - account: SignerMnemonicAccountMeta - analytics: ReturnType - swapTxContext: ValidatedSwapTxContext - setCurrentStep: SetCurrentStepFn - setSteps: (steps: TransactionStep[]) => void - onSuccess: () => void - onFailure: () => void -} - -// eslint-disable-next-line consistent-return -function* swap(params: SwapParams) { - const { analytics, swapTxContext, selectChain, startChainId, onFailure } = params - const steps = yield* call(generateTransactionSteps, swapTxContext) - params.setSteps(steps) - - // Switch chains if needed - const swapChainId = swapTxContext.trade.inputAmount.currency.chainId - if (swapChainId !== startChainId) { - const chainSwitched = yield* call(selectChain, swapChainId) - if (!chainSwitched) { - onFailure() - return undefined - } - } - - switch (swapTxContext.routing) { - case Routing.CLASSIC: - return yield* classicSwap({ - ...params, - swapTxContext, - steps, - analytics, - }) - case Routing.DUTCH_V2: - return yield* uniswapXSwap({ ...params, swapTxContext, steps }) - // case Routing.BRIDGE: - // return yield* bridgingSaga({ ...params, swapTxContext }) - } -} - -function* classicSwap( - params: SwapParams & { swapTxContext: ValidatedClassicSwapTxAndGasInfo; steps: TransactionStep[] }, -) { - const { - account, - setCurrentStep, - steps, - swapTxContext: { trade }, - analytics, - } = params - - let signature: string | undefined - - try { - for (const step of steps) { - switch (step.type) { - case TransactionStepType.TokenRevocationTransaction: - case TransactionStepType.TokenApprovalTransaction: { - yield* call(handleApprovalTransactionStep, { account, step, setCurrentStep }) - break - } - case TransactionStepType.Permit2Signature: { - signature = yield* call(handleSignatureStep, { account, step, setCurrentStep }) - break - } - case TransactionStepType.SwapTransaction: - case TransactionStepType.SwapTransactionAsync: { - yield* call(handleSwapTransactionStep, { account, signature, step, setCurrentStep, trade, analytics }) - break - } - default: { - throw new UnexpectedSwapStateError('Unexpected step type') - } - } - } - } catch (e) { - // TODO(WEB-4921): pass errors to onFailure and to handle in UI - logger.error(e, { tags: { file: 'swapSaga', function: 'classicSwap' } }) - } - - yield* call(params.onSuccess) -} - -function* uniswapXSwap( - params: SwapParams & { - swapTxContext: ValidatedUniswapXSwapTxAndGasInfo - steps: TransactionStep[] - analytics: ReturnType - }, -) { - const { - account, - setCurrentStep, - steps, - swapTxContext: { trade }, - analytics, - } = params - - try { - for (const step of steps) { - switch (step.type) { - case TransactionStepType.WrapTransaction: { - yield* call(handleWrapStep, { account, step, setCurrentStep }) - break - } - case TransactionStepType.TokenRevocationTransaction: - case TransactionStepType.TokenApprovalTransaction: { - yield* call(handleApprovalTransactionStep, { account, step, setCurrentStep }) - break - } - case TransactionStepType.UniswapXSignature: { - yield* call(handleUniswapXSignatureStep, { account, step, setCurrentStep, trade, analytics }) - break - } - default: { - throw new UnexpectedSwapStateError('Unexpected step type') - } - } - } - } catch (e) { - // TODO(WEB-4921): pass errors to onFailure and to handle in UI - logger.error(e, { tags: { file: 'swapSaga', function: 'uniswapXSwap' } }) - } - - yield* call(params.onSuccess) -} - -export const swapSaga = createSaga(swap, 'swapSaga') - -/** Callback to submit trades and track progress */ -export function useSwapCallback(): SwapCallback { - const appDispatch = useDispatch() - const formatter = useLocalizationContext() - const swapStartTimestamp = useSelector(selectSwapStartTimestamp) - const selectChain = useSelectChain() - const startChainId = useAccount().chainId - - const portfolioBalanceUsd = useTotalBalancesUsdForAnalytics() - - return useCallback( - (args: SwapCallbackParams) => { - const { - account, - swapTxContext, - onSuccess, - onFailure, - currencyInAmountUSD, - currencyOutAmountUSD, - isAutoSlippage, - isFiatInputMode, - setCurrentStep, - setSteps, - } = args - const { trade, gasFee } = swapTxContext - - const analytics = getBaseTradeAnalyticsProperties({ - formatter, - trade, - currencyInAmountUSD, - currencyOutAmountUSD, - portfolioBalanceUsd, - }) - const swapParams = { - swapTxContext, - account, - analytics, - onSuccess, - onFailure, - setCurrentStep, - setSteps, - selectChain, - startChainId, - } - appDispatch(swapSaga.actions.trigger(swapParams)) - - const blockNumber = getClassicQuoteFromResponse(trade?.quote)?.blockNumber?.toString() - - sendAnalyticsEvent(SwapEventName.SWAP_SUBMITTED_BUTTON_CLICKED, { - ...analytics, - estimated_network_fee_wei: gasFee.value, - gas_limit: isClassic(swapTxContext) ? swapTxContext.txRequest?.gasLimit?.toString() : undefined, - transaction_deadline_seconds: trade.deadline, - swap_quote_block_number: blockNumber, - is_auto_slippage: isAutoSlippage, - swap_flow_duration_milliseconds: swapStartTimestamp ? Date.now() - swapStartTimestamp : undefined, - is_fiat_input_mode: isFiatInputMode, - }) - - // Reset swap start timestamp now that the swap has been submitted - appDispatch(updateSwapStartTimestamp({ timestamp: undefined })) - }, - [formatter, portfolioBalanceUsd, selectChain, startChainId, appDispatch, swapStartTimestamp], - ) -} diff --git a/apps/web/src/state/sagas/transactions/uniswapx.ts b/apps/web/src/state/sagas/transactions/uniswapx.ts deleted file mode 100644 index ccd015c25b0..00000000000 --- a/apps/web/src/state/sagas/transactions/uniswapx.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { formatSwapSignedAnalyticsEventProperties } from 'lib/utils/analytics' -import { PopupType, addPopup } from 'state/application/reducer' -import { HandleSignatureStepParams, getSwapTransactionInfo, handleSignatureStep } from 'state/sagas/transactions/utils' -import { addSignature } from 'state/signatures/reducer' -import { SignatureType, UnfilledUniswapXOrderDetails } from 'state/signatures/types' -import { call, put } from 'typed-redux-saga' -import { UniswapXOrderStatus } from 'types/uniswapx' -import { submitOrder } from 'uniswap/src/data/apiClients/tradingApi/TradingApiClient' -import { InterfaceEventNameLocal } from 'uniswap/src/features/telemetry/constants' -import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' -import { getBaseTradeAnalyticsProperties } from 'uniswap/src/features/transactions/swap/analytics' -import { UniswapXTrade } from 'uniswap/src/features/transactions/swap/types/trade' -import { UniswapXSignatureStep } from 'uniswap/src/features/transactions/swap/utils/generateTransactionSteps' -import { UniverseChainId } from 'uniswap/src/types/chains' -import { percentFromFloat } from 'utilities/src/format/percent' -import { logger } from 'utilities/src/logger/logger' - -interface HandleUniswapXSignatureStepParams extends HandleSignatureStepParams { - trade: UniswapXTrade - analytics: ReturnType -} -export function* handleUniswapXSignatureStep(params: HandleUniswapXSignatureStepParams) { - const { trade, analytics } = params - const quote = trade.quote.quote - const orderHash = quote.orderId - const chainId = trade.inputAmount.currency.chainId - const signatureDetails = getUniswapXSignatureInfo(params.step, trade, chainId) - - const analyticsParams: Parameters[0] = { - trade, - allowedSlippage: percentFromFloat(trade.slippageTolerance), - fiatValues: { - amountIn: analytics.token_in_amount_usd, - amountOut: analytics.token_out_amount_usd, - feeUsd: analytics.fee_usd, - }, - portfolioBalanceUsd: analytics.total_balances_usd, - } - - try { - const signature = yield* call(handleSignatureStep, params) - - sendAnalyticsEvent( - InterfaceEventNameLocal.UniswapXSignatureRequested, - formatSwapSignedAnalyticsEventProperties(analyticsParams), - ) - - yield* call(submitOrder, { signature, quote, routing: trade.routing }) - - sendAnalyticsEvent( - InterfaceEventNameLocal.UniswapXOrderSubmitted, - formatSwapSignedAnalyticsEventProperties(analyticsParams), - ) - - yield* put(addSignature(signatureDetails)) - - yield* put(addPopup({ content: { type: PopupType.Order, orderHash }, key: orderHash })) - } catch (e) { - // TODO(WEB-4921): pass errors to onFailure and to handle in UI - logger.error(e, { tags: { file: 'uniswapx', function: 'handleUniswapXSignatureStep' } }) - - sendAnalyticsEvent(InterfaceEventNameLocal.UniswapXOrderPostError, { - ...formatSwapSignedAnalyticsEventProperties(analyticsParams), - detail: e.message, - }) - } -} - -function getUniswapXSignatureInfo( - step: UniswapXSignatureStep, - trade: UniswapXTrade, - chainId: UniverseChainId, -): UnfilledUniswapXOrderDetails { - const swapInfo = getSwapTransactionInfo(trade) - - return { - type: SignatureType.SIGN_UNISWAPX_V2_ORDER, - id: step.quote.orderId, - addedTime: Date.now(), - chainId, - offerer: trade.quote.quote.orderInfo.reactor, - orderHash: trade.quote.quote.orderId, - status: UniswapXOrderStatus.OPEN, - swapInfo, - } -} diff --git a/apps/web/src/state/sagas/transactions/utils.ts b/apps/web/src/state/sagas/transactions/utils.ts deleted file mode 100644 index 2e4c4460287..00000000000 --- a/apps/web/src/state/sagas/transactions/utils.ts +++ /dev/null @@ -1,169 +0,0 @@ -import { JsonRpcSigner, TransactionResponse, Web3Provider } from '@ethersproject/providers' -import { TradeType } from '@uniswap/sdk-core' -import { wagmiConfig } from 'components/Web3Provider/wagmiConfig' -import { clientToProvider } from 'hooks/useEthersProvider' -import { addTransaction, finalizeTransaction } from 'state/transactions/reducer' -import { - ApproveTransactionInfo, - ExactInputSwapTransactionInfo, - ExactOutputSwapTransactionInfo, - TransactionInfo, - TransactionType, -} from 'state/transactions/types' -import { call, put, take } from 'typed-redux-saga' -import { TransactionStatus } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' -import { AccountMeta } from 'uniswap/src/features/accounts/types' -import { SetCurrentStepFn } from 'uniswap/src/features/transactions/swap/types/swapCallback' -import { ClassicTrade, UniswapXTrade } from 'uniswap/src/features/transactions/swap/types/trade' -import { - OnChainTransactionStep, - SignatureTransactionStep, - TokenApprovalTransactionStep, - TokenRevocationTransactionStep, - TransactionStep, -} from 'uniswap/src/features/transactions/swap/utils/generateTransactionSteps' -import { isUniswapX } from 'uniswap/src/features/transactions/swap/utils/routing' -import { currencyId } from 'uniswap/src/utils/currencyId' -import { percentFromFloat } from 'utilities/src/format/percent' -import { getConnectorClient } from 'wagmi/actions' - -class MissingProviderError extends Error { - constructor(message: string) { - super(message) - this.name = 'MissingProviderError' - } -} -class TransactionFailureError extends Error { - step: TransactionStep - - constructor(message: string, step: TransactionStep) { - super(message) - this.name = 'TransactionFailureError' - this.step = step - } -} - -export interface HandleSignatureStepParams { - step: T - setCurrentStep: SetCurrentStepFn -} -export function* handleSignatureStep({ setCurrentStep, step }: HandleSignatureStepParams) { - // Trigger UI prompting user to accept - setCurrentStep({ step, accepted: false }) - - const signer = yield* call(getSigner) - const signature = yield* call([signer, '_signTypedData'], step.domain, step.types, step.values) - - return signature -} - -export interface HandleOnChainStepParams { - account: AccountMeta - info: TransactionInfo - step: T - setCurrentStep: SetCurrentStepFn - shouldWaitForConfirmation?: boolean - onModification?: (response: TransactionResponse) => void -} -export function* handleOnChainStep(params: HandleOnChainStepParams) { - const { account, step, setCurrentStep, info, shouldWaitForConfirmation = true, onModification } = params - const signer = yield* call(getSigner) - - // Trigger UI prompting user to accept - setCurrentStep({ step, accepted: false }) - - const response = yield* call([signer, 'sendTransaction'], step.txRequest) - const { hash, nonce, data } = response - - // Trigger waiting UI after user accepts - setCurrentStep({ step, accepted: true }) - - // Add transaction to local state to start polling for status - yield* put(addTransaction({ from: account.address, info, hash, nonce, chainId: step.txRequest.chainId })) - - if (step.txRequest.data !== data) { - onModification?.(response) - } - - if (shouldWaitForConfirmation) { - // Delay returning until transaction is confirmed - yield* call(waitForTransaction, hash, step) - } - - return hash -} - -interface HandleApprovalStepParams - extends Omit, 'info'> {} -export function* handleApprovalTransactionStep(params: HandleApprovalStepParams) { - const { step } = params - const info = getApprovalTransactionInfo(step) - return yield* call(handleOnChainStep, { ...params, info }) -} - -function getApprovalTransactionInfo( - approvalStep: TokenApprovalTransactionStep | TokenRevocationTransactionStep, -): ApproveTransactionInfo { - return { - type: TransactionType.APPROVAL, - tokenAddress: approvalStep.token.address, - spender: approvalStep.spender, - amount: approvalStep.amount, - } -} - -/** Returns when a transaction is confirmed in local state. Throws an error if the transaction fails. */ -function* waitForTransaction(hash: string, step: TransactionStep) { - while (true) { - const { payload } = yield* take>(finalizeTransaction.type) - if (payload.hash === hash) { - if (payload.status === TransactionStatus.Confirmed) { - return - } else { - throw new TransactionFailureError('Transaction not successful', step) - } - } - } -} - -async function getProvider(): Promise { - const client = await getConnectorClient(wagmiConfig) - const provider = clientToProvider(client) - - if (!provider) { - throw new MissingProviderError(`Failed to get provider during transaction flow`) - } - - return provider -} - -async function getSigner(): Promise { - return (await getProvider()).getSigner() -} - -type SwapInfo = ExactInputSwapTransactionInfo | ExactOutputSwapTransactionInfo -export function getSwapTransactionInfo(trade: ClassicTrade): SwapInfo -export function getSwapTransactionInfo(trade: UniswapXTrade): SwapInfo & { isUniswapXOrder: true } -export function getSwapTransactionInfo(trade: ClassicTrade | UniswapXTrade): SwapInfo { - const slippage = percentFromFloat(trade.slippageTolerance) - - return { - type: TransactionType.SWAP, - inputCurrencyId: currencyId(trade.inputAmount.currency), - outputCurrencyId: currencyId(trade.outputAmount.currency), - isUniswapXOrder: isUniswapX(trade), - ...(trade.tradeType === TradeType.EXACT_INPUT - ? { - tradeType: TradeType.EXACT_INPUT, - inputCurrencyAmountRaw: trade.inputAmount.quotient.toString(), - expectedOutputCurrencyAmountRaw: trade.outputAmount.quotient.toString(), - minimumOutputCurrencyAmountRaw: trade.minimumAmountOut(slippage).quotient.toString(), - } - : { - tradeType: TradeType.EXACT_OUTPUT, - maximumInputCurrencyAmountRaw: trade.maximumAmountIn(slippage).quotient.toString(), - outputCurrencyAmountRaw: trade.outputAmount.quotient.toString(), - expectedInputCurrencyAmountRaw: trade.inputAmount.quotient.toString(), - }), - } -} diff --git a/apps/web/src/state/sagas/transactions/wrapSaga.ts b/apps/web/src/state/sagas/transactions/wrapSaga.ts deleted file mode 100644 index 06666bc4932..00000000000 --- a/apps/web/src/state/sagas/transactions/wrapSaga.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { Web3Provider } from '@ethersproject/providers' -import { Currency, CurrencyAmount } from '@uniswap/sdk-core' -import { useEthersWeb3Provider } from 'hooks/useEthersProvider' -import { useCallback } from 'react' -import { useDispatch } from 'react-redux' -import { PopupType, addPopup } from 'state/application/reducer' -import { HandleOnChainStepParams, handleOnChainStep } from 'state/sagas/transactions/utils' -import { TransactionType, WrapTransactionInfo } from 'state/transactions/types' -import { call, put } from 'typed-redux-saga' -import { WrapCallback, WrapCallbackParams } from 'uniswap/src/features/transactions/swap/types/wrapCallback' -import { - TransactionStepType, - WrapTransactionStep, -} from 'uniswap/src/features/transactions/swap/utils/generateTransactionSteps' -import { createSaga } from 'uniswap/src/utils/saga' -import { logger } from 'utilities/src/logger/logger' -import noop from 'utilities/src/react/noop' - -interface HandleWrapStepParams extends Omit, 'info'> {} -export function* handleWrapStep(params: HandleWrapStepParams) { - const info = getWrapTransactionInfo(params.step.amount) - return yield* call(handleOnChainStep, { ...params, info }) -} - -type WrapParams = WrapCallbackParams & { provider: Web3Provider } - -function* wrap(params: WrapParams) { - try { - const { account, inputCurrencyAmount, txRequest, provider } = params - - const step = { type: TransactionStepType.WrapTransaction, txRequest, amount: inputCurrencyAmount } as const - - const hash = yield* call(handleWrapStep, { - step, - account, - provider, - setCurrentStep: noop, - shouldWaitForConfirmation: false, - }) - - yield* put(addPopup({ content: { type: PopupType.Transaction, hash }, key: hash })) - - params.onSuccess() - } catch (error) { - logger.error(error, { tags: { file: 'wrapSaga', function: 'wrap' } }) - params.onFailure() - } -} - -function getWrapTransactionInfo(amount: CurrencyAmount): WrapTransactionInfo { - return amount.currency.isNative - ? { - type: TransactionType.WRAP, - unwrapped: false, - currencyAmountRaw: amount.quotient.toString(), - } - : { - type: TransactionType.WRAP, - unwrapped: true, - currencyAmountRaw: amount.quotient.toString(), - } -} - -export const wrapSaga = createSaga(wrap, 'wrap') - -export function useWrapCallback(): WrapCallback { - const appDispatch = useDispatch() - const provider = useEthersWeb3Provider() - - return useCallback( - (params: WrapCallbackParams) => { - if (!provider) { - throw new Error('Provider not found') - } - - appDispatch(wrapSaga.actions.trigger({ ...params, provider })) - }, - [appDispatch, provider], - ) -} diff --git a/apps/web/src/state/signatures/hooks.ts b/apps/web/src/state/signatures/hooks.ts index 23eff76e5b6..023739294d6 100644 --- a/apps/web/src/state/signatures/hooks.ts +++ b/apps/web/src/state/signatures/hooks.ts @@ -35,12 +35,9 @@ export function useOrder(orderHash: string): UniswapXOrderDetails | undefined { const order = signatures[orderHash] if ( !order || - ![ - SignatureType.SIGN_UNISWAPX_ORDER, - SignatureType.SIGN_UNISWAPX_V2_ORDER, - SignatureType.SIGN_LIMIT, - SignatureType.SIGN_PRIORITY_ORDER, - ].includes(order.type as SignatureType) + ![SignatureType.SIGN_UNISWAPX_ORDER, SignatureType.SIGN_UNISWAPX_V2_ORDER, SignatureType.SIGN_LIMIT].includes( + order.type as SignatureType, + ) ) { return undefined } @@ -105,8 +102,7 @@ function isPendingOrder(signature: SignatureDetails): signature is UniswapXOrder ].includes(signature.status) } else if ( signature.type === SignatureType.SIGN_UNISWAPX_ORDER || - signature.type === SignatureType.SIGN_UNISWAPX_V2_ORDER || - signature.type === SignatureType.SIGN_PRIORITY_ORDER + signature.type === SignatureType.SIGN_UNISWAPX_V2_ORDER ) { return [ UniswapXOrderStatus.OPEN, diff --git a/apps/web/src/state/signatures/parseRemote.ts b/apps/web/src/state/signatures/parseRemote.ts index 8d67ce84e6f..0befa375fb4 100644 --- a/apps/web/src/state/signatures/parseRemote.ts +++ b/apps/web/src/state/signatures/parseRemote.ts @@ -14,7 +14,6 @@ const SIGNATURE_TYPE_MAP: { [key in SwapOrderType]: SignatureType } = { [SwapOrderType.Limit]: SignatureType.SIGN_LIMIT, [SwapOrderType.Dutch]: SignatureType.SIGN_UNISWAPX_ORDER, [SwapOrderType.DutchV2]: SignatureType.SIGN_UNISWAPX_V2_ORDER, - // [SwapOrderType.Priority]: SignatureType.SIGN_PRIORITY_ORDER, } const ORDER_STATUS_MAP: { [key in SwapOrderStatus]: UniswapXOrderStatus } = { diff --git a/apps/web/src/state/signatures/types.ts b/apps/web/src/state/signatures/types.ts index 1e74fb7fb65..62aae21354a 100644 --- a/apps/web/src/state/signatures/types.ts +++ b/apps/web/src/state/signatures/types.ts @@ -14,14 +14,12 @@ export enum SignatureType { SIGN_UNISWAPX_ORDER = 'signUniswapXOrder', SIGN_UNISWAPX_V2_ORDER = 'signUniswapXV2Order', SIGN_LIMIT = 'signLimit', - SIGN_PRIORITY_ORDER = 'signPriorityOrder', } export const OFFCHAIN_ORDER_TYPE_TO_SIGNATURE_TYPE: Partial> = { [OffchainOrderType.DUTCH_AUCTION]: SignatureType.SIGN_UNISWAPX_ORDER, [OffchainOrderType.DUTCH_V2_AUCTION]: SignatureType.SIGN_UNISWAPX_V2_ORDER, [OffchainOrderType.LIMIT_ORDER]: SignatureType.SIGN_LIMIT, - [OffchainOrderType.PRIORITY_ORDER]: SignatureType.SIGN_PRIORITY_ORDER, } interface BaseSignatureFields { diff --git a/apps/web/src/state/swap/SwapContext.test.tsx b/apps/web/src/state/swap/SwapContext.test.tsx index 130350be02b..7f4d63e34e5 100644 --- a/apps/web/src/state/swap/SwapContext.test.tsx +++ b/apps/web/src/state/swap/SwapContext.test.tsx @@ -1,4 +1,5 @@ import { Percent } from '@uniswap/sdk-core' +import { Field } from 'components/swap/constants' import { SwapForm } from 'pages/Swap/SwapForm' import { SwapAndLimitContextProvider, SwapContextProvider } from 'state/swap/SwapContext' import { SwapAndLimitContext, SwapInfo } from 'state/swap/types' @@ -6,7 +7,6 @@ import { useSwapAndLimitContext, useSwapContext } from 'state/swap/useSwapContex import { render, screen } from 'test-utils/render' import { nativeOnChain } from 'uniswap/src/constants/tokens' import { UniverseChainId } from 'uniswap/src/types/chains' -import { CurrencyField } from 'uniswap/src/types/currency' import { SwapTab } from 'uniswap/src/types/screens/interface' jest.mock('hooks/useContract', () => ({ @@ -33,12 +33,12 @@ describe('Swap Context', () => { allowedSlippage: new Percent(5, 1000), autoSlippage: new Percent(5, 1000), currencies: { - input: undefined, - output: undefined, + INPUT: undefined, + OUTPUT: undefined, }, currencyBalances: { - input: undefined, - output: undefined, + INPUT: undefined, + OUTPUT: undefined, }, inputError: expect.any(Object), inputTax: new Percent(0), @@ -54,7 +54,7 @@ describe('Swap Context', () => { }, setSwapState: expect.any(Function), swapState: { - independentField: 'input', + independentField: 'INPUT', typedValue: '', }, }) @@ -160,8 +160,8 @@ describe('Combined contexts', () => { // @ts-ignore rendering TestComponent sets derivedSwapInfo value expect(derivedSwapInfo?.currencies).toEqual({ - [CurrencyField.INPUT]: nativeOnChain(UniverseChainId.Mainnet), - [CurrencyField.OUTPUT]: undefined, + [Field.INPUT]: nativeOnChain(UniverseChainId.Mainnet), + [Field.OUTPUT]: undefined, }) }) }) diff --git a/apps/web/src/state/swap/SwapContext.tsx b/apps/web/src/state/swap/SwapContext.tsx index 810866cc7e6..08813ad57c2 100644 --- a/apps/web/src/state/swap/SwapContext.tsx +++ b/apps/web/src/state/swap/SwapContext.tsx @@ -1,5 +1,6 @@ import { Currency } from '@uniswap/sdk-core' -import { useReportTotalBalancesUsdForAnalytics } from 'graphql/data/apollo/useReportTotalBalancesUsdForAnalytics' +import { Field } from 'components/swap/constants' +import { useReportTotalBalancesUsdForAnalytics } from 'graphql/data/apollo/TokenBalancesProvider' import { useAccount } from 'hooks/useAccount' import usePrevious from 'hooks/usePrevious' import { useUpdateAtom } from 'jotai/utils' @@ -9,7 +10,6 @@ import { useDerivedSwapInfo } from 'state/swap/hooks' import { CurrencyState, SwapAndLimitContext, SwapContext, SwapState, initialSwapState } from 'state/swap/types' import { useSwapAndLimitContext } from 'state/swap/useSwapContext' import { InterfaceChainId } from 'uniswap/src/types/chains' -import { CurrencyField } from 'uniswap/src/types/currency' import { SwapTab } from 'uniswap/src/types/screens/interface' import { areCurrenciesEqual } from 'uniswap/src/utils/currencyId' @@ -135,7 +135,7 @@ export function SwapContextProvider({ children, }: { initialTypedValue?: string - initialIndependentField?: CurrencyField + initialIndependentField?: Field multichainUXEnabled?: boolean children: React.ReactNode }) { diff --git a/apps/web/src/state/swap/hooks.test.ts b/apps/web/src/state/swap/hooks.test.ts index 0c34748fb36..2f671d17765 100644 --- a/apps/web/src/state/swap/hooks.test.ts +++ b/apps/web/src/state/swap/hooks.test.ts @@ -3,7 +3,7 @@ import { parse } from 'qs' import { queryParametersToCurrencyState, useInitialCurrencyState } from 'state/swap/hooks' import { ETH_MAINNET } from 'test-utils/constants' import { renderHook, waitFor } from 'test-utils/render' -import { UNI, nativeOnChain } from 'uniswap/src/constants/tokens' +import { MATIC_POLYGON, UNI } from 'uniswap/src/constants/tokens' import { UniverseChainId } from 'uniswap/src/types/chains' jest.mock('uniswap/src/features/gating/hooks', () => { @@ -186,7 +186,7 @@ describe('hooks', () => { { tokenBalances: [ { - token: nativeOnChain(UniverseChainId.Polygon), + token: MATIC_POLYGON, denominatedValue: { value: 1000, }, diff --git a/apps/web/src/state/swap/hooks.tsx b/apps/web/src/state/swap/hooks.tsx index 55ddd9e41f3..f0c330d98f4 100644 --- a/apps/web/src/state/swap/hooks.tsx +++ b/apps/web/src/state/swap/hooks.tsx @@ -1,5 +1,5 @@ import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core' -import { ConnectWalletButtonText } from 'components/NavBar/accountCTAsExperimentUtils' +import { Field } from 'components/swap/constants' import { CHAIN_IDS_TO_NAMES, useSupportedChainId } from 'constants/chains' import { NATIVE_CHAIN_ID } from 'constants/tokens' import { useCurrency, useCurrencyInfo } from 'hooks/Tokens' @@ -20,17 +20,18 @@ import { CurrencyState, SerializedCurrencyState, SwapInfo, SwapState } from 'sta import { useSwapAndLimitContext, useSwapContext } from 'state/swap/useSwapContext' import { useUserSlippageToleranceWithDefault } from 'state/user/hooks' import { useTokenProjects } from 'uniswap/src/features/dataApi/tokenProjects' +import { AccountCTAsExperimentGroup, Experiments } from 'uniswap/src/features/gating/experiments' +import { useExperimentGroupName } from 'uniswap/src/features/gating/hooks' import { Trans } from 'uniswap/src/i18n' import { InterfaceChainId, UniverseChainId } from 'uniswap/src/types/chains' -import { CurrencyField } from 'uniswap/src/types/currency' import { areCurrencyIdsEqual, currencyId } from 'uniswap/src/utils/currencyId' import { isAddress } from 'utilities/src/addresses' import { getParsedChainId } from 'utils/chains' export function useSwapActionHandlers(): { - onCurrencySelection: (field: CurrencyField, currency?: Currency) => void + onCurrencySelection: (field: Field, currency: Currency) => void onSwitchTokens: (options: { newOutputHasTax: boolean; previouslyEstimatedOutput: string }) => void - onUserInput: (field: CurrencyField, typedValue: string) => void + onUserInput: (field: Field, typedValue: string) => void } { const { swapState, setSwapState } = useSwapContext() const { currencyState, setCurrencyState } = useSwapAndLimitContext() @@ -43,32 +44,31 @@ export function useSwapActionHandlers(): { ) const onCurrencySelection = useCallback( - (field: CurrencyField, currency?: Currency) => { + (field: Field, currency: Currency) => { const [currentCurrencyKey, otherCurrencyKey]: (keyof CurrencyState)[] = - field === CurrencyField.INPUT ? ['inputCurrency', 'outputCurrency'] : ['outputCurrency', 'inputCurrency'] + field === Field.INPUT ? ['inputCurrency', 'outputCurrency'] : ['outputCurrency', 'inputCurrency'] const otherCurrency = currencyState[otherCurrencyKey] // the case where we have to swap the order - if (otherCurrency && currency?.equals(otherCurrency)) { + if (otherCurrency && currency.equals(otherCurrency)) { setCurrencyState({ [currentCurrencyKey]: currency, [otherCurrencyKey]: currencyState[currentCurrencyKey], }) setSwapState((swapState) => ({ ...swapState, - independentField: - swapState.independentField === CurrencyField.INPUT ? CurrencyField.OUTPUT : CurrencyField.INPUT, + independentField: swapState.independentField === Field.INPUT ? Field.OUTPUT : Field.INPUT, })) // multichain ux case where we set input or output to different chain - } else if (currency && otherCurrency?.chainId !== currency.chainId) { - const otherCurrencyTokenProjects = field === CurrencyField.INPUT ? outputTokenProjects : inputTokenProjects + } else if (otherCurrency?.chainId !== currency.chainId) { + const otherCurrencyTokenProjects = field === Field.INPUT ? outputTokenProjects : inputTokenProjects const otherCurrency = otherCurrencyTokenProjects?.data?.find( - (project) => project?.currency.chainId === currency?.chainId, + (project) => project?.currency.chainId === currency.chainId, ) setCurrencyState((state) => ({ ...state, [currentCurrencyKey]: currency, [otherCurrencyKey]: - otherCurrency && currency && !areCurrencyIdsEqual(currencyId(currency), otherCurrency.currencyId) + otherCurrency && !areCurrencyIdsEqual(currencyId(currency), otherCurrency.currencyId) ? otherCurrency.currency : undefined, })) @@ -91,7 +91,7 @@ export function useSwapActionHandlers(): { previouslyEstimatedOutput: string }) => { // To prevent swaps with FOT tokens as exact-outputs, we leave it as an exact-in swap and use the previously estimated output amount as the new exact-in amount. - if (newOutputHasTax && swapState.independentField === CurrencyField.INPUT) { + if (newOutputHasTax && swapState.independentField === Field.INPUT) { setSwapState((swapState) => ({ ...swapState, typedValue: previouslyEstimatedOutput, @@ -99,7 +99,7 @@ export function useSwapActionHandlers(): { } else { setSwapState((prev) => ({ ...prev, - independentField: prev.independentField === CurrencyField.INPUT ? CurrencyField.OUTPUT : CurrencyField.INPUT, + independentField: prev.independentField === Field.INPUT ? Field.OUTPUT : Field.INPUT, })) } @@ -112,7 +112,7 @@ export function useSwapActionHandlers(): { ) const onUserInput = useCallback( - (field: CurrencyField, typedValue: string) => { + (field: Field, typedValue: string) => { setSwapState((state) => { return { ...state, @@ -159,7 +159,7 @@ export function useDerivedSwapInfo(state: SwapState): SwapInfo { useMemo(() => [inputCurrency ?? undefined, outputCurrency ?? undefined], [inputCurrency, outputCurrency]), ) - const isExactIn: boolean = independentField === CurrencyField.INPUT + const isExactIn: boolean = independentField === Field.INPUT const parsedAmount = useMemo( () => tryParseCurrencyAmount(typedValue, (isExactIn ? inputCurrency : outputCurrency) ?? undefined), [inputCurrency, isExactIn, outputCurrency, typedValue], @@ -188,16 +188,16 @@ export function useDerivedSwapInfo(state: SwapState): SwapInfo { const currencyBalances = useMemo( () => ({ - [CurrencyField.INPUT]: relevantTokenBalances[0], - [CurrencyField.OUTPUT]: relevantTokenBalances[1], + [Field.INPUT]: relevantTokenBalances[0], + [Field.OUTPUT]: relevantTokenBalances[1], }), [relevantTokenBalances], ) - const currencies: { [field in CurrencyField]?: Currency } = useMemo( + const currencies: { [field in Field]?: Currency } = useMemo( () => ({ - [CurrencyField.INPUT]: inputCurrency, - [CurrencyField.OUTPUT]: outputCurrency, + [Field.INPUT]: inputCurrency, + [Field.OUTPUT]: outputCurrency, }), [inputCurrency, outputCurrency], ) @@ -220,14 +220,25 @@ export function useDerivedSwapInfo(state: SwapState): SwapInfo { isClassicTrade(trade.trade) && (nativeCurrencyBalanceUSD ?? 0) < (trade.trade.totalGasUseEstimateUSDWithBuffer ?? 0) const { isDisconnected } = useAccount() + const accountsCTAExperimentGroup = useExperimentGroupName(Experiments.AccountCTAs) + const isSignIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.SignInSignUp + const isLogIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.LogInCreateAccount + const inputError = useMemo(() => { let inputError: ReactNode | undefined if (!account.isConnected) { - inputError = isDisconnected ? : + const disconnectedInputError = isSignIn ? ( + + ) : isLogIn ? ( + + ) : ( + + ) + inputError = isDisconnected ? disconnectedInputError : } - if (!currencies[CurrencyField.INPUT] || !currencies[CurrencyField.OUTPUT]) { + if (!currencies[Field.INPUT] || !currencies[Field.OUTPUT]) { inputError = inputError ?? } @@ -247,10 +258,7 @@ export function useDerivedSwapInfo(state: SwapState): SwapInfo { } // compare input balance to max input based on version - const [balanceIn, maxAmountIn] = [ - currencyBalances[CurrencyField.INPUT], - trade?.trade?.maximumAmountIn(allowedSlippage), - ] + const [balanceIn, maxAmountIn] = [currencyBalances[Field.INPUT], trade?.trade?.maximumAmountIn(allowedSlippage)] if (balanceIn && maxAmountIn && balanceIn.lessThan(maxAmountIn)) { inputError = ( @@ -272,6 +280,8 @@ export function useDerivedSwapInfo(state: SwapState): SwapInfo { currencyBalances, trade?.trade, allowedSlippage, + isSignIn, + isLogIn, isDisconnected, nativeCurrency.symbol, ]) @@ -386,7 +396,7 @@ export function useInitialCurrencyState(): { initialInputCurrency?: Currency initialOutputCurrency?: Currency initialTypedValue?: string - initialField?: CurrencyField + initialField?: Field initialChainId: InterfaceChainId initialCurrencyLoading: boolean } { @@ -445,8 +455,8 @@ export function useInitialCurrencyState(): { const initialOutputCurrency = useCurrency(initialOutputCurrencyAddress, initialChainId) const initialTypedValue = initialInputCurrency || initialOutputCurrency ? parsedCurrencyState.value : undefined const initialField = - initialTypedValue && parsedCurrencyState.field && parsedCurrencyState.field in CurrencyField - ? CurrencyField[parsedCurrencyState.field as keyof typeof CurrencyField] + initialTypedValue && parsedCurrencyState.field && parsedCurrencyState.field in Field + ? Field[parsedCurrencyState.field as keyof typeof Field] : undefined return { diff --git a/apps/web/src/state/swap/types.ts b/apps/web/src/state/swap/types.ts index 21a88263666..66e80ee9b08 100644 --- a/apps/web/src/state/swap/types.ts +++ b/apps/web/src/state/swap/types.ts @@ -1,13 +1,13 @@ import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' +import { Field } from 'components/swap/constants' import { Dispatch, ReactNode, SetStateAction, createContext } from 'react' import { InterfaceTrade, RouterPreference, TradeState } from 'state/routing/types' import { InterfaceChainId, UniverseChainId } from 'uniswap/src/types/chains' -import { CurrencyField } from 'uniswap/src/types/currency' import { SwapTab } from 'uniswap/src/types/screens/interface' export type SwapInfo = { - currencies: { [field in CurrencyField]?: Currency } - currencyBalances: { [field in CurrencyField]?: CurrencyAmount } + currencies: { [field in Field]?: Currency } + currencyBalances: { [field in Field]?: CurrencyAmount } inputTax: Percent outputTax: Percent outputFeeFiatValue?: number @@ -44,7 +44,7 @@ export const EMPTY_DERIVED_SWAP_INFO: SwapInfo = Object.freeze({ export const initialSwapState: SwapState = { typedValue: '', - independentField: CurrencyField.INPUT, + independentField: Field.INPUT, } export const SwapContext = createContext({ @@ -113,7 +113,7 @@ export interface CurrencyState { } export interface SwapState { - readonly independentField: CurrencyField + readonly independentField: Field readonly typedValue: string routerPreferenceOverride?: RouterPreference.API } diff --git a/apps/web/src/test-utils/bundle-size-test.ts b/apps/web/src/test-utils/bundle-size-test.ts index 1ad4d34d269..1e3500cf7ed 100644 --- a/apps/web/src/test-utils/bundle-size-test.ts +++ b/apps/web/src/test-utils/bundle-size-test.ts @@ -32,8 +32,8 @@ const entryGzipSize = report.reduce( 0, ) -// somewhat arbitrary, based on current size (9/19/2024) -const limit = 2_185_000 +// somewhat arbitrary, based on current size (9/17/2024) +const limit = 2_165_000 if (entryGzipSize > limit) { console.error(`Bundle size has grown too big! Entry JS size is ${entryGzipSize}, over the limit of ${limit}.`) diff --git a/apps/web/src/theme/index.tsx b/apps/web/src/theme/index.tsx index b570a7ea807..d6827ae8d6b 100644 --- a/apps/web/src/theme/index.tsx +++ b/apps/web/src/theme/index.tsx @@ -9,6 +9,8 @@ import { useIsDarkMode } from 'theme/components/ThemeToggle' import { darkDeprecatedTheme, lightDeprecatedTheme } from 'theme/deprecatedColors' import { getAccent2, getNeutralContrast } from 'theme/utils' +export const NAV_HEIGHT = 72 + export const MEDIA_WIDTHS = { deprecated_upToExtraSmall: 500, deprecated_upToSmall: 720, diff --git a/apps/web/src/tracing/errors.ts b/apps/web/src/tracing/errors.ts index c051772e891..3ddf42edec8 100644 --- a/apps/web/src/tracing/errors.ts +++ b/apps/web/src/tracing/errors.ts @@ -1,6 +1,6 @@ import { ClientOptions, ErrorEvent, EventHint } from '@sentry/types' import { ProviderRpcError } from '@web3-react/types' -import { wagmiConfig } from 'components/Web3Provider/wagmiConfig' +import { wagmiConfig } from 'components/Web3Provider/wagmi' import { didUserReject } from 'utils/swapErrorToUserReadableMessage' import { getAccount } from 'wagmi/actions' diff --git a/apps/web/src/types/position.ts b/apps/web/src/types/position.d.ts similarity index 84% rename from apps/web/src/types/position.ts rename to apps/web/src/types/position.d.ts index c0ccf926836..bce78b196ce 100644 --- a/apps/web/src/types/position.ts +++ b/apps/web/src/types/position.d.ts @@ -15,8 +15,3 @@ export interface PositionDetails { tokensOwed0: BigNumber tokensOwed1: BigNumber } - -export enum PositionField { - TOKEN0 = 'TOKEN0', - TOKEN1 = 'TOKEN1', -} diff --git a/apps/web/src/utils/chains.tsx b/apps/web/src/utils/chains.tsx index eab8b8d7852..5bb86f45347 100644 --- a/apps/web/src/utils/chains.tsx +++ b/apps/web/src/utils/chains.tsx @@ -10,7 +10,7 @@ function getChainIdFromName(name: string) { export function getParsedChainId(parsedQs?: ParsedQs) { const chain = parsedQs?.chain if (!chain || typeof chain !== 'string') { - return undefined + return } return getChainIdFromName(chain) diff --git a/apps/web/src/utils/formatNumbers.test.ts b/apps/web/src/utils/formatNumbers.test.ts index a0061539023..9153c077465 100644 --- a/apps/web/src/utils/formatNumbers.test.ts +++ b/apps/web/src/utils/formatNumbers.test.ts @@ -1,20 +1,24 @@ import { renderHook } from '@testing-library/react' import { CurrencyAmount, Percent } from '@uniswap/sdk-core' +import { useLocalCurrencyConversionRate } from 'graphql/data/ConversionRate' import { useActiveLocalCurrency } from 'hooks/useActiveLocalCurrency' import { useActiveLocale } from 'hooks/useActiveLocale' import { mocked } from 'test-utils/mocked' import { USDC_MAINNET } from 'uniswap/src/constants/tokens' import { Currency } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { DEFAULT_LOCAL_CURRENCY, FiatCurrency } from 'uniswap/src/features/fiatCurrency/constants' -import { useAppFiatCurrency } from 'uniswap/src/features/fiatCurrency/hooks' import { Locale } from 'uniswap/src/features/language/constants' import { NumberType, useFormatter } from 'utils/formatNumbers' jest.mock('hooks/useActiveLocale') jest.mock('hooks/useActiveLocalCurrency') -jest.mock('uniswap/src/features/fiatCurrency/hooks') +jest.mock('graphql/data/ConversionRate') describe('formatNumber', () => { + beforeEach(() => { + mocked(useLocalCurrencyConversionRate).mockReturnValue({ data: 1.0, isLoading: false }) + }) + it('formats token reference numbers correctly', () => { const { formatNumber } = renderHook(() => useFormatter()).result.current @@ -310,6 +314,10 @@ describe('formatNumber', () => { }) describe('formatUSDPrice', () => { + beforeEach(() => { + mocked(useLocalCurrencyConversionRate).mockReturnValue({ data: 1.0, isLoading: false }) + }) + it('format fiat price correctly', () => { const { formatFiatPrice } = renderHook(() => useFormatter()).result.current @@ -346,6 +354,10 @@ describe('formatUSDPrice', () => { }) describe('formatPercent', () => { + beforeEach(() => { + mocked(useLocalCurrencyConversionRate).mockReturnValue({ data: 1.0, isLoading: false }) + }) + it('should correctly format undefined', () => { const { formatPercent } = renderHook(() => useFormatter()).result.current @@ -375,6 +387,10 @@ describe('formatPercent', () => { }) describe('formatReviewSwapCurrencyAmount', () => { + beforeEach(() => { + mocked(useLocalCurrencyConversionRate).mockReturnValue({ data: 1.0, isLoading: false }) + }) + it('should use TokenTx formatting under a default length', () => { const { formatReviewSwapCurrencyAmount } = renderHook(() => useFormatter()).result.current @@ -407,6 +423,10 @@ describe('formatReviewSwapCurrencyAmount', () => { }) describe('formatDelta', () => { + beforeEach(() => { + mocked(useLocalCurrencyConversionRate).mockReturnValue({ data: 1.0, isLoading: false }) + }) + it.each([[null], [undefined], [Infinity], [NaN]])('should correctly format %p', (value) => { const { formatDelta } = renderHook(() => useFormatter()).result.current @@ -437,15 +457,25 @@ describe('formatDelta', () => { describe('formatToFiatAmount', () => { it('should return default values when undefined', () => { + mocked(useLocalCurrencyConversionRate).mockReturnValue({ data: 1, isLoading: false }) const { convertToFiatAmount } = renderHook(() => useFormatter()).result.current - expect(convertToFiatAmount(1)).toStrictEqual({ amount: 1.0, currency: DEFAULT_LOCAL_CURRENCY }) + expect(convertToFiatAmount()).toStrictEqual({ amount: 1.0, currency: DEFAULT_LOCAL_CURRENCY }) }) it('should return input amount for same currency', () => { - mocked(useAppFiatCurrency).mockReturnValue(FiatCurrency.UnitedStatesDollar) + mocked(useActiveLocalCurrency).mockReturnValue(FiatCurrency.UnitedStatesDollar) + mocked(useLocalCurrencyConversionRate).mockReturnValue({ data: 1, isLoading: false }) const { convertToFiatAmount } = renderHook(() => useFormatter()).result.current expect(convertToFiatAmount(12)).toStrictEqual({ amount: 12.0, currency: Currency.Usd }) }) + + it('should correctly convert different currency', () => { + mocked(useActiveLocalCurrency).mockReturnValue(FiatCurrency.CanadianDollar) + mocked(useLocalCurrencyConversionRate).mockReturnValue({ data: 0.5, isLoading: false }) + const { convertToFiatAmount } = renderHook(() => useFormatter()).result.current + + expect(convertToFiatAmount(12)).toStrictEqual({ amount: 6.0, currency: Currency.Cad }) + }) }) diff --git a/apps/web/src/utils/formatNumbers.ts b/apps/web/src/utils/formatNumbers.ts index 6733fa12442..c90a4a90318 100644 --- a/apps/web/src/utils/formatNumbers.ts +++ b/apps/web/src/utils/formatNumbers.ts @@ -1,13 +1,13 @@ import { formatEther as ethersFormatEther } from '@ethersproject/units' import { Currency, CurrencyAmount, Percent, Price, Token } from '@uniswap/sdk-core' import { getCurrencySymbolDisplayType } from 'constants/localCurrencies' +import { useLocalCurrencyConversionRate } from 'graphql/data/ConversionRate' import { useActiveLocalCurrency } from 'hooks/useActiveLocalCurrency' import { useActiveLocale } from 'hooks/useActiveLocale' import usePrevious from 'hooks/usePrevious' import { useCallback, useMemo } from 'react' import { Bound } from 'state/mint/v3/actions' import { DEFAULT_LOCAL_CURRENCY, FiatCurrency } from 'uniswap/src/features/fiatCurrency/constants' -import { useLocalizationContext } from 'uniswap/src/features/language/LocalizationContext' import { DEFAULT_LOCALE, Locale } from 'uniswap/src/features/language/constants' type Nullish = T | null | undefined @@ -727,6 +727,23 @@ function formatReviewSwapCurrencyAmount(amount: CurrencyAmount, locale return formattedAmount } +function convertToFiatAmount( + amount = 1, + toCurrency = DEFAULT_LOCAL_CURRENCY, + conversionRate = 1, +): { amount: number; currency: FiatCurrency } { + const defaultResult = { amount, currency: DEFAULT_LOCAL_CURRENCY } + + if (defaultResult.currency === toCurrency) { + return defaultResult + } + + return { + amount: amount * conversionRate, + currency: toCurrency, + } +} + // TODO: https://linear.app/uniswap/issue/WEB-3495/import-useasyncdata-from-mobile type FiatCurrencyComponents = { groupingSeparator: string @@ -818,13 +835,16 @@ function handleFallbackCurrency( // Constructs an object that injects the correct locale and local currency into each of the above formatter functions. export function useFormatter() { const { formatterLocale, formatterLocalCurrency } = useFormatterLocales() - const { convertFiatAmount, conversionRate: localCurrencyConversionRate } = useLocalizationContext() + + const formatterLocalCurrencyIsUSD = formatterLocalCurrency === FiatCurrency.UnitedStatesDollar + const { data: localCurrencyConversionRate, isLoading: localCurrencyConversionRateIsLoading } = + useLocalCurrencyConversionRate(formatterLocalCurrency, formatterLocalCurrencyIsUSD) const previousSelectedCurrency = usePrevious(formatterLocalCurrency) const previousConversionRate = usePrevious(localCurrencyConversionRate) - const shouldFallbackToPrevious = !localCurrencyConversionRate - const shouldFallbackToUSD = !localCurrencyConversionRate + const shouldFallbackToPrevious = !localCurrencyConversionRate && localCurrencyConversionRateIsLoading + const shouldFallbackToUSD = !localCurrencyConversionRate && !localCurrencyConversionRateIsLoading const currencyToFormatWith = handleFallbackCurrency( formatterLocalCurrency, previousSelectedCurrency, @@ -928,6 +948,11 @@ export function useFormatter() { [currencyToFormatWith, formatterLocale], ) + const convertToFiatAmountWithLocales = useCallback( + (amount?: number) => convertToFiatAmount(amount, currencyToFormatWith, localCurrencyConversionRateToFormatWith), + [currencyToFormatWith, localCurrencyConversionRateToFormatWith], + ) + const formatConvertedFiatNumberOrString = useCallback( (options: Omit) => formatNumberOrString({ @@ -941,7 +966,7 @@ export function useFormatter() { return useMemo( () => ({ - convertToFiatAmount: convertFiatAmount, + convertToFiatAmount: convertToFiatAmountWithLocales, formatConvertedFiatNumberOrString, formatCurrencyAmount: formatCurrencyAmountWithLocales, formatEther: formatEtherwithLocales, @@ -955,7 +980,7 @@ export function useFormatter() { formatTickPrice: formatTickPriceWithLocales, }), [ - convertFiatAmount, + convertToFiatAmountWithLocales, formatConvertedFiatNumberOrString, formatCurrencyAmountWithLocales, formatDeltaWithLocales, diff --git a/apps/web/src/utils/getFetchPolicyForKey.ts b/apps/web/src/utils/getFetchPolicyForKey.ts new file mode 100644 index 00000000000..ca6b68bc55f --- /dev/null +++ b/apps/web/src/utils/getFetchPolicyForKey.ts @@ -0,0 +1,16 @@ +import { WatchQueryFetchPolicy } from '@apollo/client' + +const keys = new Map() + +export const getFetchPolicyForKey = (key: string, expirationMs: number): WatchQueryFetchPolicy => { + const lastFetchTimestamp = keys.get(key) + const diffFromNow = lastFetchTimestamp ? Date.now() - lastFetchTimestamp : Number.MAX_SAFE_INTEGER + let fetchPolicy: WatchQueryFetchPolicy = 'cache-first' + + if (diffFromNow > expirationMs) { + keys.set(key, Date.now()) + fetchPolicy = 'network-only' + } + + return fetchPolicy +} diff --git a/apps/web/src/utils/prices.ts b/apps/web/src/utils/prices.ts index 83332c1d1a7..b5af386ab6a 100644 --- a/apps/web/src/utils/prices.ts +++ b/apps/web/src/utils/prices.ts @@ -112,7 +112,7 @@ export function getPriceImpactWarning(priceImpact: Percent): 'warning' | 'error' if (priceImpact.greaterThan(ALLOWED_PRICE_IMPACT_MEDIUM)) { return 'warning' } - return undefined + return } export function getPriceImpactColor(priceImpact: Percent): keyof DefaultTheme | undefined { diff --git a/apps/web/src/utils/transfer.ts b/apps/web/src/utils/transfer.ts index 834052f3bb1..70af6f4d74c 100644 --- a/apps/web/src/utils/transfer.ts +++ b/apps/web/src/utils/transfer.ts @@ -39,7 +39,7 @@ async function getTransferTransaction(transferInfo: TransferInfo): Promise - - + + + + + + + diff --git a/packages/ui/src/assets/icons/ellipsis.svg b/packages/ui/src/assets/icons/ellipsis.svg index f40f628bbc1..86dd1f50c57 100644 --- a/packages/ui/src/assets/icons/ellipsis.svg +++ b/packages/ui/src/assets/icons/ellipsis.svg @@ -1,5 +1,6 @@ - + + diff --git a/packages/ui/src/assets/icons/triple-dots.svg b/packages/ui/src/assets/icons/triple-dots.svg new file mode 100644 index 00000000000..b0a623fe156 --- /dev/null +++ b/packages/ui/src/assets/icons/triple-dots.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/ui/src/assets/index.ts b/packages/ui/src/assets/index.ts index f072a7c08d3..d724f04a8d5 100644 --- a/packages/ui/src/assets/index.ts +++ b/packages/ui/src/assets/index.ts @@ -34,7 +34,6 @@ export const ETH_LOGO = require('./logos/png/eth-logo.png') export const OPENSEA_LOGO = require('./logos/png/opensea-logo.png') export const ENS_LOGO = require('./logos/png/ens-logo.png') export const FROGGY = require('./graphics/froggy.png') -export const ACROSS_LOGO = require('./logos/png/across-logo.png') export const CEX_TRANSFER_MODAL_BG_LIGHT = require('./graphics/cex-transfer-modal-bg-light.png') export const CEX_TRANSFER_MODAL_BG_DARK = require('./graphics/cex-transfer-modal-bg-dark.png') diff --git a/packages/ui/src/assets/logos/png/across-logo.png b/packages/ui/src/assets/logos/png/across-logo.png deleted file mode 100644 index 3eac46903fba5cf1d225d7aabfae16715a2d931a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1214 zcmV;v1VQ_WP)wK~#7F%~?NB z6hRb!Z|;OcG&vJ3u<>X_LU9;BfcOot)&#AzxCkU#VFDylX(9*(R$^g|-$3{P#G@d9 z4bVt|#U%>{u-fU%x2U}d(ee-}~$At8u#t#&#JoDTtqAxHv*G6J7VBPO;0 zhqwu2jbAt|5OFDEnA35E#1c?C+n&@-+yjPF3s?H4qc)EuVC;CaP|M)5aFs!50cgHt zO#Uc}HCR}KSGDbt8e>0OMV`O`3iQs>$@XwqTcrSU8PniP7wR&Bpm*|R>9z_4x{&4X zd11=N@sZ;~ zmh0e7P+yz8O+0)3Dijyr!nM11KnHo7IE`0aoDk!82lNoG)X~v9i@g=Pb1Yymrd+P7 z`+wxGF6bz=CEVow-s6RErPJz|eJ3pt_VraSOlk@LvAX5g4$xT8NAC75E#wIdSrJPoTO2fjTqJl0wc8v?i|7GXLQiCI5Jui= zql-L&=d}vB3@|bSXo5N%j@~8?7;>&f0IlcI1Xw40a}HWSUWW*(CD;irCzJ@Y0!5R#o|~Y9 zyh?=oJ$|4 zRpcpjnD4yT+xW~Ajb;u0SmjD&3Ekugwq=8X6{^~}pLzt4dC)Y+q5bgOujJ%=9+>ay zUm{)8RzK66Q@M<%2gHQTr2>$U5zq#Ucs7@twF?)K zdqP4;w-R|(nb}TS1g9|G;Hyc9*N4ymM-1gzMXC}x6q@IYn2^9LB9~bfq5B@40_h-? clyoEh10*okSY%xlU;qFB07*qoM6N<$f_b7LY5)KL diff --git a/packages/ui/src/components/UniversalImage/UniversalImage.tsx b/packages/ui/src/components/UniversalImage/UniversalImage.tsx index 65ee119964e..cb692baa0ea 100644 --- a/packages/ui/src/components/UniversalImage/UniversalImage.tsx +++ b/packages/ui/src/components/UniversalImage/UniversalImage.tsx @@ -19,7 +19,6 @@ export function UniversalImage({ fallback, fastImage = false, testID, - onLoad, allowLocalUri = false, }: UniversalImageProps): JSX.Element | null { // Allow calculation of fields as needed @@ -110,7 +109,6 @@ export function UniversalImage({ alignItems="center" backgroundColor={style?.image?.backgroundColor as ColorTokens} borderRadius={style?.image?.borderRadius} - verticalAlign={style?.image?.verticalAlign} height={size.height} overflow="hidden" testID={testID ? `svg-${testID}` : undefined} @@ -130,7 +128,6 @@ export function UniversalImage({ style={style?.image} testID={testID ? `img-${testID}` : undefined} uri={imageHttpUrl} - onLoad={onLoad} /> ) } diff --git a/packages/ui/src/components/UniversalImage/internal/PlainImage.native.tsx b/packages/ui/src/components/UniversalImage/internal/PlainImage.native.tsx index b9b1b2ab0e4..37baae28de2 100644 --- a/packages/ui/src/components/UniversalImage/internal/PlainImage.native.tsx +++ b/packages/ui/src/components/UniversalImage/internal/PlainImage.native.tsx @@ -2,7 +2,7 @@ import { useState } from 'react' import { Image } from 'react-native' import { PlainImageProps } from 'ui/src/components/UniversalImage/types' -export function PlainImage({ uri, size, fallback, resizeMode, style, testID, onLoad }: PlainImageProps): JSX.Element { +export function PlainImage({ uri, size, fallback, resizeMode, style, testID }: PlainImageProps): JSX.Element { const [hasError, setHasError] = useState(false) if (hasError && fallback) { @@ -20,7 +20,6 @@ export function PlainImage({ uri, size, fallback, resizeMode, style, testID, onL onError={() => { setHasError(true) }} - onLoad={onLoad} /> ) } diff --git a/packages/ui/src/components/UniversalImage/internal/PlainImage.tsx b/packages/ui/src/components/UniversalImage/internal/PlainImage.tsx index 6771ab6eed7..94e932658d4 100644 --- a/packages/ui/src/components/UniversalImage/internal/PlainImage.tsx +++ b/packages/ui/src/components/UniversalImage/internal/PlainImage.tsx @@ -1,6 +1,37 @@ -import { PlainImageProps } from 'ui/src/components/UniversalImage/types' -import { PlatformSplitStubError } from 'utilities/src/errors' +import { useState } from 'react' +import { PlainImageProps, UniversalImageResizeMode } from 'ui/src/components/UniversalImage/types' +import { Flex } from 'ui/src/components/layout/Flex' +import { isTestEnv } from 'utilities/src/environment/env' -export function PlainImage(_props: PlainImageProps): JSX.Element { - throw new PlatformSplitStubError('PlainImage') +export function PlainImage({ uri, size, fallback, resizeMode, style, testID }: PlainImageProps): JSX.Element { + const [hasError, setHasError] = useState(false) + + // TODO cover all cases better + const objectFit = + resizeMode === UniversalImageResizeMode.Contain || resizeMode === UniversalImageResizeMode.Cover + ? resizeMode + : 'contain' + + const imgElement = ( + { + setHasError(true) + }} + /> + ) + + if (hasError && fallback) { + return fallback + } + + // TODO(MOB-3485): remove test run special casing + if (isTestEnv()) { + return {imgElement} + } else { + return imgElement + } } diff --git a/packages/ui/src/components/UniversalImage/internal/PlainImage.web.tsx b/packages/ui/src/components/UniversalImage/internal/PlainImage.web.tsx deleted file mode 100644 index 90b4bd3dc08..00000000000 --- a/packages/ui/src/components/UniversalImage/internal/PlainImage.web.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { useState } from 'react' -import { PlainImageProps, UniversalImageResizeMode } from 'ui/src/components/UniversalImage/types' -import { Flex } from 'ui/src/components/layout/Flex' -import { isTestEnv } from 'utilities/src/environment/env' - -export function PlainImage({ uri, size, fallback, resizeMode, style, testID, onLoad }: PlainImageProps): JSX.Element { - const [hasError, setHasError] = useState(false) - - // TODO cover all cases better - const objectFit = - resizeMode === UniversalImageResizeMode.Contain || resizeMode === UniversalImageResizeMode.Cover - ? resizeMode - : 'contain' - - const imgElement = ( - { - setHasError(true) - }} - onLoad={onLoad} - /> - ) - - if (hasError && fallback) { - return fallback - } - - // TODO(MOB-3485): remove test run special casing - if (isTestEnv()) { - return {imgElement} - } else { - return imgElement - } -} diff --git a/packages/ui/src/components/UniversalImage/types.ts b/packages/ui/src/components/UniversalImage/types.ts index 01274f02d68..2682ed97841 100644 --- a/packages/ui/src/components/UniversalImage/types.ts +++ b/packages/ui/src/components/UniversalImage/types.ts @@ -1,10 +1,9 @@ import type { ImageRequireSource } from 'react-native' -import type { FlexProps } from 'ui/src/components/layout/Flex' +import { FlexProps } from 'ui/src/components/layout/Flex' export interface UniversalImageStyle { backgroundColor?: string borderRadius?: number - verticalAlign?: FlexProps['verticalAlign'] } export enum UniversalImageResizeMode { @@ -40,7 +39,6 @@ export interface UniversalImageProps { fastImage?: boolean testID?: string allowLocalUri?: boolean - onLoad?: () => void } export interface PlainImageProps { @@ -50,7 +48,6 @@ export interface PlainImageProps { style?: UniversalImageStyle resizeMode?: UniversalImageResizeMode testID?: string - onLoad?: () => void } export type FastImageWrapperProps = PlainImageProps & { diff --git a/packages/ui/src/components/UniversalImage/utils.ts b/packages/ui/src/components/UniversalImage/utils.ts index d920f2b2bd8..c114edd6add 100644 --- a/packages/ui/src/components/UniversalImage/utils.ts +++ b/packages/ui/src/components/UniversalImage/utils.ts @@ -51,7 +51,6 @@ export function useSvgData(uri: string, autoplay = false): SvgData | undefined { return await fetchSVG(uri, autoplay, controllerRef.current.signal) } catch (error) { logger.error(error, { tags: { file: 'WebSvgUri', function: 'fetchSvg' }, extra: { uri } }) - return undefined } }, [autoplay, uri]) diff --git a/packages/ui/src/components/checkbox/LabeledCheckbox.tsx b/packages/ui/src/components/checkbox/LabeledCheckbox.tsx index 062658e3f8a..8788fd10155 100644 --- a/packages/ui/src/components/checkbox/LabeledCheckbox.tsx +++ b/packages/ui/src/components/checkbox/LabeledCheckbox.tsx @@ -45,8 +45,8 @@ export function LabeledCheckbox({ {checkboxPosition === 'start' && } {text && ( - - {textElement} + + {textElement} )} {checkboxPosition === 'end' && } diff --git a/packages/ui/src/components/icons/Check.tsx b/packages/ui/src/components/icons/Check.tsx index e2589206c71..75f46c587d0 100644 --- a/packages/ui/src/components/icons/Check.tsx +++ b/packages/ui/src/components/icons/Check.tsx @@ -1,4 +1,4 @@ -import { Line, Svg } from 'react-native-svg' +import { G, Path, Svg } from 'react-native-svg' // eslint-disable-next-line no-relative-import-paths/no-relative-import-paths import { createIcon } from '../factories/createIcon' @@ -6,9 +6,13 @@ import { createIcon } from '../factories/createIcon' export const [Check, AnimatedCheck] = createIcon({ name: 'Check', getIcon: (props) => ( - - - + + + + + + ), + defaultFill: '#9B9B9B', }) diff --git a/packages/ui/src/components/icons/Ellipsis.tsx b/packages/ui/src/components/icons/Ellipsis.tsx index ad262f84f15..34fbbec0deb 100644 --- a/packages/ui/src/components/icons/Ellipsis.tsx +++ b/packages/ui/src/components/icons/Ellipsis.tsx @@ -6,7 +6,7 @@ import { createIcon } from '../factories/createIcon' export const [Ellipsis, AnimatedEllipsis] = createIcon({ name: 'Ellipsis', getIcon: (props) => ( - + - - - ) -} diff --git a/packages/ui/src/components/icons/TripleDots.tsx b/packages/ui/src/components/icons/TripleDots.tsx new file mode 100644 index 00000000000..6fe639adbc8 --- /dev/null +++ b/packages/ui/src/components/icons/TripleDots.tsx @@ -0,0 +1,33 @@ +import { Path, Svg } from 'react-native-svg' + +// eslint-disable-next-line no-relative-import-paths/no-relative-import-paths +import { createIcon } from '../factories/createIcon' + +export const [TripleDots, AnimatedTripleDots] = createIcon({ + name: 'TripleDots', + getIcon: (props) => ( + + + + + + ), +}) diff --git a/packages/ui/src/components/icons/Unitag.tsx b/packages/ui/src/components/icons/Unitag.tsx index 5961cea86e5..69d30a23003 100644 --- a/packages/ui/src/components/icons/Unitag.tsx +++ b/packages/ui/src/components/icons/Unitag.tsx @@ -12,24 +12,10 @@ function _Unitag({ size = '$icon.24' }: { size: IconSizeTokens | number }): JSX. const sizeNumber = typeof size === 'number' ? size : getTokenValue(size) const universalImageSize = { height: sizeNumber, width: sizeNumber } - const getUri = () => { - if (isDarkMode) { - return isMobileApp ? UNITAG_DARK : UNITAG_DARK_SMALL - } - return isMobileApp ? UNITAG_LIGHT : UNITAG_LIGHT_SMALL - } - - return ( - + return isDarkMode ? ( + + ) : ( + ) } diff --git a/packages/ui/src/components/icons/exported.ts b/packages/ui/src/components/icons/exported.ts index 81b422f8923..1b87074dfcf 100644 --- a/packages/ui/src/components/icons/exported.ts +++ b/packages/ui/src/components/icons/exported.ts @@ -203,6 +203,7 @@ export * from './Trash' export * from './TrashFilled' export * from './TrendDown' export * from './TrendUp' +export * from './TripleDots' export * from './UniswapLogo' export * from './UniswapX' export * from './UserSquare' diff --git a/packages/ui/src/components/icons/index.tsx b/packages/ui/src/components/icons/index.tsx index d34e2a9a755..3da096b59b6 100644 --- a/packages/ui/src/components/icons/index.tsx +++ b/packages/ui/src/components/icons/index.tsx @@ -1,6 +1,5 @@ export { BackArrow } from './BackArrow' export { AnimatedCaretChange, Caret } from './Caret' -export { HeartWithFill } from './HeartWithFill' export { OSDynamicCloudIcon } from './OSDynamicCloudIcon' export { OnboardingUnicon } from './OnboardingUnicon' export { AnimatedQuestionInCircleFilled, QuestionInCircleFilled } from './QuestionInCircleFilled' diff --git a/packages/ui/src/components/menu/ContextMenu.tsx b/packages/ui/src/components/menu/ContextMenu.tsx index 7723b0c9f57..9caee05ed64 100644 --- a/packages/ui/src/components/menu/ContextMenu.tsx +++ b/packages/ui/src/components/menu/ContextMenu.tsx @@ -65,7 +65,7 @@ export function ContextMenu({ // Note: Overlay needs to be rendered in portal since parent transforms don't let fixed elements target the viewport // see: https://stackoverflow.com/a/15256339 return ( - + {/* OVERLAY */} {/* Conditional rendering needs to be used here instead of CSS so that portals aren't duplicated */} {showMenu && ( diff --git a/packages/ui/src/components/modal/AdaptiveWebModal.tsx b/packages/ui/src/components/modal/AdaptiveWebModal.tsx index 17d9f4addf8..6740fe01781 100644 --- a/packages/ui/src/components/modal/AdaptiveWebModal.tsx +++ b/packages/ui/src/components/modal/AdaptiveWebModal.tsx @@ -56,7 +56,6 @@ export function WebBottomSheet({ isOpen, onClose, children, ...rest }: ModalProp pb="$spacing16" pt="$spacing8" width="100%" - backgroundColor="$transparent" onMouseDown={() => setHandlePressed(true)} onMouseUp={() => setHandlePressed(false)} > diff --git a/packages/ui/src/components/swipeablecards/SwipeableCard.web.tsx b/packages/ui/src/components/swipeablecards/SwipeableCard.web.tsx index c55ab3a7a0d..73cc07b199e 100644 --- a/packages/ui/src/components/swipeablecards/SwipeableCard.web.tsx +++ b/packages/ui/src/components/swipeablecards/SwipeableCard.web.tsx @@ -1,58 +1,6 @@ -import { useEffect, useState } from 'react' -import { useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated' -import { AnimatedFlex } from 'ui/src/components/layout/AnimatedFlex' -import { SWIPEABLE_CARD_Y_OFFSET, SwipeableCardProps } from 'ui/src/components/swipeablecards/props' +import { SwipeableCardProps } from 'ui/src/components/swipeablecards/props' +import { NotImplementedError } from 'utilities/src/errors' -function getScale(stackIndex: number): number { - return 1 - stackIndex * 0.025 -} - -// TODO WALL-4684 - Figure out how best way to swipe functionality for web/extension -export function SwipeableCard({ - children, - stackIndex, - cardHeight, - onPress, - onLayout, -}: SwipeableCardProps): JSX.Element { - const initialYOffset = stackIndex * SWIPEABLE_CARD_Y_OFFSET - const initialScale = getScale(stackIndex) - - const yOffset = useSharedValue(initialYOffset) - const scale = useSharedValue(initialScale) - const panOffset = useSharedValue(0) - - const [height, setHeight] = useState(0) - const [targetYOffset, setTargetYOffset] = useState(initialYOffset) - - useEffect(() => { - onLayout({ height, yOffset: targetYOffset }) - }, [height, onLayout, targetYOffset]) - - useEffect(() => { - const nextYOffset = stackIndex * SWIPEABLE_CARD_Y_OFFSET - - setTargetYOffset(nextYOffset) - yOffset.value = withSpring(nextYOffset) - scale.value = withSpring(getScale(stackIndex)) - panOffset.value = 0 - }, [panOffset, scale, stackIndex, yOffset]) - - const animatedStyle = useAnimatedStyle(() => { - return { - transform: [{ translateX: panOffset.value }, { translateY: yOffset.value }, { scale: scale.value }], - cursor: onPress ? 'pointer' : undefined, - } - }, [panOffset, scale, yOffset, onPress]) - - return ( - setHeight(event.nativeEvent.layout.height)} - onPress={onPress} - > - {children} - - ) +export function SwipeableCard(_props: SwipeableCardProps): JSX.Element { + throw new NotImplementedError('SwipeableCard') } diff --git a/packages/ui/src/components/swipeablecards/SwipeableCardStack.web.tsx b/packages/ui/src/components/swipeablecards/SwipeableCardStack.web.tsx deleted file mode 100644 index 7c50f3389cf..00000000000 --- a/packages/ui/src/components/swipeablecards/SwipeableCardStack.web.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { useCallback, useState } from 'react' -import { Flex } from 'ui/src/components/layout' -import { SwipeableCard } from 'ui/src/components/swipeablecards/SwipeableCard' -import { - SWIPEABLE_CARD_Y_OFFSET, - SwipeableCardProps, - SwipeableCardStackProps, -} from 'ui/src/components/swipeablecards/props' -import { usePrevious } from 'utilities/src/react/hooks' - -type PickedCardProps = Pick - -// TODO WALL-4684 After figuring out swipe for web, clean up duplicate code with the native version -export function SwipeableCardStack({ - cards, - minCardHeight = 0, - renderCard, - keyExtractor, - onSwiped, -}: SwipeableCardStackProps): JSX.Element { - const firstCard = cards[0] - const [activeKey, setActiveKey] = useState(firstCard ? keyExtractor(firstCard) : '') - - const [containerHeight, setContainerHeight] = useState(minCardHeight + (cards.length - 1) * SWIPEABLE_CARD_Y_OFFSET) - const [cardHeight, setCardHeight] = useState(minCardHeight) - - // Uses active key to track first card for when cards are removed - // If the active card is removed, the next card becomes active or will default to the first card - const keyIndex = cards.findIndex((card) => keyExtractor(card) === activeKey) - const prevIndex = usePrevious(keyIndex) - const activeIndex = keyIndex >= 0 ? keyIndex : prevIndex ? prevIndex + 1 : 0 - - const handleSwiped = useCallback( - (card: T, index: number) => { - const nextIndex = activeIndex === cards.length - 1 ? 0 : activeIndex + 1 - const nextCard = cards[nextIndex] - const nextKey = nextCard ? keyExtractor(nextCard) : '' - - setActiveKey(nextKey) - - onSwiped?.(card, index) - }, - [activeIndex, cards, keyExtractor, onSwiped], - ) - - const handleLayout = useCallback( - ({ height, yOffset }: { height: number; yOffset: number }) => { - setContainerHeight(Math.max(containerHeight, height + yOffset)) - setCardHeight(Math.max(cardHeight, height)) - }, - [cardHeight, containerHeight], - ) - - return ( - - {cards.map((card, index) => { - const stackIndex = (index - activeIndex + cards.length) % cards.length - - return ( - - handleSwiped(card, index)} - > - {renderCard(card, stackIndex)} - - - ) - })} - - ) -} diff --git a/packages/ui/src/components/text/Text.tsx b/packages/ui/src/components/text/Text.tsx index e79a3fd2013..770a62aedd7 100644 --- a/packages/ui/src/components/text/Text.tsx +++ b/packages/ui/src/components/text/Text.tsx @@ -1,10 +1,24 @@ import { PropsWithChildren } from 'react' -import { GetProps, Text as TamaguiText, isWeb, styled } from 'tamagui' +import { GetProps, Text as TamaguiText, TextStyle, isWeb, styled } from 'tamagui' import { Flex } from 'ui/src/components/layout' import { HiddenFromScreenReaders } from 'ui/src/components/text/HiddenFromScreenReaders' import { useEnableFontScaling } from 'ui/src/components/text/useEnableFontScaling' import { Skeleton } from 'ui/src/loading/Skeleton' import { fonts } from 'ui/src/theme/fonts' +import { isAndroid } from 'utilities/src/platform' + +// android fonts appear too far down, tried includeFontPadding: false, but it seems to do nothing +// see: https://stackoverflow.com/questions/41525842/react-native-android-text-component-extra-padding +// instead setting a small negative y, which isn't beautiful but works +function getAndroidTextAdjustmentStyles(variant: keyof typeof fonts): TextStyle | null { + if (isAndroid) { + const fontSize = fonts[variant].fontSize + return { + y: -Math.round(fontSize * 0.036), + } + } + return null +} export const TextFrame = styled(TamaguiText, { fontFamily: '$body', @@ -18,6 +32,7 @@ export const TextFrame = styled(TamaguiText, { lineHeight: '$large', fontWeight: '$book', maxFontSizeMultiplier: fonts.heading1.maxFontSizeMultiplier, + ...getAndroidTextAdjustmentStyles('heading1'), }, heading2: { fontFamily: '$heading', @@ -25,6 +40,7 @@ export const TextFrame = styled(TamaguiText, { lineHeight: '$medium', fontWeight: '$book', maxFontSizeMultiplier: fonts.heading2.maxFontSizeMultiplier, + ...getAndroidTextAdjustmentStyles('heading2'), }, heading3: { fontFamily: '$heading', @@ -32,6 +48,7 @@ export const TextFrame = styled(TamaguiText, { lineHeight: '$small', fontWeight: '$book', maxFontSizeMultiplier: fonts.heading3.maxFontSizeMultiplier, + ...getAndroidTextAdjustmentStyles('heading3'), }, subheading1: { fontFamily: '$subHeading', @@ -39,6 +56,7 @@ export const TextFrame = styled(TamaguiText, { lineHeight: '$large', fontWeight: '$book', maxFontSizeMultiplier: fonts.subheading1.maxFontSizeMultiplier, + ...getAndroidTextAdjustmentStyles('subheading1'), }, subheading2: { fontFamily: '$subHeading', @@ -46,6 +64,7 @@ export const TextFrame = styled(TamaguiText, { lineHeight: '$small', fontWeight: '$book', maxFontSizeMultiplier: fonts.subheading2.maxFontSizeMultiplier, + ...getAndroidTextAdjustmentStyles('subheading2'), }, body1: { fontFamily: '$body', @@ -53,6 +72,7 @@ export const TextFrame = styled(TamaguiText, { lineHeight: '$large', fontWeight: '$book', maxFontSizeMultiplier: fonts.body1.maxFontSizeMultiplier, + ...getAndroidTextAdjustmentStyles('body1'), }, body2: { fontFamily: '$body', @@ -60,6 +80,7 @@ export const TextFrame = styled(TamaguiText, { lineHeight: '$medium', fontWeight: '$book', maxFontSizeMultiplier: fonts.body2.maxFontSizeMultiplier, + ...getAndroidTextAdjustmentStyles('body2'), }, body3: { fontFamily: '$body', @@ -67,6 +88,7 @@ export const TextFrame = styled(TamaguiText, { lineHeight: '$small', fontWeight: '$book', maxFontSizeMultiplier: fonts.body3.maxFontSizeMultiplier, + ...getAndroidTextAdjustmentStyles('body3'), }, body4: { fontFamily: '$body', @@ -74,6 +96,7 @@ export const TextFrame = styled(TamaguiText, { lineHeight: '$micro', fontWeight: '$book', maxFontSizeMultiplier: fonts.body4.maxFontSizeMultiplier, + ...getAndroidTextAdjustmentStyles('body4'), }, buttonLabel1: { fontFamily: '$button', @@ -81,6 +104,7 @@ export const TextFrame = styled(TamaguiText, { lineHeight: '$large', fontWeight: '$medium', maxFontSizeMultiplier: fonts.buttonLabel1.maxFontSizeMultiplier, + ...getAndroidTextAdjustmentStyles('buttonLabel1'), }, buttonLabel2: { fontFamily: '$button', @@ -88,6 +112,7 @@ export const TextFrame = styled(TamaguiText, { lineHeight: '$medium', fontWeight: '$medium', maxFontSizeMultiplier: fonts.buttonLabel2.maxFontSizeMultiplier, + ...getAndroidTextAdjustmentStyles('buttonLabel1'), }, buttonLabel3: { fontFamily: '$button', @@ -95,6 +120,7 @@ export const TextFrame = styled(TamaguiText, { lineHeight: '$small', fontWeight: '$medium', maxFontSizeMultiplier: fonts.buttonLabel3.maxFontSizeMultiplier, + ...getAndroidTextAdjustmentStyles('buttonLabel1'), }, buttonLabel4: { fontFamily: '$button', @@ -102,6 +128,7 @@ export const TextFrame = styled(TamaguiText, { lineHeight: '$micro', fontWeight: '$medium', maxFontSizeMultiplier: fonts.buttonLabel4.maxFontSizeMultiplier, + ...getAndroidTextAdjustmentStyles('buttonLabel2'), }, monospace: { fontFamily: '$body', diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index 8f8d723a930..52c217f6972 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -36,7 +36,6 @@ export type { Adapt, CircleProps, ColorTokens, - GetProps, GetRef, InputProps, PopperProps, diff --git a/packages/ui/src/scripts/componentize-icons.ts b/packages/ui/src/scripts/componentize-icons.ts index 75c27a354b9..eaeeb17e88d 100644 --- a/packages/ui/src/scripts/componentize-icons.ts +++ b/packages/ui/src/scripts/componentize-icons.ts @@ -82,7 +82,6 @@ async function generateSVGComponent(svg: string, fileName: string): Promise { if (!imageUrl) { - return undefined + return } const imageColors = await ImageColors.getColors(imageUrl, { @@ -44,5 +44,5 @@ export async function getExtractedColors( } } - return undefined + return } diff --git a/packages/uniswap/jest-setup.js b/packages/uniswap/jest-setup.js index be374e4588b..f745d4cd185 100644 --- a/packages/uniswap/jest-setup.js +++ b/packages/uniswap/jest-setup.js @@ -8,7 +8,7 @@ import { mockSharedPersistQueryClientProvider } from 'uniswap/src/test/mocks/moc jest.mock('react-native-localize', () => mockRNLocalize) -jest.mock('uniswap/src/features/language/LocalizationContext', () => mockLocalizationContext({})) +jest.mock('uniswap/src/features/language/LocalizationContext', () => mockLocalizationContext) // Use native modal jest.mock('uniswap/src/components/modals/Modal', () => { diff --git a/packages/uniswap/package.json b/packages/uniswap/package.json index 7fe91882ec8..e7dfaba5de4 100644 --- a/packages/uniswap/package.json +++ b/packages/uniswap/package.json @@ -15,8 +15,7 @@ "lint:fix": "eslint . --ext ts,tsx --fix", "test": "jest --passWithNoTests", "tradingapi:schema": "curl https://api.uniswap.org/v2/trade/api.json -o ./src/data/tradingApi/api.json", - "tradingapi:generate": "openapi --input ./src/data/tradingApi/api.json --output ./src/data/tradingApi/__generated__ --client axios --useOptions --exportServices true --exportModels true && yarn tradingapi:add-local-types", - "tradingapi:add-local-types": "node --no-warnings=ExperimentalWarning --loader ts-node/esm ./src/data/tradingApi/modifyTradingApiTypes.mts", + "tradingapi:generate": "openapi --input ./src/data/tradingApi/api.json --output ./src/data/tradingApi/__generated__ --client axios --useOptions --exportServices true --exportModels true", "snapshots": "jest -u", "typecheck": "tsc -b" }, @@ -41,13 +40,13 @@ "@tanstack/react-query": "5.51.16", "@tanstack/react-query-persist-client": "5.51.23", "@typechain/ethers-v5": "7.2.0", - "@uniswap/analytics-events": "2.37.0", + "@uniswap/analytics-events": "2.36.0", "@uniswap/client-explore": "0.0.9", - "@uniswap/client-pools": "0.0.3", + "@uniswap/client-pools": "0.0.0", "@uniswap/permit2-sdk": "1.3.0", "@uniswap/router-sdk": "1.9.2", "@uniswap/sdk-core": "5.3.0", - "@uniswap/uniswapx-sdk": "^2.1.0-beta.14", + "@uniswap/uniswapx-sdk": "^2.1.0-beta.8", "@uniswap/v2-sdk": "4.3.2", "@uniswap/v3-sdk": "3.14.0", "apollo-link-rest": "0.9.0", @@ -120,7 +119,6 @@ "jest-presets": "workspace:^", "react-dom": "18.2.0", "react-native-dotenv": "3.2.0", - "ts-morph": "23.0.0", "tsafe": "1.6.4", "typechain": "5.2.0", "typescript": "5.3.3" diff --git a/packages/uniswap/src/components/ConfirmSwapModal/ProgressIndicator.tsx b/packages/uniswap/src/components/ConfirmSwapModal/ProgressIndicator.tsx index 099c6fb9f61..3bec6edadc4 100644 --- a/packages/uniswap/src/components/ConfirmSwapModal/ProgressIndicator.tsx +++ b/packages/uniswap/src/components/ConfirmSwapModal/ProgressIndicator.tsx @@ -1,23 +1,64 @@ -import { Flex, Separator } from 'ui/src' -import { - TokenApprovalTransactionStepRow, - TokenRevocationTransactionStepRow, -} from 'uniswap/src/components/ConfirmSwapModal/steps/Approve' -import { Permit2SignatureStepRow } from 'uniswap/src/components/ConfirmSwapModal/steps/Permit' -import { SwapTransactionStepRow } from 'uniswap/src/components/ConfirmSwapModal/steps/Swap' -import { WrapTransactionStepRow } from 'uniswap/src/components/ConfirmSwapModal/steps/Wrap' -import { StepStatus } from 'uniswap/src/components/ConfirmSwapModal/types' -import { - TransactionStep, - TransactionStepType, -} from 'uniswap/src/features/transactions/swap/utils/generateTransactionSteps' +import { useMemo } from 'react' +import { Flex, Separator, useExtractedTokenColor, useSporeColors } from 'ui/src' +import { Sign } from 'ui/src/components/icons/Sign' +import { Swap } from 'ui/src/components/icons/Swap' +import { DEP_accentColors, iconSizes } from 'ui/src/theme' +import { Step, StepDetails, StepStatus } from 'uniswap/src/components/ConfirmSwapModal/Step' +import { CurrencyLogo } from 'uniswap/src/components/CurrencyLogo/CurrencyLogo' +import { uniswapUrls } from 'uniswap/src/constants/urls' +import { Routing } from 'uniswap/src/data/tradingApi/__generated__' +import { useCurrencyInfo, useNativeCurrencyInfo } from 'uniswap/src/features/tokens/useCurrencyInfo' +import { ClassicTrade, UniswapXTrade } from 'uniswap/src/features/transactions/swap/types/trade' +import { TransactionStep, TransactionStepType } from 'uniswap/src/features/transactions/swap/utils/generateSwapSteps' +import { t } from 'uniswap/src/i18n' +import { UniverseChainId } from 'uniswap/src/types/chains' +import { buildCurrencyId } from 'uniswap/src/utils/currencyId' -interface ProgressIndicatorProps { +const IconWrapper = ({ children }: { children: JSX.Element }): JSX.Element => { + return ( + + {children} + + ) +} + +const SwapIcon = (): JSX.Element => ( + + + +) + +const SignIcon = (): JSX.Element => ( + + + +) + +export default function ProgressIndicator({ + steps, + currentStep, + trade, +}: { steps: TransactionStep[] currentStep?: { step: TransactionStep; accepted: boolean } -} + trade: ClassicTrade | UniswapXTrade +}): JSX.Element | null { + const colors = useSporeColors() + const nativeCurrency = useNativeCurrencyInfo(trade?.inputAmount.currency.chainId) + const currencyId = buildCurrencyId( + trade?.inputAmount.currency.chainId as UniverseChainId, + trade?.inputAmount.currency.isToken + ? trade?.inputAmount.currency.address + : trade.inputAmount.currency.wrapped.address, + ) + const currencyInfo = useCurrencyInfo(currencyId) + const inputTokenColor = useExtractedTokenColor( + currencyInfo?.logoUrl, + trade?.inputAmount.currency.symbol, + /*background=*/ colors.surface1.val, + /*default=*/ colors.neutral3.val, + ) -export function ProgressIndicator({ currentStep, steps }: ProgressIndicatorProps): JSX.Element | null { function getStatus(targetStep: TransactionStep): StepStatus { const currentIndex = steps.findIndex((step) => step.type === currentStep?.step.type) const targetIndex = steps.indexOf(targetStep) @@ -30,6 +71,74 @@ export function ProgressIndicator({ currentStep, steps }: ProgressIndicatorProps } } + const stepDetails: Record = useMemo( + () => ({ + [TransactionStepType.WrapTransaction]: { + icon: , + rippleColor: inputTokenColor.tokenColor ?? undefined, + previewTitle: t('common.wrap', { symbol: nativeCurrency?.currency.symbol }), + actionRequiredTitle: t('common.wrapIn', { symbol: nativeCurrency?.currency.symbol }), + inProgressTitle: t('common.wrappingToken', { symbol: nativeCurrency?.currency.symbol }), + learnMoreLinkText: t('common.whyWrap', { symbol: nativeCurrency?.currency.symbol }), + learnMoreLinkHref: uniswapUrls.helpArticleUrls.wethExplainer, + }, + [TransactionStepType.TokenRevocationTransaction]: { + icon: , + rippleColor: inputTokenColor.tokenColor ?? undefined, + previewTitle: t('common.resetLimit', { symbol: currencyInfo?.currency.symbol }), + actionRequiredTitle: t('common.resetLimitWallet', { symbol: currencyInfo?.currency.symbol }), + inProgressTitle: t('common.resettingLimit', { symbol: currencyInfo?.currency.symbol }), + }, + [TransactionStepType.TokenApprovalTransaction]: { + icon: , + rippleColor: inputTokenColor.tokenColor ?? undefined, + previewTitle: t('common.approveSpend', { symbol: currencyInfo?.currency.symbol }), + actionRequiredTitle: t('common.wallet.approve'), + inProgressTitle: t('common.approvePending'), + learnMoreLinkText: t('common.whyApprove'), + learnMoreLinkHref: uniswapUrls.helpArticleUrls.approvalsExplainer, + }, + [TransactionStepType.Permit2Signature]: { + icon: , + rippleColor: colors.accent1.val, + previewTitle: t('common.signMessage'), + actionRequiredTitle: t('common.signMessageWallet'), + learnMoreLinkText: t('common.whySign'), + learnMoreLinkHref: uniswapUrls.helpArticleUrls.approvalsExplainer, + }, + [TransactionStepType.SwapTransaction]: { + icon: , + rippleColor: DEP_accentColors.blue400, + previewTitle: t('swap.confirmSwap'), + actionRequiredTitle: t('common.confirmSwap'), + inProgressTitle: t('common.swapPending'), + ...(trade?.routing === Routing.DUTCH_V2 && { + timeToStart: trade.order.info.deadline - Math.floor(Date.now() / 1000), + delayedStartTitle: t('common.confirmTimedOut'), + }), + learnMoreLinkText: t('common.learnMoreSwap'), + learnMoreLinkHref: uniswapUrls.helpArticleUrls.howToSwapTokens, + }, + [TransactionStepType.SwapTransactionAsync]: { + icon: , + rippleColor: DEP_accentColors.blue400, + previewTitle: t('swap.confirmSwap'), + actionRequiredTitle: t('common.confirmSwap'), + inProgressTitle: t('common.swapPending'), + learnMoreLinkText: t('common.learnMoreSwap'), + learnMoreLinkHref: uniswapUrls.helpArticleUrls.howToSwapTokens, + }, + [TransactionStepType.UniswapXSignature]: { + icon: , + rippleColor: DEP_accentColors.blue400, + previewTitle: t('swap.confirmSwap'), + actionRequiredTitle: t('common.confirmSwap'), + inProgressTitle: t('common.swapPending'), + }, + }), + [trade, currencyInfo, inputTokenColor.tokenColor, nativeCurrency?.currency.symbol, colors.accent1], + ) + if (steps.length === 0) { return null } @@ -37,29 +146,14 @@ export function ProgressIndicator({ currentStep, steps }: ProgressIndicatorProps return ( - {steps.map((step, i) => ( - - - {i !== steps.length - 1 && } - - ))} + {steps.map((step, i) => { + return ( + + + {i !== steps.length - 1 && } + + ) + })} ) } - -function Step({ step, status }: { step: TransactionStep; status: StepStatus }): JSX.Element { - switch (step.type) { - case TransactionStepType.WrapTransaction: - return - case TransactionStepType.TokenApprovalTransaction: - return - case TransactionStepType.TokenRevocationTransaction: - return - case TransactionStepType.Permit2Signature: - return - case TransactionStepType.SwapTransaction: - case TransactionStepType.SwapTransactionAsync: - case TransactionStepType.UniswapXSignature: - return - } -} diff --git a/packages/uniswap/src/components/ConfirmSwapModal/Step.tsx b/packages/uniswap/src/components/ConfirmSwapModal/Step.tsx new file mode 100644 index 00000000000..93b24e5e7b9 --- /dev/null +++ b/packages/uniswap/src/components/ConfirmSwapModal/Step.tsx @@ -0,0 +1,173 @@ +import { ReactElement, useEffect, useState } from 'react' +import { Anchor, ColorTokens, Flex, SpinningLoader, Text } from 'ui/src' +import { Check } from 'ui/src/components/icons/Check' +import { PulseRipple } from 'ui/src/loading/PulseRipple' +import { fonts, iconSizes, spacing } from 'ui/src/theme' + +export interface StepDetails { + // Left-justified icon representing the step and grayed out when step is not active + icon: ReactElement + // Ripple animation around the icon of the currently active step (use color extraction to select) + rippleColor?: string + // Text shown before the step becomes active + previewTitle: string + // Text shown when the step is active and awaiting user input + actionRequiredTitle: string | ReactElement + // Text shown when user input has been accepted and step has yet to complete + inProgressTitle?: string + // Amount of time in seconds the user has to take action on a step (e.g. UniswapX exclusivity window) + timeToStart?: number + // Text shown when timeToStart is exceeded (countdown reaches zero) + delayedStartTitle?: string + // Anchor text displayed for the Learn-More link + learnMoreLinkText?: string + // URL for Learn-More link (opened in new tab) + learnMoreLinkHref?: string +} + +export enum StepStatus { + Preview, + Active, + InProgress, + Complete, +} + +function Icon({ + stepStatus, + icon, + rippleColor, +}: { + stepStatus: StepStatus + icon: ReactElement + rippleColor?: string +}): JSX.Element { + if (stepStatus === StepStatus.InProgress) { + return ( + + + + ) + } + return ( + + {stepStatus === StepStatus.Active && } + + {icon} + + + ) +} + +function Title({ + stepStatus, + stepDetails, + isTimeRemaining, +}: { + stepStatus: StepStatus + stepDetails: StepDetails + isTimeRemaining: boolean +}): JSX.Element | null { + switch (stepStatus) { + case StepStatus.Preview: + return ( + + {stepDetails.previewTitle} + + ) + case StepStatus.Active: + return ( + + {isTimeRemaining ? stepDetails.actionRequiredTitle : stepDetails.delayedStartTitle} + + ) + case StepStatus.InProgress: + return ( + + {isTimeRemaining ? stepDetails.inProgressTitle : null} + + ) + case StepStatus.Complete: + return ( + + {stepDetails.previewTitle} + + ) + default: + return null + } +} + +function Timer({ secondsRemaining }: { secondsRemaining: number }): JSX.Element { + const minutes = Math.floor(secondsRemaining / 60) + const seconds = secondsRemaining % 60 + const minutesText = minutes < 10 ? `0${minutes}` : minutes + const secondsText = seconds < 10 ? `0${seconds}` : seconds + const timerText = `${minutesText}:${secondsText}` + return ( + + {timerText} + + ) +} + +export function Step({ stepStatus, stepDetails }: { stepStatus: StepStatus; stepDetails: StepDetails }): JSX.Element { + // Timer is shown in two cases: + // (1) User has a specified amount of time to perform a required action. Timer starts running as soon as the step becomes active. + // (2) Step has an estimated amount of time in which it should be completed. Timer starts running when step is in progress. + const [secondsRemaining, setSecondsRemaining] = useState(null) + useEffect(() => { + if (stepStatus === StepStatus.Active && stepDetails?.timeToStart) { + setSecondsRemaining(stepDetails.timeToStart) + } else { + setSecondsRemaining(null) + return + } + + const timer = setInterval(() => { + setSecondsRemaining((prevSecondsRemaining) => { + if (prevSecondsRemaining && prevSecondsRemaining > 0) { + return prevSecondsRemaining - 1 + } + clearInterval(timer) + return 0 + }) + }, 1000) + + return (): void => clearInterval(timer) + }, [stepStatus, stepDetails.timeToStart]) + + return ( + + + + + 0} + stepDetails={stepDetails} + stepStatus={stepStatus} + /> + {stepStatus === StepStatus.Active && stepDetails.learnMoreLinkHref && stepDetails.learnMoreLinkText && ( + + {stepDetails.learnMoreLinkText} + + )} + + + {secondsRemaining !== null && } + {stepStatus === StepStatus.Complete && } + + ) +} diff --git a/packages/uniswap/src/components/ConfirmSwapModal/steps/Approve.tsx b/packages/uniswap/src/components/ConfirmSwapModal/steps/Approve.tsx deleted file mode 100644 index cb3abcbc3bd..00000000000 --- a/packages/uniswap/src/components/ConfirmSwapModal/steps/Approve.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { useTranslation } from 'react-i18next' -import { StepRowProps, StepRowSkeleton } from 'uniswap/src/components/ConfirmSwapModal/steps/StepRowSkeleton' -import { StepStatus } from 'uniswap/src/components/ConfirmSwapModal/types' -import { uniswapUrls } from 'uniswap/src/constants/urls' -import { - TokenApprovalTransactionStep, - TokenRevocationTransactionStep, -} from 'uniswap/src/features/transactions/swap/utils/generateTransactionSteps' - -export function TokenApprovalTransactionStepRow({ - step, - status, -}: StepRowProps): JSX.Element { - const { t } = useTranslation() - const { token } = step - const symbol = token.symbol - - const title = { - [StepStatus.Preview]: t('common.approveSpend', { symbol }), - [StepStatus.Active]: t('common.wallet.approve'), - [StepStatus.InProgress]: t('common.approvePending'), - [StepStatus.Complete]: t('common.approveSpend', { symbol }), - }[status] - - return ( - - ) -} - -export function TokenRevocationTransactionStepRow(props: StepRowProps): JSX.Element { - const { step, status } = props - - const { t } = useTranslation() - const { token } = step - const symbol = token.symbol - - const title = { - [StepStatus.Preview]: t('common.resetLimit', { symbol }), - [StepStatus.Active]: t('common.resetLimitWallet', { symbol }), - [StepStatus.InProgress]: t('common.resettingLimit', { symbol }), - [StepStatus.Complete]: t('common.resetLimit', { symbol }), - }[status] - - return -} diff --git a/packages/uniswap/src/components/ConfirmSwapModal/steps/Permit.tsx b/packages/uniswap/src/components/ConfirmSwapModal/steps/Permit.tsx deleted file mode 100644 index 214bd7ddaf3..00000000000 --- a/packages/uniswap/src/components/ConfirmSwapModal/steps/Permit.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { useTranslation } from 'react-i18next' -import { Flex, useSporeColors } from 'ui/src' -import { Sign } from 'ui/src/components/icons/Sign' -import { StepRowProps, StepRowSkeleton } from 'uniswap/src/components/ConfirmSwapModal/steps/StepRowSkeleton' -import { StepStatus } from 'uniswap/src/components/ConfirmSwapModal/types' -import { uniswapUrls } from 'uniswap/src/constants/urls' -import { Permit2SignatureStep } from 'uniswap/src/features/transactions/swap/utils/generateTransactionSteps' - -const SignIcon = (): JSX.Element => ( - - - -) - -export function Permit2SignatureStepRow({ status }: StepRowProps): JSX.Element { - const { t } = useTranslation() - const colors = useSporeColors() - - const title = status === StepStatus.Active ? t('common.signMessageWallet') : t('common.signMessage') - - return ( - } - learnMore={{ - url: uniswapUrls.helpArticleUrls.approvalsExplainer, - text: t('common.whySign'), - }} - rippleColor={colors.accent1.val} - status={status} - /> - ) -} diff --git a/packages/uniswap/src/components/ConfirmSwapModal/steps/StepRowSkeleton.tsx b/packages/uniswap/src/components/ConfirmSwapModal/steps/StepRowSkeleton.tsx deleted file mode 100644 index c80cd1c98f9..00000000000 --- a/packages/uniswap/src/components/ConfirmSwapModal/steps/StepRowSkeleton.tsx +++ /dev/null @@ -1,120 +0,0 @@ -import { Currency } from '@uniswap/sdk-core' -import { PropsWithChildren, useMemo } from 'react' -import { Anchor, ColorTokens, Flex, SpinningLoader, Text, useExtractedTokenColor, useSporeColors } from 'ui/src' -import { Check } from 'ui/src/components/icons/Check' -import { PulseRipple } from 'ui/src/loading/PulseRipple' -import { fonts, iconSizes, spacing } from 'ui/src/theme' -import { StepStatus } from 'uniswap/src/components/ConfirmSwapModal/types' -import { CurrencyLogo } from 'uniswap/src/components/CurrencyLogo/CurrencyLogo' -import { useCurrencyInfo } from 'uniswap/src/features/tokens/useCurrencyInfo' -import { TransactionStep } from 'uniswap/src/features/transactions/swap/utils/generateTransactionSteps' -import { currencyId } from 'uniswap/src/utils/currencyId' - -export interface StepRowProps { - step: TStepType - status: StepStatus -} - -interface StepRowSkeletonProps { - /** If passed, the step row icon will be the currency logo. */ - currency?: Currency - /** Icon to display if there is no currency to be displayed for this step. */ - icon?: JSX.Element - /** Color to display for the ripple effect around the icon or currency logo. This will default to a currency logo extracted color, if currency is defined. */ - rippleColor?: string - status: StepStatus - title: string - secondsRemaining?: number - learnMore?: { url: string; text: string } -} - -export function StepRowSkeleton(props: StepRowSkeletonProps): JSX.Element { - const { currency, icon, secondsRemaining, title, learnMore, status, rippleColor } = props - const colors = useSporeColors() - - const currencyInfo = useCurrencyInfo(currency ? currencyId(currency) : undefined) - const { tokenColor } = useExtractedTokenColor( - currencyInfo?.logoUrl, - currency?.symbol, - /*background=*/ colors.surface1.val, - /*default=*/ colors.neutral3.val, - ) - - const titleColor = status === StepStatus.Active || status === StepStatus.InProgress ? '$neutral1' : '$neutral2' - - return ( - - - - {icon ?? } - - - - {title} - - {status === StepStatus.Active && learnMore && ( - - {learnMore.text} - - )} - - - {!!secondsRemaining && } - {status === StepStatus.Complete && } - - ) -} - -function StepIconWrapper({ - children, - rippleColor, - stepStatus, -}: PropsWithChildren<{ - stepStatus: StepStatus - rippleColor?: string -}>): JSX.Element { - if (stepStatus === StepStatus.InProgress) { - return ( - - - - ) - } - return ( - - {stepStatus === StepStatus.Active && } - - {children} - - - ) -} - -function Timer({ secondsRemaining }: { secondsRemaining: number }): JSX.Element | null { - const timerText = useMemo(() => { - const minutes = Math.floor(secondsRemaining / 60) - const seconds = secondsRemaining % 60 - const minutesText = minutes < 10 ? `0${minutes}` : minutes - const secondsText = seconds < 10 ? `0${seconds}` : seconds - return `${minutesText}:${secondsText}` - }, [secondsRemaining]) - - return ( - - {timerText} - - ) -} diff --git a/packages/uniswap/src/components/ConfirmSwapModal/steps/Swap.tsx b/packages/uniswap/src/components/ConfirmSwapModal/steps/Swap.tsx deleted file mode 100644 index f1f669aad26..00000000000 --- a/packages/uniswap/src/components/ConfirmSwapModal/steps/Swap.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { useEffect, useState } from 'react' -import { useTranslation } from 'react-i18next' -import { Flex, useSporeColors } from 'ui/src' -import { Swap } from 'ui/src/components/icons/Swap' -import { StepRowProps, StepRowSkeleton } from 'uniswap/src/components/ConfirmSwapModal/steps/StepRowSkeleton' -import { StepStatus } from 'uniswap/src/components/ConfirmSwapModal/types' -import { uniswapUrls } from 'uniswap/src/constants/urls' -import { - SwapTransactionStep, - SwapTransactionStepAsync, - TransactionStepType, - UniswapXSignatureStep, -} from 'uniswap/src/features/transactions/swap/utils/generateTransactionSteps' -import noop from 'utilities/src/react/noop' - -const SwapIcon = (): JSX.Element => ( - - - -) - -type SwapSteps = SwapTransactionStep | SwapTransactionStepAsync | UniswapXSignatureStep -export function SwapTransactionStepRow({ step, status }: StepRowProps): JSX.Element { - const { t } = useTranslation() - const colors = useSporeColors() - - const deadline = step.type === TransactionStepType.UniswapXSignature ? step.deadline : undefined - const secondsRemaining = useSecondsUntilDeadline(deadline, status) - - const active = status === StepStatus.Active - const ranOutOfTimeTitle = active && deadline && !secondsRemaining ? t('common.confirmTimedOut') : undefined - - const title = - ranOutOfTimeTitle ?? - { - [StepStatus.Preview]: t('swap.confirmSwap'), - [StepStatus.Active]: t('common.confirmSwap'), - [StepStatus.InProgress]: t('common.swapPending'), - [StepStatus.Complete]: t('swap.confirmSwap'), - }[status] - - return ( - } - learnMore={{ - url: uniswapUrls.helpArticleUrls.howToSwapTokens, - text: t('common.learnMoreSwap'), - }} - rippleColor={colors.DEP_blue400.val} - status={status} - secondsRemaining={secondsRemaining} - /> - ) -} - -function useSecondsUntilDeadline(deadline: number | undefined, status: StepStatus): number | undefined { - const [secondsRemaining, setSecondsRemaining] = useState() - - useEffect(() => { - if (!deadline || status !== StepStatus.Active) { - setSecondsRemaining(undefined) - return noop - } - - const secondsUntilDeadline = deadline - Math.floor(Date.now() / 1000) - if (secondsUntilDeadline <= 0) { - return noop - } - - setSecondsRemaining(secondsUntilDeadline) - - const timer = setInterval(() => { - setSecondsRemaining((prevSecondsRemaining) => { - if (!prevSecondsRemaining) { - clearInterval(timer) - return prevSecondsRemaining - } - - return prevSecondsRemaining - 1 - }) - }, 1000) - - return () => clearInterval(timer) - }, [deadline, status]) - - return secondsRemaining -} diff --git a/packages/uniswap/src/components/ConfirmSwapModal/steps/Wrap.tsx b/packages/uniswap/src/components/ConfirmSwapModal/steps/Wrap.tsx deleted file mode 100644 index b4b511fa408..00000000000 --- a/packages/uniswap/src/components/ConfirmSwapModal/steps/Wrap.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { useTranslation } from 'react-i18next' -import { StepRowProps, StepRowSkeleton } from 'uniswap/src/components/ConfirmSwapModal/steps/StepRowSkeleton' -import { StepStatus } from 'uniswap/src/components/ConfirmSwapModal/types' -import { uniswapUrls } from 'uniswap/src/constants/urls' -import { WrapTransactionStep } from 'uniswap/src/features/transactions/swap/utils/generateTransactionSteps' - -export function WrapTransactionStepRow({ step, status }: StepRowProps): JSX.Element { - const { t } = useTranslation() - - const { amount } = step - const { currency } = amount - const { symbol } = currency - - const title = { - [StepStatus.Active]: t('common.wrapIn', { symbol }), - [StepStatus.InProgress]: t('common.wrappingToken', { symbol }), - [StepStatus.Preview]: t('common.wrap', { symbol }), - [StepStatus.Complete]: t('common.wrap', { symbol }), - }[status] - - return ( - - ) -} diff --git a/packages/uniswap/src/components/ConfirmSwapModal/types.ts b/packages/uniswap/src/components/ConfirmSwapModal/types.ts deleted file mode 100644 index eb54268a266..00000000000 --- a/packages/uniswap/src/components/ConfirmSwapModal/types.ts +++ /dev/null @@ -1,6 +0,0 @@ -export enum StepStatus { - Preview, - Active, - InProgress, - Complete, -} diff --git a/packages/uniswap/src/components/CurrencyInputPanel/CurrencyInputPanel.tsx b/packages/uniswap/src/components/CurrencyInputPanel/CurrencyInputPanel.tsx index b12cbed4ac7..07c2988fbbc 100644 --- a/packages/uniswap/src/components/CurrencyInputPanel/CurrencyInputPanel.tsx +++ b/packages/uniswap/src/components/CurrencyInputPanel/CurrencyInputPanel.tsx @@ -19,7 +19,7 @@ import { errorShakeAnimation } from 'ui/src/animations/errorShakeAnimation' import { AlertTriangleFilled } from 'ui/src/components/icons/AlertTriangleFilled' import { AnimatedFlex } from 'ui/src/components/layout/AnimatedFlex' import { useDynamicFontSizing } from 'ui/src/hooks/useDynamicFontSizing' -import { fonts, spacing } from 'ui/src/theme' +import { fonts } from 'ui/src/theme' import { AmountInput } from 'uniswap/src/components/CurrencyInputPanel/AmountInput' import { MaxAmountButton } from 'uniswap/src/components/CurrencyInputPanel/MaxAmountButton' import { SelectTokenButton } from 'uniswap/src/components/CurrencyInputPanel/SelectTokenButton' @@ -164,8 +164,6 @@ export const CurrencyInputPanel = memo( MIN_INPUT_FONT_SIZE, ) - const lineHeight = fontSize * 1.2 - // This is needed to ensure that the text resizes when modified from outside the component (e.g. custom numpad) useEffect(() => { if (value) { @@ -235,7 +233,6 @@ export const CurrencyInputPanel = memo( alignItems="center" justifyContent={!currencyInfo ? 'flex-end' : 'space-between'} py="$spacing8" - minHeight={MAX_INPUT_FONT_SIZE * 1.2 + 2 * spacing.spacing8} style={shakeStyle} > {isFiatMode && ( @@ -243,7 +240,8 @@ export const CurrencyInputPanel = memo( allowFontScaling color={showInsufficientBalanceWarning ? '$statusCritical' : color} fontSize={fontSize} - lineHeight={lineHeight} + height={fontSize} + lineHeight={fontSize} mr="$spacing4" > {fiatCurrencySymbol} @@ -283,11 +281,10 @@ export const CurrencyInputPanel = memo( // (the text input height is greater than the font size and the input is // centered vertically, so the caret is cut off but the text is not) fontSize={fontSize} - lineHeight={lineHeight} fontWeight="$book" maxDecimals={isFiatMode ? MAX_FIAT_INPUT_DECIMALS : currencyInfo.currency.decimals} maxFontSizeMultiplier={fonts.heading2.maxFontSizeMultiplier} - minHeight={lineHeight} + minHeight={2 * MAX_INPUT_FONT_SIZE} overflow="visible" placeholder="0" placeholderTextColor={colors.neutral3.val} @@ -330,7 +327,7 @@ export const CurrencyInputPanel = memo( - + {showInsufficientBalanceWarning && } {!hideCurrencyBalance && ( diff --git a/packages/uniswap/src/components/CurrencyLogo/CurrencyLogo.test.tsx b/packages/uniswap/src/components/CurrencyLogo/CurrencyLogo.test.tsx index a70caef7b1d..88494bfa7e1 100644 --- a/packages/uniswap/src/components/CurrencyLogo/CurrencyLogo.test.tsx +++ b/packages/uniswap/src/components/CurrencyLogo/CurrencyLogo.test.tsx @@ -3,10 +3,6 @@ import { ARBITRUM_DAI_CURRENCY_INFO, UNI_CURRENCY_INFO, arbitrumDaiCurrencyInfo import { renderWithProviders } from 'uniswap/src/test/render' import { render } from 'uniswap/src/test/test-utils' -jest.mock('ui/src/components/UniversalImage/internal/PlainImage', () => ({ - ...jest.requireActual('ui/src/components/UniversalImage/internal/PlainImage.web'), -})) - describe(CurrencyLogo, () => { it('renders without error', () => { const tree = render() diff --git a/packages/uniswap/src/components/CurrencyLogo/SplitLogo.test.tsx b/packages/uniswap/src/components/CurrencyLogo/SplitLogo.test.tsx index d47fdb43d2b..d76fdf6abe7 100644 --- a/packages/uniswap/src/components/CurrencyLogo/SplitLogo.test.tsx +++ b/packages/uniswap/src/components/CurrencyLogo/SplitLogo.test.tsx @@ -3,10 +3,6 @@ import { DAI_CURRENCY_INFO, ETH_CURRENCY_INFO, daiCurrencyInfo, ethCurrencyInfo import { render, within } from 'uniswap/src/test/test-utils' import { UniverseChainId } from 'uniswap/src/types/chains' -jest.mock('ui/src/components/UniversalImage/internal/PlainImage', () => ({ - ...jest.requireActual('ui/src/components/UniversalImage/internal/PlainImage.web'), -})) - describe(SplitLogo, () => { it('renders without error', () => { const tree = render( diff --git a/packages/uniswap/src/components/CurrencyLogo/TokenLogo.test.tsx b/packages/uniswap/src/components/CurrencyLogo/TokenLogo.test.tsx index f53e6057d0c..ee2908fff87 100644 --- a/packages/uniswap/src/components/CurrencyLogo/TokenLogo.test.tsx +++ b/packages/uniswap/src/components/CurrencyLogo/TokenLogo.test.tsx @@ -6,10 +6,6 @@ import { UniverseChainId } from 'uniswap/src/types/chains' // we silence the error logs to keep the test output clean. jest.mock('utilities/src/logger/logger') -jest.mock('ui/src/components/UniversalImage/internal/PlainImage', () => ({ - ...jest.requireActual('ui/src/components/UniversalImage/internal/PlainImage.web'), -})) - describe('TokenLogo', () => { it('renders without error', () => { const tree = render() diff --git a/packages/uniswap/src/components/CurrencyLogo/TokenLogo.tsx b/packages/uniswap/src/components/CurrencyLogo/TokenLogo.tsx index 00075a5068f..5dcb2114fdd 100644 --- a/packages/uniswap/src/components/CurrencyLogo/TokenLogo.tsx +++ b/packages/uniswap/src/components/CurrencyLogo/TokenLogo.tsx @@ -1,4 +1,4 @@ -import { memo, useState } from 'react' +import { memo } from 'react' import { Flex, Text, UniversalImage, useColorSchemeFromSeed, useSporeColors } from 'ui/src' import { iconSizes, validColor } from 'ui/src/theme' import { STATUS_RATIO } from 'uniswap/src/components/CurrencyLogo/CurrencyLogo' @@ -24,8 +24,6 @@ export const TokenLogo = memo(function _TokenLogo({ hideNetworkLogo, networkLogoBorderWidth = 1.5, }: TokenLogoProps): JSX.Element { - const [showBackground, setShowBackground] = useState(false) - const colors = useSporeColors() const { foreground, background } = useColorSchemeFromSeed(name ?? symbol ?? '') @@ -71,35 +69,17 @@ export const TokenLogo = memo(function _TokenLogo({ size={{ height: size, width: size }} style={{ image: { + backgroundColor: colors.white.val, borderRadius: size / 2, }, }} testID="token-image" uri={url ?? undefined} - onLoad={() => setShowBackground(true)} /> ) return ( - - + {tokenImage} {showNetworkLogo && ( diff --git a/packages/uniswap/src/components/CurrencyLogo/__snapshots__/CurrencyLogo.test.tsx.snap b/packages/uniswap/src/components/CurrencyLogo/__snapshots__/CurrencyLogo.test.tsx.snap index c953ec4db6d..d44a23de5fb 100644 --- a/packages/uniswap/src/components/CurrencyLogo/__snapshots__/CurrencyLogo.test.tsx.snap +++ b/packages/uniswap/src/components/CurrencyLogo/__snapshots__/CurrencyLogo.test.tsx.snap @@ -8,31 +8,11 @@ exports[`CurrencyLogo renders a currency logo with network logo 1`] = ` "flexDirection": "column", "height": 40, "justifyContent": "center", - "position": "relative", "width": 40, } } testID="token-logo" > - - - - - , []) - - if (!isBridgingEnabled) { - return ( - - {suggestedTokens.map((token) => ( - - ))} - - ) - } - - return ( - token.currencyInfo.currencyId} - ItemSeparatorComponent={itemSeparatorComponent} - renderItem={({ item: token }) => ( - - )} - showsHorizontalScrollIndicator={false} - /> - ) -} diff --git a/packages/uniswap/src/components/TokenSelector/HorizontalTokenList/HorizontalTokenList.tsx b/packages/uniswap/src/components/TokenSelector/HorizontalTokenList/HorizontalTokenList.tsx deleted file mode 100644 index cf062a6f1b0..00000000000 --- a/packages/uniswap/src/components/TokenSelector/HorizontalTokenList/HorizontalTokenList.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { OnSelectCurrency, TokenOption, TokenSection } from 'uniswap/src/components/TokenSelector/types' -import { PlatformSplitStubError } from 'utilities/src/errors' - -export type HorizontalTokenListProps = { - tokens: TokenOption[] - onSelectCurrency: OnSelectCurrency - index: number - section: TokenSection -} - -export function HorizontalTokenList(_props: HorizontalTokenListProps): JSX.Element { - throw new PlatformSplitStubError('TokenSectionBaseList') -} diff --git a/packages/uniswap/src/components/TokenSelector/TokenOptionItem.tsx b/packages/uniswap/src/components/TokenSelector/TokenOptionItem.tsx index 822d68b8a64..b74cc2e6642 100644 --- a/packages/uniswap/src/components/TokenSelector/TokenOptionItem.tsx +++ b/packages/uniswap/src/components/TokenSelector/TokenOptionItem.tsx @@ -155,8 +155,8 @@ function _TokenOptionItem({ setShowWarningModal(false)} - onAcknowledge={onAcceptTokenWarning} + onAccept={onAcceptTokenWarning} + onClose={(): void => setShowWarningModal(false)} /> ) diff --git a/packages/uniswap/src/components/TokenSelector/TokenSectionBaseList.web.tsx b/packages/uniswap/src/components/TokenSelector/TokenSectionBaseList.web.tsx index dd3cc619cfb..c6061b2f9af 100644 --- a/packages/uniswap/src/components/TokenSelector/TokenSectionBaseList.web.tsx +++ b/packages/uniswap/src/components/TokenSelector/TokenSectionBaseList.web.tsx @@ -10,8 +10,7 @@ import { SectionRowInfo, TokenSectionBaseListProps, } from 'uniswap/src/components/TokenSelector/TokenSectionBaseList' -import { isHorizontalListSection } from 'uniswap/src/components/TokenSelector/TokenSelectorList' -import { TokenOptionSection } from 'uniswap/src/components/TokenSelector/types' +import { isSuggestedTokenSection } from 'uniswap/src/components/TokenSelector/TokenSelectorList' export const ITEM_SECTION_HEADER_ROW_HEIGHT = 40 const ITEM_ROW_HEIGHT = 68 @@ -28,9 +27,9 @@ function isSectionHeader(rowInfo: BaseListData): rowInfo is BaseListSectionRowIn return !('renderItem' in rowInfo) } -function isHorizontalTokenRowInfo(rowInfo: BaseListData): boolean { +function isSuggestedTokenRowInfo(rowInfo: BaseListData): boolean { const isHeader = isSectionHeader(rowInfo) - return !isHeader && isHorizontalListSection(rowInfo.section) + return !isHeader && isSuggestedTokenSection(rowInfo.section) } export function TokenSectionBaseList({ @@ -70,7 +69,7 @@ export function TokenSectionBaseList({ key: section.sectionKey, renderSectionHeader, } - if (section.sectionKey !== TokenOptionSection.SuggestedTokens) { + if (!isSuggestedTokenSection(section)) { acc.push(sectionInfo) } @@ -114,7 +113,7 @@ export function TokenSectionBaseList({ return 0 } - if (isHorizontalTokenRowInfo(item)) { + if (isSuggestedTokenRowInfo(item)) { if (!isSectionHeader(item)) { if (isArray(item.item) && !item.item.length) { return 0 diff --git a/packages/uniswap/src/components/TokenSelector/TokenSectionHeader.tsx b/packages/uniswap/src/components/TokenSelector/TokenSectionHeader.tsx index 7408ddb5689..c870ad61cbc 100644 --- a/packages/uniswap/src/components/TokenSelector/TokenSectionHeader.tsx +++ b/packages/uniswap/src/components/TokenSelector/TokenSectionHeader.tsx @@ -11,11 +11,10 @@ import { TokenOptionSection } from 'uniswap/src/components/TokenSelector/types' export type TokenSectionHeaderProps = { sectionKey: TokenOptionSection rightElement?: JSX.Element - name?: string } -export function SectionHeader({ sectionKey, rightElement, name }: TokenSectionHeaderProps): JSX.Element | null { - const title = useTokenOptionsSectionTitle(sectionKey, name) +export function SectionHeader({ sectionKey, rightElement }: TokenSectionHeaderProps): JSX.Element | null { + const title = useTokenOptionsSectionTitle(sectionKey) const icon = getTokenOptionsSectionIcon(sectionKey) if (sectionKey === TokenOptionSection.SuggestedTokens) { return null @@ -33,7 +32,7 @@ export function SectionHeader({ sectionKey, rightElement, name }: TokenSectionHe ) } -export function useTokenOptionsSectionTitle(section: TokenOptionSection, name?: string): string { +export function useTokenOptionsSectionTitle(section: TokenOptionSection): string { const { t } = useTranslation() switch (section) { case TokenOptionSection.BridgingTokens: @@ -50,10 +49,8 @@ export function useTokenOptionsSectionTitle(section: TokenOptionSection, name?: return t('tokens.selector.section.search') case TokenOptionSection.SuggestedTokens: return '' // no suggested tokens header - case TokenOptionSection.SearchResultsByNetwork: - return name ?? '' default: - return section + return '' } } diff --git a/packages/uniswap/src/components/TokenSelector/TokenSelector.tsx b/packages/uniswap/src/components/TokenSelector/TokenSelector.tsx index e991f2525b4..bc43d1b619e 100644 --- a/packages/uniswap/src/components/TokenSelector/TokenSelector.tsx +++ b/packages/uniswap/src/components/TokenSelector/TokenSelector.tsx @@ -13,13 +13,12 @@ import { TokenSelectorSwapInputList } from 'uniswap/src/components/TokenSelector import { TokenSelectorSwapOutputList } from 'uniswap/src/components/TokenSelector/TokenSelectorSwapOutputList' import { flowToModalName } from 'uniswap/src/components/TokenSelector/flowToModalName' import { useFilterCallbacks } from 'uniswap/src/components/TokenSelector/hooks' -import { TokenOptionSection, TokenSection, TokenSelectorFlow } from 'uniswap/src/components/TokenSelector/types' +import { TokenSection, TokenSelectorFlow } from 'uniswap/src/components/TokenSelector/types' import PasteButton from 'uniswap/src/components/buttons/PasteButton' import { useBottomSheetContext } from 'uniswap/src/components/modals/BottomSheetContext' import { Modal } from 'uniswap/src/components/modals/Modal' import { NetworkFilter } from 'uniswap/src/components/network/NetworkFilter' import { useUniswapContext } from 'uniswap/src/contexts/UniswapContext' -import { TradeableAsset } from 'uniswap/src/entities/assets' import { CurrencyInfo } from 'uniswap/src/features/dataApi/types' import { SearchContext } from 'uniswap/src/features/search/SearchContext' import { SearchTextInput } from 'uniswap/src/features/search/SearchTextInput' @@ -37,7 +36,6 @@ import { useTrace } from 'utilities/src/telemetry/trace/TraceContext' import { useDebounce } from 'utilities/src/time/timing' export const TOKEN_SELECTOR_WEB_MAX_WIDTH = 400 -export const TOKEN_SELECTOR_WEB_MAX_HEIGHT = 700 export enum TokenSelectorVariation { // used for Send flow, only show currencies with a balance @@ -56,24 +54,17 @@ export interface TokenSelectorProps { activeAccountAddress?: string chainId?: UniverseChainId chainIds?: UniverseChainId[] - input?: TradeableAsset isSurfaceReady?: boolean isLimits?: boolean onClose: () => void onSelectChain?: (chainId: UniverseChainId | null) => void - onSelectCurrency: ( - currency: Currency, - currencyField: CurrencyField, - context: SearchContext, - isBridgePair: boolean, - ) => void + onSelectCurrency: (currency: Currency, currencyField: CurrencyField, context: SearchContext) => void } export function TokenSelectorContent({ currencyField, flow, variation, - input, activeAccountAddress, chainId, chainIds = WALLET_SUPPORTED_CHAIN_IDS, @@ -149,8 +140,7 @@ export function TokenSelectorContent({ query: searchContext.query, }) - const isBridgePair = section.sectionKey === TokenOptionSection.BridgingTokens - onSelectCurrency(currencyInfo.currency, currencyField, searchContext, isBridgePair) + onSelectCurrency(currencyInfo.currency, currencyField, searchContext) }, [flow, page, currencyField, onSelectCurrency, debouncedSearchFilter], ) @@ -202,7 +192,6 @@ export function TokenSelectorContent({ isKeyboardOpen={isKeyboardOpen} parsedChainFilter={parsedChainFilter} searchFilter={searchFilter} - input={input} onSelectCurrency={onSelectCurrencyCallback} /> ) @@ -231,7 +220,6 @@ export function TokenSelectorContent({ case TokenSelectorVariation.SwapOutput: return ( ) } - - return undefined }, [ searchInFocus, searchFilter, @@ -253,7 +239,6 @@ export function TokenSelectorContent({ debouncedSearchFilter, parsedChainFilter, onSendEmptyActionPress, - input, ]) return ( @@ -344,7 +329,6 @@ function _TokenSelectorModal(props: TokenSelectorProps): JSX.Element { backgroundColor={colors.surface1.val} isModalOpen={isModalOpen} maxWidth={isWeb ? TOKEN_SELECTOR_WEB_MAX_WIDTH : undefined} - maxHeight={isInterface ? TOKEN_SELECTOR_WEB_MAX_HEIGHT : undefined} name={ModalName.TokenSelector} padding="$none" snapPoints={['65%', '100%']} diff --git a/packages/uniswap/src/components/TokenSelector/TokenSelectorList.tsx b/packages/uniswap/src/components/TokenSelector/TokenSelectorList.tsx index 96efe0b5cf1..443310bd4d7 100644 --- a/packages/uniswap/src/components/TokenSelector/TokenSelectorList.tsx +++ b/packages/uniswap/src/components/TokenSelector/TokenSelectorList.tsx @@ -3,7 +3,6 @@ import { useTranslation } from 'react-i18next' import { AnimateTransition, Flex, Loader, Skeleton, Text } from 'ui/src' import { fonts } from 'ui/src/theme' import { BaseCard } from 'uniswap/src/components/BaseCard/BaseCard' -import { HorizontalTokenList } from 'uniswap/src/components/TokenSelector/HorizontalTokenList/HorizontalTokenList' import { TokenOptionItem } from 'uniswap/src/components/TokenSelector/TokenOptionItem' import { TokenSectionBaseList, @@ -11,6 +10,8 @@ import { } from 'uniswap/src/components/TokenSelector/TokenSectionBaseList' import { ITEM_SECTION_HEADER_ROW_HEIGHT } from 'uniswap/src/components/TokenSelector/TokenSectionBaseList.web' import { SectionHeader, TokenSectionHeaderProps } from 'uniswap/src/components/TokenSelector/TokenSectionHeader' +import { renderSuggestedTokenItem } from 'uniswap/src/components/TokenSelector/renderSuggestedTokenItem' +import { suggestedTokensKeyExtractor } from 'uniswap/src/components/TokenSelector/suggestedTokensKeyExtractor' import { OnSelectCurrency, TokenOption, @@ -24,21 +25,11 @@ import { UniverseChainId } from 'uniswap/src/types/chains' import { CurrencyId } from 'uniswap/src/types/currency' import { NumberType } from 'utilities/src/format/types' -function isHorizontalListTokenItem( - data: TokenOption | TokenOption[], - section?: TokenSection, - chainFilter?: UniverseChainId | null, -): data is TokenOption[] { - if (section?.sectionKey === TokenOptionSection.BridgingTokens) { - return !chainFilter && Array.isArray(data) - } +function isSuggestedTokenItem(data: TokenOption | TokenOption[]): data is TokenOption[] { return Array.isArray(data) } -export function isHorizontalListSection(section: TokenSection, chainFilter?: UniverseChainId | null): boolean { - if (section.sectionKey === TokenOptionSection.BridgingTokens) { - return !chainFilter - } +export function isSuggestedTokenSection(section: TokenSection): boolean { return section.sectionKey === TokenOptionSection.SuggestedTokens } @@ -141,11 +132,11 @@ function _TokenSelectorList({ const renderItem = useCallback( ({ item, section, index }: { item: TokenOption | TokenOption[]; section: TokenSection; index: number }) => { - if (isHorizontalListTokenItem(item, section, chainFilter) && isHorizontalListSection(section)) { - return + if (isSuggestedTokenItem(item) && isSuggestedTokenSection(section)) { + return renderSuggestedTokenItem({ item, section, index, onSelectCurrency }) } - if (!isHorizontalListTokenItem(item, section, chainFilter)) { + if (!isSuggestedTokenItem(item) && !isSuggestedTokenSection(section)) { return ( ( - + ), [], ) @@ -214,8 +205,8 @@ function _TokenSelectorList({ } function key(item: TokenOption | TokenOption[]): CurrencyId { - if (isHorizontalListTokenItem(item)) { - return item.map((token) => token.currencyInfo.currencyId).join('-') + if (isSuggestedTokenItem(item)) { + return suggestedTokensKeyExtractor(item) } return item.currencyInfo.currencyId diff --git a/packages/uniswap/src/components/TokenSelector/TokenSelectorSearchResultsList.tsx b/packages/uniswap/src/components/TokenSelector/TokenSelectorSearchResultsList.tsx index e5594f1cecd..3ef2e3fdd89 100644 --- a/packages/uniswap/src/components/TokenSelector/TokenSelectorSearchResultsList.tsx +++ b/packages/uniswap/src/components/TokenSelector/TokenSelectorSearchResultsList.tsx @@ -5,7 +5,6 @@ import { SectionHeader } from 'uniswap/src/components/TokenSelector/TokenSection import { TokenSelectorList } from 'uniswap/src/components/TokenSelector/TokenSelectorList' import { useAddToSearchHistory, useTokenSectionsForSearchResults } from 'uniswap/src/components/TokenSelector/hooks' import { OnSelectCurrency, TokenOptionSection } from 'uniswap/src/components/TokenSelector/types' -import { TradeableAsset } from 'uniswap/src/entities/assets' import { UniverseChainId } from 'uniswap/src/types/chains' function EmptyResults({ searchFilter }: { searchFilter: string }): JSX.Element { @@ -33,7 +32,6 @@ function _TokenSelectorSearchResultsList({ debouncedParsedSearchFilter, isBalancesOnlySearch, isKeyboardOpen, - input, }: { onSelectCurrency: OnSelectCurrency activeAccountAddress?: string @@ -44,7 +42,6 @@ function _TokenSelectorSearchResultsList({ debouncedParsedSearchFilter: string | null isBalancesOnlySearch: boolean isKeyboardOpen?: boolean - input: TradeableAsset | undefined }): JSX.Element { const { t } = useTranslation() const { registerSearch } = useAddToSearchHistory() @@ -58,7 +55,6 @@ function _TokenSelectorSearchResultsList({ chainFilter ?? parsedChainFilter, debouncedParsedSearchFilter ?? debouncedSearchFilter, isBalancesOnlySearch, - input, ) const onSelectCurrency: OnSelectCurrency = (currencyInfo, section, index) => { diff --git a/packages/uniswap/src/components/TokenSelector/TokenSelectorSwapInputList.tsx b/packages/uniswap/src/components/TokenSelector/TokenSelectorSwapInputList.tsx index 7d46fe94532..020a8f3aec5 100644 --- a/packages/uniswap/src/components/TokenSelector/TokenSelectorSwapInputList.tsx +++ b/packages/uniswap/src/components/TokenSelector/TokenSelectorSwapInputList.tsx @@ -82,7 +82,7 @@ function useTokenSectionsForSwapInput({ const sections = useMemo(() => { if (isSwapListLoading(loading, portfolioSection, popularSection)) { - return undefined + return } return [ diff --git a/packages/uniswap/src/components/TokenSelector/TokenSelectorSwapOutputList.tsx b/packages/uniswap/src/components/TokenSelector/TokenSelectorSwapOutputList.tsx index cdfcdc5dcf8..cfdb1b3505b 100644 --- a/packages/uniswap/src/components/TokenSelector/TokenSelectorSwapOutputList.tsx +++ b/packages/uniswap/src/components/TokenSelector/TokenSelectorSwapOutputList.tsx @@ -1,7 +1,6 @@ import { memo, useCallback, useMemo } from 'react' import { TokenSelectorList } from 'uniswap/src/components/TokenSelector/TokenSelectorList' import { - useBridgingTokensOptions, useCommonTokensOptionsWithFallback, useFavoriteTokensOptions, usePopularTokensOptions, @@ -20,18 +19,13 @@ import { useTokenOptionsSection, } from 'uniswap/src/components/TokenSelector/utils' import { GqlResult } from 'uniswap/src/data/types' -import { FeatureFlags } from 'uniswap/src/features/gating/flags' -import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' import { UniverseChainId } from 'uniswap/src/types/chains' import { isMobileApp } from 'utilities/src/platform' function useTokenSectionsForSwapOutput({ activeAccountAddress, chainFilter, - input, }: TokenSectionsHookProps): GqlResult { - const isBridgingEnabled = useFeatureFlag(FeatureFlags.Bridging) - const { data: portfolioTokenOptions, error: portfolioTokenOptionsError, @@ -62,42 +56,26 @@ function useTokenSectionsForSwapOutput({ // if there is no chain filter then we show mainnet tokens } = useCommonTokensOptionsWithFallback(activeAccountAddress, chainFilter ?? UniverseChainId.Mainnet) - const { - data: bridgingTokenOptions, - error: bridgingTokenOptionsError, - refetch: refetchBridgingTokenOptions, - loading: bridgingTokenOptionsLoading, - } = useBridgingTokensOptions({ input, walletAddress: activeAccountAddress, chainFilter }) - const recentlySearchedTokenOptions = useRecentlySearchedTokens(chainFilter) const error = (!portfolioTokenOptions && portfolioTokenOptionsError) || (!popularTokenOptions && popularTokenOptionsError) || (!favoriteTokenOptions && favoriteTokenOptionsError) || - (!commonTokenOptions && commonTokenOptionsError) || - (!bridgingTokenOptions && bridgingTokenOptionsError) + (!commonTokenOptions && commonTokenOptionsError) const loading = portfolioTokenOptionsLoading || popularTokenOptionsLoading || favoriteTokenOptionsLoading || - commonTokenOptionsLoading || - bridgingTokenOptionsLoading + commonTokenOptionsLoading const refetchAll = useCallback(() => { refetchPortfolioTokenOptions?.() refetchPopularTokenOptions?.() refetchFavoriteTokenOptions?.() refetchCommonTokenOptions?.() - refetchBridgingTokenOptions?.() - }, [ - refetchBridgingTokenOptions, - refetchCommonTokenOptions, - refetchFavoriteTokenOptions, - refetchPopularTokenOptions, - refetchPortfolioTokenOptions, - ]) + }, [refetchCommonTokenOptions, refetchFavoriteTokenOptions, refetchPopularTokenOptions, refetchPortfolioTokenOptions]) // we draw the Suggested pills as a single item of a section list, so `data` is TokenOption[][] const suggestedSection = useTokenOptionsSection(TokenOptionSection.SuggestedTokens, [commonTokenOptions ?? []]) @@ -107,16 +85,14 @@ function useTokenSectionsForSwapOutput({ const popularMinusPortfolioTokens = tokenOptionDifference(popularTokenOptions, portfolioTokenOptions) const popularSection = useTokenOptionsSection(TokenOptionSection.PopularTokens, popularMinusPortfolioTokens) - const bridgingSection = useTokenOptionsSection(TokenOptionSection.BridgingTokens, [bridgingTokenOptions ?? []]) const sections = useMemo(() => { if (isSwapListLoading(loading, portfolioSection, popularSection)) { - return undefined + return } return [ ...(suggestedSection ?? []), - ...(isBridgingEnabled ? bridgingSection ?? [] : []), ...(portfolioSection ?? []), ...(recentSection ?? []), // TODO(WEB-3061): Favorited wallets/tokens @@ -124,16 +100,7 @@ function useTokenSectionsForSwapOutput({ ...(isMobileApp ? favoriteSection ?? [] : []), ...(popularSection ?? []), ] - }, [ - loading, - portfolioSection, - popularSection, - suggestedSection, - isBridgingEnabled, - bridgingSection, - recentSection, - favoriteSection, - ]) + }, [favoriteSection, loading, popularSection, portfolioSection, recentSection, suggestedSection]) return useMemo( () => ({ @@ -151,7 +118,6 @@ function _TokenSelectorSwapOutputList({ activeAccountAddress, chainFilter, isKeyboardOpen, - input, }: TokenSectionsHookProps & { onSelectCurrency: OnSelectCurrency chainFilter: UniverseChainId | null @@ -164,7 +130,6 @@ function _TokenSelectorSwapOutputList({ } = useTokenSectionsForSwapOutput({ activeAccountAddress, chainFilter, - input, }) return ( { export function useCurrencies(currencyIds: string[]): GqlResult { const { data: baseCurrencyInfos, loading, error, refetch } = useTokenProjects(currencyIds) - const persistedError = usePersistedError(loading, error instanceof ApolloError ? error : undefined) + const persistedError = usePersistedError(loading, error) // TokenProjects returns tokens on every network, so filter out native assets that have a // bridged version on other networks @@ -195,7 +176,7 @@ export function useFavoriteCurrencies(): GqlResult { const favoriteCurrencyIds = useSelector(selectFavoriteTokens) const { data: favoriteTokensOnAllChains, loading, error, refetch } = useTokenProjects(favoriteCurrencyIds) - const persistedError = usePersistedError(loading, error instanceof ApolloError ? error : undefined) + const persistedError = usePersistedError(loading, error) // useTokenProjects returns each token on Arbitrum, Optimism, Polygon, // so we need to filter out the tokens which user has actually favorited @@ -334,72 +315,6 @@ export function useTokenSectionsForEmptySearch(chainFilter: UniverseChainId | nu ) } -export function useBridgingTokensOptions({ - input, - walletAddress, - chainFilter, -}: { - input: TradeableAsset | undefined - walletAddress: Address | undefined - chainFilter: UniverseChainId | null -}): GqlResult { - const isBridgingEnabled = useFeatureFlag(FeatureFlags.Bridging) - - const tokenIn = input?.address ? getTokenAddressFromChainForTradingApi(input.address, input.chainId) : undefined - const tokenInChainId = toTradingApiSupportedChainId(input?.chainId) - - const { - data: swappableTokens, - isLoading: loadingSwappableTokens, - error: errorSwappableTokens, - refetch: refetchSwappableTokens, - } = useTradingApiSwappableTokensQuery({ - params: - tokenIn && tokenInChainId && isBridgingEnabled - ? { - tokenIn, - tokenInChainId, - } - : undefined, - }) - - // Get portfolio balance for returned tokens - const { - data: portfolioBalancesById, - error: portfolioBalancesByIdError, - refetch: portfolioBalancesByIdRefetch, - loading: loadingPorfolioBalancesById, - } = usePortfolioBalancesForAddressById(isBridgingEnabled ? walletAddress : undefined) - - const tokenOptions = useSwappableTokensToTokenOptions(swappableTokens?.tokens, portfolioBalancesById) - const filteredTokenOptions = useMemo(() => filter(tokenOptions ?? null, chainFilter), [chainFilter, tokenOptions]) - - const error = (!portfolioBalancesById && portfolioBalancesByIdError) || (!tokenOptions && errorSwappableTokens) - - const refetch = useCallback(async () => { - if (isBridgingEnabled) { - portfolioBalancesByIdRefetch?.() - await refetchSwappableTokens?.() - } - }, [portfolioBalancesByIdRefetch, refetchSwappableTokens, isBridgingEnabled]) - - if (!isBridgingEnabled) { - return { - data: undefined, - loading: false, - error: undefined, - refetch: undefined, - } - } - - return { - data: filteredTokenOptions, - loading: loadingSwappableTokens || loadingPorfolioBalancesById, - error: error || undefined, - refetch, - } -} - export function useCurrencyInfosToTokenOptions({ currencyInfos, portfolioBalancesById, @@ -430,48 +345,7 @@ export function useCurrencyInfosToTokenOptions({ }, [currencyInfos, portfolioBalancesById, sortAlphabetically]) } -export function useSwappableTokensToTokenOptions( - swappableTokens: GetSwappableTokensResponse['tokens'] | undefined, - portfolioBalancesById?: Record, -): TokenOption[] | undefined { - return useMemo(() => { - if (!swappableTokens) { - return undefined - } - - // We sort the tokens by chain in the same order chains in the network selector - const chainOrder = WALLET_SUPPORTED_CHAIN_IDS - const sortedSwappableTokens = [...swappableTokens].sort((a, b) => { - if (!a || !b) { - return 0 - } - const chainIdA = toSupportedChainId(a.chainId) - const chainIdB = toSupportedChainId(b.chainId) - if (!chainIdA || !chainIdB) { - return 0 - } - return chainOrder.indexOf(chainIdA) - chainOrder.indexOf(chainIdB) - }) - - return sortedSwappableTokens - .map((token) => { - const chainId = toSupportedChainId(token.chainId) - const validInput = token.address && token.chainId && portfolioBalancesById - if (!chainId || !validInput) { - return undefined - } - - const isNative = token.address === NATIVE_ADDRESS_FOR_TRADING_API - return ( - portfolioBalancesById[isNative ? buildNativeCurrencyId(chainId) : buildCurrencyId(chainId, token.address)] ?? - createEmptyTokenOptionFromSwappableToken(token) - ) - }) - .filter((tokenOption): tokenOption is TokenOption => tokenOption !== undefined) - }, [swappableTokens, portfolioBalancesById]) -} - -export function useCommonTokensOptions( +function useCommonTokensOptions( address: Address | undefined, chainFilter: UniverseChainId | null, ): GqlResult { @@ -685,11 +559,7 @@ export function useTokenSectionsForSearchResults( chainFilter: UniverseChainId | null, searchFilter: string | null, isBalancesOnlySearch: boolean, - input: TradeableAsset | undefined, ): GqlResult { - const { t } = useTranslation() - const isBridgingEnabled = useFeatureFlag(FeatureFlags.Bridging) - const { data: portfolioBalancesById, error: portfolioBalancesByIdError, @@ -704,14 +574,6 @@ export function useTokenSectionsForSearchResults( loading: portfolioTokenOptionsLoading, } = usePortfolioTokenOptions(address, chainFilter, searchFilter ?? undefined) - // Bridging tokens are only shown if input is provided - const { - data: bridgingTokenOptions, - error: bridgingTokenOptionsError, - refetch: refetchBridgingTokenOptions, - loading: bridgingTokenOptionsLoading, - } = useBridgingTokensOptions({ input, walletAddress: address, chainFilter }) - // Only call search endpoint if isBalancesOnlySearch is false const { data: searchResultCurrencies, @@ -725,29 +587,15 @@ export function useTokenSectionsForSearchResults( }, [searchResultCurrencies, portfolioBalancesById, searchFilter]) const loading = - portfolioTokenOptionsLoading || - portfolioBalancesByIdLoading || - (!isBalancesOnlySearch && searchTokensLoading) || - bridgingTokenOptionsLoading + portfolioTokenOptionsLoading || portfolioBalancesByIdLoading || (!isBalancesOnlySearch && searchTokensLoading) - const searchResultsSections = useTokenOptionsSection( + const sections = useTokenOptionsSection( TokenOptionSection.SearchResults, // Use local search when only searching balances isBalancesOnlySearch ? portfolioTokenOptions : searchResults, ) - // If there are bridging options, we need to extract them from the search results and then prepend them as a new section above. - // The remaining non-bridging search results will be shown in a section with a different name - const networkName = chainFilter ? UNIVERSE_CHAIN_INFO[chainFilter].label : undefined - const searchResultsSectionHeader = networkName - ? t('tokens.selector.section.otherSearchResults', { network: networkName }) - : undefined - const sections = isBridgingEnabled - ? mergeSearchResultsWithBridgingTokens(searchResultsSections, bridgingTokenOptions, searchResultsSectionHeader) - : searchResultsSections - const error = - (!bridgingTokenOptions && bridgingTokenOptionsError) || (!portfolioBalancesById && portfolioBalancesByIdError) || (!portfolioTokenOptions && portfolioTokenOptionsError) || (!isBalancesOnlySearch && !searchResults && searchTokensError) @@ -756,16 +604,7 @@ export function useTokenSectionsForSearchResults( refetchPortfolioBalances?.() refetchSearchTokens?.() refetchPortfolioTokenOptions?.() - if (isBridgingEnabled) { - refetchBridgingTokenOptions?.() - } - }, [ - isBridgingEnabled, - refetchBridgingTokenOptions, - refetchPortfolioBalances, - refetchPortfolioTokenOptions, - refetchSearchTokens, - ]) + }, [refetchPortfolioBalances, refetchPortfolioTokenOptions, refetchSearchTokens]) return useMemo( () => ({ diff --git a/packages/uniswap/src/components/TokenSelector/HorizontalTokenList/HorizontalTokenList.web.tsx b/packages/uniswap/src/components/TokenSelector/renderSuggestedTokenItem.tsx similarity index 52% rename from packages/uniswap/src/components/TokenSelector/HorizontalTokenList/HorizontalTokenList.web.tsx rename to packages/uniswap/src/components/TokenSelector/renderSuggestedTokenItem.tsx index a04d89fb12e..74f2a273509 100644 --- a/packages/uniswap/src/components/TokenSelector/HorizontalTokenList/HorizontalTokenList.web.tsx +++ b/packages/uniswap/src/components/TokenSelector/renderSuggestedTokenItem.tsx @@ -1,15 +1,20 @@ -import { Flex } from 'ui/src/' -import { HorizontalTokenListProps } from 'uniswap/src/components/TokenSelector/HorizontalTokenList/HorizontalTokenList' +import { Flex } from 'ui/src' import { SuggestedToken } from 'uniswap/src/components/TokenSelector/SuggestedToken' +import { OnSelectCurrency, TokenOption, TokenSection } from 'uniswap/src/components/TokenSelector/types' -export function HorizontalTokenList({ - tokens: suggestedTokens, - onSelectCurrency, +export function renderSuggestedTokenItem({ + item: suggestedTokens, index, section, -}: HorizontalTokenListProps): JSX.Element { + onSelectCurrency, +}: { + item: TokenOption[] + section: TokenSection + index: number + onSelectCurrency: OnSelectCurrency +}): JSX.Element { return ( - + {suggestedTokens.map((token) => ( token.currencyInfo.currencyId).join('-') +} diff --git a/packages/uniswap/src/components/TokenSelector/types.ts b/packages/uniswap/src/components/TokenSelector/types.ts index 701aa99af81..c40e22557d8 100644 --- a/packages/uniswap/src/components/TokenSelector/types.ts +++ b/packages/uniswap/src/components/TokenSelector/types.ts @@ -1,4 +1,3 @@ -import { TradeableAsset } from 'uniswap/src/entities/assets' import { CurrencyInfo } from 'uniswap/src/features/dataApi/types' import { UniverseChainId } from 'uniswap/src/types/chains' import { FiatNumberType } from 'utilities/src/format/types' @@ -20,20 +19,17 @@ export enum TokenOptionSection { SearchResults = 'searchResults', SuggestedTokens = 'suggestedTokens', BridgingTokens = 'bridgingTokens', - SearchResultsByNetwork = 'searchResultsByNetwork', } export type TokenSection = { data: TokenOption[] | TokenOption[][] sectionKey: TokenOptionSection - name?: string rightElement?: JSX.Element } export type TokenSectionsHookProps = { activeAccountAddress?: string chainFilter: UniverseChainId | null - input?: TradeableAsset isKeyboardOpen?: boolean } diff --git a/packages/uniswap/src/components/TokenSelector/utils.tsx b/packages/uniswap/src/components/TokenSelector/utils.tsx index 2061b470727..002fdc3006b 100644 --- a/packages/uniswap/src/components/TokenSelector/utils.tsx +++ b/packages/uniswap/src/components/TokenSelector/utils.tsx @@ -1,7 +1,4 @@ import { TokenOption, TokenOptionSection, TokenSection } from 'uniswap/src/components/TokenSelector/types' -import { tradingApiSwappableTokenToCurrencyInfo } from 'uniswap/src/data/apiClients/tradingApi/utils/tradingApiSwappableTokenToCurrencyInfo' -import { SafetyLevel as GqlSafetyLevel } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' -import { GetSwappableTokensResponse, SafetyLevel } from 'uniswap/src/data/tradingApi/__generated__' import { CurrencyInfo, PortfolioBalance } from 'uniswap/src/features/dataApi/types' import { areCurrencyIdsEqual } from 'uniswap/src/utils/currencyId' import { differenceWith } from 'utilities/src/primitives/array' @@ -14,37 +11,6 @@ export function createEmptyBalanceOption(currencyInfo: CurrencyInfo): TokenOptio } } -export function createEmptyTokenOptionFromSwappableToken( - token: GetSwappableTokensResponse['tokens'][0], -): TokenOption | undefined { - const currencyInfo = tradingApiSwappableTokenToCurrencyInfo(token) - - if (!currencyInfo) { - return undefined - } - - return { - currencyInfo, - balanceUSD: null, - quantity: null, - } -} - -export function toGqlSafetyLevel(safetyLevel: SafetyLevel): GqlSafetyLevel | null { - switch (safetyLevel) { - case SafetyLevel.BLOCKED: - return GqlSafetyLevel.Blocked - case SafetyLevel.MEDIUM_WARNING: - return GqlSafetyLevel.MediumWarning - case SafetyLevel.STRONG_WARNING: - return GqlSafetyLevel.StrongWarning - case SafetyLevel.VERIFIED: - return GqlSafetyLevel.Verified - default: - return null - } -} - // get items in `currencies` that are not in `without` // e.g. difference([B, C, D], [A, B, C]) would return ([D]) export function tokenOptionDifference( @@ -67,7 +33,7 @@ export function formatSearchResults( searchFilter: string | null, ): TokenOption[] | undefined { if (!searchResultCurrencies) { - return undefined + return } const formattedOptions = searchResultCurrencies.map((currencyInfo): TokenOption => { @@ -93,69 +59,6 @@ export function formatSearchResults( return formattedOptions } -/** - * Utility to merge the search results with the bridging tokens. - * Also updates the search results section name accordingly - */ -export function mergeSearchResultsWithBridgingTokens( - searchResults: TokenSection[] | undefined, - bridgingTokens: TokenOption[] | undefined, - sectionHeaderString: string | undefined, -): TokenSection[] | undefined { - if (!searchResults || !bridgingTokens || bridgingTokens.length === 0) { - return searchResults - } - - const extractedBridgingTokens: TokenOption[] = [] - - const extractedSearchResults = searchResults.map((section) => { - const sectionResults2D: TokenOption[][] = [] - const sectionResults: TokenOption[] = [] - section.data.forEach((token) => { - if (isTokenOptionArray(token)) { - // 2D array is for horizontal token list sections, which is not applicable for search results - sectionResults2D.push(token) - return - } - - const isBridgingToken = bridgingTokens.some((bridgingToken) => - areCurrencyIdsEqual(token.currencyInfo.currencyId, bridgingToken.currencyInfo.currencyId), - ) - - if (isBridgingToken) { - extractedBridgingTokens.push(token) - } else { - sectionResults.push(token) - } - }) - - return { - ...section, - data: sectionResults2D.length > 0 ? sectionResults2D : sectionResults, - } - }) - - const bridgingSection: TokenSection = { - sectionKey: TokenOptionSection.BridgingTokens, - data: extractedBridgingTokens, - } - - // Update the search results section name to "Other tokens on {{network}}" if there is a valid bridging section - const searchResultsSection = extractedSearchResults.find( - (section) => section.sectionKey === TokenOptionSection.SearchResults, - ) - if (bridgingSection.data.length > 0 && searchResultsSection && sectionHeaderString) { - searchResultsSection.name = sectionHeaderString - } - - // Remove empty sections - return [bridgingSection, ...extractedSearchResults].filter((section) => section.data.length > 0) -} - -export function isTokenOptionArray(option: TokenOption | TokenOption[]): option is TokenOption[] { - return Array.isArray(option) -} - function isExactTokenOptionMatch(searchResult: TokenOption, query: string): boolean { return ( searchResult.currencyInfo.currency.name?.toLowerCase() === query.toLowerCase() || @@ -167,25 +70,12 @@ export function useTokenOptionsSection( sectionKey: TokenOptionSection, tokenOptions?: TokenOption[] | TokenOption[][], rightElement?: JSX.Element, - name?: string, ): TokenSection[] | undefined { - if (!tokenOptions) { - return undefined - } - - // If it is a 2D array, check if any of the inner arrays are not empty - // Otherwise, check if the array is not empty - const is2DArray = tokenOptions?.length > 0 && Array.isArray(tokenOptions[0]) - const hasData = is2DArray - ? tokenOptions.some((item) => isTokenOptionArray(item) && item.length > 0) - : tokenOptions.length > 0 - - return hasData + return tokenOptions?.length ? [ { sectionKey, data: tokenOptions, - name, rightElement, }, ] diff --git a/packages/uniswap/src/components/dropdowns/ActionSheetDropdown.tsx b/packages/uniswap/src/components/dropdowns/ActionSheetDropdown.tsx index 57f246516f4..0684ed90156 100644 --- a/packages/uniswap/src/components/dropdowns/ActionSheetDropdown.tsx +++ b/packages/uniswap/src/components/dropdowns/ActionSheetDropdown.tsx @@ -93,7 +93,7 @@ export function ActionSheetDropdown({ useEffect(() => { if (!isWeb) { - return undefined + return } function resizeListener(): void { @@ -245,7 +245,7 @@ function DropdownContent({ const [windowScrollY, setWindowScrollY] = useState(0) useEffect(() => { if (!isWeb) { - return undefined + return } function scrollListener(): void { diff --git a/packages/uniswap/src/components/modals/Modal.native.tsx b/packages/uniswap/src/components/modals/Modal.native.tsx index 5a5680c45dd..6182121f08b 100644 --- a/packages/uniswap/src/components/modals/Modal.native.tsx +++ b/packages/uniswap/src/components/modals/Modal.native.tsx @@ -39,8 +39,6 @@ function useModalBackHandler(modalRef: React.RefObject, enabled: bool return subscription.remove } - - return undefined }, [modalRef, enabled]) } diff --git a/packages/uniswap/src/components/modals/Modal.web.tsx b/packages/uniswap/src/components/modals/Modal.web.tsx index 76c85e24b63..eb35d9b8969 100644 --- a/packages/uniswap/src/components/modals/Modal.web.tsx +++ b/packages/uniswap/src/components/modals/Modal.web.tsx @@ -1,9 +1,8 @@ import { useEffect, useState } from 'react' -import { AdaptiveWebModal, isWeb } from 'ui/src' +import { AdaptiveWebModal } from 'ui/src' import { ModalProps } from 'uniswap/src/components/modals/ModalProps' import Trace from 'uniswap/src/features/telemetry/Trace' -import { INTERFACE_NAV_HEIGHT } from 'uniswap/src/theme/heights' -import { isExtension, isInterface } from 'utilities/src/platform' +import { isInterface } from 'utilities/src/platform' const ANIMATION_MS = 200 @@ -16,7 +15,6 @@ export function Modal({ isModalOpen = true, alignment = 'center', maxWidth, - maxHeight, padding = '$spacing12', }: ModalProps): JSX.Element { const [fullyClosed, setFullyClosed] = useState(false) @@ -37,31 +35,21 @@ export function Modal({ clearTimeout(tm) } } - return undefined }, [isModalOpen]) const isTopAligned = alignment === 'top' - const justifyContent = isTopAligned ? 'flex-start' : isWeb ? undefined : 'center' return ( diff --git a/packages/uniswap/src/components/modals/PaginatedModals.tsx b/packages/uniswap/src/components/modals/PaginatedModals.tsx index a888d85557e..19c6b785126 100644 --- a/packages/uniswap/src/components/modals/PaginatedModals.tsx +++ b/packages/uniswap/src/components/modals/PaginatedModals.tsx @@ -1,7 +1,7 @@ import { memo, useCallback, useRef, useState } from 'react' export type PaginatedModalProps = { - onAcknowledge: () => void + onConfirm: () => void onClose: () => void key: number } @@ -62,5 +62,5 @@ type PageProps = { } const Page = memo(function _Page({ modalIndex, renderModal, onClose, onConfirm }: PageProps): JSX.Element | null { - return renderModal({ onClose: () => onClose(modalIndex), onAcknowledge: onConfirm, key: modalIndex }) + return renderModal({ onClose: () => onClose(modalIndex), onConfirm, key: modalIndex }) }) diff --git a/packages/uniswap/src/components/modals/WarningModal/WarningModal.tsx b/packages/uniswap/src/components/modals/WarningModal/WarningModal.tsx index 1c1c58045fb..e92eba7e834 100644 --- a/packages/uniswap/src/components/modals/WarningModal/WarningModal.tsx +++ b/packages/uniswap/src/components/modals/WarningModal/WarningModal.tsx @@ -3,7 +3,7 @@ import { PropsWithChildren, ReactNode } from 'react' import type { ColorValue } from 'react-native' import { Button, Flex, Text, useSporeColors } from 'ui/src' import { AlertTriangleFilled } from 'ui/src/components/icons/AlertTriangleFilled' -import { ThemeNames, opacify } from 'ui/src/theme' +import { opacify } from 'ui/src/theme' import { Modal } from 'uniswap/src/components/modals/Modal' import { getAlertColor } from 'uniswap/src/components/modals/WarningModal/getAlertColor' import { WarningSeverity } from 'uniswap/src/components/modals/WarningModal/types' @@ -11,20 +11,21 @@ import { ModalNameType } from 'uniswap/src/features/telemetry/constants' import { TestID } from 'uniswap/src/test/fixtures/testIDs' import { isWeb } from 'utilities/src/platform' -type WarningModalContentProps = { +export type WarningModalProps = { + isOpen: boolean onClose?: () => void - onReject?: () => void - onAcknowledge?: () => void - hideHandlebar?: boolean + onCancel?: () => void + onConfirm?: () => void + modalName: ModalNameType title?: string titleComponent?: ReactNode caption?: string captionComponent?: ReactNode - rejectText?: string - acknowledgeText?: string - rejectButtonTheme?: ThemeNames - acknowledgeButtonTheme?: ThemeNames + closeText?: string + confirmText?: string severity?: WarningSeverity + isDismissible?: boolean + hideHandlebar?: boolean icon?: ReactNode // when icon is undefined we default it to triangle, this allows us to hide it hideIcon?: boolean @@ -33,106 +34,31 @@ type WarningModalContentProps = { maxWidth?: number } -export type WarningModalProps = { - isOpen: boolean - isDismissible?: boolean - modalName: ModalNameType -} & WarningModalContentProps - -export function WarningModalContent({ +export function WarningModal({ + isOpen, onClose, - onReject, - onAcknowledge, + onCancel, + onConfirm, + modalName, title, titleComponent, caption, captionComponent, - rejectText: rejectText, - rejectButtonTheme, - acknowledgeText, - acknowledgeButtonTheme, + closeText, + confirmText, severity = WarningSeverity.Medium, children, + isDismissible = true, + hideHandlebar = false, icon, hideIcon, - maxWidth, - hideHandlebar = false, backgroundIconColor, -}: PropsWithChildren): JSX.Element { + maxWidth, +}: PropsWithChildren): JSX.Element { const colors = useSporeColors() const alertColor = getAlertColor(severity) const alertColorValue = alertColor.text as keyof typeof colors - return ( - - {!hideIcon && ( - - {icon ?? } - - )} - {title && ( - - {title} - - )} - {titleComponent} - {caption && ( - - {caption} - - )} - {captionComponent} - {children} - - {rejectText && ( - - )} - {acknowledgeText && ( - - )} - - - ) -} - -export function WarningModal(props: PropsWithChildren): JSX.Element { - const { hideHandlebar, isDismissible = true, isOpen, maxWidth, modalName, onClose } = props - const colors = useSporeColors() - return ( ): JSX.E name={modalName} onClose={onClose} > - + + {!hideIcon && ( + + {icon ?? } + + )} + {title && ( + + {title} + + )} + {titleComponent} + {caption && ( + + {caption} + + )} + {captionComponent} + {children} + + {closeText && ( + + )} + {confirmText && ( + + )} + + ) } diff --git a/packages/uniswap/src/constants/chains.ts b/packages/uniswap/src/constants/chains.ts index 9c1ef44e41b..a3976d33932 100644 --- a/packages/uniswap/src/constants/chains.ts +++ b/packages/uniswap/src/constants/chains.ts @@ -22,6 +22,7 @@ import { DAI_ARBITRUM_ONE, DAI_OPTIMISM, DAI_POLYGON, + POL_POLYGON, USDB_BLAST, USDC, USDC_ARBITRUM, @@ -627,7 +628,7 @@ export const UNIVERSE_CHAIN_INFO: Record = { backendChain: { chain: BackendChainId.Polygon as InterfaceGqlChain, backendSupported: true, - nativeTokenBackendAddress: '0x0000000000000000000000000000000000001010', + nativeTokenBackendAddress: POL_POLYGON.address, isSecondaryChain: false, }, blockWaitMsBeforeWarning: 600000, @@ -684,7 +685,7 @@ export const UNIVERSE_CHAIN_INFO: Record = { chain: BackendChainId.Polygon as InterfaceGqlChain, isSecondaryChain: true, backendSupported: true, - nativeTokenBackendAddress: '0x0000000000000000000000000000000000001010', + nativeTokenBackendAddress: POL_POLYGON.address, }, blockPerMainnetEpochForChainId: 1, blockWaitMsBeforeWarning: 600000, diff --git a/packages/uniswap/src/constants/tokens.ts b/packages/uniswap/src/constants/tokens.ts index 59abbf8fb41..cc91c23f8e0 100644 --- a/packages/uniswap/src/constants/tokens.ts +++ b/packages/uniswap/src/constants/tokens.ts @@ -119,6 +119,22 @@ export const BUSD_BSC = new Token(UniverseChainId.Bnb, '0xe9e7CEA3DedcA5984780Ba export const DAI_BSC = new Token(UniverseChainId.Bnb, '0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3', 18, 'DAI', 'DAI') +export const MATIC_POLYGON = new Token( + UniverseChainId.Polygon, + '0x0000000000000000000000000000000000001010', + 18, + 'MATIC', + 'Matic', +) + +export const POL_POLYGON = new Token( + UniverseChainId.Polygon, + '0x0000000000000000000000000000000000001010', + 18, + 'POL', + 'POL', +) + export const DAI_POLYGON = new Token( UniverseChainId.Polygon, '0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063', @@ -554,8 +570,6 @@ export function isCelo(chainId: number): chainId is UniverseChainId.Celo | Unive return chainId === UniverseChainId.CeloAlfajores || chainId === UniverseChainId.Celo } -// Celo has a precompile for its native asset that is fully-compliant with ERC20 interface -// so we can treat it as an ERC20 token. (i.e. $CELO pools are created with its ERC20 precompile) function getCeloNativeCurrency(chainId: number): Token { switch (chainId) { case UniverseChainId.CeloAlfajores: @@ -571,8 +585,6 @@ export function isPolygon(chainId: number): chainId is UniverseChainId.Polygon | return chainId === UniverseChainId.PolygonMumbai || chainId === UniverseChainId.Polygon } -// Polygon also has a precompile, but its precompile is not fully erc20-compatible. -// So we treat Polygon's native asset as NativeCurrency since we can't treat it like an ERC20 token. class PolygonNativeCurrency extends NativeCurrency { equals(other: Currency): boolean { return other.isNative && other.chainId === this.chainId @@ -591,7 +603,7 @@ class PolygonNativeCurrency extends NativeCurrency { if (!isPolygon(chainId)) { throw new Error('Not Polygon') } - super(chainId, 18, 'POL', 'Polygon Ecosystem Token') + super(chainId, 18, 'MATIC', 'Matic') } } diff --git a/packages/uniswap/src/constants/urls.ts b/packages/uniswap/src/constants/urls.ts index 9254eb58562..52b50630e86 100644 --- a/packages/uniswap/src/constants/urls.ts +++ b/packages/uniswap/src/constants/urls.ts @@ -88,7 +88,6 @@ export const uniswapUrls = { swap: '/v1/swap', order: '/v1/order', orders: '/v1/orders', - swaps: '/v1/swaps', swappableTokens: '/v1/swappable_tokens', checkLpApproval: '/v1/check_approval_lp', createLp: '/v1/create_lp_position', diff --git a/packages/uniswap/src/data/apiClients/hooks/useQueryWithImmediateGarbageCollection.ts b/packages/uniswap/src/data/apiClients/hooks/useQueryWithImmediateGarbageCollection.ts index 3069320d8f9..ed8a4cbb9b7 100644 --- a/packages/uniswap/src/data/apiClients/hooks/useQueryWithImmediateGarbageCollection.ts +++ b/packages/uniswap/src/data/apiClients/hooks/useQueryWithImmediateGarbageCollection.ts @@ -25,7 +25,7 @@ export function useQueryWithImmediateGarbageCollection( useEffect(() => { if (skip || !immediateGcTime) { - return undefined + return } const timeSinceLastUpdate = Date.now() - dataUpdatedAt diff --git a/packages/uniswap/src/data/apiClients/tradingApi/TradingApiClient.ts b/packages/uniswap/src/data/apiClients/tradingApi/TradingApiClient.ts index 3b954208bcc..9a97d265116 100644 --- a/packages/uniswap/src/data/apiClients/tradingApi/TradingApiClient.ts +++ b/packages/uniswap/src/data/apiClients/tradingApi/TradingApiClient.ts @@ -5,15 +5,12 @@ import { SwappableTokensParams } from 'uniswap/src/data/apiClients/tradingApi/us import { ApprovalRequest, ApprovalResponse, - BridgeQuote, - ChainId, ClassicQuote, CreateSwapRequest, CreateSwapResponse, DutchQuoteV2, GetOrdersResponse, GetSwappableTokensResponse, - GetSwapsResponse, IndicativeQuoteRequest, IndicativeQuoteResponse, OrderRequest, @@ -23,12 +20,11 @@ import { ReduceLPPositionRequest, ReduceLPPositionResponse, Routing, - TransactionHash, } from 'uniswap/src/data/tradingApi/__generated__' // TradingAPI team is looking into updating type generation to produce the following types for it's current QuoteResponse type: // See: https://linear.app/uniswap/issue/API-236/explore-changing-the-quote-schema-to-pull-out-a-basequoteresponse -export type DiscriminatedQuoteResponse = ClassicQuoteResponse | DutchQuoteResponse | BridgeQuoteResponse +export type DiscriminatedQuoteResponse = ClassicQuoteResponse | DutchQuoteResponse export type DutchQuoteResponse = QuoteResponse & { quote: DutchQuoteV2 @@ -40,11 +36,6 @@ export type ClassicQuoteResponse = QuoteResponse & { routing: Routing.CLASSIC } -export type BridgeQuoteResponse = QuoteResponse & { - quote: BridgeQuote - routing: Routing.BRIDGE -} - export const TRADING_API_CACHE_KEY = 'TradingApi' const TradingApiClient = createApiClient({ @@ -111,12 +102,3 @@ export async function reduceLpPosition(params: ReduceLPPositionRequest): Promise }), }) } - -export async function fetchSwaps(params: { txHashes: TransactionHash[]; chainId: ChainId }): Promise { - return await TradingApiClient.get(uniswapUrls.tradingApiPaths.swaps, { - params: { - txHashes: params.txHashes.join(','), - chainId: params.chainId, - }, - }) -} diff --git a/packages/uniswap/src/data/apiClients/tradingApi/utils/tradingApiSwappableTokenToCurrencyInfo.ts b/packages/uniswap/src/data/apiClients/tradingApi/utils/tradingApiSwappableTokenToCurrencyInfo.ts deleted file mode 100644 index 41c5b86c534..00000000000 --- a/packages/uniswap/src/data/apiClients/tradingApi/utils/tradingApiSwappableTokenToCurrencyInfo.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { toGqlSafetyLevel } from 'uniswap/src/components/TokenSelector/utils' -import { getNativeAddress } from 'uniswap/src/constants/addresses' -import { GetSwappableTokensResponse } from 'uniswap/src/data/tradingApi/__generated__' -import { toSupportedChainId } from 'uniswap/src/features/chains/utils' -import { CurrencyInfo } from 'uniswap/src/features/dataApi/types' -import { buildCurrency } from 'uniswap/src/features/dataApi/utils' -import { NATIVE_ADDRESS_FOR_TRADING_API } from 'uniswap/src/features/transactions/swap/utils/tradingApi' -import { currencyId } from 'uniswap/src/utils/currencyId' - -export function tradingApiSwappableTokenToCurrencyInfo( - token: GetSwappableTokensResponse['tokens'][0], -): CurrencyInfo | undefined { - const isNative = token.address === NATIVE_ADDRESS_FOR_TRADING_API - const supportedChainId = toSupportedChainId(token.chainId) - - if (!supportedChainId) { - return undefined - } - - const currency = buildCurrency({ - chainId: supportedChainId, - address: isNative ? getNativeAddress(supportedChainId) : token.address, - decimals: token.decimals, - symbol: token.symbol, - name: token.name, - }) - - if (!currency) { - return undefined - } - - const currencyInfo: CurrencyInfo = { - currency, - currencyId: currencyId(currency), - logoUrl: token.project?.logo?.url, - isSpam: token.project?.isSpam, - safetyLevel: toGqlSafetyLevel(token.project?.safetyLevel), - } - - return currencyInfo -} diff --git a/packages/uniswap/src/data/apiClients/uniswapApi/useGasFeeQuery.ts b/packages/uniswap/src/data/apiClients/uniswapApi/useGasFeeQuery.ts index 9b5003526a1..0c6caeabb77 100644 --- a/packages/uniswap/src/data/apiClients/uniswapApi/useGasFeeQuery.ts +++ b/packages/uniswap/src/data/apiClients/uniswapApi/useGasFeeQuery.ts @@ -4,7 +4,7 @@ import { uniswapUrls } from 'uniswap/src/constants/urls' import { useQueryWithImmediateGarbageCollection } from 'uniswap/src/data/apiClients/hooks/useQueryWithImmediateGarbageCollection' import { UseQueryWithImmediateGarbageCollectionApiHelperHookArgs } from 'uniswap/src/data/apiClients/types' import { UNISWAP_API_CACHE_KEY, fetchGasFee } from 'uniswap/src/data/apiClients/uniswapApi/UniswapApiClient' -import { GasStrategy } from 'uniswap/src/data/tradingApi/types' +import { GasStrategy } from 'uniswap/src/data/tradingApi/__generated__' import { GasFeeResponse } from 'uniswap/src/features/gas/types' export function useGasFeeQuery({ diff --git a/packages/uniswap/src/data/graphql/uniswap-data-api/queries.graphql b/packages/uniswap/src/data/graphql/uniswap-data-api/queries.graphql index 98fc9323a64..ab7402b2f6a 100644 --- a/packages/uniswap/src/data/graphql/uniswap-data-api/queries.graphql +++ b/packages/uniswap/src/data/graphql/uniswap-data-api/queries.graphql @@ -369,15 +369,12 @@ query PortfolioBalances( logoUrl name safetyLevel + isSpam } feeData { buyFeeBps sellFeeBps } - protectionInfo { - result - attackTypes - } } tokenProjectMarket { relativeChange24: pricePercentChange(duration: DAY) { @@ -438,9 +435,9 @@ query MultiplePortfolioBalances( address symbol decimals - name project { id + name logoUrl safetyLevel isSpam @@ -647,10 +644,10 @@ query TokenDetailsScreen( query TokenProjects($contracts: [ContractInput!]!) { tokenProjects(contracts: $contracts) { id + name logoUrl safetyLevel tokens { - name chain address decimals @@ -1046,9 +1043,9 @@ query SearchTokens($searchQuery: String!, $chains: [Chain!]) { address decimals symbol - name project { id + name logoUrl safetyLevel } @@ -1074,9 +1071,9 @@ query ExploreSearch( value } } - name project { id + name logoUrl safetyLevel } @@ -1119,9 +1116,9 @@ fragment TopTokenParts on Token { value } } - name project { id + name logoUrl markets(currencies: [USD]) { id @@ -1166,8 +1163,8 @@ fragment AITopTokenParts on Token { value } } - name project { + name markets(currencies: [USD]) { price { value @@ -1197,9 +1194,9 @@ fragment HomeScreenTokenParts on Token { symbol chain address - name project { id + name logoUrl markets(currencies: [USD]) { id @@ -1224,23 +1221,22 @@ query HomeScreenTokens($contracts: [ContractInput!]!, $chain: Chain!) { query FavoriteTokenCard($chain: Chain!, $address: String) { token(chain: $chain, address: $address) { - id - address - chain symbol - name - market(currency: USD) { - id - price { - value - } - pricePercentChange(duration: DAY) { - value - } - } + chain + address project { id + name logoUrl + markets(currencies: [USD]) { + id + price { + value + } + pricePercentChange24h { + value + } + } } } } @@ -1250,7 +1246,9 @@ query Tokens($contracts: [ContractInput!]!) { symbol chain address - name + project { + name + } } } diff --git a/packages/uniswap/src/data/graphql/uniswap-data-api/web/ConvertWeb.graphql b/packages/uniswap/src/data/graphql/uniswap-data-api/web/ConvertWeb.graphql new file mode 100644 index 00000000000..87f250ed1ad --- /dev/null +++ b/packages/uniswap/src/data/graphql/uniswap-data-api/web/ConvertWeb.graphql @@ -0,0 +1,7 @@ +query ConvertWeb($toCurrency: Currency!) { + convert(fromAmount: { currency: USD, value: 1.0 }, toCurrency: $toCurrency) { + id + value + currency + } +} diff --git a/packages/uniswap/src/data/rest/getPools.ts b/packages/uniswap/src/data/rest/getPools.ts deleted file mode 100644 index afa1211c150..00000000000 --- a/packages/uniswap/src/data/rest/getPools.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* eslint-disable no-restricted-imports */ -import { PartialMessage } from '@bufbuild/protobuf' -import { ConnectError } from '@connectrpc/connect' -import { useQuery } from '@connectrpc/connect-query' -import { UseQueryResult } from '@tanstack/react-query' -import { listPools } from '@uniswap/client-pools/dist/pools/v1/api-PoolsService_connectquery' -import { ListPoolsRequest, ListPoolsResponse } from '@uniswap/client-pools/dist/pools/v1/api_pb' -import { getPositionsTestTransport } from 'uniswap/src/data/rest/getPositions' - -export function useGetPoolsByTokens( - input?: PartialMessage, -): UseQueryResult { - return useQuery(listPools, input, { transport: getPositionsTestTransport }) -} diff --git a/packages/uniswap/src/data/rest/getPositions.ts b/packages/uniswap/src/data/rest/getPositions.ts index 23fa7a9d6ca..b0c76327587 100644 --- a/packages/uniswap/src/data/rest/getPositions.ts +++ b/packages/uniswap/src/data/rest/getPositions.ts @@ -1,18 +1,115 @@ /* eslint-disable no-restricted-imports */ import { PartialMessage } from '@bufbuild/protobuf' import { ConnectError } from '@connectrpc/connect' -import { useQuery } from '@connectrpc/connect-query' -import { createConnectTransport } from '@connectrpc/connect-web' import { UseQueryResult } from '@tanstack/react-query' -import { listPositions } from '@uniswap/client-pools/dist/pools/v1/api-PoolsService_connectquery' -import { ListPositionsRequest, ListPositionsResponse } from '@uniswap/client-pools/dist/pools/v1/api_pb' +import { GetPositionsRequest, GetPositionsResponse } from '@uniswap/client-pools/dist/pools/v1/api_pb' +import { PositionStatus, ProtocolVersion } from '@uniswap/client-pools/dist/pools/v1/types_pb' -export const getPositionsTestTransport = createConnectTransport({ - baseUrl: '', // TODO: replace with the prod url and update in csp.json as well -}) +const TEST_POSITIONS_DATA = { + positions: [ + { + chainId: 1, + protocolVersion: ProtocolVersion.V2, + v2Pair: { + token0: { + chainId: 1, + address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + symbol: 'USDC', + decimals: 6, + }, + token1: { + chainId: 1, + address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + symbol: 'WETH', + decimals: 18, + }, + liquidityToken: { + chainId: 1, + address: '0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc', + symbol: 'UNI-V2', + decimals: 18, + }, + reserve0: '45641156316559', + reserve1: '17196237072419173119561', + }, + status: PositionStatus.IN_RANGE, + }, + { + chainId: 1, + protocolVersion: ProtocolVersion.V3, + v3Position: { + tokenId: '785499', + tickLower: '197440', + tickUpper: '198810', + liquidity: '0', + token0: { + chainId: 1, + address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + symbol: 'USDC', + decimals: 6, + }, + token1: { + chainId: 1, + address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + symbol: 'WETH', + decimals: 18, + }, + feeTier: '500', + currentTick: '197497', + currentPrice: '1539126286317107746121848509365654', + tickSpacing: '10', + token0UncollectedFees: '0', + token1UncollectedFees: '0', + }, + status: PositionStatus.OUT_OF_RANGE, + }, + { + chainId: 1, + protocolVersion: ProtocolVersion.V4, + v4Position: { + poolPosition: { + tokenId: '785426', + tickLower: '197110', + tickUpper: '197730', + liquidity: '45985818120589024', + token0: { + chainId: 1, + address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + symbol: 'USDC', + decimals: 6, + }, + token1: { + chainId: 1, + address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', + symbol: 'WETH', + decimals: 18, + }, + feeTier: '500', + currentTick: '197497', + currentPrice: '1539126286317107746121848509365654', + tickSpacing: '10', + token0UncollectedFees: '0', + token1UncollectedFees: '0', + }, + hooks: [ + { + address: '0x4c9AF439b1A6761B8E549D8d226A468a6b2803A8', + }, + ], + }, + status: PositionStatus.IN_RANGE, + }, + ], +} export function useGetPositionsQuery( - input?: PartialMessage, -): UseQueryResult { - return useQuery(listPositions, input, { transport: getPositionsTestTransport }) + // eslint-disable-next-line @typescript-eslint/no-unused-vars + input?: PartialMessage, +): UseQueryResult { + return { + data: TEST_POSITIONS_DATA as unknown as GetPositionsResponse, + isLoading: false, + error: null, + } as UseQueryResult + // return useQuery(getPositions, input, { transport: uniswapGetTransport }) } diff --git a/packages/uniswap/src/data/tradingApi/api.json b/packages/uniswap/src/data/tradingApi/api.json index af1272aacab..cd1d26b938f 100644 --- a/packages/uniswap/src/data/tradingApi/api.json +++ b/packages/uniswap/src/data/tradingApi/api.json @@ -1 +1 @@ -{"openapi":"3.0.0","servers":[{"description":"Uniswap trading APIs Beta","url":"https://beta.trade-api.gateway.uniswap.org/v1"},{"description":"Uniswap trading APIs","url":"https://trade-api.gateway.uniswap.org/v1"}],"info":{"version":"1.0.0","title":"Token Trading","description":"Uniswap trading APIs for fungible tokens."},"paths":{"/check_approval":{"post":{"tags":["Approval"],"summary":"Check if token approval is required","description":"Checks if the swapper has the required approval. If the swapper does not have the required approval, then the response will include the transaction to approve the token. If the swapper has the required approval, then the response will be empty. If the parameter `includeGasInfo` is set to `true`, then the response will include the gas fee for the approval transaction.","operationId":"check_approval","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/ApprovalSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/ApprovalUnauthorized401"},"404":{"$ref":"#/components/responses/ApprovalNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/quote":{"post":{"tags":["Quote"],"summary":"Get a quote","description":"Get a quote according to the provided configuration. Optionally adds a fee to the quote according to the API key being used. The fee is **ALWAYS** taken from the output token. If there is a fee and the trade is `EXACT_INPUT`, then the output amount will **NOT** include the fee subtraction. For `EXACT_INPUT` swaps, use `portionBips` to calculate the fee from the quoted amount. If there is a fee and the trade is `EXACT_OUTPUT`, then the input amount will **NOT** include the fee addition to account for the fee. For `EXACT_OUTPUT` swaps, use `portionAmount` to get the fee. \n \n We also support Wrapping and Unwrapping of native tokens on their respective chains. Wrapping and Unwrapping only works for when `routingPreference` is `CLASSIC`, `BEST_PRICE`, or `BEST_PRICE_V2`. We do not support `UNISWAPX` or `UNISWAPX_V2` for these actions.","operationId":"aggregator_quote","security":[{"apiKey":[]}],"parameters":[{"$ref":"#/components/parameters/universalRouterVersionHeader"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/QuoteSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/Unauthorized401"},"404":{"$ref":"#/components/responses/QuoteNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/order":{"post":{"tags":["Order"],"summary":"Create a gasless order","description":"Submits a new gasless encoded order. The order will be validated and if valid, will be submitted to the filler network. The network will try to fill the order at the quoted `startAmount`, and if not, the amount will start decaying until the `endAmount` is reached. While the order is within `decayEndTime`, the `orderStatus` is `open`. If the order does not get filled after the `decayEndTime` has passed, that is reflected in the `expired` `orderStatus`. then The order will be filled at the best price possible. Once the order is filled, `orderStatus` becomes `filled`.","operationId":"post_dutch_order","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderRequest"}}}},"responses":{"201":{"$ref":"#/components/responses/OrderSuccess201"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/Unauthorized401"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/orders":{"get":{"tags":["Order"],"summary":"Get gasless orders","description":"Retrieve gasless orders filtered by query param(s). Some fields on the order can be used as query param.","operationId":"get_dutch_order","security":[{"apiKey":[]}],"parameters":[{"$ref":"#/components/parameters/orderTypeParam"},{"$ref":"#/components/parameters/orderIdParam"},{"$ref":"#/components/parameters/orderIdsParam"},{"$ref":"#/components/parameters/limitParam"},{"$ref":"#/components/parameters/orderStatusParam"},{"$ref":"#/components/parameters/swapperParam"},{"$ref":"#/components/parameters/sortKeyParam"},{"$ref":"#/components/parameters/sortParam"},{"$ref":"#/components/parameters/fillerParam"},{"$ref":"#/components/parameters/cursorParam"}],"responses":{"200":{"$ref":"#/components/responses/OrdersSuccess200"},"400":{"$ref":"#/components/responses/OrdersBadRequest400"},"404":{"$ref":"#/components/responses/OrdersNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/swap":{"post":{"tags":["Swap"],"summary":"Create swap calldata","description":"Create the calldata for a swap transaction (including wrap/unwrap) against the Uniswap Protocols. If the `quote` parameter includes the fee parameters, then the calldata will include the fee disbursement. The gas estimates will be **more precise** when the the response calldata would be valid if submitted on-chain.","operationId":"create_swap_transaction","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSwapRequest"}}}},"parameters":[{"$ref":"#/components/parameters/universalRouterVersionHeader"}],"responses":{"200":{"$ref":"#/components/responses/CreateSwapSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/SwapUnauthorized401"},"404":{"$ref":"#/components/responses/SwapNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/swaps":{"get":{"tags":["Swap"],"summary":"Get swaps status","description":"Get the status of a swap or bridge transactions.","operationId":"get_swaps","security":[{"apiKey":[]}],"parameters":[{"$ref":"#/components/parameters/transactionHashesParam"},{"$ref":"#/components/parameters/chainIdParam"}],"responses":{"200":{"$ref":"#/components/responses/GetSwapsSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"404":{"$ref":"#/components/responses/SwapNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/indicative_quote":{"post":{"tags":["IndicativeQuote"],"summary":"Get an indicative quote","description":"Get an indicative quote according to the provided configuration. The quote will not include a fee.","operationId":"indicative_quote","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IndicativeQuoteRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/IndicativeQuoteSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"404":{"$ref":"#/components/responses/QuoteNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/send":{"post":{"tags":["Send"],"summary":"Create send calldata","description":"Create the calldata for a send transaction.","operationId":"create_send","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSendRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/CreateSendSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/Unauthorized401"},"404":{"$ref":"#/components/responses/SendNotFound404"},"429":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/swappable_tokens":{"get":{"tags":["SwappableTokens"],"summary":"Get swappable tokens","description":"Get the swappable tokens for the given configuration. Either tokenIn (with tokenInChainId or (tokenInChainId and tokenOutChainId)) or tokenOut (with tokenOutChainId or (tokenOutChainId and tokenInChainId)) must be provided but not both.","operationId":"get_swappable_tokens","security":[{"apiKey":[]}],"parameters":[{"$ref":"#/components/parameters/tokenInParam"},{"$ref":"#/components/parameters/tokenOutParam"},{"$ref":"#/components/parameters/bridgeTokenInChainIdParam"},{"$ref":"#/components/parameters/bridgeTokenOutChainIdParam"}],"responses":{"200":{"$ref":"#/components/responses/GetSwappableTokensSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/Unauthorized401"},"404":{"$ref":"#/components/responses/QuoteNotFound404"},"429":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/limit_order_quote":{"post":{"tags":["LimitOrderQuote"],"summary":"Get a limit order quote","description":"Get a quote for a limit order according to the provided configuration.","operationId":"get_limit_order_quote","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LimitOrderQuoteRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/LimitOrderQuoteSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/Unauthorized401"},"404":{"$ref":"#/components/responses/QuoteNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/lp/approve":{"post":{"tags":["Liquidity"],"summary":"Check if tokens and permits need to be approved to add liquidity","description":"Checks if the wallet address has the required approvals. If the wallet address does not have the required approval, then the response will include the transactions to approve the tokens. If the wallet address has the required approval, then the response will be empty for the corresponding tokens. If the parameter `includeGasInfo` is set to `true`, then the response will include the gas fees for the approval transactions.","operationId":"check_approval_lp","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckApprovalLPRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/CheckApprovalLPSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/ApprovalUnauthorized401"},"404":{"$ref":"#/components/responses/ApprovalNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/lp/create":{"post":{"tags":["Liquidity"],"summary":"Create pool and position calldata","description":"Create pool and position calldata. If the pool is not yet created, then the response will include the transaction to create the new pool with the initial price. If the pool is already created, then the response will not have the transaction to create the pool. The response will also have the transaction to create the position for the corresponding pool. If the parameter `includeGasInfo` is set to `true`, then the response will include the gas fees for the creation transactions.","operationId":"create_lp_position","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLPPositionRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/CreateLPPositionSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/ApprovalUnauthorized401"},"404":{"$ref":"#/components/responses/LPNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/lp/increase":{"post":{"tags":["Liquidity"],"summary":"Increase LP position calldata","description":"The response will also have the transaction to increase the position for the corresponding pool. If the parameter `includeGasInfo` is set to `true`, then the response will include the gas fees for the increase transaction.","operationId":"increase_lp_position","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncreaseLPPositionRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/IncreaseLPPositionSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/ApprovalUnauthorized401"},"404":{"$ref":"#/components/responses/LPNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/lp/decrease":{"post":{"tags":["Liquidity"],"summary":"Reduce LP position calldata","description":"The response will also have the transaction to reduce the position for the corresponding pool. If the parameter `includeGasInfo` is set to `true`, then the response will include the gas fees for the reduce transaction.","operationId":"reduce_lp_position","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReduceLPPositionRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/ReduceLPPositionSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/ApprovalUnauthorized401"},"404":{"$ref":"#/components/responses/LPNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/lp/claim":{"post":{"tags":["Liquidity"],"summary":"Claim LP fees calldata","description":"The response will also have the transaction to claim the fees for an LP position for the corresponding pool. If the parameter `includeGasInfo` is set to `true`, then the response will include the gas fees for the claim transaction.","operationId":"claim_lp_fees","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimLPFeesRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/ClaimLPFeesSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/ApprovalUnauthorized401"},"404":{"$ref":"#/components/responses/LPNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}}},"components":{"responses":{"OrdersSuccess200":{"description":"The request orders matching the query parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetOrdersResponse"}}}},"OrderSuccess201":{"description":"Encoded order submitted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderResponse"}}}},"QuoteSuccess200":{"description":"Quote request successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteResponse"}}}},"LimitOrderQuoteSuccess200":{"description":"Limit Order Quote request successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LimitOrderQuoteResponse"}}}},"CheckApprovalLPSuccess200":{"description":"Approve LP successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckApprovalLPResponse"}}}},"ApprovalSuccess200":{"description":"Check approval successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalResponse"}}}},"CreateSendSuccess200":{"description":"Create send successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSendResponse"}}}},"CreateSwapSuccess200":{"description":"Create swap successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSwapResponse"}}}},"GetSwapsSuccess200":{"description":"Get swap successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSwapsResponse"}}}},"GetSwappableTokensSuccess200":{"description":"Get swappable tokens successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSwappableTokensResponse"}}}},"CreateLPPositionSuccess200":{"description":"Create LP Position successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLPPositionResponse"}}}},"IncreaseLPPositionSuccess200":{"description":"Create LP Position successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncreaseLPPositionResponse"}}}},"ReduceLPPositionSuccess200":{"description":"Reduce LP Position successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReduceLPPositionResponse"}}}},"ClaimLPFeesSuccess200":{"description":"Claim LP Fees successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimLPFeesResponse"}}}},"BadRequest400":{"description":"RequestValidationError, Bad Input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err400"}}}},"ApprovalUnauthorized401":{"description":"UnauthorizedError eg. Account is blocked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err401"}}}},"ApprovalNotFound404":{"description":"ResourceNotFound eg. Token allowance not found or Gas info not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err404"}}}},"Unauthorized401":{"description":"UnauthorizedError eg. Account is blocked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err401"}}}},"QuoteNotFound404":{"description":"ResourceNotFound eg. No quotes available or Gas fee/price not available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err404"}}}},"SendNotFound404":{"description":"ResourceNotFound eg. Gas fee not available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err404"}}}},"SwapBadRequest400":{"description":"RequestValidationError, Bad Input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err400"}}}},"SwapUnauthorized401":{"description":"UnauthorizedError eg. Account is blocked or Fee is not enabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err401"}}}},"SwapNotFound404":{"description":"ResourceNotFound eg. No quotes available or Gas fee/price not available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err404"}}}},"OrdersNotFound404":{"description":"Orders not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err404"}}}},"LPNotFound404":{"description":"ResourceNotFound eg. Cant Find LP Position.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err404"}}}},"OrdersBadRequest400":{"description":"RequestValidationError eg. Token allowance not valid or Insufficient Funds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err400"}}}},"RateLimitedErr429":{"description":"Ratelimited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err429"}}}},"InternalErr500":{"description":"Unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err500"}}}},"Timeout504":{"description":"Request duration limit reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err504"}}}},"IndicativeQuoteSuccess200":{"description":"Indicative quote request successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IndicativeQuoteResponse"}}}}},"schemas":{"NullablePermit":{"allOf":[{"$ref":"#/components/schemas/Permit"},{"type":"object","nullable":true}]},"TokenAmount":{"type":"string"},"SwapStatus":{"type":"string","enum":["PENDING","SUCCESS","NOT_FOUND","FAILED","EXPIRED"]},"GetSwapsResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"swaps":{"type":"array","items":{"type":"object","properties":{"swapType":{"$ref":"#/components/schemas/Routing"},"status":{"$ref":"#/components/schemas/SwapStatus"},"txHash":{"type":"string"},"swapId":{"type":"number"}}}}},"required":["requestId","status"]},"GetSwappableTokensResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"tokens":{"type":"array","items":{"type":"object","properties":{"address":{"$ref":"#/components/schemas/Address"},"chainId":{"$ref":"#/components/schemas/ChainId"},"name":{"type":"string"},"symbol":{"type":"string"},"project":{"$ref":"#/components/schemas/TokenProject"},"isSpam":{"type":"boolean"},"decimals":{"type":"number"}},"required":["address","chainId","name","symbol","project","decimals"]}}},"required":["requestId","tokens"]},"CreateSwapRequest":{"type":"object","description":"The parameters **signature** and **permitData** should only be included if *permitData* was returned from **/quote**.","properties":{"quote":{"oneOf":[{"$ref":"#/components/schemas/ClassicQuote"},{"$ref":"#/components/schemas/WrapUnwrapQuote"},{"$ref":"#/components/schemas/BridgeQuote"}]},"signature":{"type":"string","description":"The signed permit."},"includeGasInfo":{"type":"boolean","default":false,"deprecated":true,"description":"Use `refreshGasPrice` instead."},"refreshGasPrice":{"type":"boolean","default":false,"description":"If true, the gas price will be re-fetched from the network."},"simulateTransaction":{"type":"boolean","default":false,"description":"If true, the transaction will be simulated. If the simulation results on an onchain error, endpoint will return an error."},"permitData":{"allOf":[{"$ref":"#/components/schemas/Permit"}]},"safetyMode":{"$ref":"#/components/schemas/SwapSafetyMode"},"deadline":{"type":"integer","description":"The deadline for the swap in unix timestamp format. If the deadline is not defined OR in the past then the default deadline is 30 minutes."},"urgency":{"$ref":"#/components/schemas/Urgency"}},"required":["quote"]},"CreateSendRequest":{"type":"object","properties":{"sender":{"$ref":"#/components/schemas/Address"},"recipient":{"$ref":"#/components/schemas/Address"},"token":{"$ref":"#/components/schemas/Address"},"amount":{"$ref":"#/components/schemas/TokenAmount"},"chainId":{"$ref":"#/components/schemas/ChainId"},"urgency":{"$ref":"#/components/schemas/Urgency"}},"required":["sender","recipient","token","amount"]},"UniversalRouterVersion":{"type":"string","enum":["1.2","2.0"],"default":"1.2"},"Address":{"type":"string","pattern":"^(0x)?[0-9a-fA-F]{40}$"},"PositionConfig":{"type":"object","properties":{"poolKey":{"$ref":"#/components/schemas/RequestId"},"tickLower":{"type":"number"},"tickUpper":{"type":"number"}},"required":["poolKey","tickLower","tickUpper"]},"PoolKey":{"type":"object","properties":{"token0":{"$ref":"#/components/schemas/Address"},"token1":{"$ref":"#/components/schemas/Address"},"fee":{"type":"number"},"tickSpacing":{"type":"number"},"hooks":{"$ref":"#/components/schemas/Address"}},"required":["token0","token1","fee","tickSpacing"]},"ClassicGasUseEstimateUSD":{"description":"The gas fee you would pay if you opted for a CLASSIC swap over a Uniswap X order in terms of USD.","type":"string"},"CreateSwapResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"swap":{"$ref":"#/components/schemas/TransactionRequest"},"gasFee":{"type":"string"}},"required":["requestId","swap"]},"CreateSendResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"send":{"$ref":"#/components/schemas/TransactionRequest"},"gasFee":{"type":"string"},"gasFeeUSD":{"type":"number"}},"required":["requestId","send"]},"QuoteResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"quote":{"$ref":"#/components/schemas/Quote"},"routing":{"$ref":"#/components/schemas/Routing"},"permitData":{"$ref":"#/components/schemas/NullablePermit"}},"required":["routing","quote","permitData","requestId"]},"LimitOrderQuoteResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"quote":{"$ref":"#/components/schemas/DutchQuote"},"routing":{"type":"string","enum":["LIMIT_ORDER"]},"permitData":{"$ref":"#/components/schemas/NullablePermit"}},"required":["routing","quote","permitData","requestId"]},"QuoteRequest":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/TradeType"},"amount":{"type":"string"},"tokenInChainId":{"$ref":"#/components/schemas/ChainId"},"tokenOutChainId":{"$ref":"#/components/schemas/ChainId"},"tokenIn":{"type":"string"},"tokenOut":{"type":"string"},"swapper":{"$ref":"#/components/schemas/Address"},"slippageTolerance":{"description":"For **Classic** swaps, the slippage tolerance is the maximum amount the price can change between the time the transaction is submitted and the time it is executed. The slippage tolerance is represented as a percentage of the total value of the swap. \n\n Slippage tolerance works differently in **DutchLimit** swaps, it does not set a limit on the Spread in an order. See [here](https://uniswap-docs.readme.io/reference/faqs#why-do-the-uniswapx-quotes-have-more-slippage-than-the-tolerance-i-set) for more information. \n\n **NOTE**: slippage is in terms of trade type. If the trade type is `EXACT_INPUT`, then the slippage is in terms of the output token. If the trade type is `EXACT_OUTPUT`, then the slippage is in terms of the input token.","type":"number"},"autoSlippage":{"$ref":"#/components/schemas/AutoSlippage"},"routingPreference":{"$ref":"#/components/schemas/RoutingPreference"},"protocols":{"$ref":"#/components/schemas/Protocols"},"spreadOptimization":{"$ref":"#/components/schemas/SpreadOptimization"},"urgency":{"$ref":"#/components/schemas/Urgency"}},"required":["type","amount","tokenInChainId","tokenOutChainId","tokenIn","tokenOut","swapper"]},"LimitOrderQuoteRequest":{"type":"object","properties":{"swapper":{"$ref":"#/components/schemas/Address"},"limitPrice":{"type":"string"},"amount":{"type":"string"},"orderDeadline":{"type":"number"},"type":{"$ref":"#/components/schemas/TradeType"},"tokenIn":{"type":"string"},"tokenOut":{"type":"string"},"tokenInChainId":{"$ref":"#/components/schemas/ChainId"},"tokenOutChainId":{"$ref":"#/components/schemas/ChainId"}},"required":["swapper","type","amount","tokenIn","tokenOut","tokenInChainId","tokenOutChainId"]},"GetOrdersResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"orders":{"type":"array","items":{"$ref":"#/components/schemas/UniswapXOrder"}},"cursor":{"type":"string"}},"required":["orders","requestId"]},"OrderResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"orderId":{"type":"string"},"orderStatus":{"$ref":"#/components/schemas/OrderStatus"}},"required":["requestId","orderId","orderStatus"]},"OrderRequest":{"type":"object","properties":{"signature":{"type":"string","description":"The signed permit."},"quote":{"oneOf":[{"$ref":"#/components/schemas/DutchQuote"},{"$ref":"#/components/schemas/DutchQuoteV2"}]},"routing":{"$ref":"#/components/schemas/Routing"}},"required":["signature","quote"]},"Urgency":{"type":"string","enum":["normal","fast","urgent"],"description":"The urgency determines the urgency of the transaction. The default value is `urgent`.","default":"urgent"},"Protocols":{"type":"array","items":{"$ref":"#/components/schemas/ProtocolItems"},"description":"The protocols to use for the swap/order. If the `protocols` field is defined, then you can only set the `routingPreference` to `BEST_PRICE`"},"Err400":{"type":"object","properties":{"errorCode":{"default":"RequestValidationError","type":"string"},"detail":{"type":"string"}}},"Err401":{"type":"object","properties":{"errorCode":{"default":"UnauthorizedError","type":"string"},"detail":{"type":"string"}}},"Err404":{"type":"object","properties":{"errorCode":{"default":"ResourceNotFound","type":"string"},"detail":{"type":"string"}}},"Err429":{"type":"object","properties":{"errorCode":{"default":"Ratelimited","type":"string"},"detail":{"type":"string"}}},"Err500":{"type":"object","properties":{"errorCode":{"default":"InternalServerError","type":"string"},"detail":{"type":"string"}}},"Err504":{"type":"object","properties":{"errorCode":{"default":"Timeout","type":"string"},"detail":{"type":"string"}}},"ChainId":{"type":"number","enum":[1,10,56,137,8453,42161,81457,43114,42220,7777777,324,11155111]},"OrderInput":{"type":"object","properties":{"token":{"type":"string"},"startAmount":{"type":"string"},"endAmount":{"type":"string"}},"required":["token"]},"OrderOutput":{"type":"object","properties":{"token":{"type":"string"},"startAmount":{"type":"string"},"endAmount":{"type":"string"},"isFeeOutput":{"type":"boolean"},"recipient":{"type":"string"}},"required":["token"]},"CosignerData":{"type":"object","properties":{"decayStartTime":{"type":"number"},"decayEndTime":{"type":"number"},"exclusiveFiller":{"type":"string"},"inputOverride":{"type":"string"},"outputOverrides":{"type":"array","items":{"type":"string"}}}},"SettledAmount":{"type":"object","properties":{"tokenOut":{"$ref":"#/components/schemas/Address"},"amountOut":{"type":"string"},"tokenIn":{"$ref":"#/components/schemas/Address"},"amountIn":{"type":"string"}}},"OrderType":{"type":"string","enum":["DutchLimit","Dutch","Dutch_V2"]},"OrderTypeQuery":{"type":"string","enum":["Dutch","Dutch_V2","Dutch_V1_V2","Limit"]},"UniswapXOrder":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/OrderType"},"encodedOrder":{"type":"string"},"signature":{"type":"string"},"nonce":{"type":"string"},"orderStatus":{"$ref":"#/components/schemas/OrderStatus"},"orderId":{"type":"string"},"chainId":{"$ref":"#/components/schemas/ChainId"},"quoteId":{"type":"string"},"swapper":{"type":"string"},"txHash":{"type":"string"},"input":{"$ref":"#/components/schemas/OrderInput"},"outputs":{"type":"array","items":{"$ref":"#/components/schemas/OrderOutput"}},"settledAmounts":{"type":"array","items":{"$ref":"#/components/schemas/SettledAmount"}},"cosignature":{"type":"string"},"cosignerData":{"$ref":"#/components/schemas/CosignerData"}},"required":["encodedOrder","signature","nonce","orderId","orderStatus","chainId","type"]},"SortKey":{"type":"string","enum":["createdAt"]},"OrderId":{"type":"string"},"OrderIds":{"type":"string"},"OrderStatus":{"type":"string","enum":["open","expired","error","cancelled","filled","unverified","insufficient-funds"]},"Permit":{"type":"object","properties":{"domain":{"type":"object"},"values":{"type":"object"},"types":{"type":"object"}}},"TokenProject":{"type":"object","properties":{"logo":{"$ref":"#/components/schemas/TokenProjectLogo","nullable":true},"safetyLevel":{"$ref":"#/components/schemas/SafetyLevel"},"isSpam":{"type":"boolean"}},"required":["logo","safetyLevel","isSpam"]},"TokenProjectLogo":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"DutchInput":{"type":"object","properties":{"startAmount":{"type":"string"},"endAmount":{"type":"string"},"token":{"type":"string"}},"required":["startAmount","endAmount","type"]},"DutchOutput":{"type":"object","properties":{"startAmount":{"type":"string"},"endAmount":{"type":"string"},"token":{"type":"string"},"recipient":{"type":"string"}},"required":["startAmount","endAmount","token","recipient"]},"DutchOrderInfo":{"type":"object","properties":{"chainId":{"$ref":"#/components/schemas/ChainId"},"nonce":{"type":"string"},"reactor":{"type":"string"},"swapper":{"type":"string"},"deadline":{"type":"number"},"additionalValidationContract":{"type":"string"},"additionalValidationData":{"type":"string"},"decayStartTime":{"type":"number"},"decayEndTime":{"type":"number"},"exclusiveFiller":{"type":"string"},"exclusivityOverrideBps":{"type":"string"},"input":{"$ref":"#/components/schemas/DutchInput"},"outputs":{"type":"array","items":{"$ref":"#/components/schemas/DutchOutput"}}},"required":["chainId","nonce","reactor","swapper","deadline","validationContract","validationData","startTime","endTime","exclusiveFiller","exclusivityOverrideBps","input","outputs"]},"DutchOrderInfoV2":{"type":"object","properties":{"chainId":{"$ref":"#/components/schemas/ChainId"},"nonce":{"type":"string"},"reactor":{"type":"string"},"swapper":{"type":"string"},"deadline":{"type":"number"},"additionalValidationContract":{"type":"string"},"additionalValidationData":{"type":"string"},"input":{"$ref":"#/components/schemas/DutchInput"},"outputs":{"type":"array","items":{"$ref":"#/components/schemas/DutchOutput"}},"cosigner":{"$ref":"#/components/schemas/Address"}},"required":["chainId","nonce","reactor","swapper","deadline","validationContract","validationData","startTime","endTime","exclusiveFiller","exclusivityOverrideBps","input","outputs"]},"DutchQuote":{"type":"object","properties":{"encodedOrder":{"type":"string"},"orderId":{"type":"string"},"orderInfo":{"$ref":"#/components/schemas/DutchOrderInfo"},"portionBips":{"type":"number"},"portionAmount":{"type":"string"},"portionRecipient":{"$ref":"#/components/schemas/Address"},"quoteId":{"type":"string"},"slippageTolerance":{"type":"number"},"classicGasUseEstimateUSD":{"$ref":"#/components/schemas/ClassicGasUseEstimateUSD"}},"required":["encodedOrder","orderInfo","orderId"]},"DutchQuoteV2":{"type":"object","properties":{"encodedOrder":{"type":"string"},"orderId":{"type":"string"},"orderInfo":{"$ref":"#/components/schemas/DutchOrderInfoV2"},"portionBips":{"type":"number"},"portionAmount":{"type":"string"},"portionRecipient":{"$ref":"#/components/schemas/Address"},"quoteId":{"type":"string"},"slippageTolerance":{"type":"number"},"deadlineBufferSecs":{"type":"number"},"classicGasUseEstimateUSD":{"$ref":"#/components/schemas/ClassicGasUseEstimateUSD"}},"required":["encodedOrder","orderInfo","orderId"]},"BridgeQuote":{"type":"object","properties":{"quoteId":{"type":"string"},"chainId":{"$ref":"#/components/schemas/ChainId"},"destinationChainId":{"$ref":"#/components/schemas/ChainId"},"swapper":{"$ref":"#/components/schemas/Address"},"input":{"$ref":"#/components/schemas/ClassicInput"},"output":{"$ref":"#/components/schemas/ClassicOutput"},"tradeType":{"$ref":"#/components/schemas/TradeType"},"quoteTimestamp":{"type":"number"},"gasPrice":{"type":"string"},"maxFeePerGas":{"type":"string"},"maxPriorityFeePerGas":{"type":"string"},"gasFee":{"type":"string"},"gasUseEstimate":{"type":"string"},"gasFeeUSD":{"type":"string"},"portionBips":{"type":"number"},"portionAmount":{"type":"string"},"portionRecipient":{"$ref":"#/components/schemas/Address"},"estimatedFillTimeMs":{"type":"number"}}},"SafetyLevel":{"type":"string","enum":["BLOCKED","MEDIUM_WARNING","STRONG_WARNING","VERIFIED"]},"TradeType":{"type":"string","enum":["EXACT_INPUT","EXACT_OUTPUT"]},"Routing":{"type":"string","enum":["DUTCH_LIMIT","CLASSIC","DUTCH_V2","BRIDGE","LIMIT_ORDER"]},"Quote":{"oneOf":[{"$ref":"#/components/schemas/DutchQuote"},{"$ref":"#/components/schemas/ClassicQuote"},{"$ref":"#/components/schemas/WrapUnwrapQuote"},{"$ref":"#/components/schemas/DutchQuoteV2"},{"$ref":"#/components/schemas/BridgeQuote"}]},"CheckApprovalLPRequest":{"type":"object","properties":{"protocol":{"$ref":"#/components/schemas/ProtocolItems"},"token0":{"$ref":"#/components/schemas/Address"},"token1":{"$ref":"#/components/schemas/Address"},"pairAddress":{"$ref":"#/components/schemas/Address"},"chainId":{"$ref":"#/components/schemas/ChainId"},"walletAddress":{"$ref":"#/components/schemas/Address"},"amount0":{"type":"string"},"amount1":{"type":"string"},"pairAddressAmount":{"type":"string"},"includeGasInfo":{"type":"boolean"}}},"CheckApprovalLPResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"token0Approval":{"$ref":"#/components/schemas/TransactionRequest"},"token1Approval":{"$ref":"#/components/schemas/TransactionRequest"},"pairAddressApproval":{"$ref":"#/components/schemas/TransactionRequest"},"batchedPermit2Data":{"$ref":"#/components/schemas/NullablePermit"},"gasFee0":{"type":"string"},"gasFee1":{"type":"string"},"gasFeePairAddress":{"type":"string"}}},"ApprovalRequest":{"type":"object","properties":{"walletAddress":{"$ref":"#/components/schemas/Address"},"token":{"$ref":"#/components/schemas/Address"},"amount":{"$ref":"#/components/schemas/TokenAmount"},"chainId":{"$ref":"#/components/schemas/ChainId"},"urgency":{"$ref":"#/components/schemas/Urgency"},"includeGasInfo":{"type":"boolean","default":false},"tokenOut":{"$ref":"#/components/schemas/Address"},"tokenOutChainId":{"$ref":"#/components/schemas/ChainId"}},"required":["walletAddress","token","amount"]},"ApprovalResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"approval":{"$ref":"#/components/schemas/TransactionRequest"},"cancel":{"$ref":"#/components/schemas/TransactionRequest"},"gasFee":{"type":"string"},"cancelGasFee":{"type":"string"}},"required":["requestId","approval","cancel"]},"ClassicQuote":{"type":"object","properties":{"input":{"$ref":"#/components/schemas/ClassicInput"},"output":{"$ref":"#/components/schemas/ClassicOutput"},"swapper":{"$ref":"#/components/schemas/Address"},"chainId":{"$ref":"#/components/schemas/ChainId"},"slippage":{"type":"number"},"tradeType":{"$ref":"#/components/schemas/TradeType"},"gasFee":{"type":"string","description":"The gas fee in terms of wei. It does NOT include the additional gas for token approvals."},"gasFeeUSD":{"type":"string","description":"The gas fee in terms of USD. It does NOT include the additional gas for token approvals."},"gasFeeQuote":{"type":"string","description":"The gas fee in terms of the quoted currency. It does NOT include the additional gas for token approvals."},"route":{"type":"array","items":{"type":"array","items":{"oneOf":[{"$ref":"#/components/schemas/V3PoolInRoute"},{"$ref":"#/components/schemas/V2PoolInRoute"}]}}},"portionBips":{"type":"number","description":"The portion of the swap that will be taken as a fee. The fee will be taken from the output token."},"portionAmount":{"type":"string","description":"The amount of the swap that will be taken as a fee. The fee will be taken from the output token."},"portionRecipient":{"$ref":"#/components/schemas/Address"},"routeString":{"type":"string","description":"The route in string format."},"quoteId":{"type":"string","description":"The quote id. Used for analytics purposes."},"gasUseEstimate":{"type":"string","description":"The estimated gas use. It does NOT include the additional gas for token approvals."},"blockNumber":{"type":"string","description":"The current block number."},"gasPrice":{"type":"string","description":"The gas price in terms of wei for pre EIP1559 transactions."},"maxFeePerGas":{"type":"string","description":"The maximum fee per gas in terms of wei for EIP1559 transactions."},"maxPriorityFeePerGas":{"type":"string","description":"The maximum priority fee per gas in terms of wei for EIP1559 transactions."},"txFailureReasons":{"type":"array","items":{"$ref":"#/components/schemas/TransactionFailureReason"}},"priceImpact":{"type":"number","description":"The impact the trade has on the market price of the pool, between 0-100 percent"}}},"WrapUnwrapQuote":{"type":"object","properties":{"swapper":{"$ref":"#/components/schemas/Address"},"input":{"$ref":"#/components/schemas/ClassicInput"},"output":{"$ref":"#/components/schemas/ClassicOutput"},"chainId":{"$ref":"#/components/schemas/ChainId"},"tradeType":{"$ref":"#/components/schemas/TradeType"},"gasFee":{"type":"string","description":"The gas fee in terms of wei."},"gasFeeUSD":{"type":"string","description":"The gas fee in terms of USD."},"gasFeeQuote":{"type":"string","description":"The gas fee in terms of the quoted currency."},"gasUseEstimate":{"type":"string","description":"The estimated gas use."},"gasPrice":{"type":"string","description":"The gas price in terms of wei for pre EIP1559 transactions."},"maxFeePerGas":{"type":"string","description":"The maximum fee per gas in terms of wei for EIP1559 transactions."},"maxPriorityFeePerGas":{"type":"string","description":"The maximum priority fee per gas in terms of wei for EIP1559 transactions."}}},"TokenInRoute":{"type":"object","properties":{"address":{"$ref":"#/components/schemas/Address"},"chainId":{"$ref":"#/components/schemas/ChainId"},"symbol":{"type":"string"},"decimals":{"type":"string"},"buyFeeBps":{"type":"string"},"sellFeeBps":{"type":"string"}}},"V2Reserve":{"type":"object","properties":{"token":{"$ref":"#/components/schemas/TokenInRoute"},"quotient":{"type":"string"}}},"V2PoolInRoute":{"type":"object","properties":{"type":{"type":"string","default":"v2-pool"},"address":{"$ref":"#/components/schemas/Address"},"tokenIn":{"$ref":"#/components/schemas/TokenInRoute"},"tokenOut":{"$ref":"#/components/schemas/TokenInRoute"},"reserve0":{"$ref":"#/components/schemas/V2Reserve"},"reserve1":{"$ref":"#/components/schemas/V2Reserve"},"amountIn":{"type":"string"},"amountOut":{"type":"string"}}},"V3PoolInRoute":{"type":"object","properties":{"type":{"type":"string","default":"v3-pool"},"address":{"$ref":"#/components/schemas/Address"},"tokenIn":{"$ref":"#/components/schemas/TokenInRoute"},"tokenOut":{"$ref":"#/components/schemas/TokenInRoute"},"sqrtRatioX96":{"type":"string"},"liquidity":{"type":"string"},"tickCurrent":{"type":"string"},"fee":{"type":"string"},"amountIn":{"type":"string"},"amountOut":{"type":"string"}}},"TransactionHash":{"type":"string","pattern":"^(0x)?[0-9a-fA-F]{64}$"},"ClassicInput":{"type":"object","properties":{"token":{"$ref":"#/components/schemas/Address"},"amount":{"type":"string"}}},"ClassicOutput":{"type":"object","properties":{"token":{"$ref":"#/components/schemas/Address"},"amount":{"type":"string"},"recipient":{"$ref":"#/components/schemas/Address"}}},"RequestId":{"type":"string"},"SpreadOptimization":{"type":"string","enum":["EXECUTION","PRICE"],"description":"For **Dutch Limit** orders only. When set to `EXECUTION`, quotes optimize for looser spreads at higher fill rates. When set to `PRICE`, quotes optimize for tighter spreads at lower fill rates","default":"EXECUTION"},"AutoSlippage":{"type":"string","enum":["DEFAULT"],"description":"For **Classic** swaps only. The auto slippage strategy to employ. If auto slippage is not defined then we don't compute it. If the auto slippage strategy is `DEFAULT`, then the swap will use the default slippage tolerance computation. You cannot define auto slippage and slippage tolerance at the same time. \n\n **NOTE**: slippage is in terms of trade type. If the trade type is `EXACT_INPUT`, then the slippage is in terms of the output token. If the trade type is `EXACT_OUTPUT`, then the slippage is in terms of the input token.","default":"undefined"},"RoutingPreference":{"type":"string","description":"The routing preference determines which protocol to use for the swap. If the routing preference is `UNISWAPX`, then the swap will be routed through the UniswapX Dutch Auction Protocol. If the routing preference is `CLASSIC`, then the swap will be routed through the Classic Protocol. If the routing preference is `BEST_PRICE`, then the swap will be routed through the protocol that provides the best price. When `UNIXWAPX_V2` is passed, the swap will be routed through the UniswapX V2 Dutch Auction Protocol. When `V3_ONLY` is passed, the swap will be routed ONLY through the Uniswap V3 Protocol. When `V2_ONLY` is passed, the swap will be routed ONLY through the Uniswap V2 Protocol.","enum":["CLASSIC","UNISWAPX","BEST_PRICE","BEST_PRICE_V2","UNISWAPX_V2","V3_ONLY","V2_ONLY"],"default":"BEST_PRICE"},"ProtocolItems":{"type":"string","enum":["V2","V3","V4","UNISWAPX","UNISWAPX_V2"]},"TransactionRequest":{"type":"object","properties":{"to":{"$ref":"#/components/schemas/Address"},"from":{"$ref":"#/components/schemas/Address"},"data":{"type":"string","description":"The calldata for the transaction."},"value":{"type":"string","description":"The value of the transaction in terms of wei in hex format."},"gasLimit":{"type":"string"},"chainId":{"type":"integer"},"maxFeePerGas":{"type":"string"},"maxPriorityFeePerGas":{"type":"string"},"gasPrice":{"type":"string"}},"required":["to","from","data","value","chainId"]},"TransactionFailureReason":{"type":"string","enum":["SIMULATION_ERROR","UNSUPPORTED_SIMULATION"]},"SwapSafetyMode":{"type":"string","enum":["SAFE"],"description":"The safety mode determines the safety level of the swap. If the safety mode is `SAFE`, then the swap will include a SWEEP for the native token."},"IndicativeQuoteRequest":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/TradeType"},"amount":{"type":"string"},"tokenInChainId":{"$ref":"#/components/schemas/ChainId"},"tokenOutChainId":{"$ref":"#/components/schemas/ChainId"},"tokenIn":{"type":"string"},"tokenOut":{"type":"string"}},"required":["type","amount","tokenInChainId","tokenOutChainId","tokenIn","tokenOut"]},"IndicativeQuoteResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"input":{"$ref":"#/components/schemas/IndicativeQuoteToken"},"output":{"$ref":"#/components/schemas/IndicativeQuoteToken"},"type":{"$ref":"#/components/schemas/TradeType"}},"required":["requestId","input","output","type"]},"CreateLPPositionRequest":{"type":"object","properties":{"positionConfig":{"$ref":"#/components/schemas/PositionConfig"},"walletAddress":{"$ref":"#/components/schemas/Address"},"amount0":{"type":"string"},"amount1":{"type":"string"},"amount0Max":{"type":"string"},"amount1Max":{"type":"string"},"initialPrice":{"type":"string"},"signedBatchedPermit2Data":{"type":"string"},"includeGasInfo":{"type":"boolean"}}},"CreateLPPositionResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"create":{"$ref":"#/components/schemas/TransactionRequest"},"gasFee":{"type":"string"}}},"IncreaseLPPositionRequest":{"type":"object","properties":{"positionConfigId":{"type":"string"},"walletAddress":{"$ref":"#/components/schemas/Address"},"amount0":{"type":"string"},"amount1":{"type":"string"},"amount0Max":{"type":"string"},"amount1Max":{"type":"string"},"includeGasInfo":{"type":"boolean"}}},"IncreaseLPPositionResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"increase":{"$ref":"#/components/schemas/TransactionRequest"},"gasFee":{"type":"string"}}},"ReduceLPPositionRequest":{"type":"object","properties":{"positionConfigId":{"type":"string"},"walletAddress":{"$ref":"#/components/schemas/Address"},"amount0":{"type":"string"},"amount1":{"type":"string"},"amount0Max":{"type":"string"},"amount1Max":{"type":"string"},"collectAsWeth":{"type":"boolean"},"includeGasInfo":{"type":"boolean"}}},"ReduceLPPositionResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"reduce":{"$ref":"#/components/schemas/TransactionRequest"},"gasFee":{"type":"string"}}},"ClaimLPFeesRequest":{"type":"object","properties":{"positionConfigId":{"type":"string"},"walletAddress":{"$ref":"#/components/schemas/Address"},"collectAsWeth":{"type":"boolean"},"includeGasInfo":{"type":"boolean"}}},"ClaimLPFeesResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"claim":{"$ref":"#/components/schemas/TransactionRequest"},"gasFee":{"type":"string"}}},"IndicativeQuoteToken":{"type":"object","properties":{"amount":{"type":"string"},"chainId":{"$ref":"#/components/schemas/ChainId"},"token":{"$ref":"#/components/schemas/Address"}}}},"parameters":{"universalRouterVersionHeader":{"name":"x-universal-router-version","in":"header","description":"The version of the Universal Router to use for the swap journey. *MUST* be consistent throughout the API calls.","required":false,"schema":{"$ref":"#/components/schemas/UniversalRouterVersion"}},"addressParam":{"name":"address","in":"path","schema":{"$ref":"#/components/schemas/Address"},"required":true},"tokenIdParam":{"name":"tokenId","in":"path","schema":{"type":"string"},"required":true},"cursorParam":{"name":"cursor","in":"query","schema":{"type":"string"},"required":false},"limitParam":{"name":"limit","in":"query","schema":{"type":"number"},"required":false},"chainIdParam":{"name":"chainId","in":"query","schema":{"$ref":"#/components/schemas/ChainId"},"required":false},"bridgeTokenInChainIdParam":{"name":"tokenInChainId","in":"query","schema":{"$ref":"#/components/schemas/ChainId"},"required":false},"bridgeTokenOutChainIdParam":{"name":"tokenOutChainId","in":"query","schema":{"$ref":"#/components/schemas/ChainId"},"required":false},"tokenInParam":{"name":"tokenIn","in":"query","schema":{"$ref":"#/components/schemas/Address"},"required":false},"tokenOutParam":{"name":"tokenOut","in":"query","schema":{"$ref":"#/components/schemas/Address"},"required":false},"addressPathParam":{"name":"address","in":"query","schema":{"$ref":"#/components/schemas/Address"},"required":false},"orderStatusParam":{"name":"orderStatus","in":"query","description":"Filter by order status.","required":false,"schema":{"$ref":"#/components/schemas/OrderStatus"}},"orderTypeParam":{"name":"orderType","in":"query","description":"The default orderType is Dutch_V1_V2 and will grab both Dutch and Dutch_V2 orders.","required":false,"schema":{"$ref":"#/components/schemas/OrderTypeQuery"}},"orderIdParam":{"name":"orderId","in":"query","required":false,"schema":{"$ref":"#/components/schemas/OrderId"}},"orderIdsParam":{"name":"orderIds","in":"query","required":false,"description":"ids split by commas","schema":{"$ref":"#/components/schemas/OrderIds"}},"swapperParam":{"name":"swapper","in":"query","description":"Filter by swapper address.","required":false,"schema":{"$ref":"#/components/schemas/Address"}},"fillerParam":{"name":"filler","in":"query","description":"Filter by filler address.","required":false,"schema":{"$ref":"#/components/schemas/Address"}},"sortKeyParam":{"name":"sortKey","in":"query","description":"Order the query results by the sort key.","required":false,"schema":{"$ref":"#/components/schemas/SortKey"}},"sortParam":{"name":"sort","in":"query","description":"Sort query. For example: `sort=gt(UNIX_TIMESTAMP)`, `sort=between(1675872827, 1675872930)`, or `lt(1675872930)`.","required":false,"schema":{"type":"string"}},"descParam":{"description":"Sort query results by sortKey in descending order.","name":"desc","in":"query","required":false,"schema":{"type":"string"}},"transactionHashesParam":{"description":"The transaction hashes.","name":"txHashes","in":"query","required":true,"style":"form","explode":false,"schema":{"type":"array","items":{"$ref":"#/components/schemas/TransactionHash"}}}},"securitySchemes":{"apiKey":{"type":"apiKey","in":"header","name":"x-api-key"}}},"security":[{"apiKey":[]}]} \ No newline at end of file +{"openapi":"3.0.0","servers":[{"description":"Uniswap trading APIs Beta","url":"https://beta.trade-api.gateway.uniswap.org/v1"},{"description":"Uniswap trading APIs","url":"https://trade-api.gateway.uniswap.org/v1"}],"info":{"version":"1.0.0","title":"Token Trading","description":"Uniswap trading APIs for fungible tokens."},"paths":{"/check_approval":{"post":{"tags":["Approval"],"summary":"Check if token approval is required","description":"Checks if the swapper has the required approval. If the swapper does not have the required approval, then the response will include the transaction to approve the token. If the swapper has the required approval, then the response will be empty. If the parameter `includeGasInfo` is set to `true`, then the response will include the gas fee for the approval transaction.","operationId":"check_approval","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/ApprovalSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/ApprovalUnauthorized401"},"404":{"$ref":"#/components/responses/ApprovalNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/quote":{"post":{"tags":["Quote"],"summary":"Get a quote","description":"Get a quote according to the provided configuration. Optionally adds a fee to the quote according to the API key being used. The fee is **ALWAYS** taken from the output token. If there is a fee and the trade is `EXACT_INPUT`, then the output amount will **NOT** include the fee subtraction. For `EXACT_INPUT` swaps, use `portionBips` to calculate the fee from the quoted amount. If there is a fee and the trade is `EXACT_OUTPUT`, then the input amount will **NOT** include the fee addition to account for the fee. For `EXACT_OUTPUT` swaps, use `portionAmount` to get the fee. \n \n We also support Wrapping and Unwrapping of native tokens on their respective chains. Wrapping and Unwrapping only works for when `routingPreference` is `CLASSIC`, `BEST_PRICE`, or `BEST_PRICE_V2`. We do not support `UNISWAPX` or `UNISWAPX_V2` for these actions.","operationId":"aggregator_quote","security":[{"apiKey":[]}],"parameters":[{"$ref":"#/components/parameters/universalRouterVersionHeader"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/QuoteSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/Unauthorized401"},"404":{"$ref":"#/components/responses/QuoteNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/order":{"post":{"tags":["Order"],"summary":"Create a gasless order","description":"Submits a new gasless encoded order. The order will be validated and if valid, will be submitted to the filler network. The network will try to fill the order at the quoted `startAmount`, and if not, the amount will start decaying until the `endAmount` is reached. While the order is within `decayEndTime`, the `orderStatus` is `open`. If the order does not get filled after the `decayEndTime` has passed, that is reflected in the `expired` `orderStatus`. then The order will be filled at the best price possible. Once the order is filled, `orderStatus` becomes `filled`.","operationId":"post_dutch_order","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderRequest"}}}},"responses":{"201":{"$ref":"#/components/responses/OrderSuccess201"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/Unauthorized401"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/orders":{"get":{"tags":["Order"],"summary":"Get gasless orders","description":"Retrieve gasless orders filtered by query param(s). Some fields on the order can be used as query param.","operationId":"get_dutch_order","security":[{"apiKey":[]}],"parameters":[{"$ref":"#/components/parameters/orderTypeParam"},{"$ref":"#/components/parameters/orderIdParam"},{"$ref":"#/components/parameters/orderIdsParam"},{"$ref":"#/components/parameters/limitParam"},{"$ref":"#/components/parameters/orderStatusParam"},{"$ref":"#/components/parameters/swapperParam"},{"$ref":"#/components/parameters/sortKeyParam"},{"$ref":"#/components/parameters/sortParam"},{"$ref":"#/components/parameters/fillerParam"},{"$ref":"#/components/parameters/cursorParam"}],"responses":{"200":{"$ref":"#/components/responses/OrdersSuccess200"},"400":{"$ref":"#/components/responses/OrdersBadRequest400"},"404":{"$ref":"#/components/responses/OrdersNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/swap":{"post":{"tags":["Swap"],"summary":"Create swap calldata","description":"Create the calldata for a swap transaction (including wrap/unwrap) against the Uniswap Protocols. If the `quote` parameter includes the fee parameters, then the calldata will include the fee disbursement. The gas estimates will be **more precise** when the the response calldata would be valid if submitted on-chain.","operationId":"create_swap_transaction","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSwapRequest"}}}},"parameters":[{"$ref":"#/components/parameters/universalRouterVersionHeader"}],"responses":{"200":{"$ref":"#/components/responses/CreateSwapSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/SwapUnauthorized401"},"404":{"$ref":"#/components/responses/SwapNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/swaps":{"get":{"tags":["Swap"],"summary":"Get swaps status","description":"Get the status of a swap or bridge transactions.","operationId":"get_swaps","security":[{"apiKey":[]}],"parameters":[{"$ref":"#/components/parameters/transactionHashParam"},{"$ref":"#/components/parameters/chainIdParam"}],"responses":{"200":{"$ref":"#/components/responses/GetSwapsSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"404":{"$ref":"#/components/responses/SwapNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/indicative_quote":{"post":{"tags":["IndicativeQuote"],"summary":"Get an indicative quote","description":"Get an indicative quote according to the provided configuration. The quote will not include a fee.","operationId":"indicative_quote","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IndicativeQuoteRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/IndicativeQuoteSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"404":{"$ref":"#/components/responses/QuoteNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/send":{"post":{"tags":["Send"],"summary":"Create send calldata","description":"Create the calldata for a send transaction.","operationId":"create_send","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSendRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/CreateSendSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/Unauthorized401"},"404":{"$ref":"#/components/responses/SendNotFound404"},"429":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/swappable_tokens":{"get":{"tags":["SwappableTokens"],"summary":"Get swappable tokens","description":"Get the swappable tokens for the given configuration. Either tokenIn (with tokenInChainId or (tokenInChainId and tokenOutChainId)) or tokenOut (with tokenOutChainId or (tokenOutChainId and tokenInChainId)) must be provided but not both.","operationId":"get_swappable_tokens","security":[{"apiKey":[]}],"parameters":[{"$ref":"#/components/parameters/tokenInParam"},{"$ref":"#/components/parameters/tokenOutParam"},{"$ref":"#/components/parameters/bridgeTokenInChainIdParam"},{"$ref":"#/components/parameters/bridgeTokenOutChainIdParam"}],"responses":{"200":{"$ref":"#/components/responses/GetSwappableTokensSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/Unauthorized401"},"404":{"$ref":"#/components/responses/QuoteNotFound404"},"429":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/limit_order_quote":{"post":{"tags":["LimitOrderQuote"],"summary":"Get a limit order quote","description":"Get a quote for a limit order according to the provided configuration.","operationId":"get_limit_order_quote","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LimitOrderQuoteRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/LimitOrderQuoteSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/Unauthorized401"},"404":{"$ref":"#/components/responses/QuoteNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/check_approval_lp":{"post":{"tags":["Liquidity"],"summary":"Check if tokens and permits need to be approved to add liquidity","description":"Checks if the wallet address has the required approvals. If the wallet address does not have the required approval, then the response will include the transactions to approve the tokens. If the wallet address has the required approval, then the response will be empty for the corresponding tokens. If the parameter `includeGasInfo` is set to `true`, then the response will include the gas fees for the approval transactions.","operationId":"check_approval_lp","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckApprovalLPRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/CheckApprovalLPSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/ApprovalUnauthorized401"},"404":{"$ref":"#/components/responses/ApprovalNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/create_lp_position":{"post":{"tags":["Liquidity"],"summary":"Create pool and position calldata","description":"Create pool and position calldata. If the pool is not yet created, then the response will include the transaction to create the new pool with the initial price. If the pool is already created, then the response will not have the transaction to create the pool. The response will also have the transaction to create the position for the corresponding pool. If the parameter `includeGasInfo` is set to `true`, then the response will include the gas fees for the creation transactions.","operationId":"create_lp_position","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLPPositionRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/CreateLPPositionSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/ApprovalUnauthorized401"},"404":{"$ref":"#/components/responses/LPNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/increase_lp_position":{"post":{"tags":["Liquidity"],"summary":"Increase LP position calldata","description":"The response will also have the transaction to increase the position for the corresponding pool. If the parameter `includeGasInfo` is set to `true`, then the response will include the gas fees for the increase transaction.","operationId":"increase_lp_position","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncreaseLPPositionRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/IncreaseLPPositionSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/ApprovalUnauthorized401"},"404":{"$ref":"#/components/responses/LPNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/reduce_lp_position":{"post":{"tags":["Liquidity"],"summary":"Reduce LP position calldata","description":"The response will also have the transaction to reduce the position for the corresponding pool. If the parameter `includeGasInfo` is set to `true`, then the response will include the gas fees for the reduce transaction.","operationId":"reduce_lp_position","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReduceLPPositionRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/ReduceLPPositionSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/ApprovalUnauthorized401"},"404":{"$ref":"#/components/responses/LPNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}},"/claim_lp_fees":{"post":{"tags":["Liquidity"],"summary":"Claim LP fees calldata","description":"The response will also have the transaction to claim the fees for an LP position for the corresponding pool. If the parameter `includeGasInfo` is set to `true`, then the response will include the gas fees for the claim transaction.","operationId":"claim_lp_fees","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimLPFeesRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/ClaimLPFeesSuccess200"},"400":{"$ref":"#/components/responses/BadRequest400"},"401":{"$ref":"#/components/responses/ApprovalUnauthorized401"},"404":{"$ref":"#/components/responses/LPNotFound404"},"419":{"$ref":"#/components/responses/RateLimitedErr429"},"500":{"$ref":"#/components/responses/InternalErr500"},"504":{"$ref":"#/components/responses/Timeout504"}}}}},"components":{"responses":{"OrdersSuccess200":{"description":"The request orders matching the query parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetOrdersResponse"}}}},"OrderSuccess201":{"description":"Encoded order submitted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderResponse"}}}},"QuoteSuccess200":{"description":"Quote request successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteResponse"}}}},"LimitOrderQuoteSuccess200":{"description":"Limit Order Quote request successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LimitOrderQuoteResponse"}}}},"CheckApprovalLPSuccess200":{"description":"Approve LP successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckApprovalLPResponse"}}}},"ApprovalSuccess200":{"description":"Check approval successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalResponse"}}}},"CreateSendSuccess200":{"description":"Create send successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSendResponse"}}}},"CreateSwapSuccess200":{"description":"Create swap successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSwapResponse"}}}},"GetSwapsSuccess200":{"description":"Get swap successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSwapsResponse"}}}},"GetSwappableTokensSuccess200":{"description":"Get swappable tokens successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSwappableTokensResponse"}}}},"CreateLPPositionSuccess200":{"description":"Create LP Position successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLPPositionResponse"}}}},"IncreaseLPPositionSuccess200":{"description":"Create LP Position successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncreaseLPPositionResponse"}}}},"ReduceLPPositionSuccess200":{"description":"Reduce LP Position successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReduceLPPositionResponse"}}}},"ClaimLPFeesSuccess200":{"description":"Claim LP Fees successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimLPFeesResponse"}}}},"BadRequest400":{"description":"RequestValidationError, Bad Input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err400"}}}},"ApprovalUnauthorized401":{"description":"UnauthorizedError eg. Account is blocked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err401"}}}},"ApprovalNotFound404":{"description":"ResourceNotFound eg. Token allowance not found or Gas info not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err404"}}}},"Unauthorized401":{"description":"UnauthorizedError eg. Account is blocked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err401"}}}},"QuoteNotFound404":{"description":"ResourceNotFound eg. No quotes available or Gas fee/price not available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err404"}}}},"SendNotFound404":{"description":"ResourceNotFound eg. Gas fee not available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err404"}}}},"SwapBadRequest400":{"description":"RequestValidationError, Bad Input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err400"}}}},"SwapUnauthorized401":{"description":"UnauthorizedError eg. Account is blocked or Fee is not enabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err401"}}}},"SwapNotFound404":{"description":"ResourceNotFound eg. No quotes available or Gas fee/price not available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err404"}}}},"OrdersNotFound404":{"description":"Orders not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err404"}}}},"LPNotFound404":{"description":"ResourceNotFound eg. Cant Find LP Position.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err404"}}}},"OrdersBadRequest400":{"description":"RequestValidationError eg. Token allowance not valid or Insufficient Funds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err400"}}}},"RateLimitedErr429":{"description":"Ratelimited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err429"}}}},"InternalErr500":{"description":"Unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err500"}}}},"Timeout504":{"description":"Request duration limit reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Err504"}}}},"IndicativeQuoteSuccess200":{"description":"Indicative quote request successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IndicativeQuoteResponse"}}}}},"schemas":{"NullablePermit":{"allOf":[{"$ref":"#/components/schemas/Permit"},{"type":"object","nullable":true}]},"TokenAmount":{"type":"string"},"SwapStatus":{"type":"string","enum":["PENDING","SUCCESS","NOT_FOUND","FAILED","EXPIRED"]},"FeeType":{"type":"string","enum":["legacy","eip1559"]},"GasEstimateLegacy":{"type":"object","properties":{"gasPrice":{"type":"string"},"gasLimit":{"type":"string"},"type":{"$ref":"#/components/schemas/FeeType","enum":["legacy"]},"strategy":{"$ref":"#/components/schemas/GasStrategy"},"gasFee":{"type":"string"}},"required":["gasPrice","gasLimit","type","strategy","gasFee"]},"GasEstimateEip1559":{"type":"object","properties":{"maxFeePerGas":{"type":"string"},"maxPriorityFeePerGas":{"type":"string"},"gasLimit":{"type":"string"},"type":{"$ref":"#/components/schemas/FeeType","enum":["eip1559"]},"strategy":{"$ref":"#/components/schemas/GasStrategy"},"gasFee":{"type":"string"}},"required":["maxFeePerGas","maxPriorityFeePerGas","gasLimit","type","strategy","gasFee"]},"GasEstimate":{"oneOf":[{"$ref":"#/components/schemas/GasEstimateLegacy"},{"$ref":"#/components/schemas/GasEstimateEip1559"}]},"GasStrategy":{"type":"object","properties":{"limitInflationFactor":{"type":"number"},"priceInflationFactor":{"type":"number"},"percentileThresholdFor1559Fee":{"type":"number"},"minPriorityFeeGwei":{"type":"number","nullable":true},"maxPriorityFeeGwei":{"type":"number","nullable":true}},"required":["limitInflationFactor","priceInflationFactor","percentileThresholdFor1559Fee"]},"GetSwapsResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"swaps":{"type":"array","items":{"type":"object","properties":{"swapType":{"$ref":"#/components/schemas/Routing"},"status":{"$ref":"#/components/schemas/SwapStatus"}}}}},"required":["requestId","status"]},"GetSwappableTokensResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"tokens":{"type":"array","items":{"type":"object","properties":{"address":{"$ref":"#/components/schemas/Address"},"chainId":{"$ref":"#/components/schemas/ChainId"},"name":{"type":"string"},"symbol":{"type":"string"},"project":{"$ref":"#/components/schemas/TokenProject"},"isSpam":{"type":"boolean"},"decimals":{"type":"number"}},"required":["address","chainId","name","symbol","project","decimals"]}}},"required":["requestId","tokens"]},"CreateSwapRequest":{"type":"object","description":"The parameters **signature** and **permitData** should only be included if *permitData* was returned from **/quote**.","properties":{"quote":{"oneOf":[{"$ref":"#/components/schemas/ClassicQuote"},{"$ref":"#/components/schemas/WrapUnwrapQuote"},{"$ref":"#/components/schemas/BridgeQuote"}]},"signature":{"type":"string","description":"The signed permit."},"includeGasInfo":{"type":"boolean","default":false,"deprecated":true,"description":"Use `refreshGasPrice` instead."},"refreshGasPrice":{"type":"boolean","default":false,"description":"If true, the gas price will be re-fetched from the network."},"simulateTransaction":{"type":"boolean","default":false,"description":"If true, the transaction will be simulated. If the simulation results on an onchain error, endpoint will return an error."},"permitData":{"allOf":[{"$ref":"#/components/schemas/Permit"}]},"safetyMode":{"$ref":"#/components/schemas/SwapSafetyMode"},"deadline":{"type":"integer","description":"The deadline for the swap in unix timestamp format. If the deadline is not defined OR in the past then the default deadline is 30 minutes."},"urgency":{"$ref":"#/components/schemas/Urgency"},"gasStrategies":{"type":"array","items":{"$ref":"#/components/schemas/GasStrategy"}}},"required":["quote"]},"CreateSendRequest":{"type":"object","properties":{"sender":{"$ref":"#/components/schemas/Address"},"recipient":{"$ref":"#/components/schemas/Address"},"token":{"$ref":"#/components/schemas/Address"},"amount":{"$ref":"#/components/schemas/TokenAmount"},"chainId":{"$ref":"#/components/schemas/ChainId"},"urgency":{"$ref":"#/components/schemas/Urgency"},"gasStrategies":{"type":"array","items":{"$ref":"#/components/schemas/GasStrategy"}}},"required":["sender","recipient","token","amount"]},"UniversalRouterVersion":{"type":"string","enum":["1.2","2.0"],"default":"1.2"},"Address":{"type":"string","pattern":"^(0x)?[0-9a-fA-F]{40}$"},"PositionConfig":{"type":"object","properties":{"poolKey":{"$ref":"#/components/schemas/RequestId"},"tickLower":{"type":"number"},"tickUpper":{"type":"number"}},"required":["poolKey","tickLower","tickUpper"]},"PoolKey":{"type":"object","properties":{"token0":{"$ref":"#/components/schemas/Address"},"token1":{"$ref":"#/components/schemas/Address"},"fee":{"type":"number"},"tickSpacing":{"type":"number"},"hooks":{"$ref":"#/components/schemas/Address"}},"required":["token0","token1","fee","tickSpacing"]},"ClassicGasUseEstimateUSD":{"description":"The gas fee you would pay if you opted for a CLASSIC swap over a Uniswap X order in terms of USD.","type":"string"},"CreateSwapResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"swap":{"$ref":"#/components/schemas/TransactionRequest"},"gasFee":{"type":"string"},"gasEstimates":{"type":"array","items":{"$ref":"#/components/schemas/GasEstimate"}}},"required":["requestId","swap"]},"CreateSendResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"send":{"$ref":"#/components/schemas/TransactionRequest"},"gasFee":{"type":"string"},"gasFeeUSD":{"type":"number"},"gasEstimates":{"type":"array","items":{"$ref":"#/components/schemas/GasEstimate"}}},"required":["requestId","send"]},"QuoteResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"quote":{"$ref":"#/components/schemas/Quote"},"routing":{"$ref":"#/components/schemas/Routing"},"permitData":{"$ref":"#/components/schemas/NullablePermit"}},"required":["routing","quote","permitData","requestId"]},"LimitOrderQuoteResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"quote":{"$ref":"#/components/schemas/DutchQuote"},"routing":{"type":"string","enum":["LIMIT_ORDER"]},"permitData":{"$ref":"#/components/schemas/NullablePermit"}},"required":["routing","quote","permitData","requestId"]},"QuoteRequest":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/TradeType"},"amount":{"type":"string"},"tokenInChainId":{"$ref":"#/components/schemas/ChainId"},"tokenOutChainId":{"$ref":"#/components/schemas/ChainId"},"tokenIn":{"type":"string"},"tokenOut":{"type":"string"},"swapper":{"$ref":"#/components/schemas/Address"},"slippageTolerance":{"description":"For **Classic** swaps, the slippage tolerance is the maximum amount the price can change between the time the transaction is submitted and the time it is executed. The slippage tolerance is represented as a percentage of the total value of the swap. \n\n Slippage tolerance works differently in **DutchLimit** swaps, it does not set a limit on the Spread in an order. See [here](https://uniswap-docs.readme.io/reference/faqs#why-do-the-uniswapx-quotes-have-more-slippage-than-the-tolerance-i-set) for more information. \n\n **NOTE**: slippage is in terms of trade type. If the trade type is `EXACT_INPUT`, then the slippage is in terms of the output token. If the trade type is `EXACT_OUTPUT`, then the slippage is in terms of the input token.","type":"number"},"autoSlippage":{"$ref":"#/components/schemas/AutoSlippage"},"routingPreference":{"$ref":"#/components/schemas/RoutingPreference"},"protocols":{"$ref":"#/components/schemas/Protocols"},"spreadOptimization":{"$ref":"#/components/schemas/SpreadOptimization"},"urgency":{"$ref":"#/components/schemas/Urgency"},"gasStrategies":{"type":"array","items":{"$ref":"#/components/schemas/GasStrategy"}}},"required":["type","amount","tokenInChainId","tokenOutChainId","tokenIn","tokenOut","swapper"]},"LimitOrderQuoteRequest":{"type":"object","properties":{"swapper":{"$ref":"#/components/schemas/Address"},"limitPrice":{"type":"string"},"amount":{"type":"string"},"orderDeadline":{"type":"number"},"type":{"$ref":"#/components/schemas/TradeType"},"tokenIn":{"type":"string"},"tokenOut":{"type":"string"},"tokenInChainId":{"$ref":"#/components/schemas/ChainId"},"tokenOutChainId":{"$ref":"#/components/schemas/ChainId"}},"required":["swapper","type","amount","tokenIn","tokenOut","tokenInChainId","tokenOutChainId"]},"GetOrdersResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"orders":{"type":"array","items":{"$ref":"#/components/schemas/UniswapXOrder"}},"cursor":{"type":"string"}},"required":["orders","requestId"]},"OrderResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"orderId":{"type":"string"},"orderStatus":{"$ref":"#/components/schemas/OrderStatus"}},"required":["requestId","orderId","orderStatus"]},"OrderRequest":{"type":"object","properties":{"signature":{"type":"string","description":"The signed permit."},"quote":{"oneOf":[{"$ref":"#/components/schemas/DutchQuote"},{"$ref":"#/components/schemas/DutchQuoteV2"}]},"routing":{"$ref":"#/components/schemas/Routing"}},"required":["signature","quote"]},"Urgency":{"type":"string","enum":["normal","fast","urgent"],"description":"The urgency determines the urgency of the transaction. The default value is `urgent`.","default":"urgent"},"Protocols":{"type":"array","items":{"$ref":"#/components/schemas/ProtocolItems"},"description":"The protocols to use for the swap/order. If the `protocols` field is defined, then you can only set the `routingPreference` to `BEST_PRICE`"},"Err400":{"type":"object","properties":{"errorCode":{"default":"RequestValidationError","type":"string"},"detail":{"type":"string"}}},"Err401":{"type":"object","properties":{"errorCode":{"default":"UnauthorizedError","type":"string"},"detail":{"type":"string"}}},"Err404":{"type":"object","properties":{"errorCode":{"default":"ResourceNotFound","type":"string"},"detail":{"type":"string"}}},"Err429":{"type":"object","properties":{"errorCode":{"default":"Ratelimited","type":"string"},"detail":{"type":"string"}}},"Err500":{"type":"object","properties":{"errorCode":{"default":"InternalServerError","type":"string"},"detail":{"type":"string"}}},"Err504":{"type":"object","properties":{"errorCode":{"default":"Timeout","type":"string"},"detail":{"type":"string"}}},"ChainId":{"type":"number","enum":[1,10,56,137,8453,42161,81457,43114,42220,7777777,324]},"OrderInput":{"type":"object","properties":{"token":{"type":"string"},"startAmount":{"type":"string"},"endAmount":{"type":"string"}},"required":["token"]},"OrderOutput":{"type":"object","properties":{"token":{"type":"string"},"startAmount":{"type":"string"},"endAmount":{"type":"string"},"isFeeOutput":{"type":"boolean"},"recipient":{"type":"string"}},"required":["token"]},"CosignerData":{"type":"object","properties":{"decayStartTime":{"type":"number"},"decayEndTime":{"type":"number"},"exclusiveFiller":{"type":"string"},"inputOverride":{"type":"string"},"outputOverrides":{"type":"array","items":{"type":"string"}}}},"SettledAmount":{"type":"object","properties":{"tokenOut":{"$ref":"#/components/schemas/Address"},"amountOut":{"type":"string"},"tokenIn":{"$ref":"#/components/schemas/Address"},"amountIn":{"type":"string"}}},"OrderType":{"type":"string","enum":["DutchLimit","Dutch","Dutch_V2"]},"OrderTypeQuery":{"type":"string","enum":["Dutch","Dutch_V2","Dutch_V1_V2","Limit"]},"UniswapXOrder":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/OrderType"},"encodedOrder":{"type":"string"},"signature":{"type":"string"},"nonce":{"type":"string"},"orderStatus":{"$ref":"#/components/schemas/OrderStatus"},"orderId":{"type":"string"},"chainId":{"$ref":"#/components/schemas/ChainId"},"quoteId":{"type":"string"},"swapper":{"type":"string"},"txHash":{"type":"string"},"input":{"$ref":"#/components/schemas/OrderInput"},"outputs":{"type":"array","items":{"$ref":"#/components/schemas/OrderOutput"}},"settledAmounts":{"type":"array","items":{"$ref":"#/components/schemas/SettledAmount"}},"cosignature":{"type":"string"},"cosignerData":{"$ref":"#/components/schemas/CosignerData"}},"required":["encodedOrder","signature","nonce","orderId","orderStatus","chainId","type"]},"SortKey":{"type":"string","enum":["createdAt"]},"OrderId":{"type":"string"},"OrderIds":{"type":"string"},"OrderStatus":{"type":"string","enum":["open","expired","error","cancelled","filled","unverified","insufficient-funds"]},"Permit":{"type":"object","properties":{"domain":{"type":"object"},"values":{"type":"object"},"types":{"type":"object"}}},"TokenProject":{"type":"object","properties":{"logo":{"$ref":"#/components/schemas/TokenProjectLogo"},"safetyLevel":{"$ref":"#/components/schemas/SafetyLevel"},"isSpam":{"type":"boolean"}},"required":["logo","safetyLevel","isSpam"]},"TokenProjectLogo":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"DutchInput":{"type":"object","properties":{"startAmount":{"type":"string"},"endAmount":{"type":"string"},"token":{"type":"string"}},"required":["startAmount","endAmount","type"]},"DutchOutput":{"type":"object","properties":{"startAmount":{"type":"string"},"endAmount":{"type":"string"},"token":{"type":"string"},"recipient":{"type":"string"}},"required":["startAmount","endAmount","token","recipient"]},"DutchOrderInfo":{"type":"object","properties":{"chainId":{"$ref":"#/components/schemas/ChainId"},"nonce":{"type":"string"},"reactor":{"type":"string"},"swapper":{"type":"string"},"deadline":{"type":"number"},"additionalValidationContract":{"type":"string"},"additionalValidationData":{"type":"string"},"decayStartTime":{"type":"number"},"decayEndTime":{"type":"number"},"exclusiveFiller":{"type":"string"},"exclusivityOverrideBps":{"type":"string"},"input":{"$ref":"#/components/schemas/DutchInput"},"outputs":{"type":"array","items":{"$ref":"#/components/schemas/DutchOutput"}}},"required":["chainId","nonce","reactor","swapper","deadline","validationContract","validationData","startTime","endTime","exclusiveFiller","exclusivityOverrideBps","input","outputs"]},"DutchOrderInfoV2":{"type":"object","properties":{"chainId":{"$ref":"#/components/schemas/ChainId"},"nonce":{"type":"string"},"reactor":{"type":"string"},"swapper":{"type":"string"},"deadline":{"type":"number"},"additionalValidationContract":{"type":"string"},"additionalValidationData":{"type":"string"},"input":{"$ref":"#/components/schemas/DutchInput"},"outputs":{"type":"array","items":{"$ref":"#/components/schemas/DutchOutput"}},"cosigner":{"$ref":"#/components/schemas/Address"}},"required":["chainId","nonce","reactor","swapper","deadline","validationContract","validationData","startTime","endTime","exclusiveFiller","exclusivityOverrideBps","input","outputs"]},"DutchQuote":{"type":"object","properties":{"encodedOrder":{"type":"string"},"orderId":{"type":"string"},"orderInfo":{"$ref":"#/components/schemas/DutchOrderInfo"},"portionBips":{"type":"number"},"portionAmount":{"type":"string"},"portionRecipient":{"$ref":"#/components/schemas/Address"},"quoteId":{"type":"string"},"slippageTolerance":{"type":"number"},"classicGasUseEstimateUSD":{"$ref":"#/components/schemas/ClassicGasUseEstimateUSD"}},"required":["encodedOrder","orderInfo","orderId"]},"DutchQuoteV2":{"type":"object","properties":{"encodedOrder":{"type":"string"},"orderId":{"type":"string"},"orderInfo":{"$ref":"#/components/schemas/DutchOrderInfoV2"},"portionBips":{"type":"number"},"portionAmount":{"type":"string"},"portionRecipient":{"$ref":"#/components/schemas/Address"},"quoteId":{"type":"string"},"slippageTolerance":{"type":"number"},"deadlineBufferSecs":{"type":"number"},"classicGasUseEstimateUSD":{"$ref":"#/components/schemas/ClassicGasUseEstimateUSD"}},"required":["encodedOrder","orderInfo","orderId"]},"BridgeQuote":{"type":"object","properties":{"quoteId":{"type":"string"},"chainId":{"$ref":"#/components/schemas/ChainId"},"destinationChainId":{"$ref":"#/components/schemas/ChainId"},"swapper":{"$ref":"#/components/schemas/Address"},"input":{"$ref":"#/components/schemas/ClassicInput"},"output":{"$ref":"#/components/schemas/ClassicOutput"},"tradeType":{"$ref":"#/components/schemas/TradeType"},"quoteTimestamp":{"type":"number"},"gasPrice":{"type":"string"},"maxFeePerGas":{"type":"string"},"maxPriorityFeePerGas":{"type":"string"},"gasFee":{"type":"string"},"gasUseEstimate":{"type":"string"},"gasFeeUSD":{"type":"string"},"portionBips":{"type":"number"},"portionAmount":{"type":"string"},"portionRecipient":{"$ref":"#/components/schemas/Address"}}},"SafetyLevel":{"type":"string","enum":["BLOCKED","MEDIUM_WARNING","STRONG_WARNING","VERIFIED"]},"TradeType":{"type":"string","enum":["EXACT_INPUT","EXACT_OUTPUT"]},"Routing":{"type":"string","enum":["DUTCH_LIMIT","CLASSIC","DUTCH_V2","BRIDGE","LIMIT_ORDER"]},"Quote":{"oneOf":[{"$ref":"#/components/schemas/DutchQuote"},{"$ref":"#/components/schemas/ClassicQuote"},{"$ref":"#/components/schemas/WrapUnwrapQuote"},{"$ref":"#/components/schemas/DutchQuoteV2"},{"$ref":"#/components/schemas/BridgeQuote"}]},"CheckApprovalLPRequest":{"type":"object","properties":{"token0":{"$ref":"#/components/schemas/Address"},"token1":{"$ref":"#/components/schemas/Address"},"walletAddress":{"$ref":"#/components/schemas/Address"},"amount0":{"type":"string"},"amount1":{"type":"string"},"includeGasInfo":{"type":"boolean"}}},"CheckApprovalLPResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"token0Approval":{"$ref":"#/components/schemas/TransactionRequest"},"token1Approval":{"$ref":"#/components/schemas/TransactionRequest"},"batchedPermit2Data":{"$ref":"#/components/schemas/NullablePermit"},"gasFee0":{"type":"string"},"gasFee1":{"type":"string"}}},"ApprovalRequest":{"type":"object","properties":{"walletAddress":{"$ref":"#/components/schemas/Address"},"token":{"$ref":"#/components/schemas/Address"},"amount":{"$ref":"#/components/schemas/TokenAmount"},"chainId":{"$ref":"#/components/schemas/ChainId"},"urgency":{"$ref":"#/components/schemas/Urgency"},"gasStrategies":{"type":"array","items":{"$ref":"#/components/schemas/GasStrategy"}},"includeGasInfo":{"type":"boolean","default":false},"tokenOut":{"$ref":"#/components/schemas/Address"},"tokenOutChainId":{"$ref":"#/components/schemas/ChainId"}},"required":["walletAddress","token","amount"]},"ApprovalResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"approval":{"$ref":"#/components/schemas/TransactionRequest"},"cancel":{"$ref":"#/components/schemas/TransactionRequest"},"gasFee":{"type":"string"},"cancelGasFee":{"type":"string"},"gasEstimates":{"type":"array","items":{"$ref":"#/components/schemas/GasEstimate"}}},"required":["requestId","approval","cancel"]},"ClassicQuote":{"type":"object","properties":{"input":{"$ref":"#/components/schemas/ClassicInput"},"output":{"$ref":"#/components/schemas/ClassicOutput"},"swapper":{"$ref":"#/components/schemas/Address"},"chainId":{"$ref":"#/components/schemas/ChainId"},"slippage":{"type":"number"},"tradeType":{"$ref":"#/components/schemas/TradeType"},"gasFee":{"type":"string","description":"The gas fee in terms of wei. It does NOT include the additional gas for token approvals."},"gasFeeUSD":{"type":"string","description":"The gas fee in terms of USD. It does NOT include the additional gas for token approvals."},"gasFeeQuote":{"type":"string","description":"The gas fee in terms of the quoted currency. It does NOT include the additional gas for token approvals."},"gasEstimates":{"type":"array","items":{"$ref":"#/components/schemas/GasEstimate"}},"route":{"type":"array","items":{"type":"array","items":{"oneOf":[{"$ref":"#/components/schemas/V3PoolInRoute"},{"$ref":"#/components/schemas/V2PoolInRoute"}]}}},"portionBips":{"type":"number","description":"The portion of the swap that will be taken as a fee. The fee will be taken from the output token."},"portionAmount":{"type":"string","description":"The amount of the swap that will be taken as a fee. The fee will be taken from the output token."},"portionRecipient":{"$ref":"#/components/schemas/Address"},"routeString":{"type":"string","description":"The route in string format."},"quoteId":{"type":"string","description":"The quote id. Used for analytics purposes."},"gasUseEstimate":{"type":"string","description":"The estimated gas use. It does NOT include the additional gas for token approvals."},"blockNumber":{"type":"string","description":"The current block number."},"gasPrice":{"type":"string","description":"The gas price in terms of wei for pre EIP1559 transactions."},"maxFeePerGas":{"type":"string","description":"The maximum fee per gas in terms of wei for EIP1559 transactions."},"maxPriorityFeePerGas":{"type":"string","description":"The maximum priority fee per gas in terms of wei for EIP1559 transactions."},"txFailureReasons":{"type":"array","items":{"$ref":"#/components/schemas/TransactionFailureReason"}},"priceImpact":{"type":"number","description":"The impact the trade has on the market price of the pool, between 0-100 percent"}}},"WrapUnwrapQuote":{"type":"object","properties":{"swapper":{"$ref":"#/components/schemas/Address"},"input":{"$ref":"#/components/schemas/ClassicInput"},"output":{"$ref":"#/components/schemas/ClassicOutput"},"chainId":{"$ref":"#/components/schemas/ChainId"},"tradeType":{"$ref":"#/components/schemas/TradeType"},"gasFee":{"type":"string","description":"The gas fee in terms of wei."},"gasFeeUSD":{"type":"string","description":"The gas fee in terms of USD."},"gasFeeQuote":{"type":"string","description":"The gas fee in terms of the quoted currency."},"gasUseEstimate":{"type":"string","description":"The estimated gas use."},"gasPrice":{"type":"string","description":"The gas price in terms of wei for pre EIP1559 transactions."},"maxFeePerGas":{"type":"string","description":"The maximum fee per gas in terms of wei for EIP1559 transactions."},"maxPriorityFeePerGas":{"type":"string","description":"The maximum priority fee per gas in terms of wei for EIP1559 transactions."}}},"TokenInRoute":{"type":"object","properties":{"address":{"$ref":"#/components/schemas/Address"},"chainId":{"$ref":"#/components/schemas/ChainId"},"symbol":{"type":"string"},"decimals":{"type":"string"},"buyFeeBps":{"type":"string"},"sellFeeBps":{"type":"string"}}},"V2Reserve":{"type":"object","properties":{"token":{"$ref":"#/components/schemas/TokenInRoute"},"quotient":{"type":"string"}}},"V2PoolInRoute":{"type":"object","properties":{"type":{"type":"string","default":"v2-pool"},"address":{"$ref":"#/components/schemas/Address"},"tokenIn":{"$ref":"#/components/schemas/TokenInRoute"},"tokenOut":{"$ref":"#/components/schemas/TokenInRoute"},"reserve0":{"$ref":"#/components/schemas/V2Reserve"},"reserve1":{"$ref":"#/components/schemas/V2Reserve"},"amountIn":{"type":"string"},"amountOut":{"type":"string"}}},"V3PoolInRoute":{"type":"object","properties":{"type":{"type":"string","default":"v3-pool"},"address":{"$ref":"#/components/schemas/Address"},"tokenIn":{"$ref":"#/components/schemas/TokenInRoute"},"tokenOut":{"$ref":"#/components/schemas/TokenInRoute"},"sqrtRatioX96":{"type":"string"},"liquidity":{"type":"string"},"tickCurrent":{"type":"string"},"fee":{"type":"string"},"amountIn":{"type":"string"},"amountOut":{"type":"string"}}},"TransactionHash":{"type":"string","pattern":"^(0x)?[0-9a-fA-F]{64}$"},"ClassicInput":{"type":"object","properties":{"token":{"$ref":"#/components/schemas/Address"},"amount":{"type":"string"}}},"ClassicOutput":{"type":"object","properties":{"token":{"$ref":"#/components/schemas/Address"},"amount":{"type":"string"},"recipient":{"$ref":"#/components/schemas/Address"}}},"RequestId":{"type":"string"},"SpreadOptimization":{"type":"string","enum":["EXECUTION","PRICE"],"description":"For **Dutch Limit** orders only. When set to `EXECUTION`, quotes optimize for looser spreads at higher fill rates. When set to `PRICE`, quotes optimize for tighter spreads at lower fill rates","default":"EXECUTION"},"AutoSlippage":{"type":"string","enum":["DEFAULT"],"description":"For **Classic** swaps only. The auto slippage strategy to employ. If auto slippage is not defined then we don't compute it. If the auto slippage strategy is `DEFAULT`, then the swap will use the default slippage tolerance computation. You cannot define auto slippage and slippage tolerance at the same time. \n\n **NOTE**: slippage is in terms of trade type. If the trade type is `EXACT_INPUT`, then the slippage is in terms of the output token. If the trade type is `EXACT_OUTPUT`, then the slippage is in terms of the input token.","default":"undefined"},"RoutingPreference":{"type":"string","description":"The routing preference determines which protocol to use for the swap. If the routing preference is `UNISWAPX`, then the swap will be routed through the UniswapX Dutch Auction Protocol. If the routing preference is `CLASSIC`, then the swap will be routed through the Classic Protocol. If the routing preference is `BEST_PRICE`, then the swap will be routed through the protocol that provides the best price. When `UNIXWAPX_V2` is passed, the swap will be routed through the UniswapX V2 Dutch Auction Protocol. When `V3_ONLY` is passed, the swap will be routed ONLY through the Uniswap V3 Protocol. When `V2_ONLY` is passed, the swap will be routed ONLY through the Uniswap V2 Protocol.","enum":["CLASSIC","UNISWAPX","BEST_PRICE","BEST_PRICE_V2","UNISWAPX_V2","V3_ONLY","V2_ONLY"],"default":"BEST_PRICE"},"ProtocolItems":{"type":"string","enum":["V2","V3","V4","UNISWAPX","UNISWAPX_V2"]},"TransactionRequest":{"type":"object","properties":{"to":{"$ref":"#/components/schemas/Address"},"from":{"$ref":"#/components/schemas/Address"},"data":{"type":"string","description":"The calldata for the transaction."},"value":{"type":"string","description":"The value of the transaction in terms of wei in hex format."},"gasLimit":{"type":"string"},"chainId":{"type":"integer"},"maxFeePerGas":{"type":"string"},"maxPriorityFeePerGas":{"type":"string"},"gasPrice":{"type":"string"}},"required":["to","from","data","value","chainId"]},"TransactionFailureReason":{"type":"string","enum":["SIMULATION_ERROR","UNSUPPORTED_SIMULATION"]},"SwapSafetyMode":{"type":"string","enum":["SAFE"],"description":"The safety mode determines the safety level of the swap. If the safety mode is `SAFE`, then the swap will include a SWEEP for the native token."},"IndicativeQuoteRequest":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/TradeType"},"amount":{"type":"string"},"tokenInChainId":{"$ref":"#/components/schemas/ChainId"},"tokenOutChainId":{"$ref":"#/components/schemas/ChainId"},"tokenIn":{"type":"string"},"tokenOut":{"type":"string"}},"required":["type","amount","tokenInChainId","tokenOutChainId","tokenIn","tokenOut"]},"IndicativeQuoteResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"input":{"$ref":"#/components/schemas/IndicativeQuoteToken"},"output":{"$ref":"#/components/schemas/IndicativeQuoteToken"},"type":{"$ref":"#/components/schemas/TradeType"}},"required":["requestId","input","output","type"]},"CreateLPPositionRequest":{"type":"object","properties":{"positionConfig":{"$ref":"#/components/schemas/PositionConfig"},"walletAddress":{"$ref":"#/components/schemas/Address"},"amount0":{"type":"string"},"amount1":{"type":"string"},"amount0Max":{"type":"string"},"amount1Max":{"type":"string"},"initialPrice":{"type":"string"},"signedBatchedPermit2Data":{"type":"string"},"includeGasInfo":{"type":"boolean"}}},"CreateLPPositionResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"create":{"$ref":"#/components/schemas/TransactionRequest"},"gasFee":{"type":"string"}}},"IncreaseLPPositionRequest":{"type":"object","properties":{"positionConfigId":{"type":"string"},"walletAddress":{"$ref":"#/components/schemas/Address"},"amount0":{"type":"string"},"amount1":{"type":"string"},"amount0Max":{"type":"string"},"amount1Max":{"type":"string"},"includeGasInfo":{"type":"boolean"}}},"IncreaseLPPositionResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"increase":{"$ref":"#/components/schemas/TransactionRequest"},"gasFee":{"type":"string"}}},"ReduceLPPositionRequest":{"type":"object","properties":{"positionConfigId":{"type":"string"},"walletAddress":{"$ref":"#/components/schemas/Address"},"amount0":{"type":"string"},"amount1":{"type":"string"},"amount0Max":{"type":"string"},"amount1Max":{"type":"string"},"collectAsWeth":{"type":"boolean"},"includeGasInfo":{"type":"boolean"}}},"ReduceLPPositionResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"reduce":{"$ref":"#/components/schemas/TransactionRequest"},"gasFee":{"type":"string"}}},"ClaimLPFeesRequest":{"type":"object","properties":{"positionConfigId":{"type":"string"},"walletAddress":{"$ref":"#/components/schemas/Address"},"collectAsWeth":{"type":"boolean"},"includeGasInfo":{"type":"boolean"}}},"ClaimLPFeesResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"claim":{"$ref":"#/components/schemas/TransactionRequest"},"gasFee":{"type":"string"}}},"IndicativeQuoteToken":{"type":"object","properties":{"amount":{"type":"string"},"chainId":{"$ref":"#/components/schemas/ChainId"},"token":{"$ref":"#/components/schemas/Address"}}}},"parameters":{"universalRouterVersionHeader":{"name":"x-universal-router-version","in":"header","description":"The version of the Universal Router to use for the swap journey. *MUST* be consistent throughout the API calls.","required":false,"schema":{"$ref":"#/components/schemas/UniversalRouterVersion"}},"addressParam":{"name":"address","in":"path","schema":{"$ref":"#/components/schemas/Address"},"required":true},"tokenIdParam":{"name":"tokenId","in":"path","schema":{"type":"string"},"required":true},"cursorParam":{"name":"cursor","in":"query","schema":{"type":"string"},"required":false},"limitParam":{"name":"limit","in":"query","schema":{"type":"number"},"required":false},"chainIdParam":{"name":"chainId","in":"query","schema":{"$ref":"#/components/schemas/ChainId"},"required":false},"bridgeTokenInChainIdParam":{"name":"tokenInChainId","in":"query","schema":{"$ref":"#/components/schemas/ChainId"},"required":false},"bridgeTokenOutChainIdParam":{"name":"tokenOutChainId","in":"query","schema":{"$ref":"#/components/schemas/ChainId"},"required":false},"tokenInParam":{"name":"tokenIn","in":"query","schema":{"$ref":"#/components/schemas/Address"},"required":false},"tokenOutParam":{"name":"tokenOut","in":"query","schema":{"$ref":"#/components/schemas/Address"},"required":false},"addressPathParam":{"name":"address","in":"query","schema":{"$ref":"#/components/schemas/Address"},"required":false},"orderStatusParam":{"name":"orderStatus","in":"query","description":"Filter by order status.","required":false,"schema":{"$ref":"#/components/schemas/OrderStatus"}},"orderTypeParam":{"name":"orderType","in":"query","description":"The default orderType is Dutch_V1_V2 and will grab both Dutch and Dutch_V2 orders.","required":false,"schema":{"$ref":"#/components/schemas/OrderTypeQuery"}},"orderIdParam":{"name":"orderId","in":"query","required":false,"schema":{"$ref":"#/components/schemas/OrderId"}},"orderIdsParam":{"name":"orderIds","in":"query","required":false,"description":"ids split by commas","schema":{"$ref":"#/components/schemas/OrderIds"}},"swapperParam":{"name":"swapper","in":"query","description":"Filter by swapper address.","required":false,"schema":{"$ref":"#/components/schemas/Address"}},"fillerParam":{"name":"filler","in":"query","description":"Filter by filler address.","required":false,"schema":{"$ref":"#/components/schemas/Address"}},"sortKeyParam":{"name":"sortKey","in":"query","description":"Order the query results by the sort key.","required":false,"schema":{"$ref":"#/components/schemas/SortKey"}},"sortParam":{"name":"sort","in":"query","description":"Sort query. For example: `sort=gt(UNIX_TIMESTAMP)`, `sort=between(1675872827, 1675872930)`, or `lt(1675872930)`.","required":false,"schema":{"type":"string"}},"descParam":{"description":"Sort query results by sortKey in descending order.","name":"desc","in":"query","required":false,"schema":{"type":"string"}},"transactionHashParam":{"description":"The transaction hash.","name":"txHash","in":"query","required":true,"schema":{"$ref":"#/components/schemas/TransactionHash"}}},"securitySchemes":{"apiKey":{"type":"apiKey","in":"header","name":"x-api-key"}}},"security":[{"apiKey":[]}]} \ No newline at end of file diff --git a/packages/uniswap/src/data/tradingApi/modifyTradingApiTypes.mts b/packages/uniswap/src/data/tradingApi/modifyTradingApiTypes.mts deleted file mode 100644 index 1235b639238..00000000000 --- a/packages/uniswap/src/data/tradingApi/modifyTradingApiTypes.mts +++ /dev/null @@ -1,92 +0,0 @@ -import { Project, SourceFile, TypeLiteralNode } from 'ts-morph' - -const project = new Project() - -const path = './src/data/tradingApi/__generated__/models' - -// Request types -const approvalRequestFile = project.addSourceFileAtPath(`${path}/ApprovalRequest.ts`) -const createSendRequestFile = project.addSourceFileAtPath(`${path}/CreateSendRequest.ts`) -const createSwapRequestFile = project.addSourceFileAtPath(`${path}/CreateSwapRequest.ts`) -const quoteRequestFile = project.addSourceFileAtPath(`${path}/QuoteRequest.ts`) -const requestFiles = [approvalRequestFile, createSendRequestFile, createSwapRequestFile, quoteRequestFile] - -// Response types -const approvalResponseFile = project.addSourceFileAtPath(`${path}/ApprovalResponse.ts`) -const createSwapResponseFile = project.addSourceFileAtPath(`${path}/CreateSwapResponse.ts`) -const createSendResponseFile = project.addSourceFileAtPath(`${path}/CreateSendResponse.ts`) -const classicQuoteFile = project.addSourceFileAtPath(`${path}/ClassicQuote.ts`) -const responseFiles = [approvalResponseFile, createSwapResponseFile, createSendResponseFile, classicQuoteFile] - -function addImport(file: SourceFile, importName: string) { - if (!file.getImportDeclaration((imp) => imp.getModuleSpecifierValue() === '../../types')) { - file.addImportDeclaration({ - namedImports: [importName], - moduleSpecifier: '../../types', - }) - } else { - const existingImport = file.getImportDeclaration((imp) => imp.getModuleSpecifierValue() === '../../types') - if ( - existingImport && - !existingImport.getNamedImports().some((namedImport) => namedImport.getName() === importName) - ) { - existingImport.addNamedImport(importName) - } - } -} - -function modifyType( - file: SourceFile, - typeName: string, - newProperties: { name: string; type: string; isOptional?: boolean }[], -) { - const typeAlias = file.getTypeAlias(typeName) - if (typeAlias) { - const typeNode = typeAlias.getTypeNode() - if (typeNode && TypeLiteralNode.isTypeLiteral(typeNode)) { - newProperties.forEach((prop) => { - const existingProperty = typeNode.getProperty(prop.name) - if (!existingProperty) { - typeNode.addProperty({ - name: prop.name, - type: prop.type, - hasQuestionToken: prop.isOptional, - }) - console.log(`Added property ${prop.name} to ${typeName}`) - } else { - console.log(`Property ${prop.name} already exists in ${typeName}`) - } - }) - } else { - console.log(`Type ${typeName} is not an object type`) - } - } else { - console.log(`Type ${typeName} not found`) - } -} - -// Modify the request interfaces -requestFiles.forEach((file) => { - addImport(file, 'GasStrategy') - modifyType(file, file.getBaseName().replace('.ts', ''), [ - { name: 'gasStrategies', type: 'GasStrategy[]', isOptional: true }, - ]) -}) - -// Modify the response interfaces -responseFiles.forEach((file) => { - addImport(file, 'GasEstimate') - modifyType(file, file.getBaseName().replace('.ts', ''), [ - { name: 'gasEstimates', type: 'GasEstimate[]', isOptional: true }, - ]) -}) - -// Save the changes -requestFiles.forEach((file) => { - file.saveSync() -}) -responseFiles.forEach((file) => { - file.saveSync() -}) - -console.log('Trading API types have been updated') diff --git a/packages/uniswap/src/data/tradingApi/types.ts b/packages/uniswap/src/data/tradingApi/types.ts deleted file mode 100644 index ccc73569b90..00000000000 --- a/packages/uniswap/src/data/tradingApi/types.ts +++ /dev/null @@ -1,35 +0,0 @@ -// These types are used in the gas estimation improvement experiment. -// They are internal to uniswap, so they are not declared in the Trading API public definition. -// Once the experiment is complete, we can remove them easily or add them to the public API definition. - -export enum FeeType { - LEGACY = 'legacy', - EIP1559 = 'eip1559', -} - -export interface GasStrategy { - limitInflationFactor: number - priceInflationFactor: number - percentileThresholdFor1559Fee: number - minPriorityFeeGwei?: number | null - maxPriorityFeeGwei?: number | null -} - -export interface GasEstimateLegacy { - gasPrice: string - gasLimit: string - type: FeeType.LEGACY - strategy: GasStrategy - gasFee: string -} - -export interface GasEstimateEip1559 { - maxFeePerGas: string - maxPriorityFeePerGas: string - gasLimit: string - type: FeeType.EIP1559 - strategy: GasStrategy - gasFee: string -} - -export type GasEstimate = GasEstimateLegacy | GasEstimateEip1559 diff --git a/packages/uniswap/src/data/types.ts b/packages/uniswap/src/data/types.ts index c0195ef55e4..1d83dcb05ee 100644 --- a/packages/uniswap/src/data/types.ts +++ b/packages/uniswap/src/data/types.ts @@ -1,8 +1,7 @@ import { QueryResult } from '@apollo/client' -import { ApolloError } from '@apollo/client/errors' + // Query result does not have a refetch property so add it here in case it needs to get returned -export type GqlResult = Pick, 'data' | 'loading'> & +export type GqlResult = Pick, 'data' | 'loading' | 'error'> & Partial, 'networkStatus'>> & { refetch?: () => void // TODO: [MOB-222] figure out the proper type for this from a QueryResult - error?: ApolloError | Error } diff --git a/packages/uniswap/src/entities/assets.ts b/packages/uniswap/src/entities/assets.ts index 4331aee6848..affffaec241 100644 --- a/packages/uniswap/src/entities/assets.ts +++ b/packages/uniswap/src/entities/assets.ts @@ -1,10 +1,10 @@ -import { UniverseChainId } from 'uniswap/src/types/chains' +import { WalletChainId } from 'uniswap/src/types/chains' export type TradeableAsset = CurrencyAsset | NFTAsset interface BaseTradeableAsset { address: Address - chainId: UniverseChainId + chainId: WalletChainId type: AssetType } diff --git a/packages/uniswap/src/extension/useIsChromeWindowFocused.ts b/packages/uniswap/src/extension/useIsChromeWindowFocused.ts index 432f8ef6be0..64d4da6e0fa 100644 --- a/packages/uniswap/src/extension/useIsChromeWindowFocused.ts +++ b/packages/uniswap/src/extension/useIsChromeWindowFocused.ts @@ -9,7 +9,7 @@ export function useIsChromeWindowFocused(): boolean { useCallback(async () => { if (!isExtension) { // This hook is ignored and always returns `true` when not in the Extension. - return undefined + return } const onFocusChangedListener = async (): Promise => { @@ -39,7 +39,7 @@ export function useIsChromeWindowFocusedWithTimeout(timeoutInMs: number): boolea useEffect(() => { if (isFocused) { setIsFocusedWithTimeout(true) - return undefined + return } const timeout = setTimeout(() => setIsFocusedWithTimeout(false), timeoutInMs) diff --git a/packages/uniswap/src/features/address/ExplorerView.tsx b/packages/uniswap/src/features/address/ExplorerView.tsx index beddbadf5d3..2066a52e2e8 100644 --- a/packages/uniswap/src/features/address/ExplorerView.tsx +++ b/packages/uniswap/src/features/address/ExplorerView.tsx @@ -31,7 +31,7 @@ export function ExplorerView({ currency, modalName }: { currency: Currency; moda - + {explorerLink} diff --git a/packages/uniswap/src/features/bridging/hooks/useSwappableTokenWithHighestBalance.ts b/packages/uniswap/src/features/bridging/hooks/useSwappableTokenWithHighestBalance.ts deleted file mode 100644 index a05af1fa69b..00000000000 --- a/packages/uniswap/src/features/bridging/hooks/useSwappableTokenWithHighestBalance.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { useMemo } from 'react' -import { useTradingApiSwappableTokensQuery } from 'uniswap/src/data/apiClients/tradingApi/useTradingApiSwappableTokensQuery' -import { tradingApiSwappableTokenToCurrencyInfo } from 'uniswap/src/data/apiClients/tradingApi/utils/tradingApiSwappableTokenToCurrencyInfo' -import { GetSwappableTokensResponse } from 'uniswap/src/data/tradingApi/__generated__' -import { CurrencyInfo, PortfolioBalance } from 'uniswap/src/features/dataApi/types' -import { FeatureFlags } from 'uniswap/src/features/gating/flags' -import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' -import { - getTokenAddressFromChainForTradingApi, - toTradingApiSupportedChainId, -} from 'uniswap/src/features/transactions/swap/utils/tradingApi' -import { WalletChainId } from 'uniswap/src/types/chains' -import { logger } from 'utilities/src/logger/logger' - -export function useSwappableTokenWithHighestBalance({ - currencyAddress, - currencyChainId, - otherChainBalances, -}: { - currencyAddress: Address - currencyChainId: WalletChainId - otherChainBalances: PortfolioBalance[] | null -}): - | { - token: GetSwappableTokensResponse['tokens'][number] - balance: PortfolioBalance - currencyInfo: CurrencyInfo - } - | undefined { - const isBridgingEnabled = useFeatureFlag(FeatureFlags.Bridging) - - const tokenIn = currencyAddress ? getTokenAddressFromChainForTradingApi(currencyAddress, currencyChainId) : undefined - const tokenInChainId = toTradingApiSupportedChainId(currencyChainId) - - const { data: swappableTokens } = useTradingApiSwappableTokensQuery({ - params: - otherChainBalances && otherChainBalances?.length > 0 && tokenIn && tokenInChainId && isBridgingEnabled - ? { - tokenIn, - tokenInChainId, - } - : undefined, - }) - - return useMemo(() => { - if (!otherChainBalances || !swappableTokens?.tokens) { - return undefined - } - - const tokenWithHighestBalance = swappableTokens.tokens.reduce< - ReturnType | undefined - >((currentHighest, token) => { - const balance = otherChainBalances.find((b) => b.currencyInfo.currency.chainId === token.chainId) - - if (!balance?.balanceUSD) { - return currentHighest - } - - if ( - !currentHighest || - !currentHighest.balance.balanceUSD || - balance.balanceUSD > currentHighest.balance.balanceUSD - ) { - const currencyInfo = tradingApiSwappableTokenToCurrencyInfo(token) - - if (!currencyInfo) { - logger.error(new Error('Failed to convert swappable token to currency info'), { - tags: { file: 'TokenDetailsScreen.tsx', function: 'useSwappableTokenWithHighestBalance' }, - extra: { token }, - }) - return currentHighest - } - - return { - token, - balance, - currencyInfo, - } - } - - return currentHighest - }, undefined) - - return tokenWithHighestBalance - }, [otherChainBalances, swappableTokens]) -} diff --git a/packages/uniswap/src/features/dataApi/balances.ts b/packages/uniswap/src/features/dataApi/balances.ts index 2170c13a395..2e81eb44a4f 100644 --- a/packages/uniswap/src/features/dataApi/balances.ts +++ b/packages/uniswap/src/features/dataApi/balances.ts @@ -88,7 +88,7 @@ export function usePortfolioBalances({ const formattedData = useMemo(() => { if (!balancesForAddress) { - return undefined + return } const byId: Record = {} @@ -102,8 +102,8 @@ export function usePortfolioBalances({ quantity, isHidden, } = balance || {} - const { name, address: tokenAddress, chain, decimals, symbol, project } = token || {} - const { logoUrl, isSpam, safetyLevel } = project || {} + const { address: tokenAddress, chain, decimals, symbol, project } = token || {} + const { name, logoUrl, isSpam, safetyLevel } = project || {} const chainId = fromGraphQLChain(chain) // require all of these fields to be defined @@ -200,7 +200,7 @@ export function usePortfolioTotalValue({ const formattedData = useMemo(() => { if (!portfolioForAddress) { - return undefined + return } return { diff --git a/packages/uniswap/src/features/dataApi/searchTokens.ts b/packages/uniswap/src/features/dataApi/searchTokens.ts index 03f5306f205..53205aba45e 100644 --- a/packages/uniswap/src/features/dataApi/searchTokens.ts +++ b/packages/uniswap/src/features/dataApi/searchTokens.ts @@ -26,7 +26,7 @@ export function useSearchTokens( const formattedData = useMemo(() => { if (!data || !data.searchTokens) { - return undefined + return } return data.searchTokens diff --git a/packages/uniswap/src/features/dataApi/tokenProjects.ts b/packages/uniswap/src/features/dataApi/tokenProjects.ts index 92abf8baa48..464211f3347 100644 --- a/packages/uniswap/src/features/dataApi/tokenProjects.ts +++ b/packages/uniswap/src/features/dataApi/tokenProjects.ts @@ -18,7 +18,7 @@ export function useTokenProjects(currencyIds: CurrencyId[]): GqlResult { if (!data || !data.tokenProjects) { - return undefined + return } return tokenProjectToCurrencyInfos(data.tokenProjects) diff --git a/packages/uniswap/src/features/dataApi/topTokens.ts b/packages/uniswap/src/features/dataApi/topTokens.ts index 3acd0ea1735..8e6597fc83a 100644 --- a/packages/uniswap/src/features/dataApi/topTokens.ts +++ b/packages/uniswap/src/features/dataApi/topTokens.ts @@ -27,7 +27,7 @@ export function usePopularTokens(chainFilter: UniverseChainId): GqlResult { if (!data || !data.topTokens) { - return undefined + return } return data.topTokens diff --git a/packages/uniswap/src/features/dataApi/utils.test.ts b/packages/uniswap/src/features/dataApi/utils.test.ts index b017ca19a4f..c1f5e7e6dc1 100644 --- a/packages/uniswap/src/features/dataApi/utils.test.ts +++ b/packages/uniswap/src/features/dataApi/utils.test.ts @@ -51,7 +51,7 @@ describe(tokenProjectToCurrencyInfos, () => { address: token.address, decimals: token.decimals, symbol: token.symbol, - name: token.name ?? project.name, + name: project.name, }), }) as CurrencyInfo @@ -145,7 +145,7 @@ describe(gqlTokenToCurrencyInfo, () => { address: token.address, decimals: token.decimals, symbol: token.symbol, - name: token.name, + name: token.project?.name, }), currencyId: `${fromGraphQLChain(token.chain)}-${token.address}`, logoUrl: token.project?.logoUrl, diff --git a/packages/uniswap/src/features/dataApi/utils.ts b/packages/uniswap/src/features/dataApi/utils.ts index cd09464f920..a5777d6aa4b 100644 --- a/packages/uniswap/src/features/dataApi/utils.ts +++ b/packages/uniswap/src/features/dataApi/utils.ts @@ -49,8 +49,8 @@ export function tokenProjectToCurrencyInfos( return tokenProjects ?.flatMap((project) => project?.tokens.map((token) => { - const { logoUrl, safetyLevel } = project ?? {} - const { name, chain, address, decimals, symbol } = token ?? {} + const { logoUrl, safetyLevel, name } = project ?? {} + const { chain, address, decimals, symbol } = token ?? {} const chainId = fromGraphQLChain(chain) if (chainFilter && chainFilter !== chainId) { @@ -163,7 +163,7 @@ export function getCurrencySafetyInfo( } export function gqlTokenToCurrencyInfo(token: NonNullable>): CurrencyInfo | null { - const { name, chain, address, decimals, symbol, project, feeData, protectionInfo } = token + const { chain, address, decimals, symbol, project, feeData, protectionInfo } = token const chainId = fromGraphQLChain(chain) const currency = buildCurrency({ @@ -171,7 +171,7 @@ export function gqlTokenToCurrencyInfo(token: NonNullable string - conversionRate?: number } const SOURCE_CURRENCY = Currency.Usd // Assuming all currency data comes from USD @@ -152,10 +151,9 @@ export function useFiatConverter({ return useMemo( () => ({ - conversionRate, convertFiatAmount: convertFiatAmountInner, convertFiatAmountFormatted: convertFiatAmountFormattedInner, }), - [conversionRate, convertFiatAmountFormattedInner, convertFiatAmountInner], + [convertFiatAmountFormattedInner, convertFiatAmountInner], ) } diff --git a/packages/uniswap/src/features/fiatOnRamp/hooks.ts b/packages/uniswap/src/features/fiatOnRamp/hooks.ts index 73bfbddecd2..3ba90ee5b45 100644 --- a/packages/uniswap/src/features/fiatOnRamp/hooks.ts +++ b/packages/uniswap/src/features/fiatOnRamp/hooks.ts @@ -51,7 +51,7 @@ export function useFormatExactCurrencyAmount(currencyAmount: string, currency: M const formatter = useLocalizationContext() if (!currencyAmount || !currency) { - return undefined + return } const formattedAmount = getFormattedCurrencyAmount(currency, currencyAmount, formatter, false, ValueType.Exact) diff --git a/packages/uniswap/src/features/gas/hooks.ts b/packages/uniswap/src/features/gas/hooks.ts index 9d1eeaa40b3..c7b094e379c 100644 --- a/packages/uniswap/src/features/gas/hooks.ts +++ b/packages/uniswap/src/features/gas/hooks.ts @@ -2,11 +2,12 @@ import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { providers } from 'ethers/lib/ethers' import { useMemo } from 'react' import { useTranslation } from 'react-i18next' +import { useConfig } from 'statsig-react' import { isWeb } from 'ui/src' import { Warning, WarningAction, WarningLabel, WarningSeverity } from 'uniswap/src/components/modals/WarningModal/types' import { PollingInterval } from 'uniswap/src/constants/misc' import { useGasFeeQuery } from 'uniswap/src/data/apiClients/uniswapApi/useGasFeeQuery' -import { GasEstimate, GasStrategy } from 'uniswap/src/data/tradingApi/types' +import { GasEstimate, GasStrategy } from 'uniswap/src/data/tradingApi/__generated__' import { AccountMeta } from 'uniswap/src/features/accounts/types' import { FormattedUniswapXGasFeeInfo, @@ -17,7 +18,7 @@ import { } from 'uniswap/src/features/gas/types' import { hasSufficientFundsIncludingGas } from 'uniswap/src/features/gas/utils' import { DynamicConfigs, GasStrategies, GasStrategyType } from 'uniswap/src/features/gating/configs' -import { Statsig, useConfig } from 'uniswap/src/features/gating/sdk/statsig' +import { Statsig } from 'uniswap/src/features/gating/sdk/statsig' import { useLocalizationContext } from 'uniswap/src/features/language/LocalizationContext' import { useOnChainNativeCurrencyBalance } from 'uniswap/src/features/portfolio/api' import { NativeCurrency } from 'uniswap/src/features/tokens/NativeCurrency' @@ -228,7 +229,7 @@ export function useTransactionGasWarning({ return useMemo(() => { // if balance is already insufficient, dont need to show warning about network fee if (gasFee === undefined || balanceInsufficient || !nativeCurrencyBalance || hasGasFunds) { - return undefined + return } return { diff --git a/packages/uniswap/src/features/gas/types.ts b/packages/uniswap/src/features/gas/types.ts index ade532f7cf8..643c33d1efa 100644 --- a/packages/uniswap/src/features/gas/types.ts +++ b/packages/uniswap/src/features/gas/types.ts @@ -1,6 +1,6 @@ import { SerializedError } from '@reduxjs/toolkit' import { FetchError } from 'uniswap/src/data/apiClients/FetchError' -import { GasEstimate, GasStrategy } from 'uniswap/src/data/tradingApi/types' +import { GasEstimate, GasStrategy } from 'uniswap/src/data/tradingApi/__generated__' import { GasFeeEstimates } from 'uniswap/src/features/transactions/types/transactionDetails' export type TransactionLegacyFeeParams = { diff --git a/packages/uniswap/src/features/gating/configs.ts b/packages/uniswap/src/features/gating/configs.ts index d65273c644e..0941a617502 100644 --- a/packages/uniswap/src/features/gating/configs.ts +++ b/packages/uniswap/src/features/gating/configs.ts @@ -1,4 +1,4 @@ -import { GasStrategy } from 'uniswap/src/data/tradingApi/types' +import { GasStrategy } from 'uniswap/src/data/tradingApi/__generated__' /** * Dynamic Configs diff --git a/packages/uniswap/src/features/gating/experiments.ts b/packages/uniswap/src/features/gating/experiments.ts index 065a82f7f6d..95e88da3765 100644 --- a/packages/uniswap/src/features/gating/experiments.ts +++ b/packages/uniswap/src/features/gating/experiments.ts @@ -10,11 +10,6 @@ export enum Experiments { AccountCTAs = 'signin_login_connect_ctas', } -export enum ArbitrumXV2ExperimentGroup { - Test = 'Test', - Control = 'Control', -} - export enum ArbitrumXV2OpenOrderProperties { PriceImprovementBps = 'priceImprovementBps', ForceOpenOrders = 'forceOpenOrders', diff --git a/packages/uniswap/src/features/gating/flags.ts b/packages/uniswap/src/features/gating/flags.ts index e8fda6a098d..9b927664df9 100644 --- a/packages/uniswap/src/features/gating/flags.ts +++ b/packages/uniswap/src/features/gating/flags.ts @@ -11,7 +11,6 @@ export enum FeatureFlags { IndicativeSwapQuotes, TokenProtection, SelfReportSpamNFTs, - UniswapXPriorityOrders, // Wallet FlashbotsPrivateRpc, @@ -33,7 +32,6 @@ export enum FeatureFlags { // Extension ExtensionAutoConnect, - ExtensionClaimUnitag, // Web AATestWeb, @@ -70,7 +68,6 @@ export const WEB_FEATURE_FLAG_NAMES = new Map([ [FeatureFlags.PortionFields, 'portion-fields'], [FeatureFlags.UniswapX, 'uniswapx'], [FeatureFlags.Datadog, 'datadog'], - [FeatureFlags.UniswapXPriorityOrders, 'uniswapx_priority_orders'], // Web Specific [FeatureFlags.UniversalSwap, 'universal_swap'], @@ -106,7 +103,6 @@ export const WALLET_FEATURE_FLAG_NAMES = new Map([ [FeatureFlags.IndicativeSwapQuotes, 'indicative-quotes'], [FeatureFlags.TokenProtection, 'token_protection'], [FeatureFlags.SelfReportSpamNFTs, 'self-report-spam-nfts'], - [FeatureFlags.UniswapXPriorityOrders, 'uniswapx_priority_orders'], // Wallet Specific [FeatureFlags.Datadog, 'datadog'], @@ -124,7 +120,6 @@ export const WALLET_FEATURE_FLAG_NAMES = new Map([ [FeatureFlags.FiatOffRamp, 'fiat-offramp'], // Extension Specific [FeatureFlags.ExtensionAutoConnect, 'extension-auto-connect'], - [FeatureFlags.ExtensionClaimUnitag, 'extension-claim-unitag'], ]) export enum FeatureFlagClient { diff --git a/packages/uniswap/src/features/language/LocalizationContext.tsx b/packages/uniswap/src/features/language/LocalizationContext.tsx index aa93529e887..e768b50bec0 100644 --- a/packages/uniswap/src/features/language/LocalizationContext.tsx +++ b/packages/uniswap/src/features/language/LocalizationContext.tsx @@ -5,7 +5,6 @@ import { useFiatConverter } from 'uniswap/src/features/fiatCurrency/conversion' import { useLocalizedFormatter } from 'uniswap/src/features/language/formatter' export type LocalizationContextState = { - conversionRate: ReturnType['conversionRate'] convertFiatAmount: ReturnType['convertFiatAmount'] convertFiatAmountFormatted: ReturnType['convertFiatAmountFormatted'] formatNumberOrString: ReturnType['formatNumberOrString'] @@ -19,13 +18,12 @@ export const LocalizationContext = createContext( (): LocalizationContextState => ({ - conversionRate, convertFiatAmount, convertFiatAmountFormatted, formatNumberOrString, @@ -35,7 +33,6 @@ export function LocalizationContextProvider({ children }: { children: ReactNode }), [ addFiatSymbolToNumber, - conversionRate, convertFiatAmount, convertFiatAmountFormatted, formatCurrencyAmount, diff --git a/packages/uniswap/src/features/providers/FlashbotsRpcProvider.test.ts b/packages/uniswap/src/features/providers/FlashbotsRpcProvider.test.ts index a533640e51a..4e9aa35312a 100644 --- a/packages/uniswap/src/features/providers/FlashbotsRpcProvider.test.ts +++ b/packages/uniswap/src/features/providers/FlashbotsRpcProvider.test.ts @@ -56,7 +56,6 @@ describe('FlashbotsRpcProvider', () => { expect(connection.headers?.['X-Flashbots-Signature']).toBe(`${testAddress}:0xsignature`) return Promise.resolve(0x3) } - return undefined }) const result = await provider.getTransactionCount(testAddress, 'pending') diff --git a/packages/uniswap/src/features/search/searchHistorySlice.ts b/packages/uniswap/src/features/search/searchHistorySlice.ts index c19c66e9237..146838ad716 100644 --- a/packages/uniswap/src/features/search/searchHistorySlice.ts +++ b/packages/uniswap/src/features/search/searchHistorySlice.ts @@ -3,7 +3,6 @@ import { SearchResult, SearchResultType } from 'uniswap/src/features/search/Sear const SEARCH_HISTORY_LENGTH = 5 -// eslint-disable-next-line consistent-return export function searchResultId(searchResult: SearchResult): string { switch (searchResult.type) { case SearchResultType.Token: diff --git a/packages/uniswap/src/features/telemetry/constants/trace.ts b/packages/uniswap/src/features/telemetry/constants/trace.ts index e0f94c55b83..898eb89d9ac 100644 --- a/packages/uniswap/src/features/telemetry/constants/trace.ts +++ b/packages/uniswap/src/features/telemetry/constants/trace.ts @@ -9,25 +9,21 @@ export const ModalName = { AccountEdit: 'account-edit-modal', AccountEditLabel: 'account-edit--label-modal', AccountSwitcher: 'account-switcher-modal', - AcrossRoutingInfo: 'across-routing-info-modal', AddLiquidity: 'add-liquidity', AddWallet: 'add-wallet-modal', BackupReminder: 'backup-reminder-modal', BackupReminderWarning: 'backup-reminder-warning-modal', BlockedAddress: 'blocked-address', - BridgingWarning: 'bridging-warning-modal', BuyNativeToken: 'buy-native-token-modal', ChooseProfilePhoto: 'choose-profile-photo-modal', CloudBackupInfo: 'cloud-backup-info-modal', DappRequest: 'dapp-request', ENSClaimPeriod: 'ens-claim-period', EnterPassword: 'enter-password-modal', - EstimatedTimeInfo: 'estimated-time-info-modal', ExchangeTransferModal: 'exchange-transfer-modal', Experiments: 'experiments', Explore: 'explore-modal', FaceIDWarning: 'face-id-warning', - FeeTierSearch: 'fee-tier-search-modal', FOTInfo: 'fee-on-transfer', FiatCurrencySelector: 'fiat-currency-selector', FiatOnRampAggregator: 'fiat-on-ramp-aggregator', diff --git a/packages/uniswap/src/features/telemetry/types.ts b/packages/uniswap/src/features/telemetry/types.ts index 0c872ebc379..3bc86ae38a6 100644 --- a/packages/uniswap/src/features/telemetry/types.ts +++ b/packages/uniswap/src/features/telemetry/types.ts @@ -18,7 +18,6 @@ import { NavBarSearchTypes, SharedEventName, SwapEventName, - SwapPriceImpactUserResponse, SwapPriceUpdateUserResponse, WalletConnectionResult, } from '@uniswap/analytics-events' @@ -68,8 +67,6 @@ export type GasEstimateAccuracyProperties = { private_rpc?: boolean is_shadow?: boolean name?: string - out_of_gas: boolean - timed_out: boolean } export type AssetDetailsBaseProperties = { @@ -96,7 +93,6 @@ type OnboardingCompletedProps = { } export type SwapTradeBaseProperties = { - total_balances_usd?: number transactionOriginType: string // We have both `allowed_slippage` (percentage) and `allowed_slippage_basis_points` because web and wallet used to track this in different ways. // We should eventually standardize on one or the other. @@ -162,10 +158,6 @@ type UniswapXTransactionResultProperties = BaseSwapTransactionResultProperties & order_hash: string } -type BridgeSwapTransactionResultProperties = BaseSwapTransactionResultProperties & { - routing: 'BRIDGE' -} - type FailedUniswapXOrderResultProperties = Omit type TransferProperties = { @@ -196,10 +188,6 @@ export type SwapPriceUpdateActionProperties = { price_update_basis_points?: number } -export type SwapPriceImpactActionProperties = { - response: SwapPriceImpactUserResponse -} - export type InterfaceSearchResultSelectionProperties = { suggestion_type: NavBarSearchTypes query_text: string @@ -630,16 +618,11 @@ export type UniverseEventProperties = { } [SharedEventName.NAVBAR_CLICKED]: undefined [SwapEventName.SWAP_MAX_TOKEN_AMOUNT_SELECTED]: undefined - [SwapEventName.SWAP_PRICE_IMPACT_ACKNOWLEDGED]: SwapPriceImpactActionProperties [SwapEventName.SWAP_PRICE_UPDATE_ACKNOWLEDGED]: SwapPriceUpdateActionProperties [SwapEventName.SWAP_TRANSACTION_COMPLETED]: | ClassicSwapTransactionResultProperties | UniswapXTransactionResultProperties - | BridgeSwapTransactionResultProperties - [SwapEventName.SWAP_TRANSACTION_FAILED]: - | ClassicSwapTransactionResultProperties - | FailedUniswapXOrderResultProperties - | BridgeSwapTransactionResultProperties + [SwapEventName.SWAP_TRANSACTION_FAILED]: ClassicSwapTransactionResultProperties | FailedUniswapXOrderResultProperties [SwapEventName.SWAP_DETAILS_EXPANDED]: ITraceContext | undefined [SwapEventName.SWAP_AUTOROUTER_VISUALIZATION_EXPANDED]: ITraceContext [SwapEventName.SWAP_QUOTE_RECEIVED]: { @@ -763,7 +746,7 @@ export type UniverseEventProperties = { } [WalletEventName.SwapSubmitted]: ( | { - routing: 'CLASSIC' | 'BRIDGE' + routing: 'CLASSIC' transaction_hash: string } | { diff --git a/packages/uniswap/src/features/tokens/TokenWarningModal.tsx b/packages/uniswap/src/features/tokens/TokenWarningModal.tsx index aa2c9ce216a..cf8ce0aa258 100644 --- a/packages/uniswap/src/features/tokens/TokenWarningModal.tsx +++ b/packages/uniswap/src/features/tokens/TokenWarningModal.tsx @@ -1,12 +1,9 @@ import { BigNumber } from '@ethersproject/bignumber' import { useState } from 'react' -import { Trans } from 'react-i18next' import { capitalize } from 'tsafe' -import { AnimateTransition, Flex, LabeledCheckbox, Text, TouchableArea, styled, useSporeColors } from 'ui/src' -import { X } from 'ui/src/components/icons/X' +import { Flex, LabeledCheckbox, Text, styled } from 'ui/src' import { BlockaidLogo } from 'ui/src/components/logos/BlockaidLogo' -import { Modal } from 'uniswap/src/components/modals/Modal' -import { WarningModalContent } from 'uniswap/src/components/modals/WarningModal/WarningModal' +import { WarningModal } from 'uniswap/src/components/modals/WarningModal/WarningModal' import { getAlertColor } from 'uniswap/src/components/modals/WarningModal/getAlertColor' import { WarningSeverity } from 'uniswap/src/components/modals/WarningModal/types' import { LearnMoreLink } from 'uniswap/src/components/text/LearnMoreLink' @@ -22,46 +19,36 @@ import DeprecatedTokenWarningModal from 'uniswap/src/features/tokens/DeprecatedT import { TokenWarningDesignTreatment, getIsFeeRelatedWarning, - getShouldHaveCombinedPluralTreatment, + getShouldHavePluralTreatment, getTokenWarningDesignTreatment, useModalHeaderText, useModalSubtitleText, } from 'uniswap/src/features/tokens/safetyUtils' -import { useTranslation } from 'uniswap/src/i18n' +import { Trans, useTranslation } from 'uniswap/src/i18n' import { currencyId } from 'uniswap/src/utils/currencyId' import { NumberType } from 'utilities/src/format/types' -import { isMobileApp } from 'utilities/src/platform' -interface TokenWarningProps { - currencyInfo0: CurrencyInfo // required, primary currency - currencyInfo1?: CurrencyInfo // defined in case of 2-token warnings; i.e. possible on the web's Pool Details Page or prefilled via /swap?inputAddress=0x...&outputAddress=0x... - isInfoOnlyWarning?: boolean // if this is an informational-only warning. Hides the Reject button - shouldBeCombinedPlural?: boolean // some 2-token warnings will be combined into one plural modal (see `getShouldHaveCombinedPluralTreatment`) - hasSecondWarning?: boolean // true if this is a 2-token warning with two separate warning screens -} - -interface TokenWarningModalContentProps extends TokenWarningProps { - onRejectButton: () => void - onAcknowledgeButton: () => void -} -interface TokenWarningModalProps extends TokenWarningProps { +interface Props { isVisible: boolean - onReject?: () => void // callback on user rejecting warning (i.e., may close the modal & clear all inputs) - onToken0BlockAcknowledged?: () => void // callback containing custom behavior for a blocked token - onToken1BlockAcknowledged?: () => void - closeModalOnly: () => void // callback that purely just closes the modal - onAcknowledge: () => void + currencyInfo0: CurrencyInfo + currencyInfo1?: CurrencyInfo + disableAccept?: boolean // only show message and close button + onClose: () => void + onAccept: () => void } -function TokenWarningModalContent({ +/** + * Warning speedbump for selecting certain tokens. + */ +export default function TokenWarningModal({ + isVisible, currencyInfo0, currencyInfo1, - isInfoOnlyWarning, - onRejectButton, - onAcknowledgeButton, - shouldBeCombinedPlural, - hasSecondWarning, -}: TokenWarningModalContentProps): JSX.Element | null { + disableAccept, + onClose, + onAccept, +}: Props): JSX.Element | null { + const tokenProtectionEnabled = useFeatureFlag(FeatureFlags.TokenProtection) const { t } = useTranslation() const [dontShowAgain, setDontShowAgain] = useState(false) // TODO(WALL-4596): implement dismissedTokenWarnings redux @@ -70,217 +57,106 @@ function TokenWarningModalContent({ const mockWarningSeverity = WarningSeverity.Medium // FIXME(WALL-4686): temp mock var; need to dedupe warning severity usage with TokenWarningDesignTreatment + const plural = getShouldHavePluralTreatment( + currencyInfo0.currency, + currencyInfo0.safetyInfo, + currencyInfo1?.currency, + currencyInfo1?.safetyInfo, + ) + const titleText = useModalHeaderText( currencyInfo0.currency, currencyInfo0.safetyInfo, - shouldBeCombinedPlural ? currencyInfo1?.currency : undefined, - shouldBeCombinedPlural ? currencyInfo1?.safetyInfo : undefined, + plural ? currencyInfo1?.currency : undefined, + plural ? currencyInfo1?.safetyInfo : undefined, ) const subtitleText = useModalSubtitleText( currencyInfo0.currency, currencyInfo0.safetyInfo, - shouldBeCombinedPlural ? currencyInfo1?.currency : undefined, - shouldBeCombinedPlural ? currencyInfo1?.safetyInfo : undefined, + plural ? currencyInfo1?.currency : undefined, + plural ? currencyInfo1?.safetyInfo : undefined, ) if (designTreatment === TokenWarningDesignTreatment.None) { return null } - const { background: backgroundIconColor, text: titleTextColor } = getAlertColor(mockWarningSeverity) - - return ( - - - - {subtitleText} - - - - } - rejectText={ - // if this is an informational-only warning or a 2-token warning, we should always show the Reject / back button - // or, if a token is blocked, it should not have a Reject button, only an Acknowledge button - isInfoOnlyWarning || hasSecondWarning || designTreatment !== TokenWarningDesignTreatment.Blocked - ? t('common.button.back') - : undefined - } - acknowledgeText={ - // if this is an informational-only warning, we don't show the Acknowledge button at all - isInfoOnlyWarning - ? undefined - : // if a token is blocked & is not part of a 2-token warning, the Acknowledge button should say "Close" - designTreatment === TokenWarningDesignTreatment.Blocked && !hasSecondWarning - ? t('common.button.close') - : // otherwise, Acknowledge button should say "Continue" - t('common.button.continue') - } - icon={} // TODO(WEB-4883): re-work WarningIcon according to severity, not safety level - severity={mockWarningSeverity} - titleComponent={ - - {titleText} - - } - onReject={onRejectButton} - onClose={onRejectButton} - onAcknowledge={onAcknowledgeButton} - > - {isFeeRelatedWarning && currencyInfo0.currency.isToken ? ( - - ) : ( - <> - - {shouldBeCombinedPlural && currencyInfo1 && ( - - )} - - )} - - {!isFeeRelatedWarning && ( - - - }} - /> - - - )} - - {!isInfoOnlyWarning && designTreatment === TokenWarningDesignTreatment.Low && ( - // only show "Don't show this warning again" checkbox if this is an actionable modal & the token is low-severity - - {t('token.safety.warning.dontShowWarningAgain')} - - } - size="$icon.16" - gap="$spacing8" - onCheckPressed={() => setDontShowAgain((s: boolean) => !s)} - /> - )} - - - ) -} - -/** - * Warning speedbump for selecting certain tokens. - */ -export default function TokenWarningModal({ - isVisible, - currencyInfo0, - currencyInfo1, - isInfoOnlyWarning, - onReject, - onToken0BlockAcknowledged, - onToken1BlockAcknowledged, - onAcknowledge, - closeModalOnly, -}: TokenWarningModalProps): JSX.Element | null { - const tokenProtectionEnabled = useFeatureFlag(FeatureFlags.TokenProtection) - const colors = useSporeColors() - - // If BOTH tokens are blocked or BOTH are low-severity, they'll be combined into one plural modal - const combinedPlural = getShouldHaveCombinedPluralTreatment( - currencyInfo0.currency, - currencyInfo0.safetyInfo, - currencyInfo1?.currency, - currencyInfo1?.safetyInfo, - ) - const isBlocked0 = - getTokenWarningDesignTreatment(currencyInfo0.currency, currencyInfo0.safetyInfo) === - TokenWarningDesignTreatment.Blocked - const isBlocked1 = - getTokenWarningDesignTreatment(currencyInfo1?.currency, currencyInfo1?.safetyInfo) === - TokenWarningDesignTreatment.Blocked - - const [warningIndex, setWarningIndex] = useState<0 | 1>(0) - const hasSecondWarning = Boolean(!combinedPlural && currencyInfo1) + const showActionButton = !disableAccept && designTreatment !== TokenWarningDesignTreatment.Blocked return tokenProtectionEnabled ? ( - + + {subtitleText} + + + + } + closeText={ + designTreatment === TokenWarningDesignTreatment.Blocked ? t('common.button.close') : t('common.button.back') + } + confirmText={showActionButton ? t('common.button.continue') : undefined} + icon={} // TODO(WEB-4883): re-work WarningIcon according to severity, not safety level + isOpen={isVisible} + modalName={ModalName.TokenWarningModal} + severity={mockWarningSeverity} + titleComponent={ + + {titleText} + + } + onCancel={onClose} + onClose={onClose} + onConfirm={onAccept} > - - {hasSecondWarning && ( - - {warningIndex + 1} - - {' '} - / 2 - - - )} - - - - + {currencyInfo0.currency.isToken && (currencyInfo0.currency.sellFeeBps || currencyInfo0.currency.buyFeeBps) ? ( + + ) : ( + <> + + {plural && currencyInfo1 && ( + + )} + + )} + + {!isFeeRelatedWarning && ( + + + }} + /> + - - - { - if (hasSecondWarning) { - setWarningIndex(1) - } else if (isBlocked0) { - // If both tokens are blocked, they'll be combined into one plural modal. See `getShouldHaveCombinedPluralTreatment`. - combinedPlural && isBlocked1 && onToken1BlockAcknowledged?.() - onToken0BlockAcknowledged?.() - closeModalOnly() - } else { - onAcknowledge() - } - }} + )} + + {showActionButton && designTreatment === TokenWarningDesignTreatment.Low && ( + + {t('token.safety.warning.dontShowWarningAgain')} + + } + size="$icon.16" + gap="$spacing8" + onCheckPressed={() => setDontShowAgain((s: boolean) => !s)} /> - {hasSecondWarning && currencyInfo1 && ( - { - setWarningIndex(0) - }} - onAcknowledgeButton={() => { - if (isBlocked0 || isBlocked1) { - isBlocked0 && onToken0BlockAcknowledged?.() - isBlocked1 && onToken1BlockAcknowledged?.() - closeModalOnly() - } else { - onAcknowledge() - } - }} - /> - )} - - + )} + ) : ( ) } @@ -292,8 +168,9 @@ export const WarningModalInfoContainer = styled(Flex, { borderWidth: 1, borderColor: '$surface3', px: '$spacing16', - py: isMobileApp ? '$spacing8' : '$spacing12', + py: '$spacing12', alignItems: 'center', + overflow: 'hidden', flexWrap: 'nowrap', }) diff --git a/packages/uniswap/src/features/tokens/deprecatedSafetyUtils.ts b/packages/uniswap/src/features/tokens/deprecatedSafetyUtils.ts index 0c884d2fb42..4d85aee6e77 100644 --- a/packages/uniswap/src/features/tokens/deprecatedSafetyUtils.ts +++ b/packages/uniswap/src/features/tokens/deprecatedSafetyUtils.ts @@ -14,7 +14,5 @@ export function getTokenSafetyHeaderText(safetyLevel: Maybe, t: App return t('token.safetyLevel.strong.header') case SafetyLevel.Blocked: return t('token.safetyLevel.blocked.header') - default: - return undefined } } diff --git a/packages/uniswap/src/features/tokens/hooks.ts b/packages/uniswap/src/features/tokens/hooks.ts index e99d3011053..2b62b40116d 100644 --- a/packages/uniswap/src/features/tokens/hooks.ts +++ b/packages/uniswap/src/features/tokens/hooks.ts @@ -20,7 +20,7 @@ export function usePopularTokens(): { const popularTokens = useMemo(() => { if (!data || !data.topTokens) { - return undefined + return } // special case to replace weth with eth because the backend does not return eth data @@ -32,7 +32,7 @@ export function usePopularTokens(): { return data.topTokens .map((token) => { if (!token) { - return undefined + return } const isWeth = areAddressesEqual(token.address, wethAddress) && token?.chain === Chain.Ethereum diff --git a/packages/uniswap/src/features/tokens/safetyUtils.test.ts b/packages/uniswap/src/features/tokens/safetyUtils.test.ts index cfc0a454976..dd19e1c2e28 100644 --- a/packages/uniswap/src/features/tokens/safetyUtils.test.ts +++ b/packages/uniswap/src/features/tokens/safetyUtils.test.ts @@ -3,7 +3,7 @@ import { ProtectionResult } from 'uniswap/src/data/graphql/uniswap-data-api/__ge import { AttackType, SafetyInfo, TokenList } from 'uniswap/src/features/dataApi/types' import { TokenWarningDesignTreatment, - getShouldHaveCombinedPluralTreatment, + getShouldHavePluralTreatment, getTokenWarningDesignTreatment, useModalHeaderText, useModalSubtitleText, @@ -95,20 +95,18 @@ describe('safetyUtils', () => { describe('getShouldHavePluralTreatment', () => { it('should return false when only one currency is provided', () => { - expect(getShouldHaveCombinedPluralTreatment(mockCurrency, mockSafetyInfo)).toBe(false) + expect(getShouldHavePluralTreatment(mockCurrency, mockSafetyInfo)).toBe(false) }) it('should return true when both currencies have Low warning', () => { const lowSafetyInfo = { ...mockSafetyInfo, tokenList: TokenList.NonDefault } - expect(getShouldHaveCombinedPluralTreatment(mockCurrency, lowSafetyInfo, mockCurrency, lowSafetyInfo)).toBe(true) + expect(getShouldHavePluralTreatment(mockCurrency, lowSafetyInfo, mockCurrency, lowSafetyInfo)).toBe(true) }) it('should return false when one has low warning and the other has high warning', () => { const lowSafetyInfo = { ...mockSafetyInfo, tokenList: TokenList.NonDefault } const highSafetyInfo = { ...mockSafetyInfo, protectionResult: ProtectionResult.Malicious } - expect(getShouldHaveCombinedPluralTreatment(mockCurrency, lowSafetyInfo, mockCurrency, highSafetyInfo)).toBe( - false, - ) + expect(getShouldHavePluralTreatment(mockCurrency, lowSafetyInfo, mockCurrency, highSafetyInfo)).toBe(false) }) }) diff --git a/packages/uniswap/src/features/tokens/safetyUtils.ts b/packages/uniswap/src/features/tokens/safetyUtils.ts index e53be53ea68..0d2a714c6d6 100644 --- a/packages/uniswap/src/features/tokens/safetyUtils.ts +++ b/packages/uniswap/src/features/tokens/safetyUtils.ts @@ -89,7 +89,6 @@ export function getIsFeeRelatedWarning(currency?: Currency, safetyInfo?: Maybe, @@ -125,7 +124,7 @@ export function getTokenWarningDesignTreatment( // Only combine into one plural-languaged modal if there are two tokens prefilled at the same time, and BOTH are low or BOTH are blocked // i.e. interface PDP, or interface prefilled via URL `?inputCurrency=0x...&outputCurrency=0x...` -export function getShouldHaveCombinedPluralTreatment( +export function getShouldHavePluralTreatment( currency0: Currency, safetyInfo0?: Maybe, currency1?: Currency, @@ -145,14 +144,13 @@ export function getShouldHaveCombinedPluralTreatment( return plural ?? false } -// eslint-disable-next-line consistent-return export function useModalHeaderText( currency0: Currency, safetyInfo0?: Maybe, currency1?: Currency, safetyInfo1?: Maybe, ): string | null { - const shouldHavePluralTreatment = getShouldHaveCombinedPluralTreatment(currency0, safetyInfo0, currency1, safetyInfo1) + const shouldHavePluralTreatment = getShouldHavePluralTreatment(currency0, safetyInfo0, currency1, safetyInfo1) if (!shouldHavePluralTreatment && (currency1 || safetyInfo1)) { throw new Error('Should only combine into one plural-languaged modal if BOTH are low or BOTH are blocked') } @@ -194,7 +192,7 @@ export function useModalHeaderText( } } -// eslint-disable-next-line @typescript-eslint/no-unused-vars, consistent-return +// eslint-disable-next-line @typescript-eslint/no-unused-vars function useCardHeaderText(currency: Currency, safetyInfo?: Maybe): string | null { const { t } = useTranslation() const tokenProtectionWarning = getTokenProtectionWarning(currency, safetyInfo) @@ -234,7 +232,7 @@ export function useModalSubtitleText( currency1?: Currency, safetyInfo1?: Maybe, ): string | null { - const shouldHavePluralTreatment = getShouldHaveCombinedPluralTreatment(currency0, safetyInfo0, currency1, safetyInfo1) + const shouldHavePluralTreatment = getShouldHavePluralTreatment(currency0, safetyInfo0, currency1, safetyInfo1) if (!shouldHavePluralTreatment && (currency1 || safetyInfo1)) { throw new Error('Should only combine into one plural-languaged modal if BOTH are low or BOTH are blocked') } @@ -257,7 +255,6 @@ export function useModalSubtitleText( type: NumberType.Percentage, }) - // eslint-disable-next-line consistent-return const warningCopy = ((): string | null => { switch (tokenProtectionWarning) { case TokenProtectionWarning.MaliciousHoneypot: @@ -316,7 +313,7 @@ export function useModalSubtitleText( return warningCopy } -// eslint-disable-next-line @typescript-eslint/no-unused-vars, consistent-return +// eslint-disable-next-line @typescript-eslint/no-unused-vars function useCardSubtitleText(currency: Currency, safetyInfo?: Maybe): string | null { const { t } = useTranslation() const { formatNumberOrString } = useLocalizationContext() diff --git a/packages/uniswap/src/features/tokens/slice/hooks.ts b/packages/uniswap/src/features/tokens/slice/hooks.ts index af0c3c863bd..572a58d845e 100644 --- a/packages/uniswap/src/features/tokens/slice/hooks.ts +++ b/packages/uniswap/src/features/tokens/slice/hooks.ts @@ -26,7 +26,7 @@ export function useDismissedTokenWarnings(info: Maybe } else { // handle tokens if (info?.isToken) { - dispatch(dismissTokenWarning({ token: serializeToken(info) })) + return dispatch(dismissTokenWarning({ token: serializeToken(info) })) } } }, [isBasicInfo, info, dispatch]) diff --git a/packages/uniswap/src/features/tokens/useCurrencyInfo.ts b/packages/uniswap/src/features/tokens/useCurrencyInfo.ts index e2a423c094b..a2d8772b309 100644 --- a/packages/uniswap/src/features/tokens/useCurrencyInfo.ts +++ b/packages/uniswap/src/features/tokens/useCurrencyInfo.ts @@ -17,7 +17,7 @@ export function useCurrencyInfo( return useMemo(() => { if (!data?.token || !_currencyId) { - return undefined + return } return gqlTokenToCurrencyInfo(data.token) diff --git a/packages/uniswap/src/features/transactions/DecimalPadInput/DecimalPad.native.tsx b/packages/uniswap/src/features/transactions/DecimalPadInput/DecimalPad.native.tsx index f13fa6cbe4b..612f4cfb0ef 100644 --- a/packages/uniswap/src/features/transactions/DecimalPadInput/DecimalPad.native.tsx +++ b/packages/uniswap/src/features/transactions/DecimalPadInput/DecimalPad.native.tsx @@ -30,8 +30,7 @@ export const DecimalPad = memo(function DecimalPad({ disabledKeys = {}, maxHeight, onKeyPress, - onKeyLongPressStart, - onKeyLongPressEnd, + onKeyLongPress, onReady, onTriggerInputShakeAnimation, }: DecimalPadProps): JSX.Element { @@ -147,8 +146,7 @@ export const DecimalPad = memo(function DecimalPad({ // Because of this, we don't set the `disabled` prop on the number keys so we can trigger the `onPress` event. disabled={disabled || (isKeyDisabled && !shouldTriggerShake)} sizeMultiplier={sizeMultiplier} - onLongPressStart={shouldTriggerShake ? onTriggerInputShakeAnimation : onKeyLongPressStart} - onLongPressEnd={shouldTriggerShake ? undefined : onKeyLongPressEnd} + onLongPress={shouldTriggerShake ? onTriggerInputShakeAnimation : onKeyLongPress} onPress={shouldTriggerShake ? onTriggerInputShakeAnimation : onKeyPress} /> ) @@ -163,8 +161,7 @@ type KeyButtonProps = KeyProps & { disabled?: boolean sizeMultiplier: SizeMultiplier onPress?: (label: KeyLabel, action: KeyAction) => void - onLongPressStart?: (label: KeyLabel, action: KeyAction) => void - onLongPressEnd?: (label: KeyLabel, action: KeyAction) => void + onLongPress?: (label: KeyLabel, action: KeyAction) => void } const animationOptions = { duration: KEY_PRESS_ANIMATION_DURATION_MS } @@ -175,8 +172,7 @@ const KeyButton = memo(function KeyButton({ label, sizeMultiplier, onPress, - onLongPressStart, - onLongPressEnd, + onLongPress, }: KeyButtonProps): JSX.Element { const { decimalSeparator } = useAppFiatCurrencyInfo() const { hapticFeedback } = useHapticFeedback() @@ -185,24 +181,24 @@ const KeyButton = memo(function KeyButton({ const opacity = useSharedValue(1) const handlePress = useCallback(async (): Promise => { + if (disabled) { + return + } onPress?.(label, action) scale.value = withSequence(withTiming(1.3, animationOptions), withTiming(1, animationOptions)) opacity.value = withSequence(withTiming(0.75, animationOptions), withTiming(1, animationOptions)) await hapticFeedback.impact() - }, [action, hapticFeedback, label, onPress, opacity, scale]) - - const handleLongPressStart = useCallback((): void => { - onLongPressStart?.(label, action) - }, [action, label, onLongPressStart]) + }, [action, disabled, hapticFeedback, label, onPress, opacity, scale]) - const handleLongPressEnd = useCallback((): void => { - onLongPressEnd?.(label, action) - }, [action, label, onLongPressEnd]) + const handleLongPress = useCallback((): void => { + if (disabled) { + return + } + onLongPress?.(label, action) + }, [action, disabled, label, onLongPress]) - // We use `onBegin` because we want to react as soon as the user touches the key, not when they release it. - const tap = Gesture.Tap().onBegin(handlePress).enabled(!disabled) - // We use `onStart` because we want to start reacting to this event when the long press is actually detected. - const longPress = Gesture.LongPress().onStart(handleLongPressStart).onEnd(handleLongPressEnd).enabled(!disabled) + const tap = Gesture.Tap().onBegin(handlePress) + const longPress = Gesture.LongPress().onStart(handleLongPress) const composedGesture = Gesture.Simultaneous(tap, longPress) const color = disabled ? '$neutral3' : '$neutral1' diff --git a/packages/uniswap/src/features/transactions/DecimalPadInput/DecimalPadInput.tsx b/packages/uniswap/src/features/transactions/DecimalPadInput/DecimalPadInput.tsx index bb641afc7cf..3d2edf47537 100644 --- a/packages/uniswap/src/features/transactions/DecimalPadInput/DecimalPadInput.tsx +++ b/packages/uniswap/src/features/transactions/DecimalPadInput/DecimalPadInput.tsx @@ -1,14 +1,4 @@ -import { - RefObject, - forwardRef, - memo, - useCallback, - useEffect, - useImperativeHandle, - useMemo, - useRef, - useState, -} from 'react' +import { RefObject, forwardRef, memo, useCallback, useEffect, useImperativeHandle, useMemo, useState } from 'react' import { Flex } from 'ui/src' import { TextInputProps } from 'uniswap/src/components/input/TextInput' import { DecimalPad } from 'uniswap/src/features/transactions/DecimalPadInput/DecimalPad' @@ -17,9 +7,6 @@ import type { LayoutChangeEvent } from 'react-native' import { KeyAction, KeyLabel } from 'uniswap/src/features/transactions/DecimalPadInput/types' import { maxDecimalsReached } from 'utilities/src/format/truncateToMaxDecimals' -const LONG_PRESS_DELETE_INTERVAL_MS = 20 -const LONG_PRESS_DELETE_INTERVAL_DELIMITER_MS = 750 - type DisableKeyCondition = (value: string) => boolean type DecimalPadInputProps = { @@ -199,85 +186,24 @@ export const DecimalPadInput = memo( [disabled, handleInsert, handleDelete], ) - const deletingTimeout = useRef | undefined>(undefined) - const stopDeleting = useCallback(() => clearTimeout(deletingTimeout.current), []) - - const onLongPressStart = useCallback( - (_: KeyLabel, action: KeyAction) => { - if (disabled || action !== KeyAction.Delete) { - return - } - - // We delete one character at a time until we've deleted either half of the input text or more than 5 characters, - // and then we start deleting by "word" (ie. up until the next decimal or thousand separator). - - const initialAmountLength = valueRef.current.length - - const deleteWithTimeout = (): void => { - const start = getCurrentSelection().start ?? valueRef.current.length - const isCursorAtTheEnd = start === valueRef.current.length - - const hasDeletedMoreThanHalfCharacters = valueRef.current.length <= initialAmountLength / 2 - const hasDeletedMoreThanFiveCharacters = initialAmountLength - valueRef.current.length >= 5 - - // If we haven't deleted more than half of the input or more than 5 characters, we delete one character at a time. - if (!isCursorAtTheEnd || !(hasDeletedMoreThanHalfCharacters || hasDeletedMoreThanFiveCharacters)) { - handleDelete() - deletingTimeout.current = setTimeout(deleteWithTimeout, LONG_PRESS_DELETE_INTERVAL_MS) - return - } - - const nextDelimiterPosition = Math.max( - valueRef.current.lastIndexOf('.'), - valueRef.current.lastIndexOf(','), - valueRef.current.lastIndexOf(' '), - ) - - // If we found a thousand or decimal separator, we delete up until that delimiter. - if (nextDelimiterPosition > 0) { - resetSelection({ start: nextDelimiterPosition, end: nextDelimiterPosition }) - updateValue(valueRef.current.slice(0, nextDelimiterPosition)) - - // When we delete by delimiter, we want to have a slightly longer delay so the user has enough time to stop long pressing. - deletingTimeout.current = setTimeout(deleteWithTimeout, LONG_PRESS_DELETE_INTERVAL_DELIMITER_MS) - return - } - - // If we've already deleted more than half of the input and there are no more delimiters to delete by, we delete everything. - resetSelection({ start: 0, end: 0 }) - updateValue('') - return - } - - deleteWithTimeout() - }, - [disabled, getCurrentSelection, handleDelete, resetSelection, updateValue, valueRef], - ) - - const onLongPressEnd = useCallback( + const onLongPress = useCallback( (_: KeyLabel, action: KeyAction) => { if (disabled || action !== KeyAction.Delete) { return } - stopDeleting() + resetSelection({ start: 0, end: 0 }) + updateValue('') }, - [disabled, stopDeleting], + [disabled, updateValue, resetSelection], ) - useEffect(() => { - // Clear the interval when the component unmounts. - // This shouldn't be necessary, but it's a good practice to avoid potential issues with `onLongPressEnd` not firing in some unknown edge case. - return () => stopDeleting() - }, [stopDeleting]) - return ( > maxHeight: number | null onKeyPress?: (label: KeyLabel, action: KeyAction) => void - onKeyLongPressStart?: (label: KeyLabel, action: KeyAction) => void - onKeyLongPressEnd?: (label: KeyLabel, action: KeyAction) => void + onKeyLongPress?: (label: KeyLabel, action: KeyAction) => void onReady: () => void onTriggerInputShakeAnimation: () => void } diff --git a/packages/uniswap/src/features/transactions/TransactionDetails/TransactionDetails.tsx b/packages/uniswap/src/features/transactions/TransactionDetails/TransactionDetails.tsx index 31973e8474f..e2e57ef9a5d 100644 --- a/packages/uniswap/src/features/transactions/TransactionDetails/TransactionDetails.tsx +++ b/packages/uniswap/src/features/transactions/TransactionDetails/TransactionDetails.tsx @@ -16,8 +16,6 @@ import { FeeOnTransferFeeGroupProps, } from 'uniswap/src/features/transactions/TransactionDetails/FeeOnTransferFee' import { SwapFee } from 'uniswap/src/features/transactions/TransactionDetails/SwapFee' -import { AcrossRoutingInfo } from 'uniswap/src/features/transactions/swap/modals/AcrossRoutingInfo' -import { EstimatedTime } from 'uniswap/src/features/transactions/swap/review/EstimatedTime' import { UniswapXGasBreakdown } from 'uniswap/src/features/transactions/swap/types/swapTxAndGasInfo' import { SwapFeeInfo } from 'uniswap/src/features/transactions/swap/types/trade' import { WalletChainId } from 'uniswap/src/types/chains' @@ -35,8 +33,6 @@ interface TransactionDetailsProps { onShowWarning?: () => void indicative?: boolean isSwap?: boolean - isBridgeTrade?: boolean - estimatedBridgingTime?: number AccountDetails?: JSX.Element transactionUSDValue?: Maybe> } @@ -56,9 +52,7 @@ export function TransactionDetails({ indicative = false, isSwap, transactionUSDValue, - isBridgeTrade, AccountDetails, - estimatedBridgingTime, }: PropsWithChildren): JSX.Element { const { t } = useTranslation() const warningColor = getAlertColor(warning?.severity) @@ -111,7 +105,6 @@ export function TransactionDetails({ {showChildren ? {children} : null} {feeOnTransferProps && } - {isSwap && isBridgeTrade && } {isSwap && } - {isSwap && isBridgeTrade && } {AccountDetails} diff --git a/packages/uniswap/src/features/transactions/TransactionModal/TransactionModal.web.tsx b/packages/uniswap/src/features/transactions/TransactionModal/TransactionModal.web.tsx index 30b53e51f40..a5fd6cbffe3 100644 --- a/packages/uniswap/src/features/transactions/TransactionModal/TransactionModal.web.tsx +++ b/packages/uniswap/src/features/transactions/TransactionModal/TransactionModal.web.tsx @@ -18,7 +18,6 @@ export function TransactionModal({ onClose, openWalletRestoreModal, walletNeedsRestore, - swapRedirectCallback, modalName, }: TransactionModalProps): JSX.Element { const [screen, setScreen] = useState(TransactionScreen.Form) @@ -31,7 +30,6 @@ export function TransactionModal({ walletNeedsRestore={walletNeedsRestore} screen={screen} setScreen={setScreen} - swapRedirectCallback={swapRedirectCallback} onClose={onClose} > {children} diff --git a/packages/uniswap/src/features/transactions/TransactionModal/TransactionModalContext.tsx b/packages/uniswap/src/features/transactions/TransactionModal/TransactionModalContext.tsx index 769631f993d..59aa9dae28d 100644 --- a/packages/uniswap/src/features/transactions/TransactionModal/TransactionModalContext.tsx +++ b/packages/uniswap/src/features/transactions/TransactionModal/TransactionModalContext.tsx @@ -1,31 +1,14 @@ -import { Currency } from '@uniswap/sdk-core' import { createContext, PropsWithChildren, useContext, useMemo } from 'react' /* eslint-disable no-restricted-imports */ import type { StyleProp } from 'react-native/Libraries/StyleSheet/StyleSheet' import type { ViewStyle } from 'react-native/Libraries/StyleSheet/StyleSheetTypes' import { AuthTrigger } from 'uniswap/src/features/auth/types' -import { UniverseChainId } from 'uniswap/src/types/chains' -import { CurrencyField } from 'uniswap/src/types/currency' export enum TransactionScreen { Form = 'Form', Review = 'Review', } -export type SwapRedirectFn = ({ - inputCurrency, - outputCurrency, - typedValue, - independentField, - chainId, -}: { - inputCurrency?: Currency - outputCurrency?: Currency - typedValue?: string - independentField?: CurrencyField - chainId: UniverseChainId -}) => void - export type TransactionModalContextState = { bottomSheetViewStyles: StyleProp openWalletRestoreModal?: () => void @@ -35,7 +18,6 @@ export type TransactionModalContextState = { authTrigger?: AuthTrigger screen: TransactionScreen setScreen: (newScreen: TransactionScreen) => void - swapRedirectCallback?: SwapRedirectFn } export const TransactionModalContext = createContext(undefined) @@ -50,7 +32,6 @@ export function TransactionModalContextProvider({ walletNeedsRestore, screen, setScreen, - swapRedirectCallback, }: PropsWithChildren): JSX.Element { const state = useMemo( (): TransactionModalContextState => ({ @@ -61,7 +42,6 @@ export function TransactionModalContextProvider({ openWalletRestoreModal, screen, setScreen, - swapRedirectCallback, walletNeedsRestore, }), [ @@ -72,7 +52,6 @@ export function TransactionModalContextProvider({ openWalletRestoreModal, screen, setScreen, - swapRedirectCallback, walletNeedsRestore, ], ) diff --git a/packages/uniswap/src/features/transactions/TransactionModal/TransactionModalProps.tsx b/packages/uniswap/src/features/transactions/TransactionModal/TransactionModalProps.tsx index cbbeb4f9172..f08d2ccbb17 100644 --- a/packages/uniswap/src/features/transactions/TransactionModal/TransactionModalProps.tsx +++ b/packages/uniswap/src/features/transactions/TransactionModal/TransactionModalProps.tsx @@ -9,7 +9,6 @@ export type TransactionModalProps = PropsWithChildren<{ modalName: ModalNameType onClose: () => void openWalletRestoreModal?: TransactionModalContextState['openWalletRestoreModal'] - swapRedirectCallback?: TransactionModalContextState['swapRedirectCallback'] walletNeedsRestore?: TransactionModalContextState['walletNeedsRestore'] BiometricsIcon?: TransactionModalContextState['BiometricsIcon'] authTrigger?: TransactionModalContextState['authTrigger'] diff --git a/packages/uniswap/src/features/transactions/hooks/useUSDTokenUpdater.ts b/packages/uniswap/src/features/transactions/hooks/useUSDTokenUpdater.ts index db77f1b613e..ab6c2575a28 100644 --- a/packages/uniswap/src/features/transactions/hooks/useUSDTokenUpdater.ts +++ b/packages/uniswap/src/features/transactions/hooks/useUSDTokenUpdater.ts @@ -36,7 +36,7 @@ export function useUSDTokenUpdater({ useEffect(() => { if (!currency || !price) { - return undefined + return } const exactAmountUSD = (parseFloat(exactAmountFiat) / conversionRate).toFixed(NUM_DECIMALS_USD) diff --git a/packages/uniswap/src/features/transactions/modals/BlockedAddressModal.tsx b/packages/uniswap/src/features/transactions/modals/BlockedAddressModal.tsx index a21e9646939..d5d837eda2a 100644 --- a/packages/uniswap/src/features/transactions/modals/BlockedAddressModal.tsx +++ b/packages/uniswap/src/features/transactions/modals/BlockedAddressModal.tsx @@ -9,7 +9,7 @@ export function BlockedAddressModal({ isOpen, onClose }: { isOpen: boolean; onCl return ( } isOpen={isOpen} modalName={ModalName.SwapWarning} severity={WarningSeverity.Low} title={t('account.wallet.viewOnly.title')} onClose={onDismiss} - onAcknowledge={onDismiss} + onConfirm={onDismiss} /> ) } diff --git a/packages/uniswap/src/features/transactions/selectors.ts b/packages/uniswap/src/features/transactions/selectors.ts index 9ed4d5fc1e2..7eb3681bf79 100644 --- a/packages/uniswap/src/features/transactions/selectors.ts +++ b/packages/uniswap/src/features/transactions/selectors.ts @@ -45,12 +45,12 @@ export const makeSelectAddressTransactions = (): Selector< (_: UniswapState, address: Address | null) => address, (transactions, address) => { if (!address) { - return undefined + return } const addressTransactions = transactions[address] if (!addressTransactions) { - return undefined + return } return unique(flattenObjectOfObjects(addressTransactions), (tx, _, self) => { @@ -175,7 +175,6 @@ export const makeSelectUniswapXOrder = (): Selector< } } } - return undefined }, ) // Returns a list of past recipients ordered from most to least recent diff --git a/packages/uniswap/src/features/transactions/send/types.ts b/packages/uniswap/src/features/transactions/send/types.ts index 494b3e93664..30d4f210d5b 100644 --- a/packages/uniswap/src/features/transactions/send/types.ts +++ b/packages/uniswap/src/features/transactions/send/types.ts @@ -2,13 +2,13 @@ import { AssetType } from 'uniswap/src/entities/assets' import { CurrencyInfo } from 'uniswap/src/features/dataApi/types' import { GQLNftAsset } from 'uniswap/src/features/nfts/types' import { BaseDerivedInfo } from 'uniswap/src/features/transactions/types/baseDerivedInfo' -import { UniverseChainId } from 'uniswap/src/types/chains' +import { WalletChainId } from 'uniswap/src/types/chains' import { CurrencyField } from 'uniswap/src/types/currency' export type DerivedSendInfo = BaseDerivedInfo & { currencyTypes: { [CurrencyField.INPUT]?: AssetType } currencyInInfo?: CurrencyInfo | null - chainId: UniverseChainId + chainId: WalletChainId exactAmountFiat: string exactCurrencyField: CurrencyField.INPUT isFiatInput?: boolean diff --git a/packages/uniswap/src/features/transactions/slice.ts b/packages/uniswap/src/features/transactions/slice.ts index 3bf3e1031fa..0d6629f9ab0 100644 --- a/packages/uniswap/src/features/transactions/slice.ts +++ b/packages/uniswap/src/features/transactions/slice.ts @@ -36,14 +36,6 @@ const slice = createSlice({ assert(state?.[from]?.[chainId]?.[id], `updateTransaction: Attempted to update a missing tx with id ${id}`) state[from]![chainId]![id] = transaction }, - updateTransactionWithoutWatch: (state, { payload: transaction }: PayloadAction) => { - const { chainId, id, from } = transaction - assert( - state?.[from]?.[chainId]?.[id], - `updateTransactionWithoutWatch: Attempted to update a missing tx with id ${id}`, - ) - state[from]![chainId]![id] = transaction - }, finalizeTransaction: (state, { payload: transaction }: PayloadAction) => { const { chainId, id, status, receipt, from, hash } = transaction assert(state?.[from]?.[chainId]?.[id], `finalizeTransaction: Attempted to finalize a missing tx with id ${id}`) @@ -134,7 +126,6 @@ export const { resetTransactions, upsertFiatOnRampTransaction, updateTransaction, - updateTransactionWithoutWatch, } = slice.actions export const { reducer: transactionReducer } = slice diff --git a/packages/uniswap/src/features/transactions/swap/SwapFlow.tsx b/packages/uniswap/src/features/transactions/swap/SwapFlow.tsx index 1146c0bf40a..610b14d5284 100644 --- a/packages/uniswap/src/features/transactions/swap/SwapFlow.tsx +++ b/packages/uniswap/src/features/transactions/swap/SwapFlow.tsx @@ -24,16 +24,12 @@ import { WrapCallback } from 'uniswap/src/features/transactions/swap/types/wrapC export interface SwapFlowProps extends Omit { prefilledState?: SwapFormState customSettings?: SwapSettingConfig[] - hideHeader?: boolean - hideFooter?: boolean swapCallback: SwapCallback wrapCallback: WrapCallback } export function SwapFlow({ prefilledState, - hideHeader, - hideFooter, customSettings = [], swapCallback, wrapCallback, @@ -41,7 +37,7 @@ export function SwapFlow({ }: SwapFlowProps): JSX.Element { return ( - + diff --git a/packages/uniswap/src/features/transactions/swap/analytics.ts b/packages/uniswap/src/features/transactions/swap/analytics.ts index 4db05384506..d48a13cb94e 100644 --- a/packages/uniswap/src/features/transactions/swap/analytics.ts +++ b/packages/uniswap/src/features/transactions/swap/analytics.ts @@ -43,13 +43,11 @@ export function getBaseTradeAnalyticsProperties({ trade, currencyInAmountUSD, currencyOutAmountUSD, - portfolioBalanceUsd, }: { formatter: LocalizationContextState trade: Trade currencyInAmountUSD?: Maybe> currencyOutAmountUSD?: Maybe> - portfolioBalanceUsd?: number }): SwapTradeBaseProperties { const portionAmount = getClassicQuoteFromResponse(trade?.quote)?.portionAmount @@ -66,12 +64,11 @@ export function getBaseTradeAnalyticsProperties({ const slippagePercent = percentFromFloat(trade.slippageTolerance ?? 0) return { - total_balances_usd: portfolioBalanceUsd, token_in_symbol: trade.inputAmount.currency.symbol, token_out_symbol: trade.outputAmount.currency.symbol, token_in_address: getCurrencyAddressForAnalytics(trade.inputAmount.currency), token_out_address: getCurrencyAddressForAnalytics(trade.outputAmount.currency), - price_impact_basis_points: trade.priceImpact?.multiply(100).toSignificant(), + price_impact_basis_points: trade.priceImpact.multiply(100).toSignificant(), chain_id: trade.inputAmount.currency.chainId, token_in_amount: trade.inputAmount.toExact(), token_out_amount: formatter.formatCurrencyAmount({ @@ -80,9 +77,8 @@ export function getBaseTradeAnalyticsProperties({ }), token_in_amount_usd: currencyInAmountUSD ? parseFloat(currencyInAmountUSD.toFixed(2)) : undefined, token_out_amount_usd: currencyOutAmountUSD ? parseFloat(currencyOutAmountUSD.toFixed(2)) : undefined, - allowed_slippage: - trade.slippageTolerance !== undefined ? parseFloat(trade.slippageTolerance.toFixed(2)) : undefined, - allowed_slippage_basis_points: trade.slippageTolerance ? trade.slippageTolerance * 100 : undefined, + allowed_slippage: parseFloat(trade.slippageTolerance.toFixed(2)), + allowed_slippage_basis_points: trade.slippageTolerance * 100, fee_amount: portionAmount, requestId: trade.quote?.requestId, ura_request_id: trade.quote?.requestId, @@ -143,7 +139,7 @@ export function getBaseTradeAnalyticsPropertiesFromSwapInfo({ token_out_symbol: outputCurrencyAmount?.currency.symbol, token_in_address: inputCurrencyAmount ? getCurrencyAddressForAnalytics(inputCurrencyAmount?.currency) : '', token_out_address: outputCurrencyAmount ? getCurrencyAddressForAnalytics(outputCurrencyAmount?.currency) : '', - price_impact_basis_points: derivedSwapInfo.trade.trade?.priceImpact?.multiply(100)?.toSignificant(), + price_impact_basis_points: derivedSwapInfo.trade.trade?.priceImpact.multiply(100).toSignificant(), estimated_network_fee_usd: undefined, chain_id: chainId, token_in_amount: inputCurrencyAmount?.toExact() ?? '', diff --git a/packages/uniswap/src/features/transactions/swap/contexts/SwapFormContext.tsx b/packages/uniswap/src/features/transactions/swap/contexts/SwapFormContext.tsx index e07d3e6de4e..42f038b1c60 100644 --- a/packages/uniswap/src/features/transactions/swap/contexts/SwapFormContext.tsx +++ b/packages/uniswap/src/features/transactions/swap/contexts/SwapFormContext.tsx @@ -21,15 +21,13 @@ export type SwapFormState = { exactAmountToken?: string exactCurrencyField: CurrencyField focusOnCurrencyField?: CurrencyField - filteredChainIds: { [key in CurrencyField]?: UniverseChainId } + filteredChainId?: UniverseChainId input?: TradeableAsset output?: TradeableAsset selectingCurrencyField?: CurrencyField txId?: string isFiatMode: boolean isSubmitting: boolean - hideFooter?: boolean - hideSettings?: boolean tradeProtocolPreference: TradeProtocolPreference } @@ -42,16 +40,13 @@ type SwapFormContextState = { exactAmountFiatRef: React.MutableRefObject exactAmountTokenRef: React.MutableRefObject updateSwapForm: (newState: Partial) => void - resetSwapForm: () => void } & SwapFormState & DerivedSwapFormState -function getDefaultInputCurrency(chainId: UniverseChainId): TradeableAsset { - return { - address: getNativeAddress(chainId), - chainId, - type: AssetType.Currency, - } +const ETH_TRADEABLE_ASSET: Readonly = { + address: getNativeAddress(UniverseChainId.Mainnet), + chainId: UniverseChainId.Mainnet, + type: AssetType.Currency, } const DEFAULT_STATE: Readonly> = { @@ -59,8 +54,8 @@ const DEFAULT_STATE: Readonly> = { exactAmountToken: '', exactCurrencyField: CurrencyField.INPUT, focusOnCurrencyField: CurrencyField.INPUT, - filteredChainIds: {}, - input: getDefaultInputCurrency(UniverseChainId.Mainnet), + filteredChainId: undefined, + input: ETH_TRADEABLE_ASSET, output: undefined, isFiatMode: false, isSubmitting: false, @@ -72,13 +67,9 @@ export const SwapFormContext = createContext(u export function SwapFormContextProvider({ children, - hideFooter, - hideSettings, prefilledState, }: { children: ReactNode - hideFooter?: boolean - hideSettings?: boolean prefilledState?: SwapFormState }): JSX.Element { const amountUpdatedTimeRef = useRef(0) @@ -110,14 +101,6 @@ export function SwapFormContextProvider({ [setSwapForm, datadogEnabled], ) - const resetSwapForm = useCallback(() => { - // Reset to default state, except avoid resetting the current chain - setSwapForm((prev) => ({ - ...DEFAULT_STATE, - input: getDefaultInputCurrency(prev.output?.chainId ?? UniverseChainId.Mainnet), - })) - }, [setSwapForm]) - const [debouncedExactAmountToken, isDebouncingExactAmountToken] = useDebounceWithStatus( swapForm.exactAmountToken, SWAP_FORM_DEBOUNCE_TIME_MS, @@ -157,7 +140,7 @@ export function SwapFormContextProvider({ exactAmountTokenRef, exactCurrencyField: swapForm.exactCurrencyField, focusOnCurrencyField: swapForm.focusOnCurrencyField, - filteredChainIds: swapForm.filteredChainIds, + filteredChainId: swapForm.filteredChainId, input: swapForm.input, isFiatMode: swapForm.isFiatMode, isSubmitting: swapForm.isSubmitting, @@ -165,10 +148,7 @@ export function SwapFormContextProvider({ tradeProtocolPreference: swapForm.tradeProtocolPreference, selectingCurrencyField: swapForm.selectingCurrencyField, txId: swapForm.txId, - hideFooter, - hideSettings, updateSwapForm, - resetSwapForm, }), [ swapForm.customSlippageTolerance, @@ -177,7 +157,7 @@ export function SwapFormContextProvider({ swapForm.exactAmountToken, swapForm.exactCurrencyField, swapForm.focusOnCurrencyField, - swapForm.filteredChainIds, + swapForm.filteredChainId, swapForm.input, swapForm.isFiatMode, swapForm.isSubmitting, @@ -186,10 +166,7 @@ export function SwapFormContextProvider({ swapForm.selectingCurrencyField, swapForm.txId, derivedSwapInfo, - hideSettings, - hideFooter, updateSwapForm, - resetSwapForm, ], ) diff --git a/packages/uniswap/src/features/transactions/swap/form/SwapFormButton.tsx b/packages/uniswap/src/features/transactions/swap/form/SwapFormButton.tsx index d3313b838ea..3ef719df817 100644 --- a/packages/uniswap/src/features/transactions/swap/form/SwapFormButton.tsx +++ b/packages/uniswap/src/features/transactions/swap/form/SwapFormButton.tsx @@ -1,7 +1,8 @@ /* eslint-disable complexity */ import { useCallback, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' -import { AnimatePresence, Button, ColorTokens, Flex, Text, isWeb, useIsShortMobileDevice } from 'ui/src' +import { AnimatePresence, Button, ColorTokens, Flex, SpinningLoader, Text, isWeb, useIsShortMobileDevice } from 'ui/src' +import { iconSizes } from 'ui/src/theme' import { useAccountMeta, useUniswapContext } from 'uniswap/src/contexts/UniswapContext' import { AccountType } from 'uniswap/src/features/accounts/types' import { AccountCTAsExperimentGroup, Experiments } from 'uniswap/src/features/gating/experiments' @@ -16,6 +17,7 @@ import { import { ViewOnlyModal } from 'uniswap/src/features/transactions/modals/ViewOnlyModal' import { useSwapFormContext } from 'uniswap/src/features/transactions/swap/contexts/SwapFormContext' import { useParsedSwapWarnings } from 'uniswap/src/features/transactions/swap/hooks/useSwapWarnings' +import { isUniswapX } from 'uniswap/src/features/transactions/swap/utils/routing' import { isWrapAction } from 'uniswap/src/features/transactions/swap/utils/wrap' import { useIsBlocked } from 'uniswap/src/features/trm/hooks' import { TestID } from 'uniswap/src/test/fixtures/testIDs' @@ -31,13 +33,13 @@ export function SwapFormButton(): JSX.Element { const isShortMobileDevice = useIsShortMobileDevice() const activeAccount = useAccountMeta() - const { walletNeedsRestore, setScreen, swapRedirectCallback } = useTransactionModalContext() + const { walletNeedsRestore, setScreen } = useTransactionModalContext() const { derivedSwapInfo, isSubmitting, updateSwapForm, exactAmountFiat, exactAmountToken } = useSwapFormContext() const { blockingWarning, insufficientBalanceWarning, insufficientGasFundsWarning } = useParsedSwapWarnings() const [showViewOnlyModal, setShowViewOnlyModal] = useState(false) - const { wrapType, trade, currencies, chainId, exactCurrencyField } = derivedSwapInfo + const { wrapType, trade, currencies, chainId } = derivedSwapInfo const { isBlocked, isBlockedLoading } = useIsBlocked(activeAccount?.address) @@ -53,16 +55,8 @@ export function SwapFormButton(): JSX.Element { const { onConnectWallet } = useUniswapContext() const onReviewPress = useCallback(() => { - if (swapRedirectCallback) { - swapRedirectCallback({ - inputCurrency: currencies[CurrencyField.INPUT]?.currency, - outputCurrency: currencies[CurrencyField.OUTPUT]?.currency, - typedValue: exactAmountToken, - independentField: exactCurrencyField, - chainId, - }) - // Active account will only ever be undefined on web - } else if (!activeAccount && onConnectWallet) { + // Active account will only ever be undefined on web + if (!activeAccount && onConnectWallet) { onConnectWallet() } else if (isViewOnlyWallet) { setShowViewOnlyModal(true) @@ -70,18 +64,10 @@ export function SwapFormButton(): JSX.Element { updateSwapForm({ txId: createTransactionId() }) setScreen(TransactionScreen.Review) } - }, [ - activeAccount, - currencies, - onConnectWallet, - exactAmountToken, - exactCurrencyField, - chainId, - isViewOnlyWallet, - setScreen, - swapRedirectCallback, - updateSwapForm, - ]) + }, [activeAccount, isViewOnlyWallet, onConnectWallet, setScreen, updateSwapForm]) + + // TODO(WEB-4821): Remove uniswapx submission logic since this component will no longer be rendered during submission + const showUniswapXSubmittingUI = trade.trade && isUniswapX(trade?.trade) && isSubmitting const invalidTokenSelection = Object.values(currencies).some((currency) => !currency) const invalidAmountSelection = !exactAmountFiat && !exactAmountToken @@ -94,9 +80,6 @@ export function SwapFormButton(): JSX.Element { const isLogIn = accountsCTAExperimentGroup === AccountCTAsExperimentGroup.LogInCreateAccount const getButtonText = (): string => { - if (swapRedirectCallback) { - return t('common.getStarted') - } if (!activeAccount) { return isSignIn ? t('nav.signIn.button') : isLogIn ? t('nav.logIn.button') : t('common.connectWallet.button') } @@ -127,16 +110,8 @@ export function SwapFormButton(): JSX.Element { buttonText: string } = { backgroundColor: - !activeAccount || isSubmitting - ? '$accent2' - : isBlockingWithCustomMessage && !swapRedirectCallback - ? '$surface2' - : '$accent1', - buttonTextColor: !activeAccount - ? '$accent1' - : isBlockingWithCustomMessage && !swapRedirectCallback - ? '$neutral2' - : '$white', + !activeAccount || isSubmitting ? '$accent2' : isBlockingWithCustomMessage ? '$surface2' : '$accent1', + buttonTextColor: !activeAccount ? '$accent1' : isBlockingWithCustomMessage ? '$neutral2' : '$white', buttonText: getButtonText(), } @@ -149,7 +124,8 @@ export function SwapFormButton(): JSX.Element { pressStyle={{ backgroundColor: buttonProps.backgroundColor, opacity: 0.7 }} hoverStyle={{ backgroundColor: buttonProps.backgroundColor, opacity: 0.9 }} backgroundColor={buttonProps.backgroundColor} - disabled={!!activeAccount && reviewButtonDisabled && !isViewOnlyWallet && !swapRedirectCallback} + disabled={!!activeAccount && reviewButtonDisabled && !isViewOnlyWallet} + icon={showUniswapXSubmittingUI ? : undefined} // use opacity 1 for states with error text, because surface2 is hard to read with default disabled opacity opacity={isViewOnlyWallet ? 0.4 : isBlockingWithCustomMessage ? 1 : undefined} size={isShortMobileDevice ? 'small' : isWeb ? 'medium' : 'large'} @@ -157,9 +133,13 @@ export function SwapFormButton(): JSX.Element { width="100%" onPress={onReviewPress} > - - {buttonProps.buttonText} - + {showUniswapXSubmittingUI ? ( + + ) : ( + + {buttonProps.buttonText} + + )} setShowViewOnlyModal(false)} /> diff --git a/packages/uniswap/src/features/transactions/swap/form/SwapFormScreen.tsx b/packages/uniswap/src/features/transactions/swap/form/SwapFormScreen.tsx index 1baae54ed31..9d72a157080 100644 --- a/packages/uniswap/src/features/transactions/swap/form/SwapFormScreen.tsx +++ b/packages/uniswap/src/features/transactions/swap/form/SwapFormScreen.tsx @@ -63,7 +63,6 @@ const ON_SELECTION_CHANGE_WAIT_TIME_MS = 500 interface SwapFormScreenProps { hideContent: boolean - hideFooter?: boolean customSettings: SwapSettingConfig[] } @@ -73,14 +72,14 @@ interface SwapFormScreenProps { */ export function SwapFormScreen({ hideContent, customSettings }: SwapFormScreenProps): JSX.Element { const { bottomSheetViewStyles } = useTransactionModalContext() - const { selectingCurrencyField, hideSettings } = useSwapFormContext() + const { selectingCurrencyField } = useSwapFormContext() const showTokenSelector = !hideContent && !!selectingCurrencyField return ( {!isInterface && /* Interface renders its own header with multiple tabs */} - {!hideSettings && } + {!hideContent && } @@ -108,7 +107,6 @@ function SwapFormContent(): JSX.Element { input, isFiatMode, output, - hideFooter, updateSwapForm, } = useSwapFormContext() @@ -439,11 +437,6 @@ function SwapFormContent(): JSX.Element { const decimalPadValueRef = decimalPadControlledField === exactCurrencyField ? exactValueRef : formattedDerivedValueRef - // If exact output will fail due to FoT tokens, the field should be disabled and un-focusable. - // Also, for bridging, the output field should be disabled since Across does not have exact in vs. exact out. - const isBridge = input && output && input?.chainId !== output?.chainId - const exactOutputDisabled = isBridge || exactOutputWillFail - const [showWarning, setShowWarning] = useState(false) const timeoutRef = useRef(null) const showTemporaryFoTWarning = (): void => { @@ -512,7 +505,7 @@ function SwapFormContent(): JSX.Element { currencyBalance={currencyBalances[CurrencyField.OUTPUT]} currencyField={CurrencyField.OUTPUT} currencyInfo={currencies[CurrencyField.OUTPUT]} - disabled={exactOutputDisabled} + disabled={exactOutputWillFail} // If exact output will fail due to FoT tokens, the input field should be disabled and un-focusable focus={focusOnCurrencyField === CurrencyField.OUTPUT} isFiatMode={isFiatMode && exactFieldIsOutput} isLoading={!exactFieldIsOutput && isSwapDataLoading} @@ -521,7 +514,7 @@ function SwapFormContent(): JSX.Element { usdValue={currencyAmountsUSDValue[CurrencyField.OUTPUT]} value={exactFieldIsOutput ? exactValue : formattedDerivedValue} valueIsIndicative={!exactFieldIsOutput && trade.indicativeTrade && !trade.trade} - onPressDisabled={isBridge ? undefined : showTemporaryFoTWarning} + onPressDisabled={showTemporaryFoTWarning} onPressIn={onFocusOutput} onSelectionChange={onOutputSelectionChange} onSetExactAmount={onSetExactAmountOutput} @@ -560,14 +553,12 @@ function SwapFormContent(): JSX.Element { )} - {!hideFooter && ( - - - {showWarning && } - - {!showWarning && } - - )} + + + {showWarning && } + + {!showWarning && } + {!isWeb && ( diff --git a/packages/uniswap/src/features/transactions/swap/form/SwapFormSettings.tsx b/packages/uniswap/src/features/transactions/swap/form/SwapFormSettings.tsx index b0ffca5b5d5..851c4dd383d 100644 --- a/packages/uniswap/src/features/transactions/swap/form/SwapFormSettings.tsx +++ b/packages/uniswap/src/features/transactions/swap/form/SwapFormSettings.tsx @@ -43,7 +43,7 @@ export function SwapFormSettings({ customSettings }: { customSettings: SwapSetti const rightAlignment = isMobileApp ? 24 : 4 return ( - + { + (currency: Currency, field: CurrencyField) => { const tradeableAsset: TradeableAsset = { address: currencyAddress(currency), chainId: currency.chainId, @@ -56,7 +55,7 @@ export function SwapTokenSelector({ isModalOpen }: { isModalOpen: boolean }): JS exactCurrencyField === CurrencyField.INPUT ? CurrencyField.OUTPUT : CurrencyField.INPUT newState.focusOnCurrencyField = newState.exactCurrencyField newState[otherField] = previouslySelectedTradableAsset - } else if (!chainsAreEqual && !isBridgePair) { + } else if (!chainsAreEqual) { // if new token chain changes, try to find the other token's match on the new chain const otherFieldTokenProjects = otherField === CurrencyField.INPUT ? inputTokenProjects : outputTokenProjects const otherCurrency = otherFieldTokenProjects?.data?.find( @@ -74,20 +73,7 @@ export function SwapTokenSelector({ isModalOpen }: { isModalOpen: boolean }): JS : undefined } - if (!isBridgePair) { - // If selecting output, set the input and output chainIds - // If selecting input and output is already selected, also set the input chainId - if (field === CurrencyField.OUTPUT || !!output) { - filteredChainIds[CurrencyField.INPUT] = currency.chainId - filteredChainIds[CurrencyField.OUTPUT] = currency.chainId - // If selecting input, only set the output chainId - } else { - filteredChainIds[CurrencyField.OUTPUT] = currency.chainId - } - - newState.filteredChainIds = filteredChainIds - } - + newState.filteredChainId = currency.chainId newState[field] = tradeableAsset updateSwapForm(newState) @@ -95,23 +81,13 @@ export function SwapTokenSelector({ isModalOpen }: { isModalOpen: boolean }): JS // Hide screen when done selecting. onHideTokenSelector() }, - [ - exactCurrencyField, - input, - inputTokenProjects, - filteredChainIds, - onHideTokenSelector, - output, - outputTokenProjects, - updateSwapForm, - ], + [exactCurrencyField, input, inputTokenProjects, onHideTokenSelector, output, outputTokenProjects, updateSwapForm], ) const props: TokenSelectorProps = { isModalOpen, activeAccountAddress, - chainId: filteredChainIds[selectingCurrencyField ?? CurrencyField.INPUT], - input, + chainId: filteredChainId, // token selector modal will only open on currency field selection; casting to satisfy typecheck here - we should consider refactoring the types here to avoid casting currencyField: selectingCurrencyField as CurrencyField, flow: TokenSelectorFlow.Swap, diff --git a/packages/uniswap/src/features/transactions/swap/form/footer/GasAndWarningRows.web.tsx b/packages/uniswap/src/features/transactions/swap/form/footer/GasAndWarningRows.web.tsx index e610dcf801e..e200ca3428d 100644 --- a/packages/uniswap/src/features/transactions/swap/form/footer/GasAndWarningRows.web.tsx +++ b/packages/uniswap/src/features/transactions/swap/form/footer/GasAndWarningRows.web.tsx @@ -24,7 +24,7 @@ export function GasAndWarningRows(): JSX.Element { const { derivedSwapInfo } = useSwapFormContext() const { trade } = derivedSwapInfo - const priceImpact = trade.trade?.priceImpact ? normalizePriceImpact(trade.trade?.priceImpact) : undefined + const priceImpact = trade.trade ? normalizePriceImpact(trade.trade?.priceImpact) : undefined const [showWarningModal, setShowWarningModal] = useState(false) diff --git a/packages/uniswap/src/features/transactions/swap/hooks/useAcceptedTrade.ts b/packages/uniswap/src/features/transactions/swap/hooks/useAcceptedTrade.ts index 464ee9890e8..f114c4145c8 100644 --- a/packages/uniswap/src/features/transactions/swap/hooks/useAcceptedTrade.ts +++ b/packages/uniswap/src/features/transactions/swap/hooks/useAcceptedTrade.ts @@ -34,7 +34,7 @@ export function useAcceptedTrade({ const onAcceptTrade = (): undefined => { if (!trade) { - return + return undefined } setAcceptedDerivedSwapInfo(derivedSwapInfo) diff --git a/packages/uniswap/src/features/transactions/swap/hooks/useDerivedSwapInfo.ts b/packages/uniswap/src/features/transactions/swap/hooks/useDerivedSwapInfo.ts index b1843ae2f22..07fd4bcdfde 100644 --- a/packages/uniswap/src/features/transactions/swap/hooks/useDerivedSwapInfo.ts +++ b/packages/uniswap/src/features/transactions/swap/hooks/useDerivedSwapInfo.ts @@ -89,7 +89,6 @@ export function useDerivedSwapInfo({ currency: otherCurrency, }) } - return undefined }, [exactAmountToken, isWrap, otherCurrency]) const sendPortionEnabled = useFeatureFlag(FeatureFlags.PortionFields) diff --git a/packages/uniswap/src/features/transactions/swap/hooks/usePermit2Signature.ts b/packages/uniswap/src/features/transactions/swap/hooks/usePermit2Signature.ts index 21162addaea..8196cb0a126 100644 --- a/packages/uniswap/src/features/transactions/swap/hooks/usePermit2Signature.ts +++ b/packages/uniswap/src/features/transactions/swap/hooks/usePermit2Signature.ts @@ -24,7 +24,7 @@ export function usePermit2SignatureWithData({ permitData, skip }: { permitData: const permitSignatureFetcher = useCallback(async () => { if (skip || !signer || !domain || !types || !values) { - return undefined + return } return await signTypedData( diff --git a/packages/uniswap/src/features/transactions/swap/hooks/useSetTradeSlippage.ts b/packages/uniswap/src/features/transactions/swap/hooks/useSetTradeSlippage.ts index 988023a3603..0f9bfd2956d 100644 --- a/packages/uniswap/src/features/transactions/swap/hooks/useSetTradeSlippage.ts +++ b/packages/uniswap/src/features/transactions/swap/hooks/useSetTradeSlippage.ts @@ -5,7 +5,6 @@ import { DynamicConfigs, SwapConfigKey } from 'uniswap/src/features/gating/confi import { useDynamicConfigValue } from 'uniswap/src/features/gating/hooks' import { useUSDCValue } from 'uniswap/src/features/transactions/swap/hooks/useUSDCPrice' import { Trade, TradeWithStatus } from 'uniswap/src/features/transactions/swap/types/trade' -import { isBridge } from 'uniswap/src/features/transactions/swap/utils/routing' import { getClassicQuoteFromResponse, transformTradingApiResponseToTrade, @@ -19,10 +18,6 @@ export function useSetTradeSlippage( const autoSlippageTolerance = useCalculateAutoSlippage(trade?.trade) return useMemo(() => { - if (trade.trade && isBridge(trade.trade)) { - // Bridge trades don't have slippage - return { trade, autoSlippageTolerance: 0 } - } // If the user has set a custom slippage, use that in the trade instead of the auto-slippage if (!trade.trade || userSetSlippage) { return { trade, autoSlippageTolerance } diff --git a/packages/uniswap/src/features/transactions/swap/hooks/useSwapTxAndGasInfo.test.ts b/packages/uniswap/src/features/transactions/swap/hooks/useSwapTxAndGasInfo.test.ts index 7dd16a34b7e..6e559cfafa3 100644 --- a/packages/uniswap/src/features/transactions/swap/hooks/useSwapTxAndGasInfo.test.ts +++ b/packages/uniswap/src/features/transactions/swap/hooks/useSwapTxAndGasInfo.test.ts @@ -1,7 +1,6 @@ import { renderHook } from '@testing-library/react-hooks' import { UNI, WBTC } from 'uniswap/src/constants/tokens' -import { Routing } from 'uniswap/src/data/tradingApi/__generated__/index' -import { FeeType } from 'uniswap/src/data/tradingApi/types' +import { FeeType, Routing } from 'uniswap/src/data/tradingApi/__generated__/index' import { AccountType, SignerMnemonicAccountMeta } from 'uniswap/src/features/accounts/types' import { DEFAULT_GAS_STRATEGY } from 'uniswap/src/features/gas/hooks' import { useSwapTxAndGasInfo } from 'uniswap/src/features/transactions/swap/hooks/useSwapTxAndGasInfo' @@ -65,16 +64,14 @@ describe('useSwapTxAndGasInfo', () => { const mockSwapTxInfo: TransactionRequestInfo = { transactionRequest: { to: '0x456', chainId: 1 }, gasFeeResult: { value: '123', isLoading: false, error: null }, - gasEstimate: { - swapEstimates: { - activeEstimate: { - gasLimit: '500000', - gasFee: '600000', - maxFeePerGas: '700000', - maxPriorityFeePerGas: '800000', - type: FeeType.EIP1559, - strategy: DEFAULT_GAS_STRATEGY, - }, + gasEstimates: { + activeEstimate: { + gasLimit: '500000', + gasFee: '600000', + maxFeePerGas: '700000', + maxPriorityFeePerGas: '800000', + type: FeeType.EIP1559, + strategy: DEFAULT_GAS_STRATEGY, }, }, permitSignature: undefined, @@ -119,9 +116,10 @@ describe('useSwapTxAndGasInfo', () => { }, approvalError: false, indicativeTrade: undefined, - permit: undefined, + permitSignature: undefined, + permitData: undefined, + permitDataLoading: undefined, swapRequestArgs: undefined, - unsigned: false, }) }) }) diff --git a/packages/uniswap/src/features/transactions/swap/hooks/useSwapTxAndGasInfo.ts b/packages/uniswap/src/features/transactions/swap/hooks/useSwapTxAndGasInfo.ts index c33571fc8e2..41191a9a968 100644 --- a/packages/uniswap/src/features/transactions/swap/hooks/useSwapTxAndGasInfo.ts +++ b/packages/uniswap/src/features/transactions/swap/hooks/useSwapTxAndGasInfo.ts @@ -13,9 +13,8 @@ import { import { ApprovalAction, Trade } from 'uniswap/src/features/transactions/swap/types/trade' import { sumGasFees } from 'uniswap/src/features/transactions/swap/utils/gas' import { isUniswapX } from 'uniswap/src/features/transactions/swap/utils/routing' -import { validatePermit, validateTransactionRequest } from 'uniswap/src/features/transactions/swap/utils/trade' +import { validateTransactionRequest } from 'uniswap/src/features/transactions/swap/utils/trade' import { CurrencyField } from 'uniswap/src/types/currency' -import { isInterface } from 'utilities/src/platform' export function useSwapTxAndGasInfo({ derivedSwapInfo, @@ -36,7 +35,6 @@ export function useSwapTxAndGasInfo({ chainId, wrapType, currencyInAmount: currencyAmounts[CurrencyField.INPUT], - currencyOutAmount: currencyAmounts[CurrencyField.OUTPUT], routing: trade?.routing, }) @@ -53,7 +51,7 @@ export function useSwapTxAndGasInfo({ const approvalError = tokenApprovalInfo?.action === ApprovalAction.Unknown const gasFeeEstimation: SwapGasFeeEstimation = { - ...swapTxInfo.gasEstimate, + swapEstimates: swapTxInfo.gasEstimates, approvalEstimates: tokenApprovalInfo?.gasEstimates, } @@ -62,8 +60,6 @@ export function useSwapTxAndGasInfo({ const approveTxRequest = validateTransactionRequest(tokenApprovalInfo?.txRequest) const revocationTxRequest = validateTransactionRequest(tokenApprovalInfo?.cancelTxRequest) const txRequest = validateTransactionRequest(swapTxInfo.transactionRequest) - const permit = validatePermit(swapTxInfo.permitData) - const unsigned = Boolean(isInterface && swapTxInfo.permitData) if (trade?.routing === Routing.DUTCH_V2) { const signature = swapTxInfo.permitSignature @@ -84,25 +80,12 @@ export function useSwapTxAndGasInfo({ revocationTxRequest, orderParams, gasFee, - gasFeeEstimation, gasFeeBreakdown, approvalError, - permit, - } - } else if (trade?.routing === Routing.BRIDGE) { - return { - routing: Routing.BRIDGE, - trade, - indicativeTrade: undefined, // Bridge trades don't have indicative trades - txRequest, - approveTxRequest, - revocationTxRequest, - gasFee, - gasFeeEstimation, - approvalError, + permitData: swapTxInfo.permitData, + permitDataLoading: swapTxInfo.permitDataLoading, swapRequestArgs: swapTxInfo.swapRequestArgs, - permit, - unsigned, + permitSignature: swapTxInfo.permitSignature, } } else { return { @@ -115,18 +98,20 @@ export function useSwapTxAndGasInfo({ gasFee, gasFeeEstimation, approvalError, + permitData: swapTxInfo.permitData, + permitDataLoading: swapTxInfo.permitDataLoading, swapRequestArgs: swapTxInfo.swapRequestArgs, - permit, - unsigned, + permitSignature: swapTxInfo.permitSignature, } } }, [ indicativeTrade, - swapTxInfo.gasEstimate, + swapTxInfo.gasEstimates, swapTxInfo.gasFeeResult, swapTxInfo.permitSignature, swapTxInfo.transactionRequest, swapTxInfo.permitData, + swapTxInfo.permitDataLoading, swapTxInfo.swapRequestArgs, tokenApprovalInfo, trade, diff --git a/packages/uniswap/src/features/transactions/swap/hooks/useSwapWarnings.test.ts b/packages/uniswap/src/features/transactions/swap/hooks/useSwapWarnings.test.ts index 7b1dd33ed60..8b7cb9a2d25 100644 --- a/packages/uniswap/src/features/transactions/swap/hooks/useSwapWarnings.test.ts +++ b/packages/uniswap/src/features/transactions/swap/hooks/useSwapWarnings.test.ts @@ -1,7 +1,6 @@ import { CurrencyAmount } from '@uniswap/sdk-core' import { WarningLabel } from 'uniswap/src/components/modals/WarningModal/types' import { DAI, USDC } from 'uniswap/src/constants/tokens' -import { Locale } from 'uniswap/src/features/language/constants' import { NativeCurrency } from 'uniswap/src/features/tokens/NativeCurrency' import { getSwapWarnings } from 'uniswap/src/features/transactions/swap/hooks/useSwapWarnings' import { DerivedSwapInfo } from 'uniswap/src/features/transactions/swap/types/derivedSwapInfo' @@ -112,7 +111,7 @@ const tradeErrorState: DerivedSwapInfo = { gasEstimates: createGasFeeEstimates(), }, } -const { formatPercent } = mockLocalizedFormatter(Locale.EnglishUnitedStates) +const { formatPercent } = mockLocalizedFormatter describe(getSwapWarnings, () => { it('catches incomplete form errors', async () => { diff --git a/packages/uniswap/src/features/transactions/swap/hooks/useTokenApprovalInfo.test.ts b/packages/uniswap/src/features/transactions/swap/hooks/useTokenApprovalInfo.test.ts index d8c9635c59b..b957603e8da 100644 --- a/packages/uniswap/src/features/transactions/swap/hooks/useTokenApprovalInfo.test.ts +++ b/packages/uniswap/src/features/transactions/swap/hooks/useTokenApprovalInfo.test.ts @@ -1,9 +1,8 @@ import { renderHook } from '@testing-library/react-hooks' import { CurrencyAmount, Token } from '@uniswap/sdk-core' -import { DAI, USDC } from 'uniswap/src/constants/tokens' +import { DAI } from 'uniswap/src/constants/tokens' import { useCheckApprovalQuery } from 'uniswap/src/data/apiClients/tradingApi/useCheckApprovalQuery' -import { Routing } from 'uniswap/src/data/tradingApi/__generated__/index' -import { FeeType } from 'uniswap/src/data/tradingApi/types' +import { FeeType, Routing } from 'uniswap/src/data/tradingApi/__generated__/index' import { AccountMeta, AccountType } from 'uniswap/src/features/accounts/types' import { DEFAULT_GAS_STRATEGY } from 'uniswap/src/features/gas/hooks' import { @@ -28,16 +27,13 @@ describe('useTokenApprovalInfo', () => { const mockAccount: AccountMeta = { address: '0x123', type: AccountType.SignerMnemonic } const mockTokenIn = new Token(UniverseChainId.Mainnet, DAI.address, DAI.decimals, DAI.symbol, DAI.name) - const mockTokenOut = new Token(UniverseChainId.Mainnet, USDC.address, USDC.decimals, USDC.symbol, USDC.name) const mockCurrencyInAmount = CurrencyAmount.fromRawAmount(mockTokenIn, '1000000000000000000') // 1 TKIN - const mockCurrencyOutAmount = CurrencyAmount.fromRawAmount(mockTokenOut, '2000000000000000000') // 2 TKOUT const mockParams: TokenApprovalInfoParams = { chainId: UniverseChainId.Mainnet, wrapType: WrapType.NotApplicable, currencyInAmount: mockCurrencyInAmount, - currencyOutAmount: mockCurrencyOutAmount, routing: Routing.CLASSIC, account: mockAccount, skip: false, diff --git a/packages/uniswap/src/features/transactions/swap/hooks/useTokenApprovalInfo.ts b/packages/uniswap/src/features/transactions/swap/hooks/useTokenApprovalInfo.ts index d5361b60062..eb3b1842d28 100644 --- a/packages/uniswap/src/features/transactions/swap/hooks/useTokenApprovalInfo.ts +++ b/packages/uniswap/src/features/transactions/swap/hooks/useTokenApprovalInfo.ts @@ -20,7 +20,6 @@ export interface TokenApprovalInfoParams { chainId: WalletChainId wrapType: WrapType currencyInAmount: Maybe> - currencyOutAmount?: Maybe> routing: Routing | undefined account?: AccountMeta skip?: boolean @@ -35,7 +34,7 @@ interface TokenApprovalGasInfo { export function useTokenApprovalInfo( params: TokenApprovalInfoParams, ): (TokenApprovalInfo & TokenApprovalGasInfo) | undefined { - const { account, chainId, wrapType, currencyInAmount, currencyOutAmount, routing, skip } = params + const { account, chainId, wrapType, currencyInAmount, routing, skip } = params const isWrap = wrapType !== WrapType.NotApplicable @@ -44,34 +43,22 @@ export function useTokenApprovalInfo( const currencyIn = routing === Routing.DUTCH_V2 ? currencyInAmount?.currency.wrapped : currencyInAmount?.currency const amount = currencyInAmount?.quotient.toString() - const tokenInAddress = getTokenAddressForApi(currencyIn) - - // Only used for bridging - const isBridge = routing === Routing.BRIDGE - const currencyOut = currencyOutAmount?.currency - const tokenOutAddress = getTokenAddressForApi(currencyOut) + const tokenAddress = getTokenAddressForApi(currencyIn) const approvalRequestArgs: ApprovalRequest | undefined = useMemo(() => { - const tokenInChainId = toTradingApiSupportedChainId(chainId) - const tokenOutChainId = toTradingApiSupportedChainId(currencyOut?.chainId) + const supportedChainId = toTradingApiSupportedChainId(chainId) - if (!address || !amount || !currencyIn || !tokenInAddress || !tokenInChainId) { - return undefined - } - if (isBridge && !tokenOutAddress && !tokenOutChainId) { + if (!address || !amount || !currencyIn || !tokenAddress || !supportedChainId) { return undefined } - return { walletAddress: address, - token: tokenInAddress, + token: tokenAddress, amount, - chainId: tokenInChainId, + chainId: supportedChainId, includeGasInfo: true, - tokenOut: tokenOutAddress, - tokenOutChainId, } - }, [address, amount, chainId, currencyIn, currencyOut?.chainId, isBridge, tokenInAddress, tokenOutAddress]) + }, [address, amount, chainId, currencyIn, tokenAddress]) const shouldSkip = skip || !approvalRequestArgs || isWrap || !address const activeGasStrategy = useActiveGasStrategy(chainId, 'general') diff --git a/packages/uniswap/src/features/transactions/swap/hooks/useTrade.ts b/packages/uniswap/src/features/transactions/swap/hooks/useTrade.ts index 8a2c18f2a00..065d0f718be 100644 --- a/packages/uniswap/src/features/transactions/swap/hooks/useTrade.ts +++ b/packages/uniswap/src/features/transactions/swap/hooks/useTrade.ts @@ -73,14 +73,7 @@ export function useTrade({ const activeGasStrategy = useActiveGasStrategy(tokenInChainId, 'swap') const shadowGasStrategies = useShadowGasStrategies(tokenInChainId, 'swap') - const isBridging = currencyIn?.chainId !== currencyOut?.chainId - - const routingPreference = getRoutingPreferenceForSwapRequest( - tradeProtocolPreference, - uniswapXEnabled, - isBridging, - isUSDQuote, - ) + const routingPreference = getRoutingPreferenceForSwapRequest(tradeProtocolPreference, uniswapXEnabled, isUSDQuote) const requestTradeType = tradeType === TradeType.EXACT_INPUT ? TradingApiTradeType.EXACT_INPUT : TradingApiTradeType.EXACT_OUTPUT diff --git a/packages/uniswap/src/features/transactions/swap/hooks/useTransactionRequestInfo.test.ts b/packages/uniswap/src/features/transactions/swap/hooks/useTransactionRequestInfo.test.ts deleted file mode 100644 index 2e647b4a06b..00000000000 --- a/packages/uniswap/src/features/transactions/swap/hooks/useTransactionRequestInfo.test.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { renderHook } from '@testing-library/react-hooks' -import { providers } from 'ethers/lib/ethers' -import { useTradingApiSwapQuery } from 'uniswap/src/data/apiClients/tradingApi/useTradingApiSwapQuery' -import { AccountMeta, AccountType } from 'uniswap/src/features/accounts/types' -import { useTransactionGasFee } from 'uniswap/src/features/gas/hooks' -import { GasFeeResult } from 'uniswap/src/features/gas/types' -import { usePermit2SignatureWithData } from 'uniswap/src/features/transactions/swap/hooks/usePermit2Signature' -import { useTransactionRequestInfo } from 'uniswap/src/features/transactions/swap/hooks/useTransactionRequestInfo' -import { useWrapTransactionRequest } from 'uniswap/src/features/transactions/swap/hooks/useWrapTransactionRequest' -import { WrapType } from 'uniswap/src/features/transactions/types/wrap' -import { ETH, WETH } from 'uniswap/src/test/fixtures' -import { createMockDerivedSwapInfo, createMockTokenApprovalInfo } from 'uniswap/src/test/fixtures/transactions/swap' -import { UniverseChainId } from 'uniswap/src/types/chains' - -jest.mock('uniswap/src/data/apiClients/tradingApi/useTradingApiSwapQuery') -jest.mock('uniswap/src/features/transactions/swap/hooks/usePermit2Signature') -jest.mock('uniswap/src/features/transactions/swap/hooks/useWrapTransactionRequest') -jest.mock('uniswap/src/features/gas/hooks') -jest.mock('uniswap/src/features/gating/hooks', () => { - return { - useDynamicConfigValue: jest.fn().mockImplementation((config: unknown, key: unknown, defaultVal: unknown) => { - return defaultVal - }), - } -}) - -const mockUseTradingApiSwapQuery = useTradingApiSwapQuery as jest.Mock -const mockUsePermit2SignatureWithData = usePermit2SignatureWithData as jest.Mock -const mockUseWrapTransactionRequest = useWrapTransactionRequest as jest.Mock -const mockUseTransactionGasFee = useTransactionGasFee as jest.Mock - -describe('useTransactionRequestInfo', () => { - const mockAccount: AccountMeta = { address: '0x123', type: AccountType.SignerMnemonic } - const mockWrapGasFee: GasFeeResult = { - value: '250000', - params: { - gasLimit: '250000', - maxFeePerGas: '300000', - maxPriorityFeePerGas: '350000', - }, - isLoading: false, - error: null, - } - const swapQueryResult = { - data: { - requestId: '123', - swap: { - from: '0x123', - data: '0x', - value: '0', - to: '0xSwap', - chainId: UniverseChainId.Mainnet, - gasLimit: '500000', - maxFeePerGas: '600000', - maxPriorityFeePerGas: '700000', - }, - }, - error: null, - isLoading: false, - } - - beforeEach(() => { - jest.clearAllMocks() - }) - - it('should include gas fee values from wrapGasFee in the returned wrap transactionRequest', () => { - // Swap needs wrapping - const mockDerivedSwapInfo = createMockDerivedSwapInfo(ETH, WETH, '1000000000000000000', '1000000000', { - wrapType: WrapType.Wrap, - }) - mockUseWrapTransactionRequest.mockReturnValue({ - to: '0xWrap', - chainId: UniverseChainId.Mainnet, - }) - mockUsePermit2SignatureWithData.mockReturnValue({ signature: undefined, isLoading: false }) - mockUseTradingApiSwapQuery.mockReturnValue(swapQueryResult) - mockUseTransactionGasFee.mockReturnValue(mockWrapGasFee) - - const { result } = renderHook(() => - useTransactionRequestInfo({ - derivedSwapInfo: mockDerivedSwapInfo, - tokenApprovalInfo: createMockTokenApprovalInfo(), - account: mockAccount, - skip: false, - }), - ) - - expect(result.current.transactionRequest).toMatchObject({ - to: '0xWrap', - chainId: UniverseChainId.Mainnet, - gasLimit: '250000', - maxFeePerGas: '300000', - maxPriorityFeePerGas: '350000', - }) - }) - - it('should return the swap transactionRequest when wrap is not applicable', () => { - // Swap does not need wrapping - const mockDerivedSwapInfo = createMockDerivedSwapInfo(ETH, WETH, '1000000000000000000', '1000000000') - - mockUseWrapTransactionRequest.mockReturnValue(null) - mockUsePermit2SignatureWithData.mockReturnValue({ signature: undefined, isLoading: false }) - mockUseTradingApiSwapQuery.mockReturnValue(swapQueryResult) - mockUseTransactionGasFee.mockReturnValue({ error: null, isLoading: false }) - - const { result } = renderHook(() => - useTransactionRequestInfo({ - derivedSwapInfo: mockDerivedSwapInfo, - tokenApprovalInfo: createMockTokenApprovalInfo(), - account: mockAccount, - skip: false, - }), - ) - - expect(result.current.transactionRequest).toMatchObject({ - to: '0xSwap', - chainId: UniverseChainId.Mainnet, - gasLimit: '500000', - maxFeePerGas: '600000', - maxPriorityFeePerGas: '700000', - }) - }) -}) diff --git a/packages/uniswap/src/features/transactions/swap/hooks/useTransactionRequestInfo.ts b/packages/uniswap/src/features/transactions/swap/hooks/useTransactionRequestInfo.ts index 124e4670be7..9990a06cfbf 100644 --- a/packages/uniswap/src/features/transactions/swap/hooks/useTransactionRequestInfo.ts +++ b/packages/uniswap/src/features/transactions/swap/hooks/useTransactionRequestInfo.ts @@ -5,7 +5,6 @@ import { useTradingApiSwapQuery } from 'uniswap/src/data/apiClients/tradingApi/u import { CreateSwapRequest, NullablePermit, - Routing, TransactionFailureReason, } from 'uniswap/src/data/tradingApi/__generated__/index' import { AccountMeta } from 'uniswap/src/features/accounts/types' @@ -19,19 +18,14 @@ import { getBaseTradeAnalyticsPropertiesFromSwapInfo } from 'uniswap/src/feature import { usePermit2SignatureWithData } from 'uniswap/src/features/transactions/swap/hooks/usePermit2Signature' import { useWrapTransactionRequest } from 'uniswap/src/features/transactions/swap/hooks/useWrapTransactionRequest' import { DerivedSwapInfo } from 'uniswap/src/features/transactions/swap/types/derivedSwapInfo' -import { SwapGasFeeEstimation } from 'uniswap/src/features/transactions/swap/types/swapTxAndGasInfo' import { ApprovalAction, TokenApprovalInfo } from 'uniswap/src/features/transactions/swap/types/trade' import { isUniswapX } from 'uniswap/src/features/transactions/swap/utils/routing' -import { - getBridgeQuoteFromResponse, - getClassicQuoteFromResponse, - isClassicQuote, -} from 'uniswap/src/features/transactions/swap/utils/tradingApi' +import { getClassicQuoteFromResponse } from 'uniswap/src/features/transactions/swap/utils/tradingApi' import { GasFeeEstimates } from 'uniswap/src/features/transactions/types/transactionDetails' import { WrapType } from 'uniswap/src/features/transactions/types/wrap' import { isDetoxBuild } from 'utilities/src/environment/constants' import { logger } from 'utilities/src/logger/logger' -import { isInterface, isMobileApp } from 'utilities/src/platform' +import { isMobileApp } from 'utilities/src/platform' import { ONE_SECOND_MS } from 'utilities/src/time/time' export const UNKNOWN_SIM_ERROR = 'Unknown gas simulation error' @@ -43,7 +37,7 @@ export interface TransactionRequestInfo { permitData?: NullablePermit permitDataLoading?: boolean gasFeeResult: GasFeeResult - gasEstimate: SwapGasFeeEstimation + gasEstimates?: GasFeeEstimates swapRequestArgs: CreateSwapRequest | undefined } @@ -65,40 +59,37 @@ export function useTransactionRequestInfo({ const { trade: tradeWithStatus, customDeadline } = derivedSwapInfo const { trade } = tradeWithStatus || { trade: undefined } - const isBridgeTrade = trade?.routing === Routing.BRIDGE const permitData = trade?.quote?.permitData - // checks within functions for type of trade - const swapQuote = getClassicQuoteFromResponse(trade?.quote) ?? getBridgeQuoteFromResponse(trade?.quote) + const swapQuote = getClassicQuoteFromResponse(trade?.quote) // Quote indicates we need to include a signed permit message const requiresPermit2Sig = !!permitData - // On interface, we do not fetch signature until after swap is clicked, as it requires user interaction. - const signatureInfo = usePermit2SignatureWithData({ permitData, skip: skip || isInterface }) + const signatureInfo = usePermit2SignatureWithData({ permitData, skip }) /** - * Simulate transactions to ensure they will not fail on-chain. - * Do not simulate for bridge transactions or txs that need an approval - * as those require Tenderly to simulate and it is not currently integrated into the gas servic + * Simulate transactions to ensure they will not fail on-chain. Do not simulate for txs that need an approval as those require Tenderly to simulate and it is not currently integrated into the gas service */ - const shouldSimulateTxn = isBridgeTrade ? false : tokenApprovalInfo?.action === ApprovalAction.None - const missingSig = requiresPermit2Sig && !signatureInfo.signature + const shouldSimulateTxn = tokenApprovalInfo?.action === ApprovalAction.None // Format request args const swapRequestArgs: CreateSwapRequest | undefined = useMemo(() => { + if (requiresPermit2Sig && !signatureInfo.signature) { + return undefined + } // TODO: MOB(2438) https://linear.app/uniswap/issue/MOB-2438/uniswap-x-clean-old-trading-api-code if (!swapQuote) { return undefined } // We cant get correct calldata from /swap if we dont have a valid slippage tolerance - if (tradeWithStatus.trade?.slippageTolerance === undefined && !isBridgeTrade) { + if (tradeWithStatus.trade?.slippageTolerance === undefined) { return undefined } - // TODO: update this when api does slippage calculation for us + // TODO: remove this when api does slippage calculation for us // https://linear.app/uniswap/issue/MOB-2581/remove-slippage-adjustment-in-swap-request - const quote = { + const quoteWithSlippage = { ...swapQuote, - slippage: tradeWithStatus.trade?.slippageTolerance, + slippage: tradeWithStatus.trade.slippageTolerance, } // if custom deadline is set (in minutes), convert to unix timestamp format from now @@ -106,7 +97,7 @@ export function useTransactionRequestInfo({ const deadline = customDeadline ? Math.floor(Date.now() / 1000) + deadlineSeconds : undefined const swapArgs: CreateSwapRequest = { - quote, + quote: quoteWithSlippage, permitData: permitData ?? undefined, signature: signatureInfo.signature, simulateTransaction: shouldSimulateTxn, @@ -119,13 +110,13 @@ export function useTransactionRequestInfo({ }, [ activeGasStrategy, customDeadline, - isBridgeTrade, permitData, + requiresPermit2Sig, shadowGasStrategies, shouldSimulateTxn, signatureInfo.signature, swapQuote, - tradeWithStatus, + tradeWithStatus.trade?.slippageTolerance, ]) // Wrap transaction request @@ -138,17 +129,12 @@ export function useTransactionRequestInfo({ wrapGasFeeRef.current = currentWrapGasFee } // Wrap gas cost should not change significantly between trades, so we can use the last value if current is unavailable. - const wrapGasFee: GasFeeResult = useMemo( + const wrapGasFee = useMemo( () => ({ ...currentWrapGasFee, value: currentWrapGasFee.value ?? wrapGasFeeRef.current.value }), [currentWrapGasFee], ) - const wrapTxRequestWithGasFee = useMemo( - () => ({ ...wrapTxRequest, ...(wrapGasFee.params ?? {}) }), - [wrapTxRequest, wrapGasFee], - ) - - const skipTransactionRequest = !swapRequestArgs || isWrapApplicable || skip || missingSig + const skipTransactionRequest = !swapRequestArgs || isWrapApplicable || skip const tradingApiSwapRequestMs = useDynamicConfigValue( DynamicConfigs.Swap, @@ -173,8 +159,7 @@ export function useTransactionRequestInfo({ const swapGasFee = swapQuote?.gasFee // This is a case where simulation fails on backend, meaning txn is expected to fail - const simulationError = - isClassicQuote(swapQuote) && swapQuote?.txFailureReasons?.includes(TransactionFailureReason.SIMULATION_ERROR) + const simulationError = swapQuote?.txFailureReasons?.includes(TransactionFailureReason.SIMULATION_ERROR) const gasEstimateError = useMemo( () => (simulationError ? new Error(UNKNOWN_SIM_ERROR) : error), [simulationError, error], @@ -225,27 +210,23 @@ export function useTransactionRequestInfo({ } }, [data?.swap, derivedSwapInfo, formatter, gasEstimateError, swapRequestArgs, trade]) - const gasEstimate: SwapGasFeeEstimation = useMemo(() => { + const gasEstimates = useMemo(() => { const activeGasEstimate = data?.gasEstimates?.find((e) => areEqualGasStrategies(e.strategy, activeGasStrategy)) - const swapGasEstimate: GasFeeEstimates | undefined = activeGasEstimate + return activeGasEstimate ? { activeEstimate: activeGasEstimate, shadowEstimates: data?.gasEstimates?.filter((e) => e !== activeGasEstimate), } : undefined - return { - swapEstimates: swapGasEstimate, - wrapEstimates: wrapGasFee.gasEstimates, - } - }, [data?.gasEstimates, activeGasStrategy, wrapGasFee.gasEstimates]) + }, [data?.gasEstimates, activeGasStrategy]) return { gasFeeResult, - transactionRequest: isWrapApplicable ? wrapTxRequestWithGasFee : data?.swap, + transactionRequest: isWrapApplicable ? wrapTxRequest : data?.swap, permitSignature: signatureInfo.signature, permitDataLoading: signatureInfo.isLoading, permitData, - gasEstimate, + gasEstimates, swapRequestArgs, } } diff --git a/packages/uniswap/src/features/transactions/swap/hooks/useUSDCPrice.ts b/packages/uniswap/src/features/transactions/swap/hooks/useUSDCPrice.ts index a1eaad6e4ee..2ec119f9cc7 100644 --- a/packages/uniswap/src/features/transactions/swap/hooks/useUSDCPrice.ts +++ b/packages/uniswap/src/features/transactions/swap/hooks/useUSDCPrice.ts @@ -63,7 +63,7 @@ export function useUSDCPrice(currency?: Currency): Price | u return useMemo(() => { if (!stablecoin) { - return undefined + return } if (currencyIsStablecoin) { @@ -72,7 +72,7 @@ export function useUSDCPrice(currency?: Currency): Price | u } if (!trade || !isClassic(trade) || !trade.routes?.[0] || !quoteAmount || !currency) { - return undefined + return } const { numerator, denominator } = trade.routes[0].midPrice diff --git a/packages/uniswap/src/features/transactions/swap/hooks/useWrapTransactionRequest.ts b/packages/uniswap/src/features/transactions/swap/hooks/useWrapTransactionRequest.ts index 00078485f3e..ca9ee2dbab1 100644 --- a/packages/uniswap/src/features/transactions/swap/hooks/useWrapTransactionRequest.ts +++ b/packages/uniswap/src/features/transactions/swap/hooks/useWrapTransactionRequest.ts @@ -42,7 +42,7 @@ const getWrapTransactionRequest = async ( currencyAmountIn: Maybe>, ): Promise => { if (!address || !currencyAmountIn || !provider || (wrapType === WrapType.NotApplicable && !isUniswapXWrap)) { - return undefined + return } const wethContract = await getWethContract(chainId, provider) diff --git a/packages/uniswap/src/features/transactions/swap/modals/AcrossRoutingInfo.tsx b/packages/uniswap/src/features/transactions/swap/modals/AcrossRoutingInfo.tsx deleted file mode 100644 index ae394e219ae..00000000000 --- a/packages/uniswap/src/features/transactions/swap/modals/AcrossRoutingInfo.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { useTranslation } from 'react-i18next' -import { Flex, Text, UniversalImage } from 'ui/src' -import { ACROSS_LOGO } from 'ui/src/assets' -import { InfoCircle } from 'ui/src/components/icons/InfoCircle' -import { iconSizes } from 'ui/src/theme' -import { WarningInfo } from 'uniswap/src/components/modals/WarningModal/WarningInfo' -import { WarningSeverity } from 'uniswap/src/components/modals/WarningModal/types' -import { LearnMoreLink } from 'uniswap/src/components/text/LearnMoreLink' -import { uniswapUrls } from 'uniswap/src/constants/urls' -import { ModalName } from 'uniswap/src/features/telemetry/constants' -import { isMobileApp } from 'utilities/src/platform' - -export function AcrossRoutingInfo(): JSX.Element { - const { t } = useTranslation() - - return ( - - - - {t('swap.details.orderRouting')} - - - - - - - Across API - - - - } - infoButton={ - isMobileApp ? ( - - ) : undefined - } - modalProps={{ - caption: t('swap.details.orderRoutingInfo'), - rejectText: t('common.button.close'), - modalName: ModalName.AcrossRoutingInfo, - severity: WarningSeverity.None, - title: t('swap.details.orderRouting'), - icon: ( - - ), - }} - tooltipProps={{ - text: ( - - {t('swap.details.orderRoutingInfo')} - - ), - placement: 'top', - }} - trigger={null} - /> - ) -} diff --git a/packages/uniswap/src/features/transactions/swap/modals/FeeOnTransferWarning.tsx b/packages/uniswap/src/features/transactions/swap/modals/FeeOnTransferWarning.tsx index d8dec731890..c40e991e7e5 100644 --- a/packages/uniswap/src/features/transactions/swap/modals/FeeOnTransferWarning.tsx +++ b/packages/uniswap/src/features/transactions/swap/modals/FeeOnTransferWarning.tsx @@ -26,7 +26,7 @@ export function FeeOnTransferWarning({ children }: PropsWithChildren): JSX.Eleme modalProps={{ backgroundIconColor: colors.DEP_magentaDark.val, caption, - rejectText: t('common.button.close'), + closeText: t('common.button.close'), icon: ( ), - rejectText: t('common.button.close'), + closeText: t('common.button.close'), icon: , modalName: ModalName.NetworkFeeInfo, severity: WarningSeverity.None, diff --git a/packages/uniswap/src/features/transactions/swap/modals/PriceImpactWarning.tsx b/packages/uniswap/src/features/transactions/swap/modals/PriceImpactWarning.tsx index 5d7bc981431..29f28c071b3 100644 --- a/packages/uniswap/src/features/transactions/swap/modals/PriceImpactWarning.tsx +++ b/packages/uniswap/src/features/transactions/swap/modals/PriceImpactWarning.tsx @@ -14,7 +14,7 @@ export function PriceImpactWarning({ children, warning }: PropsWithChildren<{ wa } isOpen={isOpen} modalName={ModalName.SwapWarning} severity={warning.severity} title={warning.title ?? ''} onClose={onClose} - onAcknowledge={onClose} + onConfirm={onClose} /> ) } diff --git a/packages/uniswap/src/features/transactions/swap/modals/UniswapXInfo.tsx b/packages/uniswap/src/features/transactions/swap/modals/UniswapXInfo.tsx index f78242aedfc..e2abd512d6a 100644 --- a/packages/uniswap/src/features/transactions/swap/modals/UniswapXInfo.tsx +++ b/packages/uniswap/src/features/transactions/swap/modals/UniswapXInfo.tsx @@ -31,7 +31,7 @@ export function UniswapXInfo({ modalProps={{ backgroundIconColor: opacify(16, colors.uniswapXPurple), caption: t('uniswapx.description'), - rejectText: t('common.button.close'), + closeText: t('common.button.close'), icon: , modalName: ModalName.UniswapXInfo, severity: WarningSeverity.None, diff --git a/packages/uniswap/src/features/transactions/swap/review/EstimatedTime.tsx b/packages/uniswap/src/features/transactions/swap/review/EstimatedTime.tsx deleted file mode 100644 index 7525d03e82c..00000000000 --- a/packages/uniswap/src/features/transactions/swap/review/EstimatedTime.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { useMemo } from 'react' -import { useTranslation } from 'react-i18next' -import { Flex, Text } from 'ui/src' -import { ONE_MINUTE_MS, ONE_SECOND_MS } from 'utilities/src/time/time' - -interface EstimatedTimeProps { - timeMs?: number - showOnlyIfLong?: boolean -} - -export function EstimatedTime({ timeMs, showOnlyIfLong }: EstimatedTimeProps): JSX.Element | null { - const { t } = useTranslation() - - const estimatedBridgingTime = useMemo(() => { - if (!timeMs) { - return null - } - - const minutes = Math.floor(timeMs / ONE_MINUTE_MS) - const seconds = Math.floor((timeMs % ONE_MINUTE_MS) / ONE_SECOND_MS) - - if (seconds === 0) { - return t('bridging.estimatedTime.minutesOnly', { minutes }) - } else if (minutes === 0) { - return t('bridging.estimatedTime.secondsOnly', { seconds }) - } else { - return t('bridging.estimatedTime.minutesAndSeconds', { - minutes, - seconds, - }) - } - }, [timeMs, t]) - - if (!timeMs || !estimatedBridgingTime || (showOnlyIfLong && timeMs < ONE_MINUTE_MS)) { - return null - } - - return ( - - - {t('swap.bridging.estimatedTime')} - - - {estimatedBridgingTime} - - - ) -} diff --git a/packages/uniswap/src/features/transactions/swap/review/MaxSlippageRow.tsx b/packages/uniswap/src/features/transactions/swap/review/MaxSlippageRow.tsx index 8eda35beeda..fe4ae674b45 100644 --- a/packages/uniswap/src/features/transactions/swap/review/MaxSlippageRow.tsx +++ b/packages/uniswap/src/features/transactions/swap/review/MaxSlippageRow.tsx @@ -1,4 +1,4 @@ -import { TradeType } from '@uniswap/sdk-core' +import { Currency, TradeType } from '@uniswap/sdk-core' import { PropsWithChildren } from 'react' import { useTranslation } from 'react-i18next' import { Flex, Text, TouchableArea, isWeb, useSporeColors } from 'ui/src' @@ -13,7 +13,7 @@ import { CurrencyInfo } from 'uniswap/src/features/dataApi/types' import { useLocalizationContext } from 'uniswap/src/features/language/LocalizationContext' import { ModalName } from 'uniswap/src/features/telemetry/constants' import { DerivedSwapInfo } from 'uniswap/src/features/transactions/swap/types/derivedSwapInfo' -import { BridgeTrade, IndicativeTrade, TradeWithSlippage } from 'uniswap/src/features/transactions/swap/types/trade' +import { IndicativeTrade, Trade } from 'uniswap/src/features/transactions/swap/types/trade' import { slippageToleranceToPercent } from 'uniswap/src/features/transactions/swap/utils/format' import { NumberType } from 'utilities/src/format/types' @@ -39,10 +39,6 @@ export function MaxSlippageRow({ throw new Error('Invalid render of `MaxSlippageInfo` with no `acceptedTrade`') } - if (acceptedTrade instanceof BridgeTrade) { - throw new Error('Invalid render of `MaxSlippageInfo` for bridge trade') - } - // If we don't have a custom slippage tolerance set, we won't have a tolerance to display for an indicative quote, // since only the full quote has a slippage tolerance. In this case, we display a loading state until the full quote is received. const showLoadingState = acceptedTrade.indicative && !acceptedTrade.slippageTolerance @@ -87,7 +83,7 @@ export function MaxSlippageRow({ } type SlippageWarningContentProps = PropsWithChildren<{ - trade: TradeWithSlippage | IndicativeTrade + trade: Trade | IndicativeTrade isCustomSlippage: boolean autoSlippageTolerance?: number }> @@ -186,7 +182,7 @@ export function SlippageWarningContent({ modalProps={{ backgroundIconColor: colors.surface2.get(), captionComponent: captionContent, - rejectText: t('common.button.close'), + closeText: t('common.button.close'), icon: , modalName: ModalName.SlippageInfo, severity: WarningSeverity.None, diff --git a/packages/uniswap/src/features/transactions/swap/review/SwapDetails.tsx b/packages/uniswap/src/features/transactions/swap/review/SwapDetails.tsx index 2bfc8c8f319..7c52d6ba88f 100644 --- a/packages/uniswap/src/features/transactions/swap/review/SwapDetails.tsx +++ b/packages/uniswap/src/features/transactions/swap/review/SwapDetails.tsx @@ -9,13 +9,11 @@ import Trace from 'uniswap/src/features/telemetry/Trace' import { ElementName } from 'uniswap/src/features/telemetry/constants' import { FeeOnTransferFeeGroupProps } from 'uniswap/src/features/transactions/TransactionDetails/FeeOnTransferFee' import { TransactionDetails } from 'uniswap/src/features/transactions/TransactionDetails/TransactionDetails' -import { EstimatedTime } from 'uniswap/src/features/transactions/swap/review/EstimatedTime' import { MaxSlippageRow } from 'uniswap/src/features/transactions/swap/review/MaxSlippageRow' import { SwapRateRatio } from 'uniswap/src/features/transactions/swap/review/SwapRateRatio' import { DerivedSwapInfo } from 'uniswap/src/features/transactions/swap/types/derivedSwapInfo' import { UniswapXGasBreakdown } from 'uniswap/src/features/transactions/swap/types/swapTxAndGasInfo' import { getSwapFeeUsdFromDerivedSwapInfo } from 'uniswap/src/features/transactions/swap/utils/getSwapFeeUsd' -import { isBridge } from 'uniswap/src/features/transactions/swap/utils/routing' import { CurrencyField } from 'uniswap/src/types/currency' import { getFormattedCurrencyAmount, getSymbolDisplayText } from 'uniswap/src/utils/currency' import { NumberType } from 'utilities/src/format/types' @@ -51,8 +49,6 @@ export function SwapDetails({ const formatter = useLocalizationContext() const { convertFiatAmountFormatted, formatPercent } = formatter - const isBridgeTrade = derivedSwapInfo.trade.trade && isBridge(derivedSwapInfo.trade.trade) - const trade = derivedSwapInfo.trade.trade ?? derivedSwapInfo.trade.indicativeTrade const acceptedTrade = acceptedDerivedSwapInfo.trade.trade ?? acceptedDerivedSwapInfo.trade.indicativeTrade @@ -81,7 +77,7 @@ export function SwapDetails({ : undefined const feeOnTransferProps: FeeOnTransferFeeGroupProps | undefined = useMemo(() => { - if (acceptedTrade.indicative || isBridge(acceptedTrade)) { + if (acceptedTrade.indicative) { return undefined } @@ -95,17 +91,13 @@ export function SwapDetails({ tokenSymbol: acceptedTrade.outputAmount.currency.symbol ?? 'Token buy', }, } - }, [acceptedTrade]) - - const estimatedBridgingTime = useMemo(() => { - const tradeQuote = derivedSwapInfo.trade.trade?.quote - - if (!tradeQuote || !isBridge(tradeQuote)) { - return undefined - } - - return tradeQuote.quote.estimatedFillTimeMs - }, [derivedSwapInfo.trade.trade?.quote]) + }, [ + acceptedTrade.inputAmount.currency.symbol, + acceptedTrade.inputTax, + acceptedTrade.outputAmount.currency.symbol, + acceptedTrade.outputTax, + acceptedTrade.indicative, + ]) return ( @@ -141,14 +131,11 @@ export function SwapDetails({ - {isBridgeTrade && } - {!isBridgeTrade && ( - - )} + ) } diff --git a/packages/uniswap/src/features/transactions/swap/review/SwapReviewScreen.tsx b/packages/uniswap/src/features/transactions/swap/review/SwapReviewScreen.tsx index 0ee9df7262c..3d9c9556681 100644 --- a/packages/uniswap/src/features/transactions/swap/review/SwapReviewScreen.tsx +++ b/packages/uniswap/src/features/transactions/swap/review/SwapReviewScreen.tsx @@ -5,7 +5,7 @@ import { Button, Flex, SpinningLoader, Text, isWeb, useHapticFeedback, useIsShor import { BackArrow } from 'ui/src/components/icons/BackArrow' import { AnimatedFlex } from 'ui/src/components/layout/AnimatedFlex' import { iconSizes } from 'ui/src/theme' -import { ProgressIndicator } from 'uniswap/src/components/ConfirmSwapModal/ProgressIndicator' +import ProgressIndicator from 'uniswap/src/components/ConfirmSwapModal/ProgressIndicator' import { WarningModal } from 'uniswap/src/components/modals/WarningModal/WarningModal' import { useAccountMeta } from 'uniswap/src/contexts/UniswapContext' import { AccountType } from 'uniswap/src/features/accounts/types' @@ -29,14 +29,13 @@ import { TransactionAmountsReview } from 'uniswap/src/features/transactions/swap import { SwapCallback } from 'uniswap/src/features/transactions/swap/types/swapCallback' import { isValidSwapTxContext } from 'uniswap/src/features/transactions/swap/types/swapTxAndGasInfo' import { WrapCallback } from 'uniswap/src/features/transactions/swap/types/wrapCallback' -import { TransactionStep } from 'uniswap/src/features/transactions/swap/utils/generateTransactionSteps' +import { TransactionStep, generateSwapSteps } from 'uniswap/src/features/transactions/swap/utils/generateSwapSteps' import { isUniswapX } from 'uniswap/src/features/transactions/swap/utils/routing' import { getActionName, isWrapAction } from 'uniswap/src/features/transactions/swap/utils/wrap' import { WrapType } from 'uniswap/src/features/transactions/types/wrap' import { TestID } from 'uniswap/src/test/fixtures/testIDs' import { CurrencyField } from 'uniswap/src/types/currency' import { createTransactionId } from 'uniswap/src/utils/createTransactionId' -import { isInterface } from 'utilities/src/platform' interface SwapReviewScreenProps { hideContent: boolean @@ -58,9 +57,7 @@ export function SwapReviewScreen(props: SwapReviewScreenProps): JSX.Element | nu const account = useAccountMeta() const { bottomSheetViewStyles, onClose, authTrigger, setScreen } = useTransactionModalContext() - const [steps, setSteps] = useState([]) - const [currentStep, setCurrentStep] = useState<{ step: TransactionStep; accepted: boolean } | undefined>() - const isShowingInterfaceReviewSteps = Boolean(isInterface && currentStep) + const [currentStep, _setCurrentStep] = useState<{ step: TransactionStep; accepted: boolean } | undefined>() const swapTxContext = useSwapTxContext() const { gasFee } = swapTxContext @@ -74,18 +71,8 @@ export function SwapReviewScreen(props: SwapReviewScreenProps): JSX.Element | nu isSubmitting, updateSwapForm, isFiatMode, - resetSwapForm, } = useSwapFormContext() - const onSuccess = useCallback(() => { - // On interface, the swap component stays mounted; after swap we reset the form to avoid showing the previous values. - if (isInterface) { - resetSwapForm() - setScreen(TransactionScreen.Form) - } - onClose() - }, [onClose, resetSwapForm, setScreen]) - const { autoSlippageTolerance, chainId, @@ -100,6 +87,8 @@ export function SwapReviewScreen(props: SwapReviewScreenProps): JSX.Element | nu const isWrap = isWrapAction(wrapType) + const steps = useMemo(() => generateSwapSteps(swapTxContext), [swapTxContext]) + const { blockingWarning, reviewScreenWarning } = useParsedSwapWarnings() const { @@ -122,14 +111,6 @@ export function SwapReviewScreen(props: SwapReviewScreenProps): JSX.Element | nu setScreen(TransactionScreen.Form) }, [ctxExactCurrencyField, focusOnCurrencyField, setScreen, updateSwapForm]) - const onSubmitTransactionFailed = useCallback(() => { - setScreen(TransactionScreen.Review) - - // Create a new txId for the next transaction, as the existing one may be used in state to track the failed submission. - const newTxId = createTransactionId() - updateSwapForm({ isSubmitting: false, txId: newTxId }) - }, [setScreen, updateSwapForm]) - const onWrap = useMemo(() => { const inputCurrencyAmount = currencyAmounts[CurrencyField.INPUT] const txRequest = isUniswapX(swapTxContext) ? undefined : swapTxContext.txRequest @@ -138,28 +119,17 @@ export function SwapReviewScreen(props: SwapReviewScreenProps): JSX.Element | nu } return () => { - wrapCallback({ - account, - inputCurrencyAmount, - onSuccess, - onFailure: onSubmitTransactionFailed, - txRequest, - txId, - wrapType, - gasEstimates: swapTxContext.gasFeeEstimation.wrapEstimates, - }) + wrapCallback({ account, inputCurrencyAmount, onSuccess: onClose, txRequest, txId, wrapType }) } - }, [ - account, - currencyAmounts, - isWrap, - onSuccess, - onSubmitTransactionFailed, - swapTxContext, - txId, - wrapCallback, - wrapType, - ]) + }, [account, currencyAmounts, isWrap, onClose, swapTxContext, txId, wrapCallback, wrapType]) + + const onSubmitTransactionFailed = useCallback(() => { + setScreen(TransactionScreen.Review) + + // Create a new txId for the next transaction, as the existing one may be used in state to track the failed submission. + const newTxId = createTransactionId() + updateSwapForm({ isSubmitting: false, txId: newTxId }) + }, [setScreen, updateSwapForm]) const { onSwap, validSwap } = useMemo(() => { const isValidSwap = isValidSwapTxContext(swapTxContext) @@ -173,12 +143,11 @@ export function SwapReviewScreen(props: SwapReviewScreenProps): JSX.Element | nu currencyInAmountUSD: currencyAmountsUSDValue[CurrencyField.INPUT], currencyOutAmountUSD: currencyAmountsUSDValue[CurrencyField.OUTPUT], isAutoSlippage: !customSlippageTolerance, - onSuccess, + onSubmit: onClose, + steps, onFailure: onSubmitTransactionFailed, txId, isFiatInputMode: isFiatMode, - setCurrentStep, - setSteps, }) }, validSwap: true, @@ -194,7 +163,8 @@ export function SwapReviewScreen(props: SwapReviewScreenProps): JSX.Element | nu currencyAmountsUSDValue, customSlippageTolerance, isFiatMode, - onSuccess, + onClose, + steps, onSubmitTransactionFailed, swapCallback, swapTxContext, @@ -211,7 +181,7 @@ export function SwapReviewScreen(props: SwapReviewScreenProps): JSX.Element | nu isWrap ? onWrap() : onSwap() }, [reviewScreenWarning, showWarningModal, warningAcknowledged, isWrap, onWrap, onSwap]) - const onSwapButtonClick = useCallback(async () => { + const onSubmitTransaction = useCallback(async () => { updateSwapForm({ isSubmitting: true }) await hapticFeedback.success() @@ -291,15 +261,15 @@ export function SwapReviewScreen(props: SwapReviewScreenProps): JSX.Element | nu {reviewScreenWarning?.warning.title && ( )} @@ -312,7 +282,9 @@ export function SwapReviewScreen(props: SwapReviewScreenProps): JSX.Element | nu /> {currentStep ? ( - + acceptedTrade ? ( + + ) : null ) : isWrap ? ( - {!isShowingInterfaceReviewSteps && ( - - - {!isWeb && !showUniswapXSubmittingUI && ( - - diff --git a/packages/wallet/src/components/WalletPreviewCard/WalletPreviewCard.tsx b/packages/wallet/src/components/WalletPreviewCard/WalletPreviewCard.tsx index 51dcf85b24b..56c37dc4689 100644 --- a/packages/wallet/src/components/WalletPreviewCard/WalletPreviewCard.tsx +++ b/packages/wallet/src/components/WalletPreviewCard/WalletPreviewCard.tsx @@ -53,7 +53,7 @@ export default function WalletPreviewCard({ {balanceFormatted} )} - {!hideSelectionCircle && selected && } + {!hideSelectionCircle && selected && } diff --git a/packages/wallet/src/components/WalletPreviewCard/__snapshots__/WalletPreviewCard.test.tsx.snap b/packages/wallet/src/components/WalletPreviewCard/__snapshots__/WalletPreviewCard.test.tsx.snap index 0a08db473f1..cbc3e640b17 100644 --- a/packages/wallet/src/components/WalletPreviewCard/__snapshots__/WalletPreviewCard.test.tsx.snap +++ b/packages/wallet/src/components/WalletPreviewCard/__snapshots__/WalletPreviewCard.test.tsx.snap @@ -205,14 +205,11 @@ exports[`renders wallet preview card 1`] = ` align="xMidYMid" bbHeight={20} bbWidth={20} - fill="none" focusable={false} meetOrSlice={0} minX={0} minY={0} - stroke="currentColor" - strokeLinecap="round" - strokeWidth={6} + strokeWidth={8} style={ [ { @@ -232,37 +229,32 @@ exports[`renders wallet preview card 1`] = ` ] } tintColor="#FC72FF" - vbHeight={48} - vbWidth={48} + vbHeight={16} + vbWidth={16} > - - + + propList={ + [ + "fill", + "fillRule", + ] + } + > + + + diff --git a/packages/wallet/src/components/introCards/useSharedIntroCards.ts b/packages/wallet/src/components/introCards/useSharedIntroCards.ts deleted file mode 100644 index 50d7c74054c..00000000000 --- a/packages/wallet/src/components/introCards/useSharedIntroCards.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { useMemo } from 'react' -import { useTranslation } from 'react-i18next' -import { useSelector } from 'react-redux' -import { Person } from 'ui/src/components/icons' -import { AccountType } from 'uniswap/src/features/accounts/types' -import { FeatureFlags } from 'uniswap/src/features/gating/flags' -import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' -import { OnboardingCardLoggingName } from 'uniswap/src/features/telemetry/types' -import { CardType } from 'wallet/src/components/introCards/IntroCard' -import { IntroCardWrapper } from 'wallet/src/components/introCards/IntroCardStack' -import { selectHasSkippedUnitagPrompt } from 'wallet/src/features/behaviorHistory/selectors' -import { UNITAG_SUFFIX_NO_LEADING_DOT } from 'wallet/src/features/unitags/constants' -import { useCanActiveAddressClaimUnitag } from 'wallet/src/features/unitags/hooks' -import { useUnitagClaimHandler } from 'wallet/src/features/unitags/useUnitagClaimHandler' -import { useActiveAccountWithThrow } from 'wallet/src/features/wallet/hooks' - -export type IntroCardWithLogging = IntroCardWrapper & { - loggingName: OnboardingCardLoggingName -} - -type useSharedIntroCardsProps = { - navigateToUnitagClaim: () => void - navigateToUnitagIntro: () => void -} - -export function useSharedIntroCards({ - navigateToUnitagClaim, - navigateToUnitagIntro, -}: useSharedIntroCardsProps): IntroCardWithLogging[] { - const { t } = useTranslation() - const activeAccount = useActiveAccountWithThrow() - const claimUnitagEnabled = useFeatureFlag(FeatureFlags.ExtensionClaimUnitag) - - const hasSkippedUnitagPrompt = useSelector(selectHasSkippedUnitagPrompt) - const { canClaimUnitag } = useCanActiveAddressClaimUnitag() - const { handleClaim: handleUnitagClaim, handleDismiss: handleUnitagDismiss } = useUnitagClaimHandler({ - analyticsEntryPoint: 'home', - navigateToClaim: navigateToUnitagClaim, - navigateToIntro: navigateToUnitagIntro, - }) - - const shouldPromptUnitag = - activeAccount.type === AccountType.SignerMnemonic && !hasSkippedUnitagPrompt && canClaimUnitag - - return useMemo(() => { - const output: IntroCardWithLogging[] = [] - - if (shouldPromptUnitag && claimUnitagEnabled) { - output.push({ - loggingName: OnboardingCardLoggingName.ClaimUnitag, - Icon: Person, - title: t('onboarding.home.intro.unitag.title', { - unitagDomain: UNITAG_SUFFIX_NO_LEADING_DOT, - }), - description: t('onboarding.home.intro.unitag.description'), - cardType: CardType.Dismissible, - onPress: () => handleUnitagClaim(), - onClose: () => handleUnitagDismiss(), - }) - } - - return output - }, [claimUnitagEnabled, shouldPromptUnitag, handleUnitagClaim, handleUnitagDismiss, t]) -} diff --git a/packages/wallet/src/components/modals/InfoLinkModal.tsx b/packages/wallet/src/components/modals/InfoLinkModal.tsx index 447e0cd5257..6bf93f92d54 100644 --- a/packages/wallet/src/components/modals/InfoLinkModal.tsx +++ b/packages/wallet/src/components/modals/InfoLinkModal.tsx @@ -86,9 +86,6 @@ export function InfoLinkModal({ backgroundColor="transparent" borderRadius="$rounded12" color="$neutral2" - hoverStyle={{ - backgroundColor: 'transparent', - }} px="$spacing40" theme="secondary" onPress={openUniswapURL} diff --git a/packages/wallet/src/components/nfts/NFTHiddenRow.tsx b/packages/wallet/src/components/nfts/NFTHiddenRow.tsx index f9fc5068604..b6fc2fee137 100644 --- a/packages/wallet/src/components/nfts/NFTHiddenRow.tsx +++ b/packages/wallet/src/components/nfts/NFTHiddenRow.tsx @@ -14,14 +14,8 @@ export function HiddenNftsRow({ const { t } = useTranslation() return ( - - + + diff --git a/packages/wallet/src/components/nfts/ShowNFTModal.tsx b/packages/wallet/src/components/nfts/ShowNFTModal.tsx index 04d91b4301b..c35bf170ae5 100644 --- a/packages/wallet/src/components/nfts/ShowNFTModal.tsx +++ b/packages/wallet/src/components/nfts/ShowNFTModal.tsx @@ -28,7 +28,7 @@ export function ShowNFTModal(): JSX.Element { return ( <> - + diff --git a/packages/wallet/src/components/text/RelativeChange.test.tsx b/packages/wallet/src/components/text/RelativeChange.test.tsx index 28541bd44dd..3f7f1477022 100644 --- a/packages/wallet/src/components/text/RelativeChange.test.tsx +++ b/packages/wallet/src/components/text/RelativeChange.test.tsx @@ -1,6 +1,7 @@ import renderer from 'react-test-renderer' import { FiatCurrencyInfo } from 'uniswap/src/features/fiatOnRamp/types' import { Locale } from 'uniswap/src/features/language/constants' +import { mockLocalizationContext } from 'uniswap/src/test/mocks' import { TamaguiProvider } from 'wallet/src/providers/tamagui-provider' // Needs to be imported after the mock localization context @@ -31,6 +32,8 @@ jest.mock('uniswap/src/features/fiatCurrency/hooks', () => { } }) +jest.mock('uniswap/src/features/language/LocalizationContext', () => mockLocalizationContext) + it('renders a relative change', () => { const tree = renderer.create( diff --git a/packages/wallet/src/contexts/WalletNavigationContext.tsx b/packages/wallet/src/contexts/WalletNavigationContext.tsx index 10f68accb84..58e43300fc1 100644 --- a/packages/wallet/src/contexts/WalletNavigationContext.tsx +++ b/packages/wallet/src/contexts/WalletNavigationContext.tsx @@ -1,11 +1,11 @@ import { createContext, ReactNode, useContext } from 'react' import { FiatOnRampCurrency } from 'uniswap/src/features/fiatOnRamp/types' -import { getSwapPrefilledState } from 'uniswap/src/features/transactions/swap/hooks/useSwapPrefilledState' import { TransactionState } from 'uniswap/src/features/transactions/types/transactionState' import { WalletChainId } from 'uniswap/src/types/chains' import { CurrencyField } from 'uniswap/src/types/currency' import { NFTItem } from 'wallet/src/features/nfts/types' import { getSendPrefilledState } from 'wallet/src/features/transactions/send/getSendPrefilledState' +import { getSwapPrefilledState } from 'wallet/src/features/transactions/swap/hooks/useSwapPrefilledState' type NavigateToTransactionFlowTransactionState = { initialState: TransactionState diff --git a/packages/wallet/src/features/activity/hooks.ts b/packages/wallet/src/features/activity/hooks.ts index 28de10f7218..6b2f1069299 100644 --- a/packages/wallet/src/features/activity/hooks.ts +++ b/packages/wallet/src/features/activity/hooks.ts @@ -62,7 +62,7 @@ export function useFormattedTransactionDataForFeed( const transactions = useMemo(() => { if (!data) { - return undefined + return } return parseDataResponseToFeedTransactionDetails(data, hideSpamTokens) @@ -90,7 +90,7 @@ export function useFormattedTransactionDataForFeed( } if (!hasTransactions) { - return undefined + return } return [ @@ -169,7 +169,7 @@ export function useFormattedTransactionDataForActivity( const formattedTransactions = useMemo(() => { if (!data) { - return undefined + return } return parseDataResponseToTransactionDetails(data, hideSpamTokens, nftVisibility, tokenVisibilityOverrides) @@ -199,7 +199,7 @@ export function useFormattedTransactionDataForActivity( } if (!hasTransactions) { - return undefined + return } return [ diff --git a/packages/wallet/src/features/auth/saga.ts b/packages/wallet/src/features/auth/saga.ts index 312fb4e3b7b..6d6eccea411 100644 --- a/packages/wallet/src/features/auth/saga.ts +++ b/packages/wallet/src/features/auth/saga.ts @@ -14,8 +14,6 @@ function* auth(params: UnlockParams | LockParams) { } else if (params.type === AuthActionType.Lock) { return yield* call(lock) } - - return undefined } function* unlock({ password }: UnlockParams) { diff --git a/packages/wallet/src/features/behaviorHistory/slice.ts b/packages/wallet/src/features/behaviorHistory/slice.ts index d49f309ac7f..75ea2cda288 100644 --- a/packages/wallet/src/features/behaviorHistory/slice.ts +++ b/packages/wallet/src/features/behaviorHistory/slice.ts @@ -12,7 +12,6 @@ export interface BehaviorHistoryState { hasUsedExplore: boolean backupReminderLastSeenTs?: number hasViewedOffRampTooltip: boolean - hasDismissedBridgingWarning?: boolean } export const initialBehaviorHistoryState: BehaviorHistoryState = { @@ -23,7 +22,6 @@ export const initialBehaviorHistoryState: BehaviorHistoryState = { hasUsedExplore: false, backupReminderLastSeenTs: undefined, hasViewedOffRampTooltip: false, - hasDismissedBridgingWarning: false, } const slice = createSlice({ @@ -51,9 +49,6 @@ const slice = createSlice({ setHasViewedOffRampTooltip: (state, action: PayloadAction) => { state.hasViewedOffRampTooltip = action.payload }, - setHasDismissedBridgingWarning: (state, action: PayloadAction) => { - state.hasDismissedBridgingWarning = action.payload - }, // Should only be used for testing resetBehaviorHistory: (state, _action: PayloadAction) => { @@ -75,7 +70,6 @@ export const { setHasUsedExplore, setBackupReminderLastSeenTs, setHasViewedOffRampTooltip, - setHasDismissedBridgingWarning, resetBehaviorHistory, } = slice.actions diff --git a/packages/wallet/src/features/gas/adjustGasFee.ts b/packages/wallet/src/features/gas/adjustGasFee.ts index ff98d870d0a..0731aedea81 100644 --- a/packages/wallet/src/features/gas/adjustGasFee.ts +++ b/packages/wallet/src/features/gas/adjustGasFee.ts @@ -1,5 +1,5 @@ import { BigNumber, BigNumberish, providers } from 'ethers' -import { FeeType } from 'uniswap/src/data/tradingApi/types' +import { FeeType } from 'uniswap/src/data/tradingApi/__generated__' import { GasFeeResult } from 'uniswap/src/features/gas/types' import { BigNumberMax } from 'wallet/src/utils/number' diff --git a/packages/wallet/src/features/gas/hooks.ts b/packages/wallet/src/features/gas/hooks.ts index e0c08f77d08..c7e741d9801 100644 --- a/packages/wallet/src/features/gas/hooks.ts +++ b/packages/wallet/src/features/gas/hooks.ts @@ -1,7 +1,7 @@ import { BigNumber, providers } from 'ethers' import { useCallback, useMemo } from 'react' import { TRANSACTION_CANCELLATION_GAS_FACTOR } from 'uniswap/src/constants/transactions' -import { FeeType } from 'uniswap/src/data/tradingApi/types' +import { FeeType } from 'uniswap/src/data/tradingApi/__generated__' import { useTransactionGasFee } from 'uniswap/src/features/gas/hooks' import { isUniswapX } from 'uniswap/src/features/transactions/swap/utils/routing' import { TransactionDetails } from 'uniswap/src/features/transactions/types/transactionDetails' @@ -38,13 +38,13 @@ export function useCancelationGasFeeInfo(transaction: TransactionDetails): Cance return useMemo(() => { if (isUniswapXTx) { if (!uniswapXCancelRequest.data || !uniswapXGasFee.value) { - return undefined + return } return { cancelRequest: uniswapXCancelRequest.data, cancelationGasFee: uniswapXGasFee.value } } if (!baseTxGasFee.params) { - return undefined + return } let adjustedFeeDetails: FeeDetails | undefined @@ -59,7 +59,7 @@ export function useCancelationGasFeeInfo(transaction: TransactionDetails): Cance tags: { file: 'features/gas/hooks.ts', function: 'getAdjustedGasFeeDetails' }, extra: { request: transaction.options.request, currentGasFeeParams: baseTxGasFee.params }, }) - return undefined + return } const cancelRequest = { diff --git a/packages/wallet/src/features/images/ElementAfterText.tsx b/packages/wallet/src/features/images/ElementAfterText.tsx deleted file mode 100644 index afcedbdc9e2..00000000000 --- a/packages/wallet/src/features/images/ElementAfterText.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import type { FlexProps, TextProps } from 'ui/src' -import { Flex, Text, isWeb } from 'ui/src' -import { usePostTextElementPositionProps } from 'wallet/src/utils/layout' - -type ElementAfterTextProps = { - image?: JSX.Element - caption: string - wrapperProps?: FlexProps - textProps?: TextProps -} - -const DEFAULT_TEXT_PROPS: TextProps = { - color: '$neutral1', - variant: 'body2', -} - -export function ElementAfterText({ image, caption, wrapperProps, textProps }: ElementAfterTextProps): JSX.Element { - const { postTextElementPositionProps, onTextLayout } = usePostTextElementPositionProps() - - if (isWeb) { - return ( - - - {caption} - {image} - - - ) - } else { - return ( - - - {caption} - - {image} - - ) - } -} diff --git a/packages/wallet/src/features/images/RemoteSvg.tsx b/packages/wallet/src/features/images/RemoteSvg.tsx index 5dfd0ae60eb..3c3bd8eb6b9 100644 --- a/packages/wallet/src/features/images/RemoteSvg.tsx +++ b/packages/wallet/src/features/images/RemoteSvg.tsx @@ -26,7 +26,7 @@ export const RemoteSvg = ({ }: Props): JSX.Element | null => { const fetchSvg = useCallback(async () => { if (!imageHttpUrl) { - return undefined + return } try { const res = await fetch(imageHttpUrl) @@ -38,7 +38,6 @@ export const RemoteSvg = ({ tags: { file: 'RemoteSvg', function: 'fetchSvg' }, extra: { imageHttpUrl }, }) - return undefined } }, [imageHttpUrl]) diff --git a/packages/wallet/src/features/nfts/utils.ts b/packages/wallet/src/features/nfts/utils.ts index 24fed51b3ad..04c7910b74f 100644 --- a/packages/wallet/src/features/nfts/utils.ts +++ b/packages/wallet/src/features/nfts/utils.ts @@ -5,7 +5,7 @@ import { NFTItem } from 'wallet/src/features/nfts/types' export function formatNftItems(data: NftsTabQuery | undefined): NFTItem[] | undefined { const items = data?.nftBalances?.edges?.flatMap((item) => item.node) if (!items) { - return undefined + return } const nfts = items diff --git a/packages/wallet/src/features/notifications/components/NotificationToast.tsx b/packages/wallet/src/features/notifications/components/NotificationToast.tsx index 49e34d67387..4211486d67a 100644 --- a/packages/wallet/src/features/notifications/components/NotificationToast.tsx +++ b/packages/wallet/src/features/notifications/components/NotificationToast.tsx @@ -11,9 +11,9 @@ import { AnimatedFlex } from 'ui/src/components/layout/AnimatedFlex' import { borderRadii, spacing } from 'ui/src/theme' import { TestID } from 'uniswap/src/test/fixtures/testIDs' import { useTimeout } from 'utilities/src/time/timing' -import { ElementAfterText } from 'wallet/src/features/images/ElementAfterText' import { selectActiveAccountNotifications } from 'wallet/src/features/notifications/selectors' import { popNotification, setNotificationViewed } from 'wallet/src/features/notifications/slice' +import { usePostTextElementPositionProps } from 'wallet/src/utils/layout' const NOTIFICATION_HEIGHT = 64 @@ -205,6 +205,7 @@ function NotificationContent({ onPress, onPressIn, }: NotificationContentProps): JSX.Element { + const { postTextElementPositionProps, onTextLayout } = usePostTextElementPositionProps() return ( {icon} - + + + {title} + + {postCaptionElement} + + {subtitle && ( + + {subtitle} + + )} - {subtitle && ( - - {subtitle} - - )} {actionButton && ( diff --git a/packages/wallet/src/features/notifications/components/SwapPendingNotification.tsx b/packages/wallet/src/features/notifications/components/SwapPendingNotification.tsx index 29144832548..a3e835404fe 100644 --- a/packages/wallet/src/features/notifications/components/SwapPendingNotification.tsx +++ b/packages/wallet/src/features/notifications/components/SwapPendingNotification.tsx @@ -25,7 +25,6 @@ export function SwapPendingNotification({ notification }: { notification: SwapPe ) } -// eslint-disable-next-line consistent-return function getNotificationText(wrapType: WrapType, t: TFunction): string { switch (wrapType) { case WrapType.NotApplicable: diff --git a/packages/wallet/src/features/notifications/selectors.ts b/packages/wallet/src/features/notifications/selectors.ts index a03c6c911e2..491fb7fc28f 100644 --- a/packages/wallet/src/features/notifications/selectors.ts +++ b/packages/wallet/src/features/notifications/selectors.ts @@ -10,7 +10,7 @@ export const selectActiveAccountNotifications = createSelector( selectActiveAccountAddress, (notificationQueue, address) => { if (!address) { - return undefined + return } // If a notification doesn't have an address param assume it belongs to the active account return notificationQueue.filter((notif) => !notif.address || notif.address === address) diff --git a/packages/wallet/src/features/notifications/utils.test.ts b/packages/wallet/src/features/notifications/utils.test.ts index 16b71fce1d2..fb564b52ef6 100644 --- a/packages/wallet/src/features/notifications/utils.test.ts +++ b/packages/wallet/src/features/notifications/utils.test.ts @@ -1,17 +1,14 @@ import { TradeType } from '@uniswap/sdk-core' import { DAI, USDC } from 'uniswap/src/constants/tokens' -import { Locale } from 'uniswap/src/features/language/constants' import { TransactionStatus } from 'uniswap/src/features/transactions/types/transactionDetails' import { mockLocalizedFormatter } from 'uniswap/src/test/mocks' import { formSwapNotificationTitle } from 'wallet/src/features/notifications/utils' -const mockFormatter = mockLocalizedFormatter(Locale.EnglishUnitedStates) - describe(formSwapNotificationTitle, () => { it('formats successful local swap title', () => { expect( formSwapNotificationTitle( - mockFormatter, + mockLocalizedFormatter, TransactionStatus.Success, DAI, USDC, @@ -27,7 +24,7 @@ describe(formSwapNotificationTitle, () => { it('formats successful remote swap title', () => { expect( formSwapNotificationTitle( - mockFormatter, + mockLocalizedFormatter, TransactionStatus.Success, DAI, USDC, @@ -42,7 +39,7 @@ describe(formSwapNotificationTitle, () => { it('formats canceled swap title', () => { expect( formSwapNotificationTitle( - mockFormatter, + mockLocalizedFormatter, TransactionStatus.Canceled, DAI, USDC, @@ -58,7 +55,7 @@ describe(formSwapNotificationTitle, () => { it('formats failed swap title', () => { expect( formSwapNotificationTitle( - mockFormatter, + mockLocalizedFormatter, TransactionStatus.Failed, DAI, USDC, diff --git a/packages/wallet/src/features/notifications/utils.ts b/packages/wallet/src/features/notifications/utils.ts index 98cdd4ec63a..5921beb3799 100644 --- a/packages/wallet/src/features/notifications/utils.ts +++ b/packages/wallet/src/features/notifications/utils.ts @@ -11,7 +11,6 @@ import { getCurrencyDisplayText, getFormattedCurrencyAmount, getSymbolDisplayTex import { currencyIdToAddress } from 'uniswap/src/utils/currencyId' import { WalletConnectNotification } from 'wallet/src/features/notifications/types' -// eslint-disable-next-line consistent-return export const formWCNotificationTitle = (appNotification: WalletConnectNotification): string => { const { event, dappName, chainId } = appNotification diff --git a/packages/wallet/src/features/portfolio/AnimatedNumber.tsx b/packages/wallet/src/features/portfolio/AnimatedNumber.tsx index 68c1f276682..3f7b07a37ed 100644 --- a/packages/wallet/src/features/portfolio/AnimatedNumber.tsx +++ b/packages/wallet/src/features/portfolio/AnimatedNumber.tsx @@ -101,7 +101,7 @@ const RollNumber = ({ key={idx} allowFontScaling={false} fontFamily="$heading" - style={[AnimatedFontStyles.fontStyle, { height: DIGIT_HEIGHT, color: nextColor ?? currentColor }]} + style={[AnimatedFontStyles.fontStyle, { height: DIGIT_HEIGHT, color: currentColor }]} > {char} diff --git a/packages/wallet/src/features/portfolio/HiddenTokensRow.tsx b/packages/wallet/src/features/portfolio/HiddenTokensRow.tsx index 958ee23cd30..97805e93282 100644 --- a/packages/wallet/src/features/portfolio/HiddenTokensRow.tsx +++ b/packages/wallet/src/features/portfolio/HiddenTokensRow.tsx @@ -1,9 +1,10 @@ import { useTranslation } from 'react-i18next' import { Flex, ImpactFeedbackStyle, Separator, Text, TouchableArea } from 'ui/src' import { AnglesDownUp, SortVertical } from 'ui/src/components/icons' -import { isMobileApp } from 'utilities/src/platform' +import { TestID } from 'uniswap/src/test/fixtures/testIDs' export function HiddenTokensRow({ + padded = false, numHidden, isExpanded, onPress, @@ -20,29 +21,30 @@ export function HiddenTokensRow({ hapticFeedback activeOpacity={1} hapticStyle={ImpactFeedbackStyle.Light} - mx={isMobileApp && '$spacing16'} + mx="$spacing12" onPress={onPress} > - - - - - - + + + {/* just used for opacity styling, the parent TouchableArea handles event */} + + + {t('hidden.tokens.info.text.button', { numHidden })} - - - {isExpanded ? ( - - ) : ( - - )} - + {isExpanded ? ( + + ) : ( + + )} - - - + + ) diff --git a/packages/wallet/src/features/portfolio/PortfolioBalance.tsx b/packages/wallet/src/features/portfolio/PortfolioBalance.tsx index 8233bca2c08..2656248b964 100644 --- a/packages/wallet/src/features/portfolio/PortfolioBalance.tsx +++ b/packages/wallet/src/features/portfolio/PortfolioBalance.tsx @@ -6,8 +6,6 @@ import { FiatCurrency } from 'uniswap/src/features/fiatCurrency/constants' import { useAppFiatCurrency, useAppFiatCurrencyInfo } from 'uniswap/src/features/fiatCurrency/hooks' import { useLocalizationContext } from 'uniswap/src/features/language/LocalizationContext' import { NumberType } from 'utilities/src/format/types' -import { isWeb } from 'utilities/src/platform' -import { ONE_SECOND_MS } from 'utilities/src/time/time' import { RelativeChange } from 'wallet/src/components/text/RelativeChange' import { isWarmLoadingStatus } from 'wallet/src/data/utils' import AnimatedNumber from 'wallet/src/features/portfolio/AnimatedNumber' @@ -16,10 +14,6 @@ interface PortfolioBalanceProps { owner: Address } -// This ensures the color changes quicker after animating on web platforms. This could be -// safe for mobile to be the same but was kept the same as this animation is fragile -const BALANCE_CHANGE_INDICATION_DURATION = isWeb ? ONE_SECOND_MS / 2 : ONE_SECOND_MS * 2 - export const PortfolioBalance = memo(function _PortfolioBalance({ owner }: PortfolioBalanceProps): JSX.Element { const { data, loading, networkStatus } = usePortfolioTotalValue({ address: owner, @@ -47,7 +41,7 @@ export const PortfolioBalance = memo(function _PortfolioBalance({ owner }: Portf } else if (isSwapTransactionInfo(typeInfo)) { return - } else if (isBridgeTransactionInfo(typeInfo)) { - return null // TODO: Update when bridge logo is added } else if (isWCConfirmTransactionInfo(typeInfo)) { return } else if (isWrapTransactionInfo(typeInfo)) { diff --git a/packages/wallet/src/features/transactions/SummaryCards/DetailsModal/TransactionDetailsModal.tsx b/packages/wallet/src/features/transactions/SummaryCards/DetailsModal/TransactionDetailsModal.tsx index fe152cc31aa..d95eafc9e1f 100644 --- a/packages/wallet/src/features/transactions/SummaryCards/DetailsModal/TransactionDetailsModal.tsx +++ b/packages/wallet/src/features/transactions/SummaryCards/DetailsModal/TransactionDetailsModal.tsx @@ -2,7 +2,7 @@ import dayjs from 'dayjs' import { useState } from 'react' import { useTranslation } from 'react-i18next' import { Button, ContextMenu, Flex, Separator, Text, TouchableArea, isWeb } from 'ui/src' -import { AnglesDownUp, Ellipsis, SortVertical, UniswapX } from 'ui/src/components/icons' +import { AnglesDownUp, SortVertical, TripleDots, UniswapX } from 'ui/src/components/icons' import { Modal } from 'uniswap/src/components/modals/Modal' import { Routing } from 'uniswap/src/data/tradingApi/__generated__/index' import { AssetType } from 'uniswap/src/entities/assets' @@ -80,12 +80,12 @@ export function TransactionDetailsHeader({ {isWeb ? ( - + ) : ( - + )} diff --git a/packages/wallet/src/features/transactions/SummaryCards/DetailsModal/__snapshots__/SwapTransactionDetails.test.tsx.snap b/packages/wallet/src/features/transactions/SummaryCards/DetailsModal/__snapshots__/SwapTransactionDetails.test.tsx.snap index 24757ec94a3..c0e2db1cefa 100644 --- a/packages/wallet/src/features/transactions/SummaryCards/DetailsModal/__snapshots__/SwapTransactionDetails.test.tsx.snap +++ b/packages/wallet/src/features/transactions/SummaryCards/DetailsModal/__snapshots__/SwapTransactionDetails.test.tsx.snap @@ -98,7 +98,7 @@ exports[`SwapTransactionDetails Component renders SwapTransactionDetails without "borderWidth": 0, }, { - "color": "#BFBFBF", + "color": "#CECECE", "height": 20, "transform": [ { @@ -114,7 +114,7 @@ exports[`SwapTransactionDetails Component renders SwapTransactionDetails without }, ] } - tintColor="#BFBFBF" + tintColor="#CECECE" vbHeight={24} vbWidth={24} > diff --git a/packages/wallet/src/features/transactions/SummaryCards/DetailsModal/__snapshots__/TransactionDetailsModal.test.tsx.snap b/packages/wallet/src/features/transactions/SummaryCards/DetailsModal/__snapshots__/TransactionDetailsModal.test.tsx.snap index 89471cb2b37..677cb4fa07c 100644 --- a/packages/wallet/src/features/transactions/SummaryCards/DetailsModal/__snapshots__/TransactionDetailsModal.test.tsx.snap +++ b/packages/wallet/src/features/transactions/SummaryCards/DetailsModal/__snapshots__/TransactionDetailsModal.test.tsx.snap @@ -271,11 +271,12 @@ exports[`TransactionDetails Components renders TransactionDetailsHeader without align="xMidYMid" bbHeight={20} bbWidth={20} - fill="none" + fill="currentColor" focusable={false} meetOrSlice={0} minX={0} minY={0} + stroke="currentColor" strokeWidth={8} style={ [ @@ -300,17 +301,27 @@ exports[`TransactionDetails Components renders TransactionDetailsHeader without vbWidth={18} > @@ -826,7 +837,7 @@ exports[`TransactionDetails Components renders TransactionDetailsInfoRows withou "borderWidth": 0, }, { - "color": "#BFBFBF", + "color": "#CECECE", "height": 16, "width": 16, }, @@ -837,7 +848,7 @@ exports[`TransactionDetails Components renders TransactionDetailsInfoRows withou }, ] } - tintColor="#BFBFBF" + tintColor="#CECECE" vbHeight={16} vbWidth={16} > diff --git a/packages/wallet/src/features/transactions/SummaryCards/DetailsModal/types.ts b/packages/wallet/src/features/transactions/SummaryCards/DetailsModal/types.ts index 97dc0e73873..9b7bbcad45f 100644 --- a/packages/wallet/src/features/transactions/SummaryCards/DetailsModal/types.ts +++ b/packages/wallet/src/features/transactions/SummaryCards/DetailsModal/types.ts @@ -1,5 +1,4 @@ import { - BridgeTransactionInfo, ConfirmedSwapTransactionInfo, ExactInputSwapTransactionInfo, ExactOutputSwapTransactionInfo, @@ -67,10 +66,6 @@ export function isSwapTransactionInfo(typeInfo: TransactionTypeInfo): typeInfo i return typeInfo.type === TransactionType.Swap } -export function isBridgeTransactionInfo(typeInfo: TransactionTypeInfo): typeInfo is BridgeTransactionInfo { - return typeInfo.type === TransactionType.Bridge -} - export function isWCConfirmTransactionInfo(typeInfo: TransactionTypeInfo): typeInfo is WCConfirmInfo { return typeInfo.type === TransactionType.WCConfirm } diff --git a/packages/wallet/src/features/transactions/SummaryCards/SummaryItems/TransactionSummaryLayout.tsx b/packages/wallet/src/features/transactions/SummaryCards/SummaryItems/TransactionSummaryLayout.tsx index 2afcda78fa2..513eb1b496e 100644 --- a/packages/wallet/src/features/transactions/SummaryCards/SummaryItems/TransactionSummaryLayout.tsx +++ b/packages/wallet/src/features/transactions/SummaryCards/SummaryItems/TransactionSummaryLayout.tsx @@ -9,7 +9,6 @@ import { FeatureFlags } from 'uniswap/src/features/gating/flags' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' import { TransactionStatus } from 'uniswap/src/features/transactions/types/transactionDetails' import { DisplayNameText } from 'wallet/src/components/accounts/DisplayNameText' -import { ElementAfterText } from 'wallet/src/features/images/ElementAfterText' import { TransactionDetailsModal } from 'wallet/src/features/transactions/SummaryCards/DetailsModal/TransactionDetailsModal' import { useTransactionActions } from 'wallet/src/features/transactions/SummaryCards/DetailsModal/useTransactionActions' import { TransactionSummaryTitle } from 'wallet/src/features/transactions/SummaryCards/SummaryItems/TransactionSummaryTitle' @@ -22,6 +21,7 @@ import { } from 'wallet/src/features/transactions/SummaryCards/utils' import { useIsQueuedTransaction } from 'wallet/src/features/transactions/hooks' import { useActiveAccountWithThrow, useDisplayName } from 'wallet/src/features/wallet/hooks' +import { usePostTextElementPositionProps } from 'wallet/src/utils/layout' import { openTransactionLink } from 'wallet/src/utils/linking' const LOADING_SPINNER_SIZE = 20 @@ -74,6 +74,8 @@ function TransactionSummaryLayout({ } } + const { postTextElementPositionProps, onTextLayout } = usePostTextElementPositionProps() + const formattedAddedTime = useFormattedTime(transaction.addedTime) const statusIconFill = colors.surface1.get() @@ -136,14 +138,12 @@ function TransactionSummaryLayout({ {!inProgress && rightBlock} - + + + {caption} + + {postCaptionElement} + {status === TransactionStatus.Failed && onRetry && ( diff --git a/packages/wallet/src/features/transactions/SummaryCards/utils.ts b/packages/wallet/src/features/transactions/SummaryCards/utils.ts index 3dab9574bc4..51849869350 100644 --- a/packages/wallet/src/features/transactions/SummaryCards/utils.ts +++ b/packages/wallet/src/features/transactions/SummaryCards/utils.ts @@ -76,7 +76,6 @@ export function generateActivityItemRenderer( case TransactionType.Send: SummaryItem = SendSummaryItem break - case TransactionType.Bridge: // TODO: Add bridge summary item in next PR case TransactionType.Swap: SummaryItem = SwapSummaryItem break diff --git a/packages/wallet/src/features/transactions/TransactionHistoryUpdater.tsx b/packages/wallet/src/features/transactions/TransactionHistoryUpdater.tsx index cdb85ff2484..8f36b1244e1 100644 --- a/packages/wallet/src/features/transactions/TransactionHistoryUpdater.tsx +++ b/packages/wallet/src/features/transactions/TransactionHistoryUpdater.tsx @@ -214,12 +214,12 @@ export function getReceiveNotificationFromData( hideSpamTokens = false, ): ReceiveCurrencyTxNotification | ReceiveNFTNotification | undefined { if (!data || !lastTxNotificationUpdateTimestamp) { - return undefined + return } const parsedTxHistory = parseDataResponseToTransactionDetails(data, hideSpamTokens) if (!parsedTxHistory) { - return undefined + return } const latestReceivedTx = parsedTxHistory @@ -232,9 +232,13 @@ export function getReceiveNotificationFromData( tx.status === TransactionStatus.Success, ) + if (!latestReceivedTx) { + return + } + // Suppress notification if rules apply - if (!latestReceivedTx || shouldSuppressNotification(latestReceivedTx)) { - return undefined + if (shouldSuppressNotification(latestReceivedTx)) { + return } return buildReceiveNotification(latestReceivedTx, address) diff --git a/packages/wallet/src/features/transactions/cancelTransactionSaga.ts b/packages/wallet/src/features/transactions/cancelTransactionSaga.ts index 679a06ab783..568be67b278 100644 --- a/packages/wallet/src/features/transactions/cancelTransactionSaga.ts +++ b/packages/wallet/src/features/transactions/cancelTransactionSaga.ts @@ -4,7 +4,7 @@ import { Contract, providers } from 'ethers' import { call, select } from 'typed-redux-saga' import PERMIT2_ABI from 'uniswap/src/abis/permit2.json' import { Permit2 } from 'uniswap/src/abis/types' -import { isBridge, isClassic, isUniswapX } from 'uniswap/src/features/transactions/swap/utils/routing' +import { isClassic } from 'uniswap/src/features/transactions/swap/utils/routing' import { TransactionDetails, UniswapXOrderDetails } from 'uniswap/src/features/transactions/types/transactionDetails' import { getValidAddress } from 'uniswap/src/utils/addresses' import { logger } from 'utilities/src/logger/logger' @@ -21,9 +21,9 @@ export function* attemptCancelTransaction( transaction: TransactionDetails, cancelRequest: providers.TransactionRequest, ) { - if (isClassic(transaction) || isBridge(transaction)) { + if (isClassic(transaction)) { yield* call(attemptReplaceTransaction, transaction, cancelRequest, true) - } else if (isUniswapX(transaction)) { + } else { yield* call(cancelOrder, transaction, cancelRequest) } } @@ -41,7 +41,7 @@ export async function getCancelOrderTxRequest( } else { const { encodedOrder } = (await getOrders([orderHash])).orders[0] ?? {} if (!encodedOrder) { - return undefined + return } const nonce = CosignedV2DutchOrder.parse(encodedOrder, chainId).info.nonce diff --git a/packages/wallet/src/features/transactions/getAmountsFromTrade.ts b/packages/wallet/src/features/transactions/getAmountsFromTrade.ts index 5ac744bbb31..b0f7382d7fc 100644 --- a/packages/wallet/src/features/transactions/getAmountsFromTrade.ts +++ b/packages/wallet/src/features/transactions/getAmountsFromTrade.ts @@ -1,21 +1,15 @@ import { TradeType } from '@uniswap/sdk-core' import { - BridgeTransactionInfo, ConfirmedSwapTransactionInfo, ExactInputSwapTransactionInfo, ExactOutputSwapTransactionInfo, - isBridgeTypeInfo, isConfirmedSwapTypeInfo, } from 'uniswap/src/features/transactions/types/transactionDetails' export function getAmountsFromTrade( - typeInfo: - | ExactInputSwapTransactionInfo - | ExactOutputSwapTransactionInfo - | ConfirmedSwapTransactionInfo - | BridgeTransactionInfo, + typeInfo: ExactInputSwapTransactionInfo | ExactOutputSwapTransactionInfo | ConfirmedSwapTransactionInfo, ): { inputCurrencyAmountRaw: string; outputCurrencyAmountRaw: string } { - if (isConfirmedSwapTypeInfo(typeInfo) || isBridgeTypeInfo(typeInfo)) { + if (isConfirmedSwapTypeInfo(typeInfo)) { const { inputCurrencyAmountRaw, outputCurrencyAmountRaw } = typeInfo return { inputCurrencyAmountRaw, outputCurrencyAmountRaw } } diff --git a/packages/wallet/src/features/transactions/history/conversion/extractFiatOnRampTransactionDetails.ts b/packages/wallet/src/features/transactions/history/conversion/extractFiatOnRampTransactionDetails.ts index 41bfd8c3479..4b8c1a6ba59 100644 --- a/packages/wallet/src/features/transactions/history/conversion/extractFiatOnRampTransactionDetails.ts +++ b/packages/wallet/src/features/transactions/history/conversion/extractFiatOnRampTransactionDetails.ts @@ -96,7 +96,7 @@ export function extractFiatOnRampTransactionDetails( function: 'extractFiatOnRampTransactionDetails', }, }) - return undefined + return } } diff --git a/packages/wallet/src/features/transactions/history/conversion/extractUniswapXOrderDetails.ts b/packages/wallet/src/features/transactions/history/conversion/extractUniswapXOrderDetails.ts index a6c336be458..6f19b2e1abe 100644 --- a/packages/wallet/src/features/transactions/history/conversion/extractUniswapXOrderDetails.ts +++ b/packages/wallet/src/features/transactions/history/conversion/extractUniswapXOrderDetails.ts @@ -24,7 +24,6 @@ export function extractUniswapXOrderDetails(transaction: TransactionListQueryRes } const typeInfo = parseUniswapXOrderTransaction(transaction) - // TODO: does not support parsing priority orders yet since priority orders are not supported in the trading API const routing = transaction.details.swapOrderType === SwapOrderType.Limit ? Routing.DUTCH_LIMIT : Routing.DUTCH_V2 // TODO (MOB-3609): Parse and show pending limit orders in Activity feed @@ -45,7 +44,6 @@ export function extractUniswapXOrderDetails(transaction: TransactionListQueryRes } } -// eslint-disable-next-line consistent-return function remoteOrderStatusToLocalTxStatus(orderStatus: SwapOrderStatus): TransactionStatus { switch (orderStatus) { case SwapOrderStatus.Open: diff --git a/packages/wallet/src/features/transactions/history/conversion/parseTradeTransaction.ts b/packages/wallet/src/features/transactions/history/conversion/parseTradeTransaction.ts index 9af9db0f6ee..f0ff2dd909a 100644 --- a/packages/wallet/src/features/transactions/history/conversion/parseTradeTransaction.ts +++ b/packages/wallet/src/features/transactions/history/conversion/parseTradeTransaction.ts @@ -41,7 +41,7 @@ export default function parseTradeTransaction( const chainId = fromGraphQLChain(transaction.chain) if (!chainId) { - return undefined + return } const txAssetChanges = @@ -83,14 +83,14 @@ export default function parseTradeTransaction( // Invalid input/output info if (!sent || !received) { - return undefined + return } const onlyERC20Tokens = sent.__typename === 'TokenTransfer' && received.__typename === 'TokenTransfer' const containsNFT = sent.__typename === 'NftTransfer' || received.__typename === 'NftTransfer' if (!(onlyERC20Tokens || containsNFT)) { - return undefined + return } // Token swap @@ -152,7 +152,7 @@ export default function parseTradeTransaction( } if (!inputCurrencyId || !outputCurrencyId) { - return undefined + return } return { @@ -222,6 +222,4 @@ export default function parseTradeTransaction( transactedUSDValue, } } - - return undefined } diff --git a/packages/wallet/src/features/transactions/history/utils.ts b/packages/wallet/src/features/transactions/history/utils.ts index 155ac2966c6..d139ea5c033 100644 --- a/packages/wallet/src/features/transactions/history/utils.ts +++ b/packages/wallet/src/features/transactions/history/utils.ts @@ -282,11 +282,8 @@ function extractCurrencyIdFromTx(transaction: TransactionDetails | null): Curren // We only care about output currency because that's the net new asset return transaction.typeInfo.outputCurrencyId } - - return undefined } -// eslint-disable-next-line consistent-return export function remoteTxStatusToLocalTxStatus( type: RemoteTransactionType, status: RemoteTransactionStatus, diff --git a/packages/wallet/src/features/transactions/hooks.ts b/packages/wallet/src/features/transactions/hooks.ts index e6ed9253a0a..eaa4926bc91 100644 --- a/packages/wallet/src/features/transactions/hooks.ts +++ b/packages/wallet/src/features/transactions/hooks.ts @@ -34,7 +34,7 @@ export function usePendingTransactions( const transactions = useSelectAddressTransactions(address) return useMemo(() => { if (!transactions) { - return undefined + return } return transactions.filter( (tx: { status: TransactionStatus; typeInfo: { type: TransactionType } }) => @@ -69,7 +69,7 @@ export function useErroredQueuedOrders(address: Address | null): ErroredQueuedOr const transactions = useSelectAddressTransactions(address) return useMemo(() => { if (!transactions) { - return undefined + return } const erroredQueuedOrders: ErroredQueuedOrder[] = [] for (const tx of transactions) { @@ -86,7 +86,7 @@ export function useSortedPendingTransactions(address: Address | null): Transacti const transactions = usePendingTransactions(address) return useMemo(() => { if (!transactions) { - return undefined + return } return transactions.sort((a: TransactionDetails, b: TransactionDetails) => a.addedTime - b.addedTime) }, [transactions]) @@ -109,14 +109,10 @@ export function useCreateSwapFormState( const transaction = useSelectTransaction(address, chainId, txId) const inputCurrencyId = - transaction?.typeInfo.type === TransactionType.Swap || transaction?.typeInfo.type === TransactionType.Bridge - ? transaction.typeInfo.inputCurrencyId - : undefined + transaction?.typeInfo.type === TransactionType.Swap ? transaction.typeInfo.inputCurrencyId : undefined const outputCurrencyId = - transaction?.typeInfo.type === TransactionType.Swap || transaction?.typeInfo.type === TransactionType.Bridge - ? transaction.typeInfo.outputCurrencyId - : undefined + transaction?.typeInfo.type === TransactionType.Swap ? transaction.typeInfo.outputCurrencyId : undefined const inputCurrencyInfo = useCurrencyInfo(inputCurrencyId) const outputCurrencyInfo = useCurrencyInfo(outputCurrencyId) @@ -196,7 +192,6 @@ export function useMergeLocalAndRemoteTransactions( const orderHash = ensureLeading0x(tx.orderHash.toLowerCase()) return orderHashToTxHashMap.get(orderHash) ?? orderHash } - return undefined } const hashes = new Set() @@ -297,7 +292,7 @@ function useLowestPendingNonce(): BigNumberish | undefined { return useMemo(() => { let min: BigNumberish | undefined if (!pending) { - return undefined + return } pending.map((txn: TransactionDetails) => { if (isClassic(txn)) { diff --git a/packages/wallet/src/features/transactions/hooks/useAllTransactionsBetweenAddresses.ts b/packages/wallet/src/features/transactions/hooks/useAllTransactionsBetweenAddresses.ts index fa9dba5aab9..b8275a0c1f2 100644 --- a/packages/wallet/src/features/transactions/hooks/useAllTransactionsBetweenAddresses.ts +++ b/packages/wallet/src/features/transactions/hooks/useAllTransactionsBetweenAddresses.ts @@ -14,7 +14,7 @@ export function useAllTransactionsBetweenAddresses( const txnsToSearch = useSelectAddressTransactions(sender) return useMemo(() => { if (!sender || !recipient || !txnsToSearch) { - return undefined + return } return txnsToSearch.filter( (tx: TransactionDetails) => tx.typeInfo.type === TransactionType.Send && tx.typeInfo.recipient === recipient, diff --git a/packages/wallet/src/features/transactions/replaceTransactionSaga.ts b/packages/wallet/src/features/transactions/replaceTransactionSaga.ts index 1ea7bada9c2..1e99ec3e1b8 100644 --- a/packages/wallet/src/features/transactions/replaceTransactionSaga.ts +++ b/packages/wallet/src/features/transactions/replaceTransactionSaga.ts @@ -2,7 +2,6 @@ import { BigNumber, providers } from 'ethers' import { call, put, select } from 'typed-redux-saga' import { addTransaction, deleteTransaction } from 'uniswap/src/features/transactions/slice' import { - BridgeTransactionDetails, ClassicTransactionDetails, TransactionDetails, TransactionStatus, @@ -19,7 +18,7 @@ import { getProvider, getSignerManager } from 'wallet/src/features/wallet/contex import { selectAccounts } from 'wallet/src/features/wallet/selectors' export function* attemptReplaceTransaction( - transaction: ClassicTransactionDetails | BridgeTransactionDetails, + transaction: ClassicTransactionDetails, newTxRequest: providers.TransactionRequest, isCancellation = false, ) { diff --git a/packages/wallet/src/features/transactions/send/SendReviewDetails.tsx b/packages/wallet/src/features/transactions/send/SendReviewDetails.tsx index cafda2c9dc5..d61a12d80d6 100644 --- a/packages/wallet/src/features/transactions/send/SendReviewDetails.tsx +++ b/packages/wallet/src/features/transactions/send/SendReviewDetails.tsx @@ -23,7 +23,6 @@ import { useTransactionModalContext, } from 'uniswap/src/features/transactions/TransactionModal/TransactionModalContext' import { useUSDCValue } from 'uniswap/src/features/transactions/swap/hooks/useUSDCPrice' -import { WalletChainId } from 'uniswap/src/types/chains' import { CurrencyField } from 'uniswap/src/types/currency' import { currencyAddress } from 'uniswap/src/utils/currencyId' import { NumberType } from 'utilities/src/format/types' @@ -91,7 +90,7 @@ export function SendReviewDetails({ const transferERC20Callback = useSendERC20Callback( txId, - chainId as WalletChainId, + chainId, recipient, currencyInInfo ? currencyAddress(currencyInInfo.currency) : undefined, currencyAmounts[CurrencyField.INPUT]?.quotient.toString(), @@ -103,7 +102,7 @@ export function SendReviewDetails({ const transferNFTCallback = useSendNFTCallback( txId, - chainId as WalletChainId, + chainId, recipient, nftIn?.nftContract?.address, nftIn?.tokenId, @@ -186,17 +185,17 @@ export function SendReviewDetails({ {transferWarning?.title && ( )} @@ -272,7 +271,7 @@ export function SendReviewDetails({ /> } - chainId={chainId as WalletChainId} + chainId={chainId} gasFee={gasFee} showWarning={Boolean(transferWarning)} warning={transferWarning} diff --git a/packages/wallet/src/features/transactions/send/hooks/useSendTransactionRequest.ts b/packages/wallet/src/features/transactions/send/hooks/useSendTransactionRequest.ts index 4bd0ff961a0..499dcb4c310 100644 --- a/packages/wallet/src/features/transactions/send/hooks/useSendTransactionRequest.ts +++ b/packages/wallet/src/features/transactions/send/hooks/useSendTransactionRequest.ts @@ -7,7 +7,7 @@ import { Erc1155, Erc20, Erc721 } from 'uniswap/src/abis/types' import { AssetType } from 'uniswap/src/entities/assets' import { toSupportedChainId } from 'uniswap/src/features/chains/utils' import { DerivedSendInfo } from 'uniswap/src/features/transactions/send/types' -import { UniverseChainId, WalletChainId } from 'uniswap/src/types/chains' +import { UniverseChainId } from 'uniswap/src/types/chains' import { CurrencyField } from 'uniswap/src/types/currency' import { currencyAddress, isNativeCurrencyAddress } from 'uniswap/src/utils/currencyId' import { useAsyncData } from 'utilities/src/react/hooks' @@ -25,7 +25,7 @@ export function useSendTransactionRequest(derivedSendInfo: DerivedSendInfo): pro const transactionFetcher = useCallback(() => { if (!provider) { - return undefined + return } return getSendTransaction(provider, contractManager, account, derivedSendInfo) @@ -34,7 +34,6 @@ export function useSendTransactionRequest(derivedSendInfo: DerivedSendInfo): pro return useAsyncData(transactionFetcher).data } -// eslint-disable-next-line consistent-return async function getSendTransaction( provider: providers.Provider, contractManager: ContractManager, @@ -43,7 +42,7 @@ async function getSendTransaction( ): Promise { const params = getSendParams(account, derivedSendInfo) if (!params) { - return undefined + return } const { type, tokenAddress, chainId } = params @@ -59,7 +58,6 @@ async function getSendTransaction( } } -// eslint-disable-next-line consistent-return function getSendParams(account: Account, derivedSendInfo: DerivedSendInfo): SendTokenParams | undefined { const { currencyAmounts, currencyTypes, chainId, recipient, currencyInInfo, nftIn } = derivedSendInfo const tokenAddress = currencyInInfo ? currencyAddress(currencyInInfo.currency) : nftIn?.nftContract?.address @@ -67,19 +65,19 @@ function getSendParams(account: Account, derivedSendInfo: DerivedSendInfo): Send const assetType = currencyTypes[CurrencyField.INPUT] if (!chainId || !tokenAddress || !recipient || !assetType) { - return undefined + return } switch (assetType) { case AssetType.ERC1155: case AssetType.ERC721: { if (!nftIn) { - return undefined + return } return { account, - chainId: chainId as WalletChainId, + chainId, toAddress: recipient, tokenAddress, type: assetType, @@ -89,12 +87,12 @@ function getSendParams(account: Account, derivedSendInfo: DerivedSendInfo): Send case AssetType.Currency: { if (!currencyInInfo || amount === undefined) { - return undefined + return } return { account, - chainId: chainId as WalletChainId, + chainId, toAddress: recipient, tokenAddress, type: AssetType.Currency, diff --git a/packages/wallet/src/features/transactions/send/hooks/useSendWarnings.ts b/packages/wallet/src/features/transactions/send/hooks/useSendWarnings.ts index 6b0ceb9860d..e1131041423 100644 --- a/packages/wallet/src/features/transactions/send/hooks/useSendWarnings.ts +++ b/packages/wallet/src/features/transactions/send/hooks/useSendWarnings.ts @@ -25,7 +25,7 @@ export function getSendWarnings(t: TFunction, derivedSendInfo: DerivedSendInfo, const isMissingRequiredParams = checkIsMissingRequiredParams( currencyInInfo, nftIn, - chainId as WalletChainId, + chainId, recipient, !!currencyAmountIn, !!currencyBalanceIn, diff --git a/packages/wallet/src/features/transactions/sendTransactionSaga.test.ts b/packages/wallet/src/features/transactions/sendTransactionSaga.test.ts index effffeeb073..0bca10f78f4 100644 --- a/packages/wallet/src/features/transactions/sendTransactionSaga.test.ts +++ b/packages/wallet/src/features/transactions/sendTransactionSaga.test.ts @@ -106,7 +106,6 @@ describe(sendTransaction, () => { maxPriorityFeePerGas: undefined, maxFeePerGas: undefined, }, - timeoutTimestampMs: undefined, }, }), ) diff --git a/packages/wallet/src/features/transactions/sendTransactionSaga.ts b/packages/wallet/src/features/transactions/sendTransactionSaga.ts index ea082a206c6..8a7254d4664 100644 --- a/packages/wallet/src/features/transactions/sendTransactionSaga.ts +++ b/packages/wallet/src/features/transactions/sendTransactionSaga.ts @@ -7,7 +7,6 @@ import { FeatureFlags, getFeatureFlagName } from 'uniswap/src/features/gating/fl import { Statsig } from 'uniswap/src/features/gating/sdk/statsig' import { WalletEventName } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' -import { UniverseEventProperties } from 'uniswap/src/features/telemetry/types' import { makeSelectAddressTransactions } from 'uniswap/src/features/transactions/selectors' import { transactionActions } from 'uniswap/src/features/transactions/slice' import { getBaseTradeAnalyticsProperties } from 'uniswap/src/features/transactions/swap/analytics' @@ -19,26 +18,16 @@ import { TransactionStatus, TransactionType, TransactionTypeInfo, - isBridgeTypeInfo, } from 'uniswap/src/features/transactions/types/transactionDetails' import { UniverseChainId, WalletChainId } from 'uniswap/src/types/chains' import { createTransactionId } from 'uniswap/src/utils/createTransactionId' import { logger } from 'utilities/src/logger/logger' -import { ONE_MINUTE_MS } from 'utilities/src/time/time' import { isPrivateRpcSupportedOnChain } from 'wallet/src/features/providers/utils' import { getSerializableTransactionRequest } from 'wallet/src/features/transactions/utils' import { getPrivateProvider, getProvider, getSignerManager } from 'wallet/src/features/wallet/context' import { SignerManager } from 'wallet/src/features/wallet/signing/SignerManager' import { hexlifyTransaction } from 'wallet/src/utils/transaction' -// This timeout is used to trigger a log event if the transaction is pending for too long -const getTransactionTimeoutMs = (chainId: WalletChainId) => { - if (chainId === UniverseChainId.Mainnet) { - return 10 * ONE_MINUTE_MS - } - return ONE_MINUTE_MS -} - export interface SendTransactionParams { // internal id used for tracking transactions before they're submitted // this is optional as an override in txDetail.id calculation @@ -123,10 +112,9 @@ function* addTransaction( ) { const id = txId ?? createTransactionId() const request = getSerializableTransactionRequest(populatedRequest, chainId) - const timeoutTimestampMs = typeInfo.gasEstimates ? Date.now() + getTransactionTimeoutMs(chainId) : undefined const transaction: TransactionDetails = { - routing: isBridgeTypeInfo(typeInfo) ? Routing.BRIDGE : Routing.CLASSIC, + routing: Routing.CLASSIC, id, chainId, hash, @@ -137,12 +125,11 @@ function* addTransaction( options: { ...options, request, - timeoutTimestampMs, }, transactionOriginType, } - if (transaction.typeInfo.type === TransactionType.Swap || transaction.typeInfo.type === TransactionType.Bridge) { + if (transaction.typeInfo.type === TransactionType.Swap) { if (!analytics) { // Don't expect swaps from WC or Dapps to always provide analytics object if (transactionOriginType === TransactionOriginType.Internal) { @@ -152,12 +139,11 @@ function* addTransaction( }) } } else { - const event: UniverseEventProperties[WalletEventName.SwapSubmitted] = { - routing: transaction.routing === Routing.BRIDGE ? 'BRIDGE' : 'CLASSIC', + yield* call(sendAnalyticsEvent, WalletEventName.SwapSubmitted, { + routing: transaction.routing, transaction_hash: hash, ...analytics, - } - yield* call(sendAnalyticsEvent, WalletEventName.SwapSubmitted, event) + }) } } yield* put(transactionActions.addTransaction(transaction)) diff --git a/packages/wallet/src/features/transactions/swap/BridgingModal.tsx b/packages/wallet/src/features/transactions/swap/BridgingModal.tsx deleted file mode 100644 index dbbd66d5ad1..00000000000 --- a/packages/wallet/src/features/transactions/swap/BridgingModal.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { useCallback, useState } from 'react' -import { useTranslation } from 'react-i18next' -import { useDispatch } from 'react-redux' -import { Checkbox, Flex, Text, TouchableArea } from 'ui/src' -import { Shuffle } from 'ui/src/components/icons' -import { iconSizes } from 'ui/src/theme' -import { NetworkLogo } from 'uniswap/src/components/CurrencyLogo/NetworkLogo' -import { WarningModal } from 'uniswap/src/components/modals/WarningModal/WarningModal' -import { WarningSeverity } from 'uniswap/src/components/modals/WarningModal/types' -import { UNIVERSE_CHAIN_INFO } from 'uniswap/src/constants/chains' -import { ModalName } from 'uniswap/src/features/telemetry/constants' -import { UniverseChainId } from 'uniswap/src/types/chains' -import { setHasDismissedBridgingWarning } from 'wallet/src/features/behaviorHistory/slice' - -export function BridgingModal({ - isOpen, - onContinue, - onClose, - fromNetwork, - toNetwork, -}: { - isOpen: boolean - onClose: () => void - onContinue: () => void - fromNetwork: UniverseChainId - toNetwork: UniverseChainId -}): JSX.Element { - const { t } = useTranslation() - const dispatch = useDispatch() - - const [doNotShowAgainPressed, setDoNotShowAgainPressed] = useState(false) - const onPressDoNotShowAgain = useCallback(() => { - const toggled = !doNotShowAgainPressed - dispatch(setHasDismissedBridgingWarning(toggled)) - setDoNotShowAgainPressed(toggled) - }, [doNotShowAgainPressed, dispatch]) - - const icon = ( - - - - - - ) - - return ( - - - - - - {t('common.dontShowAgain')} - - - - - ) -} diff --git a/packages/wallet/src/features/transactions/swap/createSwapFormFromTxDetails.ts b/packages/wallet/src/features/transactions/swap/createSwapFormFromTxDetails.ts index ca2d46cc604..811d2c1bc28 100644 --- a/packages/wallet/src/features/transactions/swap/createSwapFormFromTxDetails.ts +++ b/packages/wallet/src/features/transactions/swap/createSwapFormFromTxDetails.ts @@ -1,11 +1,7 @@ import { Currency, TradeType } from '@uniswap/sdk-core' import { AssetType, CurrencyAsset } from 'uniswap/src/entities/assets' import { ValueType, getCurrencyAmount } from 'uniswap/src/features/tokens/getCurrencyAmount' -import { - TransactionDetails, - TransactionType, - isBridgeTypeInfo, -} from 'uniswap/src/features/transactions/types/transactionDetails' +import { TransactionDetails, TransactionType } from 'uniswap/src/features/transactions/types/transactionDetails' import { TransactionState } from 'uniswap/src/features/transactions/types/transactionState' import { CurrencyField } from 'uniswap/src/types/currency' import { currencyAddress, currencyIdToAddress } from 'uniswap/src/utils/currencyId' @@ -35,9 +31,8 @@ export function createSwapFormFromTxDetails({ try { const { typeInfo } = transactionDetails - const isBridging = isBridgeTypeInfo(typeInfo) - if (typeInfo.type !== TransactionType.Swap && !isBridging) { + if (typeInfo.type !== TransactionType.Swap) { throw new Error(`Tx hash ${txHash} does not correspond to a swap tx. It is of type ${typeInfo.type}`) } @@ -57,11 +52,8 @@ export function createSwapFormFromTxDetails({ type: AssetType.Currency, } - const exactCurrencyField = isBridging - ? CurrencyField.INPUT - : typeInfo.tradeType === TradeType.EXACT_OUTPUT - ? CurrencyField.OUTPUT - : CurrencyField.INPUT + const exactCurrencyField = + typeInfo.tradeType === TradeType.EXACT_OUTPUT ? CurrencyField.OUTPUT : CurrencyField.INPUT const { value, currency } = exactCurrencyField === CurrencyField.INPUT @@ -82,7 +74,6 @@ export function createSwapFormFromTxDetails({ logger.error(error, { tags: { file: 'createSwapFormFromTxDetails', function: 'createSwapFormFromTxDetails' }, }) - return undefined } } @@ -143,6 +134,5 @@ export function createWrapFormFromTxDetails({ logger.error(error, { tags: { file: 'createSwapFormFromTxDetails', function: 'createWrapFormFromTxDetails' }, }) - return undefined } } diff --git a/packages/wallet/src/features/transactions/swap/hooks/useMostRecentSwapTx.ts b/packages/wallet/src/features/transactions/swap/hooks/useMostRecentSwapTx.ts index 413db93a332..94e7f156993 100644 --- a/packages/wallet/src/features/transactions/swap/hooks/useMostRecentSwapTx.ts +++ b/packages/wallet/src/features/transactions/swap/hooks/useMostRecentSwapTx.ts @@ -6,10 +6,9 @@ import { flattenObjectOfObjects } from 'utilities/src/primitives/objects' export function useMostRecentSwapTx(address: Address): TransactionDetails | undefined { const transactions = useSelector(selectTransactions) const addressTransactions = transactions[address] - if (!addressTransactions) { - return undefined + if (addressTransactions) { + return flattenObjectOfObjects(addressTransactions) + .filter((tx) => tx.typeInfo.type === TransactionType.Swap) + .sort((a, b) => b.addedTime - a.addedTime)[0] } - return flattenObjectOfObjects(addressTransactions) - .filter((tx) => tx.typeInfo.type === TransactionType.Swap) - .sort((a, b) => b.addedTime - a.addedTime)[0] } diff --git a/packages/wallet/src/features/transactions/swap/hooks/useSwapCallback.ts b/packages/wallet/src/features/transactions/swap/hooks/useSwapCallback.ts index 64cfbed7953..9a12242a47c 100644 --- a/packages/wallet/src/features/transactions/swap/hooks/useSwapCallback.ts +++ b/packages/wallet/src/features/transactions/swap/hooks/useSwapCallback.ts @@ -1,7 +1,6 @@ import { SwapEventName } from '@uniswap/analytics-events' import { useCallback } from 'react' import { useDispatch, useSelector } from 'react-redux' -import { Routing } from 'uniswap/src/data/tradingApi/__generated__' import { useLocalizationContext } from 'uniswap/src/features/language/LocalizationContext' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { selectSwapStartTimestamp } from 'uniswap/src/features/timing/selectors' @@ -25,8 +24,9 @@ export function useSwapCallback(): SwapCallback { account, swapTxContext, txId, - onSuccess, + onSubmit, onFailure, + steps, currencyInAmountUSD, currencyOutAmountUSD, isAutoSlippage, @@ -34,13 +34,8 @@ export function useSwapCallback(): SwapCallback { } = args const { trade, gasFee } = swapTxContext - // unsigned (missing permit signature) swaps are only supported on interface; this is an unreachable state and the following check is included for type safety. - if (swapTxContext.routing === Routing.CLASSIC && swapTxContext.unsigned) { - throw new Error('Swaps with async signatures are not implemented for wallet') - } - const analytics = getBaseTradeAnalyticsProperties({ formatter, trade, currencyInAmountUSD, currencyOutAmountUSD }) - appDispatch(swapActions.trigger({ swapTxContext, txId, account, analytics, onSuccess, onFailure })) + appDispatch(swapActions.trigger({ swapTxContext, txId, account, analytics, steps, onSubmit, onFailure })) const blockNumber = getClassicQuoteFromResponse(trade?.quote)?.blockNumber?.toString() diff --git a/packages/uniswap/src/features/transactions/swap/hooks/useSwapPrefilledState.ts b/packages/wallet/src/features/transactions/swap/hooks/useSwapPrefilledState.ts similarity index 98% rename from packages/uniswap/src/features/transactions/swap/hooks/useSwapPrefilledState.ts rename to packages/wallet/src/features/transactions/swap/hooks/useSwapPrefilledState.ts index b90cbd3368d..6680444bf87 100644 --- a/packages/uniswap/src/features/transactions/swap/hooks/useSwapPrefilledState.ts +++ b/packages/wallet/src/features/transactions/swap/hooks/useSwapPrefilledState.ts @@ -16,7 +16,6 @@ export function useSwapPrefilledState(initialState: TransactionState | undefined exactAmountFiat: initialState.exactAmountFiat, exactAmountToken: initialState.exactAmountToken, exactCurrencyField: initialState.exactCurrencyField, - filteredChainIds: {}, focusOnCurrencyField: getFocusOnCurrencyFieldFromInitialState(initialState), input: initialState.input ?? undefined, output: initialState.output ?? undefined, diff --git a/packages/wallet/src/features/transactions/swap/modals/QueuedOrderModal.tsx b/packages/wallet/src/features/transactions/swap/modals/QueuedOrderModal.tsx index 2d95247e1d4..660a92ceb51 100644 --- a/packages/wallet/src/features/transactions/swap/modals/QueuedOrderModal.tsx +++ b/packages/wallet/src/features/transactions/swap/modals/QueuedOrderModal.tsx @@ -142,7 +142,7 @@ function useTransactionState(transaction: TransactionDetails | undefined): Trans return useMemo(() => { if (!isSwap || !inputCurrency || !outputCurrency) { - return undefined + return } const input: TradeableAsset = { diff --git a/packages/wallet/src/features/transactions/swap/modals/SwapProtectionModal.tsx b/packages/wallet/src/features/transactions/swap/modals/SwapProtectionModal.tsx index 0d5775a9107..a7db1c078bb 100644 --- a/packages/wallet/src/features/transactions/swap/modals/SwapProtectionModal.tsx +++ b/packages/wallet/src/features/transactions/swap/modals/SwapProtectionModal.tsx @@ -14,7 +14,7 @@ export function SwapProtectionInfoModal({ isOpen, onClose }: { isOpen: boolean; } isOpen={isOpen} modalName={ModalName.SwapProtection} diff --git a/packages/wallet/src/features/transactions/swap/submitOrderSaga.test.ts b/packages/wallet/src/features/transactions/swap/submitOrderSaga.test.ts index b685bb51c9a..64ff4d20785 100644 --- a/packages/wallet/src/features/transactions/swap/submitOrderSaga.test.ts +++ b/packages/wallet/src/features/transactions/swap/submitOrderSaga.test.ts @@ -2,11 +2,10 @@ import { Protocol } from '@uniswap/router-sdk' import { TradeType } from '@uniswap/sdk-core' import { testSaga } from 'redux-saga-test-plan' import { submitOrder } from 'uniswap/src/data/apiClients/tradingApi/TradingApiClient' -import { DutchOrderInfo, DutchQuoteV2, OrderRequest, Routing } from 'uniswap/src/data/tradingApi/__generated__/index' +import { OrderRequest, Routing } from 'uniswap/src/data/tradingApi/__generated__/index' import { WalletEventName } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { NativeCurrency } from 'uniswap/src/features/tokens/NativeCurrency' -import { signTypedData } from 'uniswap/src/features/transactions/signing' import { addTransaction, finalizeTransaction, updateTransaction } from 'uniswap/src/features/transactions/slice' import { QueuedOrderStatus, @@ -16,7 +15,6 @@ import { UniswapXOrderDetails, } from 'uniswap/src/features/transactions/types/transactionDetails' import { WrapType } from 'uniswap/src/features/transactions/types/wrap' -import { mockPermit } from 'uniswap/src/test/fixtures/permit' import { UniverseChainId } from 'uniswap/src/types/chains' import { currencyId } from 'uniswap/src/utils/currencyId' import { pushNotification } from 'wallet/src/features/notifications/slice' @@ -26,15 +24,8 @@ import { SubmitUniswapXOrderParams, submitUniswapXOrder, } from 'wallet/src/features/transactions/swap/submitOrderSaga' -import { getSignerManager } from 'wallet/src/features/wallet/context' import { signerMnemonicAccount } from 'wallet/src/test/fixtures' -const mockSignature = '0xMockSignature' -const mockSigner = {} -const mockSignerManager = { - getSignerForAccount: jest.fn(), -} - const baseSubmitOrderParams = { chainId: UniverseChainId.Mainnet, account: signerMnemonicAccount(), @@ -52,19 +43,14 @@ const baseSubmitOrderParams = { transactionOriginType: TransactionOriginType.Internal, }, txId: '1', - onSuccess: jest.fn(), + orderParams: { quote: { orderId: '0xMockOrderHash' } } as unknown as OrderRequest, + onSubmit: jest.fn(), onFailure: jest.fn(), - quote: { - orderId: '0xMockOrderHash', - encodedOrder: '0xMockEncodedOrder', - orderInfo: {} as DutchOrderInfo, - } as unknown as DutchQuoteV2, - permit: mockPermit, } satisfies SubmitUniswapXOrderParams const baseExpectedInitialOrderDetails: UniswapXOrderDetails = { routing: Routing.DUTCH_V2, - orderHash: '0xMockOrderHash', + orderHash: baseSubmitOrderParams.orderParams.quote.orderId, id: baseSubmitOrderParams.txId, chainId: baseSubmitOrderParams.chainId, typeInfo: baseSubmitOrderParams.typeInfo, @@ -75,12 +61,6 @@ const baseExpectedInitialOrderDetails: UniswapXOrderDetails = { transactionOriginType: TransactionOriginType.Internal, } -const expectedOrderRequest: OrderRequest = { - signature: mockSignature, - quote: baseSubmitOrderParams.quote, - routing: Routing.DUTCH_V2, -} - describe(submitUniswapXOrder, () => { beforeEach(() => { let mockTimestamp = 1 @@ -100,13 +80,7 @@ describe(submitUniswapXOrder, () => { .next() .put({ type: updateTransaction.type, payload: expectedSubmittedOrderDetails }) .next() - .call(getSignerManager) - .next(mockSignerManager) - .call([mockSignerManager, 'getSignerForAccount'], baseSubmitOrderParams.account) - .next(mockSigner) - .call(signTypedData, mockPermit.domain, mockPermit.types, mockPermit.values, mockSigner) - .next(mockSignature) - .call(submitOrder, expectedOrderRequest) + .call(submitOrder, baseSubmitOrderParams.orderParams) .next() .call(sendAnalyticsEvent, WalletEventName.SwapSubmitted, { routing: Routing.DUTCH_V2, @@ -116,7 +90,7 @@ describe(submitUniswapXOrder, () => { .next() .put(pushNotification({ type: AppNotificationType.SwapPending, wrapType: WrapType.NotApplicable })) .next() - .call(baseSubmitOrderParams.onSuccess) + .call(baseSubmitOrderParams.onSubmit) .next() .isDone() }) @@ -134,13 +108,7 @@ describe(submitUniswapXOrder, () => { .next() .put({ type: updateTransaction.type, payload: expectedSubmittedOrderDetails }) .next() - .call(getSignerManager) - .next(mockSignerManager) - .call([mockSignerManager, 'getSignerForAccount'], baseSubmitOrderParams.account) - .next(mockSigner) - .call(signTypedData, mockPermit.domain, mockPermit.types, mockPermit.values, mockSigner) - .next(mockSignature) - .call(submitOrder, expectedOrderRequest) + .call(submitOrder, baseSubmitOrderParams.orderParams) .throw(new Error('pretend the order endpoint failed')) .put({ type: updateTransaction.type, @@ -176,13 +144,7 @@ describe(submitUniswapXOrder, () => { .next({ payload: { hash: approveTxHash, status: TransactionStatus.Success } }) .put({ type: updateTransaction.type, payload: expectedSubmittedOrderDetails }) .next() - .call(getSignerManager) - .next(mockSignerManager) - .call([mockSignerManager, 'getSignerForAccount'], baseSubmitOrderParams.account) - .next(mockSigner) - .call(signTypedData, mockPermit.domain, mockPermit.types, mockPermit.values, mockSigner) - .next(mockSignature) - .call(submitOrder, expectedOrderRequest) + .call(submitOrder, baseSubmitOrderParams.orderParams) .next() .call(sendAnalyticsEvent, WalletEventName.SwapSubmitted, { routing: Routing.DUTCH_V2, @@ -192,7 +154,7 @@ describe(submitUniswapXOrder, () => { .next() .put(pushNotification({ type: AppNotificationType.SwapPending, wrapType: WrapType.NotApplicable })) .next() - .call(baseSubmitOrderParams.onSuccess) + .call(baseSubmitOrderParams.onSubmit) .next() .isDone() }) @@ -214,13 +176,7 @@ describe(submitUniswapXOrder, () => { .next({ payload: { hash: wrapTxHash, status: TransactionStatus.Success } }) .put({ type: updateTransaction.type, payload: expectedSubmittedOrderDetails }) .next() - .call(getSignerManager) - .next(mockSignerManager) - .call([mockSignerManager, 'getSignerForAccount'], baseSubmitOrderParams.account) - .next(mockSigner) - .call(signTypedData, mockPermit.domain, mockPermit.types, mockPermit.values, mockSigner) - .next(mockSignature) - .call(submitOrder, expectedOrderRequest) + .call(submitOrder, baseSubmitOrderParams.orderParams) .next() .call(sendAnalyticsEvent, WalletEventName.SwapSubmitted, { routing: Routing.DUTCH_V2, @@ -230,7 +186,7 @@ describe(submitUniswapXOrder, () => { .next() .put(pushNotification({ type: AppNotificationType.SwapPending, wrapType: WrapType.NotApplicable })) .next() - .call(baseSubmitOrderParams.onSuccess) + .call(baseSubmitOrderParams.onSubmit) .next() .isDone() }) @@ -252,13 +208,7 @@ describe(submitUniswapXOrder, () => { .next({ payload: { hash: approveTxHash, status: TransactionStatus.Success } }) .put({ type: updateTransaction.type, payload: expectedSubmittedOrderDetails }) .next() - .call(getSignerManager) - .next(mockSignerManager) - .call([mockSignerManager, 'getSignerForAccount'], baseSubmitOrderParams.account) - .next(mockSigner) - .call(signTypedData, mockPermit.domain, mockPermit.types, mockPermit.values, mockSigner) - .next(mockSignature) - .call(submitOrder, expectedOrderRequest) + .call(submitOrder, baseSubmitOrderParams.orderParams) .next() .call(sendAnalyticsEvent, WalletEventName.SwapSubmitted, { routing: Routing.DUTCH_V2, @@ -268,7 +218,7 @@ describe(submitUniswapXOrder, () => { .next() .put(pushNotification({ type: AppNotificationType.SwapPending, wrapType: WrapType.NotApplicable })) .next() - .call(baseSubmitOrderParams.onSuccess) + .call(baseSubmitOrderParams.onSubmit) .next() .isDone() }) diff --git a/packages/wallet/src/features/transactions/swap/submitOrderSaga.ts b/packages/wallet/src/features/transactions/swap/submitOrderSaga.ts index 6354f0d4cba..bac57ab5bcd 100644 --- a/packages/wallet/src/features/transactions/swap/submitOrderSaga.ts +++ b/packages/wallet/src/features/transactions/swap/submitOrderSaga.ts @@ -1,13 +1,11 @@ import { call, put, take } from 'typed-redux-saga' import { submitOrder } from 'uniswap/src/data/apiClients/tradingApi/TradingApiClient' -import { DutchQuoteV2, Routing } from 'uniswap/src/data/tradingApi/__generated__/index' +import { OrderRequest, Routing } from 'uniswap/src/data/tradingApi/__generated__/index' import { AccountMeta } from 'uniswap/src/features/accounts/types' import { WalletEventName } from 'uniswap/src/features/telemetry/constants' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' -import { signTypedData } from 'uniswap/src/features/transactions/signing' import { finalizeTransaction, transactionActions } from 'uniswap/src/features/transactions/slice' import { getBaseTradeAnalyticsProperties } from 'uniswap/src/features/transactions/swap/analytics' -import { ValidatedPermit } from 'uniswap/src/features/transactions/swap/utils/trade' import { QueuedOrderStatus, TransactionOriginType, @@ -22,7 +20,6 @@ import { logger } from 'utilities/src/logger/logger' import { ONE_SECOND_MS } from 'utilities/src/time/time' import { pushNotification } from 'wallet/src/features/notifications/slice' import { AppNotificationType } from 'wallet/src/features/notifications/types' -import { getSignerManager } from 'wallet/src/features/wallet/context' // If the app is closed during the waiting period and then reopened, the saga will resume; // the order should not be submitted if too much time has passed as it may be stale. @@ -31,39 +28,26 @@ export const ORDER_STALENESS_THRESHOLD = 45 * ONE_SECOND_MS export interface SubmitUniswapXOrderParams { // internal id used for tracking transactions before they're submitted txId?: string - quote: DutchQuoteV2 - permit: ValidatedPermit chainId: WalletChainId + orderParams: OrderRequest account: AccountMeta typeInfo: TransactionTypeInfo analytics: ReturnType approveTxHash?: string wrapTxHash?: string - onSuccess: () => void + onSubmit: () => void onFailure: () => void } export function* submitUniswapXOrder(params: SubmitUniswapXOrderParams) { - const { - quote, - permit, - approveTxHash, - wrapTxHash, - txId, - chainId, - typeInfo, - account, - analytics, - onSuccess, - onFailure, - } = params - - const orderHash = quote.orderId + const { orderParams, approveTxHash, wrapTxHash, txId, chainId, typeInfo, account, analytics, onSubmit, onFailure } = + params // Wait for approval and/or wrap transactions to confirm, otherwise order submission will fail. let waitingForApproval = Boolean(approveTxHash) let waitingForWrap = Boolean(wrapTxHash) + const orderHash = orderParams.quote.orderId const order = { routing: Routing.DUTCH_V2, orderHash, @@ -113,13 +97,7 @@ export function* submitUniswapXOrder(params: SubmitUniswapXOrderParams) { try { const addedTime = Date.now() // refresh the addedTime to match the actual submission time yield* put(transactionActions.updateTransaction({ ...order, queueStatus: QueuedOrderStatus.Submitted, addedTime })) - - const signerManager = yield* call(getSignerManager) - const signer = yield* call([signerManager, 'getSignerForAccount'], account) - - const signature = yield* call(signTypedData, permit.domain, permit.types, permit.values, signer) - - yield* call(submitOrder, { signature, quote, routing: Routing.DUTCH_V2 }) + yield* call(submitOrder, orderParams) } catch { // In the rare event that submission fails, we update the order status to prompt the user. // If the app is closed before this catch block is reached, orderWatcherSaga will handle the failure upon reopening. @@ -132,6 +110,6 @@ export function* submitUniswapXOrder(params: SubmitUniswapXOrderParams) { yield* call(sendAnalyticsEvent, WalletEventName.SwapSubmitted, properties) yield* put(pushNotification({ type: AppNotificationType.SwapPending, wrapType: WrapType.NotApplicable })) - // onSuccess does not need to be wrapped in yield* call() here, but doing so makes it easier to test call ordering in submitOrder.test.ts - yield* call(onSuccess) + // onSubmit does not need to be wrapped in yield* call() here, but doing so makes it easier to test call ordering in submitOrder.test.ts + yield* call(onSubmit) } diff --git a/packages/wallet/src/features/transactions/swap/swapSaga.test.ts b/packages/wallet/src/features/transactions/swap/swapSaga.test.ts index ef26255ea1d..665df77afb7 100644 --- a/packages/wallet/src/features/transactions/swap/swapSaga.test.ts +++ b/packages/wallet/src/features/transactions/swap/swapSaga.test.ts @@ -8,7 +8,7 @@ import JSBI from 'jsbi' import { expectSaga, testSaga } from 'redux-saga-test-plan' import { EffectProviders, StaticProvider } from 'redux-saga-test-plan/providers' import { DAI, USDC } from 'uniswap/src/constants/tokens' -import { Routing } from 'uniswap/src/data/tradingApi/__generated__/index' +import { OrderRequest, Routing } from 'uniswap/src/data/tradingApi/__generated__/index' import { NativeCurrency } from 'uniswap/src/features/tokens/NativeCurrency' import { getBaseTradeAnalyticsProperties } from 'uniswap/src/features/transactions/swap/analytics' import { ClassicTrade, UniswapXTrade } from 'uniswap/src/features/transactions/swap/types/trade' @@ -20,7 +20,6 @@ import { } from 'uniswap/src/features/transactions/types/transactionDetails' import { WrapType } from 'uniswap/src/features/transactions/types/wrap' import { WETH } from 'uniswap/src/test/fixtures' -import { mockPermit } from 'uniswap/src/test/fixtures/permit' import { UniverseChainId } from 'uniswap/src/types/chains' import { currencyId } from 'uniswap/src/utils/currencyId' import { pushNotification } from 'wallet/src/features/notifications/slice' @@ -126,11 +125,13 @@ const classicSwapParams = { gasFee: { value: '5', isLoading: false, error: null }, gasFeeEstimation: {}, approvalError: false, - permit: undefined, + permitData: undefined, + permitDataLoading: false, + permitSignature: undefined, swapRequestArgs: undefined, - unsigned: false, }, - onSuccess: jest.fn(), + steps: [], + onSubmit: jest.fn(), onFailure: jest.fn(), } satisfies SwapParams @@ -146,14 +147,16 @@ const uniswapXSwapParams = { revocationTxRequest: mockRevocationTxRequest, trade: mockUniswapXTrade, indicativeTrade: undefined, - permit: mockPermit, + orderParams: { quote: { orderId: '0xMockOrderHash' } } as unknown as OrderRequest, wrapTxRequest: undefined, gasFee: { value: '5', isLoading: false, error: null }, - gasFeeEstimation: {}, gasFeeBreakdown: { classicGasUseEstimateUSD: '5', approvalCost: '5', wrapCost: '0' }, approvalError: false, + permitData: undefined, + permitDataLoading: false, }, - onSuccess: jest.fn(), + steps: [], + onSubmit: jest.fn(), onFailure: jest.fn(), } satisfies SwapParams @@ -220,7 +223,7 @@ describe(approveAndSwap, () => { // Requires manually providing return values for each effect in `.next()`. testSaga(approveAndSwap, classicSwapParamsWithoutApprove) .next() - .call(classicSwapParams.onSuccess) + .call(classicSwapParams.onSubmit) .next() .call(shouldSubmitViaPrivateRpc, classicSwapParams.swapTxContext.txRequest.chainId) .next(false) @@ -259,7 +262,7 @@ describe(approveAndSwap, () => { .silentRun() testSaga(approveAndSwap, classicSwapParams) .next() - .call(classicSwapParams.onSuccess) + .call(classicSwapParams.onSubmit) .next() .call(shouldSubmitViaPrivateRpc, classicSwapParams.swapTxContext.txRequest.chainId) .next(false) @@ -283,9 +286,8 @@ describe(approveAndSwap, () => { approveTxHash: '0xMockApprovalTxHash', wrapTxHash: undefined, txId: uniswapXSwapParams.txId, - permit: mockPermit, - quote: uniswapXSwapParams.swapTxContext.trade.quote.quote, - onSuccess: uniswapXSwapParams.onSuccess, + orderParams: uniswapXSwapParams.swapTxContext.orderParams, + onSubmit: uniswapXSwapParams.onSubmit, onFailure: uniswapXSwapParams.onFailure, } @@ -318,8 +320,7 @@ describe(approveAndSwap, () => { swapTxContext: { ...uniswapXSwapParams.swapTxContext, wrapTxRequest: mockWrapTxRequest, - permit: mockPermit, - gasFeeEstimation: {}, + permitDataLoading: false, }, } satisfies SwapParams @@ -332,7 +333,6 @@ describe(approveAndSwap, () => { unwrapped: false, currencyAmountRaw: '1000', swapTxId: '1', - gasEstimates: undefined, }, txId: undefined, transactionOriginType: TransactionOriginType.Internal, @@ -346,10 +346,9 @@ describe(approveAndSwap, () => { approveTxHash: '0xMockApprovalTxHash', wrapTxHash: '0xMockWrapTxHash', txId: uniswapXSwapParams.txId, - permit: mockPermit, - onSuccess: uniswapXSwapParams.onSuccess, + orderParams: uniswapXSwapParams.swapTxContext.orderParams, + onSubmit: uniswapXSwapParams.onSubmit, onFailure: uniswapXSwapParams.onFailure, - quote: uniswapXSwapParams.swapTxContext.trade.quote.quote, } await expectSaga(approveAndSwap, uniswapXSwapEthInputParams) diff --git a/packages/wallet/src/features/transactions/swap/swapSaga.ts b/packages/wallet/src/features/transactions/swap/swapSaga.ts index 15538f19348..4f35de5452e 100644 --- a/packages/wallet/src/features/transactions/swap/swapSaga.ts +++ b/packages/wallet/src/features/transactions/swap/swapSaga.ts @@ -6,6 +6,7 @@ import { FeatureFlags, getFeatureFlagName } from 'uniswap/src/features/gating/fl import { Statsig } from 'uniswap/src/features/gating/sdk/statsig' import { getBaseTradeAnalyticsProperties } from 'uniswap/src/features/transactions/swap/analytics' import { ValidatedSwapTxContext } from 'uniswap/src/features/transactions/swap/types/swapTxAndGasInfo' +import { TransactionStep } from 'uniswap/src/features/transactions/swap/utils/generateSwapSteps' import { tradeToTransactionInfo } from 'uniswap/src/features/transactions/swap/utils/trade' import { ApproveTransactionInfo, @@ -18,7 +19,7 @@ import { pushNotification } from 'wallet/src/features/notifications/slice' import { AppNotificationType } from 'wallet/src/features/notifications/types' import { isPrivateRpcSupportedOnChain } from 'wallet/src/features/providers/utils' import { sendTransaction, tryGetNonce } from 'wallet/src/features/transactions/sendTransactionSaga' -import { SubmitUniswapXOrderParams, submitUniswapXOrder } from 'wallet/src/features/transactions/swap/submitOrderSaga' +import { submitUniswapXOrder } from 'wallet/src/features/transactions/swap/submitOrderSaga' import { wrap } from 'wallet/src/features/transactions/swap/wrapSaga' import { selectWalletSwapProtectionSetting } from 'wallet/src/features/wallet/selectors' import { SwapProtectionSetting } from 'wallet/src/features/wallet/slice' @@ -29,23 +30,23 @@ export type SwapParams = { account: SignerMnemonicAccountMeta analytics: ReturnType swapTxContext: ValidatedSwapTxContext - onSuccess: () => void + steps: TransactionStep[] + onSubmit: () => void onFailure: () => void } export function* approveAndSwap(params: SwapParams) { try { - const { swapTxContext, account, txId, analytics, onSuccess, onFailure } = params - const { routing, approveTxRequest } = swapTxContext + const { swapTxContext, account, txId, analytics, onSubmit, onFailure } = params + const { trade, routing, approveTxRequest } = swapTxContext const isUniswapX = routing === Routing.DUTCH_V2 - const isBridge = routing === Routing.BRIDGE const chainId = swapTxContext.trade.inputAmount.currency.chainId // For classic swaps, trigger UI changes immediately after click if (!isUniswapX) { - // onSuccess does not need to be wrapped in yield* call() here, but doing so makes it easier to test call ordering in swapSaga.test.ts - yield* call(onSuccess) + // onSubmit does not need to be wrapped in yield* call() here, but doing so makes it easier to test call ordering in swapSaga.test.ts + yield* call(onSubmit) } // MEV protection is not needed for UniswapX approval and/or wrap transactions. @@ -54,7 +55,7 @@ export function* approveAndSwap(params: SwapParams) { // otherwise for some L2s the Provider might fetch the same nonce for both transactions. let nonce = yield* call(tryGetNonce, account, chainId) - const gasFeeEstimation = swapTxContext.gasFeeEstimation + const gasFeeEstimation = swapTxContext.routing === Routing.CLASSIC ? swapTxContext.gasFeeEstimation : undefined let approveTxHash: string | undefined // Approval Logic @@ -89,8 +90,7 @@ export function* approveAndSwap(params: SwapParams) { const typeInfo = tradeToTransactionInfo(swapTxContext.trade, transactedUSDValue, gasFeeEstimation?.swapEstimates) // Swap Logic - UniswapX if (isUniswapX) { - const { trade, wrapTxRequest, permit } = swapTxContext - const quote = trade.quote.quote + const { orderParams, wrapTxRequest } = swapTxContext let wrapTxHash: string | undefined // Wrap Logic - UniswapX Eth-input @@ -102,39 +102,26 @@ export function* approveAndSwap(params: SwapParams) { inputCurrencyAmount, swapTxId: txId, skipPushNotification: true, // wrap is abstracted away in UX; we avoid showing a wrap notification - gasEstimates: gasFeeEstimation?.wrapEstimates, }) wrapTxHash = wrapResponse?.transactionResponse.hash } - const submitOrderParams: SubmitUniswapXOrderParams = { - account, - analytics, - approveTxHash, - wrapTxHash, - permit, - quote, - typeInfo, - chainId, - txId, - onSuccess, - onFailure, - } - yield* call(submitUniswapXOrder, submitOrderParams) - } else if (isBridge) { - const options = { request: { ...swapTxContext.txRequest, nonce }, submitViaPrivateRpc } - const sendTransactionParams = { + const submitOrderParams = { txId, chainId, + orderParams, + approveTxHash, + wrapTxHash, account, - options, typeInfo, analytics, - transactionOriginType: TransactionOriginType.Internal, + onSubmit, + onFailure, } - yield* call(sendTransaction, sendTransactionParams) - yield* put(pushNotification({ type: AppNotificationType.SwapPending, wrapType: WrapType.NotApplicable })) - } else { + yield* call(submitUniswapXOrder, submitOrderParams) + } + // Swap Logic - Classic + else { const options = { request: { ...swapTxContext.txRequest, nonce }, submitViaPrivateRpc } const sendTransactionParams = { txId, diff --git a/packages/wallet/src/features/transactions/swap/wrapSaga.test.ts b/packages/wallet/src/features/transactions/swap/wrapSaga.test.ts index b777bf4b671..ba181365fd6 100644 --- a/packages/wallet/src/features/transactions/swap/wrapSaga.test.ts +++ b/packages/wallet/src/features/transactions/swap/wrapSaga.test.ts @@ -22,7 +22,6 @@ const wrapTxInfo: WrapTransactionInfo = { unwrapped: false, currencyAmountRaw: '200000', swapTxId: undefined, - gasEstimates: undefined, } const unwrapTxInfo: WrapTransactionInfo = { diff --git a/packages/wallet/src/features/transactions/swap/wrapSaga.ts b/packages/wallet/src/features/transactions/swap/wrapSaga.ts index e41bb8a8b1b..d821102e605 100644 --- a/packages/wallet/src/features/transactions/swap/wrapSaga.ts +++ b/packages/wallet/src/features/transactions/swap/wrapSaga.ts @@ -3,7 +3,6 @@ import { providers } from 'ethers' import { call, put } from 'typed-redux-saga' import { AccountMeta } from 'uniswap/src/features/accounts/types' import { - GasFeeEstimates, TransactionOptions, TransactionOriginType, TransactionType, @@ -24,12 +23,11 @@ export type WrapParams = { account: AccountMeta inputCurrencyAmount: CurrencyAmount skipPushNotification?: boolean - gasEstimates?: GasFeeEstimates } export function* wrap(params: WrapParams) { try { - const { account, inputCurrencyAmount, txRequest, txId, skipPushNotification, swapTxId, gasEstimates } = params + const { account, inputCurrencyAmount, txRequest, txId, skipPushNotification, swapTxId } = params let typeInfo: TransactionTypeInfo if (inputCurrencyAmount.currency.isNative) { @@ -38,7 +36,6 @@ export function* wrap(params: WrapParams) { unwrapped: false, currencyAmountRaw: inputCurrencyAmount.quotient.toString(), swapTxId, - gasEstimates, } } else { typeInfo = { @@ -46,7 +43,6 @@ export function* wrap(params: WrapParams) { unwrapped: true, currencyAmountRaw: inputCurrencyAmount.quotient.toString(), swapTxId, - gasEstimates, } } @@ -71,7 +67,6 @@ export function* wrap(params: WrapParams) { return result } catch (error) { logger.error(error, { tags: { file: 'wrapSaga', function: 'wrap' } }) - return undefined } } diff --git a/packages/wallet/src/features/transactions/transactionWatcherSaga.test.ts b/packages/wallet/src/features/transactions/transactionWatcherSaga.test.ts index ea3e9cdda56..de7aaac81da 100644 --- a/packages/wallet/src/features/transactions/transactionWatcherSaga.test.ts +++ b/packages/wallet/src/features/transactions/transactionWatcherSaga.test.ts @@ -206,7 +206,6 @@ describe(watchFiatOnRampTransaction, () => { return confirmedTx } } - return undefined }, }, [delay(PollingInterval.Fast), Promise.resolve(() => undefined)], @@ -239,7 +238,6 @@ describe(watchFiatOnRampTransaction, () => { return confirmedTx } } - return undefined }, }, ]) diff --git a/packages/wallet/src/features/transactions/transactionWatcherSaga.ts b/packages/wallet/src/features/transactions/transactionWatcherSaga.ts index 7bd1e1d174e..ddeef0bffe4 100644 --- a/packages/wallet/src/features/transactions/transactionWatcherSaga.ts +++ b/packages/wallet/src/features/transactions/transactionWatcherSaga.ts @@ -2,11 +2,9 @@ import { ApolloClient, NormalizedCacheObject } from '@apollo/client' import { SwapEventName } from '@uniswap/analytics-events' import { TradeType } from '@uniswap/sdk-core' -import { BigNumber, BigNumberish, providers } from 'ethers' +import { BigNumberish, providers } from 'ethers' import { call, delay, fork, put, race, select, take, takeEvery } from 'typed-redux-saga' import { PollingInterval } from 'uniswap/src/constants/misc' -import { fetchSwaps } from 'uniswap/src/data/apiClients/tradingApi/TradingApiClient' -import { SwapStatus } from 'uniswap/src/data/tradingApi/__generated__' import { FiatOnRampTransactionDetails } from 'uniswap/src/features/fiatOnRamp/types' import { findGasStrategyName } from 'uniswap/src/features/gas/hooks' import { getGasPrice } from 'uniswap/src/features/gas/types' @@ -22,8 +20,7 @@ import { updateTransaction, upsertFiatOnRampTransaction, } from 'uniswap/src/features/transactions/slice' -import { isBridge, isClassic, isUniswapX } from 'uniswap/src/features/transactions/swap/utils/routing' -import { toTradingApiSupportedChainId } from 'uniswap/src/features/transactions/swap/utils/tradingApi' +import { isClassic, isUniswapX } from 'uniswap/src/features/transactions/swap/utils/routing' import { BaseSwapTransactionInfo, FinalizedTransactionDetails, @@ -53,16 +50,6 @@ import { } from 'wallet/src/features/transactions/utils' import { getProvider } from 'wallet/src/features/wallet/context' -export const SWAP_STATUS_TO_TX_STATUS: { [key in SwapStatus]: TransactionStatus } = { - [SwapStatus.PENDING]: TransactionStatus.Pending, - [SwapStatus.SUCCESS]: TransactionStatus.Success, - [SwapStatus.NOT_FOUND]: TransactionStatus.Unknown, - [SwapStatus.FAILED]: TransactionStatus.Failed, - [SwapStatus.EXPIRED]: TransactionStatus.Expired, -} - -const FINALIZED_BRIDGE_SWAP_STATUS = [SwapStatus.SUCCESS, SwapStatus.FAILED, SwapStatus.EXPIRED] - export function* transactionWatcher({ apolloClient }: { apolloClient: ApolloClient }) { logger.debug('transactionWatcherSaga', 'transactionWatcher', 'Starting tx watcher') @@ -198,13 +185,12 @@ export function* watchTransaction({ logger.debug('transactionWatcherSaga', 'watchTransaction', 'Watching for updates for tx:', hash) const provider = yield* call(getProvider, chainId) - const options = isUniswapX(transaction) ? undefined : transaction.options - const { updatedTransaction, cancel, replace, invalidated, timeout } = yield* race({ + const nonce = isUniswapX(transaction) ? undefined : transaction.options.request.nonce + const { updatedTransaction, cancel, replace, invalidated } = yield* race({ updatedTransaction: call(waitForRemoteUpdate, transaction, provider), cancel: call(waitForCancellation, chainId, id), replace: call(waitForReplacement, chainId, id), - invalidated: call(waitForTxnInvalidated, chainId, id, options?.request.nonce), - ...(options?.timeoutTimestampMs ? { timeout: call(waitForTimeout, options.timeoutTimestampMs) } : {}), + invalidated: call(waitForTxnInvalidated, chainId, id, nonce), }) // `cancel` and `updatedTransaction` conditions apply to both Classic and UniswapX transactions @@ -254,16 +240,6 @@ export function* watchTransaction({ } return } - - if (timeout && transaction.status === TransactionStatus.Pending) { - logger.warn('transactionWatcherSaga', 'watchTransaction', 'Timeout for pending tx', { - hash, - chainId, - id, - }) - yield* call(maybeLogGasEstimateAccuracy, transaction) - return - } } export async function waitForReceipt( @@ -277,16 +253,6 @@ export async function waitForReceipt( return txReceipt } -function* waitForTimeout(timeoutTimestampMs: number) { - const currentTime = Date.now() - const delayTime = timeoutTimestampMs - currentTime - if (delayTime <= 0) { - return true - } - yield* delay(delayTime) - return true -} - function* waitForRemoteUpdate(transaction: TransactionDetails, provider: providers.Provider) { let hash = transaction.hash let status = transaction.status @@ -303,7 +269,7 @@ function* waitForRemoteUpdate(transaction: TransactionDetails, provider: provide } } - // At this point, the tx should either be a classic / bridge tx or a filled order, both of which have hashes + // At this point, the tx should either be a classic tx or a filled order, both of which have hashes if (!hash) { logger.error(new Error('Watching for tx with no hash'), { tags: { @@ -312,22 +278,12 @@ function* waitForRemoteUpdate(transaction: TransactionDetails, provider: provide }, extra: { transaction }, }) - return undefined + return } const ethersReceipt = yield* call(waitForReceipt, hash, provider) const receipt = receiptFromEthersReceipt(ethersReceipt) - if (isBridge(transaction)) { - // Bridge swaps become non-cancellable after the transaction is submitted to chain. - // Update should happen without watching to avoid an infinite re-watch loop. - const updatedTransaction = { ...transaction, cancellable: false } - yield* put(transactionActions.updateTransactionWithoutWatch(updatedTransaction)) - - // Poll for bridging status from BE - status = yield* call(waitForBridgingStatus, transaction) - } - // Classic transaction status is based on receipt, while UniswapX status is based backend response. if (isClassic(transaction)) { status = getFinalizedTransactionStatus(transaction.status, ethersReceipt?.status) @@ -335,41 +291,6 @@ function* waitForRemoteUpdate(transaction: TransactionDetails, provider: provide return { ...transaction, status, receipt, hash } } -function* waitForBridgingStatus(transaction: TransactionDetails) { - const txHash = transaction.hash - const chainId = toTradingApiSupportedChainId(transaction.chainId) - - if (!txHash || !chainId) { - return TransactionStatus.Unknown - } - - let swapStatus: SwapStatus | undefined - const initialPollIntervalMs = 500 - const maxRetries = 5 - const backoffFactor = 2 // Each retry will double the wait time - - let pollIndex = 0 - while (pollIndex < maxRetries) { - const currentPollInterval = initialPollIntervalMs * Math.pow(backoffFactor, pollIndex) - yield* delay(currentPollInterval) - - const data = yield* call(fetchSwaps, { - txHashes: [txHash], - chainId, - }) - - const currentSwapStatus = data.swaps?.[0]?.status - if (currentSwapStatus && FINALIZED_BRIDGE_SWAP_STATUS.includes(currentSwapStatus)) { - swapStatus = currentSwapStatus - break - } - - pollIndex++ - } - // If we didn't get a status after polling, assume it's failed - return swapStatus ? SWAP_STATUS_TO_TX_STATUS[swapStatus] : TransactionStatus.Failed -} - function* waitForCancellation(chainId: WalletChainId, id: string) { while (true) { const { payload } = yield* take>(cancelTransaction.type) @@ -511,24 +432,11 @@ export function logTransactionEvent(actionData: ReturnType transaction.options.timeoutTimestampMs - for (const estimate of [gasEstimates.activeEstimate, ...(gasEstimates.shadowEstimates || [])]) { const gasUseDiff = getDiff(estimate.gasLimit, transaction.receipt?.gasUsed) const gasPriceDiff = getDiff(getGasPrice(estimate), transaction.receipt?.effectiveGasPrice) @@ -547,11 +455,9 @@ function maybeLogGasEstimateAccuracy(transaction: TransactionDetails) { gas_price_diff_percentage: getPercentageError(gasPriceDiff, getGasPrice(estimate)), gas_price: transaction.receipt?.effectiveGasPrice, max_priority_fee_per_gas: 'maxPriorityFeePerGas' in estimate ? estimate.maxPriorityFeePerGas : undefined, - out_of_gas, - private_rpc: isClassic(transaction) ? transaction.options.submitViaPrivateRpc ?? false : false, + private_rpc: isClassic(transaction) ? transaction.options.submitViaPrivateRpc : false, is_shadow: estimate !== gasEstimates.activeEstimate, name: findGasStrategyName(estimate), - timed_out, }) } } @@ -570,7 +476,7 @@ export function* finalizeTransaction({ // Refetch data when a local tx has confirmed yield* refetchGQLQueries({ transaction, apolloClient }) - if (transaction.typeInfo.type === TransactionType.Swap || transaction.typeInfo.type === TransactionType.Bridge) { + if (transaction.typeInfo.type === TransactionType.Swap) { const hasDoneOneSwap = (yield* select(selectSwapTransactionsCount)) === 1 if (hasDoneOneSwap) { // Only log event if it's a user's first ever swap diff --git a/packages/wallet/src/features/unitags/ClaimUnitagContent.tsx b/packages/wallet/src/features/unitags/ClaimUnitagContent.tsx index e1dfb039fc3..e8bddc88500 100644 --- a/packages/wallet/src/features/unitags/ClaimUnitagContent.tsx +++ b/packages/wallet/src/features/unitags/ClaimUnitagContent.tsx @@ -4,7 +4,7 @@ import { useCallback, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { ActivityIndicator } from 'react-native' import { useAnimatedStyle, useSharedValue, withDelay, withTiming } from 'react-native-reanimated' -import { AnimatePresence, Button, Flex, FlexProps, Text, TouchableArea, useSporeColors } from 'ui/src' +import { AnimatePresence, Button, Flex, Text, TouchableArea, useSporeColors } from 'ui/src' import { InfoCircleFilled } from 'ui/src/components/icons' import { AnimatedFlex } from 'ui/src/components/layout/AnimatedFlex' import { useDynamicFontSizing } from 'ui/src/hooks/useDynamicFontSizing' @@ -22,7 +22,6 @@ import { import { shortenAddress } from 'uniswap/src/utils/addresses' import { dismissNativeKeyboard } from 'utilities/src/device/keyboard' import { logger } from 'utilities/src/logger/logger' -import { isExtension } from 'utilities/src/platform' import { ONE_SECOND_MS } from 'utilities/src/time/time' import { UnitagInfoModal } from 'wallet/src/features/unitags/UnitagInfoModal' import { UnitagName } from 'wallet/src/features/unitags/UnitagName' @@ -45,17 +44,13 @@ const UNITAG_NAME_ANIMATE_DISTANCE_Y = imageSizes.image100 + spacing.spacing48 + export function ClaimUnitagContent({ unitagAddress, entryPoint, - animateY = true, navigationEventConsumer, onNavigateContinue, - onComplete, }: { unitagAddress?: string entryPoint: UnitagEntryPoint - animateY?: boolean navigationEventConsumer?: EventConsumer - onNavigateContinue?: (params: SharedUnitagScreenParams[UnitagScreens.ChooseProfilePicture]) => void - onComplete?: () => void + onNavigateContinue: (params: SharedUnitagScreenParams[UnitagScreens.ChooseProfilePicture]) => void // fix this any }): JSX.Element { const { t } = useTranslation() const colors = useSporeColors() @@ -76,7 +71,7 @@ export function ClaimUnitagContent({ return { opacity: addressViewOpacity.value, } - }, [addressViewOpacity]) + }) const { error: canClaimUnitagNameError, loading: loadingUnitagErrorCheck } = useCanClaimUnitagName(unitagToCheck) @@ -143,7 +138,7 @@ export function ClaimUnitagContent({ const navigateWithAnimation = useCallback( (unitag: string) => { - if (entryPoint === OnboardingScreens.Landing && !unitagAddress) { + if (!unitagAddress) { const err = new Error('unitagAddress should always be defined') logger.error(err, { tags: { file: 'ClaimUnitagScreen', function: 'navigateWithAnimation' }, @@ -173,21 +168,10 @@ export function ClaimUnitagContent({ ) // Navigate to ChooseProfilePicture screen after initial delay + translation to allow animations to finish setTimeout(() => { - onComplete?.() - if (unitagAddress && onNavigateContinue) { - onNavigateContinue({ unitag, entryPoint, address: unitagAddress, unitagFontSize: fontSize }) - } + onNavigateContinue({ unitag, entryPoint, address: unitagAddress, unitagFontSize: fontSize }) }, initialDelay + translateYDuration) }, - [ - onComplete, - onNavigateContinue, - addressViewOpacity, - entryPoint, - unitagAddress, - unitagInputContainerTranslateY, - fontSize, - ], + [onNavigateContinue, addressViewOpacity, entryPoint, unitagAddress, unitagInputContainerTranslateY, fontSize], ) // Handle when useUnitagError completes loading and returns a result after onPressContinue is called @@ -213,20 +197,6 @@ export function ClaimUnitagContent({ } } - const extensionStyling: FlexProps = isExtension - ? { - backgroundColor: '$surface1', - borderRadius: '$rounded20', - borderWidth: 1, - borderColor: '$surface3', - py: '$spacing12', - px: '$spacing20', - mb: '$spacing20', - width: '100%', - justifyContent: 'space-between', - } - : {} - return ( <> {!showTextInputView && ( @@ -259,7 +228,6 @@ export function ClaimUnitagContent({ enterStyle={{ opacity: 0, x: 40 }} exitStyle={{ opacity: 0, x: 40 }} gap="$none" - {...extensionStyling} > @@ -316,13 +284,15 @@ export function ClaimUnitagContent({ - - - {canClaimUnitagNameError} - - + {canClaimUnitagNameError && unitagToCheck === unitagInputValue && ( + + + {canClaimUnitagNameError} + + + )} - +