From f11f1081c60e3f03ae6781e57e28407719f1432b Mon Sep 17 00:00:00 2001 From: Uniswap Labs Service Account Date: Tue, 17 Dec 2024 17:15:58 +0000 Subject: [PATCH] ci(release): publish latest release --- .../@wagmi-core-npm-2.6.16-1baef7c190.patch | 23 - ...coinbase-wallet-npm-8.2.3-9c7073f079.patch | 13 - ...act-gnosis-safe-npm-8.2.4-a7e2850335.patch | 15 - ...-react-metamask-npm-8.2.4-84b10de2d2.patch | 13 - ...alletconnect-v2-npm-8.5.1-933cac0534.patch | 28 - ...cypress-hardhat-npm-2.5.0-9b9b7d7a28.patch | 12 - RELEASE | 51 +- VERSION | 2 +- apps/extension/.depcheckrc | 22 +- apps/extension/package.json | 2 + apps/extension/src/app/datadog.ts | 2 +- .../requestContent/WrapContent.tsx | 4 +- .../app/features/settings/SettingsScreen.tsx | 1 + apps/extension/src/manifest.json | 2 +- apps/extension/src/store/migrations.test.ts | 6 + apps/extension/src/store/migrations.ts | 4 +- apps/mobile/.storybook/storybook.requires.ts | 13 + apps/mobile/android/app/build.gradle | 6 +- .../ios/Uniswap.xcodeproj/project.pbxproj | 48 +- apps/mobile/package.json | 5 +- apps/mobile/src/app/App.tsx | 2 +- apps/mobile/src/app/DataDogProvider.tsx | 63 - .../mobile/src/app/DatadogProviderWrapper.tsx | 10 +- apps/mobile/src/app/migrations.test.ts | 6 + apps/mobile/src/app/migrations.ts | 5 +- apps/mobile/src/app/modals/AppModals.tsx | 5 + .../app/navigation/NavigationContainer.tsx | 7 +- apps/mobile/src/app/navigation/navigation.tsx | 61 +- .../src/app/navigation/navigationRef.tsx | 4 + .../src/app/navigation/rootNavigation.ts | 2 +- .../RemoveWallet/AssociatedAccountsList.tsx | 45 +- .../accounts/AccountHeader.test.tsx | 2 +- .../src/components/accounts/AccountHeader.tsx | 111 +- .../__snapshots__/AccountHeader.test.tsx.snap | 745 +++-- .../buttons/CopyTextButton.stories.tsx | 3 +- .../components/explore/ExploreSections.tsx | 8 +- .../explore/search/SearchResultsSection.tsx | 2 + .../forceUpgrade/ForceUpgradeModal.tsx | 147 +- .../deepLinking/handleDeepLinkSaga.test.ts | 2 +- .../deepLinking/handleDeepLinkSaga.ts | 4 + .../handleOffRampReturnLinkSaga.ts | 85 + .../deepLinking/handleSwapLinkSaga.test.ts | 69 +- .../deepLinking/handleSwapLinkSaga.ts | 44 +- .../mobile/src/features/modals/ModalsState.ts | 5 +- apps/mobile/src/features/modals/modalSlice.ts | 15 +- .../hooks/useNotificationsToggle.test.ts | 206 ++ .../hooks/useNotificationsToggle.ts | 159 + .../features/onboarding/OnboardingScreen.tsx | 4 +- apps/mobile/src/features/send/SendFlow.tsx | 10 +- .../testnetMode/TestnetSwitchModal.tsx | 59 + .../testnetMode/TestnetSwitchModalState.ts | 3 + .../src/features/walletConnect/utils.ts | 25 +- apps/mobile/src/screens/ExploreScreen.tsx | 52 +- .../src/screens/FiatOnRampConnecting.tsx | 2 +- apps/mobile/src/screens/FiatOnRampScreen.tsx | 18 +- apps/mobile/src/screens/HomeScreen.tsx | 148 +- .../screens/Import/OnDeviceRecoveryScreen.tsx | 5 +- apps/mobile/src/screens/SettingsScreen.tsx | 1 + apps/mobile/src/screens/SettingsWallet.tsx | 82 +- apps/mobile/src/test/render.tsx | 2 +- apps/web/.depcheckrc | 12 + apps/web/.env | 1 + apps/web/.eslintignore | 1 + apps/web/.eslintrc.js | 2 +- apps/web/.gitignore | 2 + apps/web/.storybook/main.ts | 71 + apps/web/.storybook/preview.tsx | 23 + apps/web/craco.config.cjs | 2 +- apps/web/package.json | 21 +- apps/web/public/pools-sitemap.xml | 130 + apps/web/public/tokens-sitemap.xml | 245 ++ .../CancelOrdersDialog.test.tsx.snap | 144 +- .../OffchainActivityModal.test.tsx.snap | 216 +- .../MiniPortfolio/Activity/parseRemote.tsx | 5 + .../LimitDetailActivityRow.test.tsx.snap | 46 +- .../__snapshots__/index.test.tsx.snap | 178 +- apps/web/src/components/Button/buttons.tsx | 13 - .../ActiveLiquidityChart2.tsx | 77 +- .../Charts/ActiveLiquidityChart/AxisRight.tsx | 17 +- .../Charts/ActiveLiquidityChart/Brush2.tsx | 19 +- .../ActiveLiquidityChart/HorizontalArea.tsx | 1 - .../LiquidityPositionRangeChart.tsx | 18 +- .../LiquidityRangeInput.tsx | 354 +- .../Charts/LiquidityRangeInput/constants.ts | 39 + .../__snapshots__/Pending.test.tsx.snap | 306 +- .../Dialog/__snapshots__/Dialog.test.tsx.snap | 144 +- .../FeatureFlagModal/FeatureFlagModal.tsx | 1 + .../components/FiatOnrampModal/constants.ts | 19 - .../src/components/FiatOnrampModal/index.tsx | 185 -- .../components/FiatOnrampModal/utils.test.ts | 80 - .../src/components/FiatOnrampModal/utils.ts | 81 - .../Liquidity/LiquidityModalHeader.test.tsx | 3 +- .../Liquidity/LiquidityPositionFeeStats.tsx | 15 +- apps/web/src/components/Logo/ChainLogo.tsx | 7 + .../src/components/NavigationTabs/index.tsx | 21 - .../PoolDetailsStatsButtons.test.tsx.snap | 62 +- .../PoolDetailsTransactionTable.test.tsx.snap | 108 +- .../src/components/TopLevelModals/index.tsx | 2 - .../__snapshots__/SwapDetails.test.tsx.snap | 232 +- .../__snapshots__/SwapHeader.test.tsx.snap | 42 +- apps/web/src/hooks/useContract.ts | 5 +- .../IncreaseLiquidityModal.tsx | 6 +- apps/web/src/pages/Landing/sections/Hero.tsx | 12 +- apps/web/src/pages/LegacyPool/redirects.tsx | 5 - .../Pool/Positions/create/CreatePosition.tsx | 5 +- .../Positions/create/RangeSelectionStep.tsx | 5 +- .../Pool/Positions/create/SelectTokenStep.tsx | 43 +- .../pages/Pool/Positions/create/shared.tsx | 3 + apps/web/src/pages/Pool/index.tsx | 168 +- apps/web/src/pages/PoolFinder/index.tsx | 339 +- .../RemoveLiquidity/RemoveLiquidityModal.tsx | 6 +- .../NewAddressSpeedBump.test.tsx.snap | 108 +- .../SendCurrencyInputForm.test.tsx.snap | 468 +-- .../SendReviewModal.test.tsx.snap | 220 +- .../SmartContractSpeedbump.test.tsx.snap | 72 +- apps/web/src/pages/Swap/index.tsx | 9 +- apps/web/src/state/migrations.ts | 4 +- apps/web/src/state/migrations/21.test.ts | 143 + apps/web/src/state/migrations/21.ts | 18 + apps/web/src/state/reducerTypeTest.ts | 2 + apps/web/src/state/routing/types.ts | 1 + apps/web/src/state/user/hooks.tsx | 7 + config/jest-presets/jest/globals.js | 1 + package.json | 7 +- packages/eslint-config/package.json | 2 +- packages/ui/package.json | 1 + packages/ui/src/assets/icons/scan-home.svg | 6 +- .../ui/src/assets/icons/settings-warning.svg | 4 + packages/ui/src/assets/index.ts | 1 + .../ui/src/assets/logos/png/monad-logo.png | Bin 0 -> 5414 bytes .../src/components/button/Button.stories.tsx | 34 + packages/ui/src/components/icons/ScanHome.tsx | 7 +- .../src/components/icons/SettingsWarning.tsx | 25 + packages/ui/src/components/icons/exported.ts | 1 + packages/ui/src/components/switch/Switch.tsx | 13 +- packages/ui/src/storybook/Spore.mdx | 92 + packages/ui/src/storybook/constants.ts | 5 - packages/ui/src/storybook/index.ts | 1 - packages/ui/src/theme/color/colors.ts | 10 + packages/uniswap/package.json | 2 +- packages/uniswap/src/assets/chainLogos.tsx | 6 + .../WarningMessage/WarningMessage.tsx | 32 + .../dropdowns/ActionSheetDropdown.test.tsx | 6 +- .../dropdowns/ActionSheetDropdown.tsx | 10 +- .../src/components/gas/NetworkFee.test.tsx | 2 +- .../uniswap/src/components/gas/NetworkFee.tsx | 4 +- .../src/components/modals/Modal.native.tsx | 4 +- .../src/components/modals/Modal.web.tsx | 2 +- .../src/components/modals/modalConstants.tsx | 29 + .../uniswap/src/components/pill/NewTag.tsx | 24 +- packages/uniswap/src/config.ts | 6 + packages/uniswap/src/constants/routing.ts | 7 + packages/uniswap/src/constants/tokens.ts | 44 + .../uniswap/src/constants/transactions.ts | 3 +- .../graphql/uniswap-data-api/schema.graphql | 1 + .../data/rest/conversionTracking/constants.ts | 2 +- .../data/rest/conversionTracking/tracking.ts | 3 - .../useConversionTracking.ts | 40 +- .../uniswap/src/data/rest/getPositions.ts | 84 +- packages/uniswap/src/data/tradingApi/api.json | 2 +- packages/uniswap/src/data/tradingApi/types.ts | 1 + .../uniswap/src/features/chains/chainInfo.ts | 63 + .../chains/hooks/useFeatureFlaggedChainIds.ts | 12 +- packages/uniswap/src/features/chains/types.ts | 9 +- .../uniswap/src/features/chains/utils.test.ts | 4 +- packages/uniswap/src/features/chains/utils.ts | 6 + .../uniswap/src/features/fiatOnRamp/types.ts | 49 +- packages/uniswap/src/features/gas/hooks.ts | 55 +- packages/uniswap/src/features/gas/types.ts | 2 + .../src/features/gas/useMaxAmountSpend.ts | 9 + packages/uniswap/src/features/gas/utils.ts | 20 + .../uniswap/src/features/gating/configs.ts | 6 +- packages/uniswap/src/features/gating/flags.ts | 2 + .../uniswap/src/features/settings/saga.ts | 9 +- .../src/features/telemetry/constants/trace.ts | 2 + .../features/telemetry/constants/uniswap.ts | 1 + .../uniswap/src/features/telemetry/types.ts | 14 +- .../src/features/tokens/slice/hooks.ts | 7 +- .../src/features/tokens/slice/slice.ts | 8 +- .../useInsufficientNativeTokenWarning.tsx | 4 +- .../TransactionDetails/TransactionDetails.tsx | 115 +- .../contexts/TransactionSettingsContext.tsx | 78 +- .../transactions/settings/selectors.ts | 8 + .../features/transactions/settings/slice.ts | 55 + .../features/transactions/swap/analytics.ts | 5 +- .../transactions/swap/form/SwapFormScreen.tsx | 10 + .../swap/form/SwapFormSettings.tsx | 80 +- .../swap/form/SwapFormSettingsButton.tsx | 92 + .../swap/form/footer/GasTradeRow.tsx | 4 +- .../swap/hooks/useSwapTxAndGasInfo.ts | 15 +- .../swap/hooks/useTokenApprovalInfo.test.ts | 1 + .../swap/hooks/useTokenApprovalInfo.ts | 57 +- .../swap/hooks/useTransactionRequestInfo.ts | 45 +- .../transactions/swap/hooks/useUSDCPrice.ts | 2 + .../transactions/swap/modals/RoutingInfo.tsx | 2 +- .../transactions/swap/review/SwapDetails.tsx | 18 +- .../swap/review/SwapReviewScreen.tsx | 11 +- .../swap/settings/SlippageControl.tsx | 115 + .../swap/settings/SlippageWarningModal.tsx | 61 + .../swap/settings/SwapSettingsRow.tsx | 50 +- .../settings/TransactionSettingsModal.tsx | 70 +- .../settings/configs/ProtocolPreference.tsx | 44 +- .../swap/settings/configs/Slippage.native.tsx | 29 +- .../swap/settings/configs/Slippage.web.tsx | 127 +- .../configs/SlippageUpdate.native.tsx | 8 + .../swap/settings/configs/SlippageUpdate.tsx | 10 + .../settings/configs/SlippageUpdate.web.tsx | 24 + .../swap/settings/configs/types.ts | 6 + .../swap/settings/useSlippageSettings.ts | 68 +- .../swap/types/swapTxAndGasInfo.ts | 10 +- .../transactions/swap/utils/styleHelpers.ts | 18 + .../features/transactions/swap/utils/trade.ts | 1 + .../transactions/types/transactionDetails.ts | 3 +- .../transactions/types/transactionState.ts | 2 + .../src/i18n/locales/source/en-US.json | 47 +- .../src/i18n/locales/translations/af-ZA.json | 41 +- .../src/i18n/locales/translations/ar-SA.json | 41 +- .../src/i18n/locales/translations/ca-ES.json | 41 +- .../src/i18n/locales/translations/cs-CZ.json | 41 +- .../src/i18n/locales/translations/da-DK.json | 41 +- .../src/i18n/locales/translations/de-DE.json | 41 +- .../src/i18n/locales/translations/el-GR.json | 41 +- .../src/i18n/locales/translations/es-ES.json | 61 +- .../src/i18n/locales/translations/fi-FI.json | 41 +- .../src/i18n/locales/translations/fil-PH.json | 61 +- .../src/i18n/locales/translations/fr-FR.json | 41 +- .../src/i18n/locales/translations/he-IL.json | 41 +- .../src/i18n/locales/translations/hi-IN.json | 41 +- .../src/i18n/locales/translations/hu-HU.json | 41 +- .../src/i18n/locales/translations/id-ID.json | 41 +- .../src/i18n/locales/translations/it-IT.json | 41 +- .../src/i18n/locales/translations/ja-JP.json | 41 +- .../src/i18n/locales/translations/ko-KR.json | 63 +- .../src/i18n/locales/translations/ms-MY.json | 41 +- .../src/i18n/locales/translations/nl-NL.json | 237 +- .../src/i18n/locales/translations/no-NO.json | 41 +- .../src/i18n/locales/translations/pl-PL.json | 41 +- .../src/i18n/locales/translations/pt-PT.json | 227 +- .../src/i18n/locales/translations/ro-RO.json | 41 +- .../src/i18n/locales/translations/ru-RU.json | 61 +- .../src/i18n/locales/translations/sl-SI.json | 41 +- .../src/i18n/locales/translations/sr-SP.json | 41 +- .../src/i18n/locales/translations/sv-SE.json | 41 +- .../src/i18n/locales/translations/sw-TZ.json | 41 +- .../src/i18n/locales/translations/tr-TR.json | 61 +- .../src/i18n/locales/translations/uk-UA.json | 41 +- .../src/i18n/locales/translations/ur-PK.json | 41 +- .../src/i18n/locales/translations/vi-VN.json | 61 +- .../src/i18n/locales/translations/zh-CN.json | 59 +- .../src/i18n/locales/translations/zh-TW.json | 59 +- packages/uniswap/src/react-native-dotenv.d.ts | 1 + .../uniswap/src/state/uniswapMigrations.ts | 31 + packages/uniswap/src/state/uniswapReducer.ts | 2 + .../uniswap/src/test/fixtures/tradingApi.ts | 2 + .../src/test/fixtures/wallet/currencies.ts | 1 + .../cloud-backup/getCloudProviderName.ts | 4 +- packages/utilities/package.json | 2 +- .../utilities/src/environment/constants.ts | 3 +- packages/utilities/src/logger/logger.ts | 20 +- packages/utilities/src/react/delayUtils.ts | 23 + packages/wallet/jest-setup.js | 1 + packages/wallet/package.json | 2 +- .../AnimatedUnitagDisplayName.native.tsx | 162 + .../accounts/AnimatedUnitagDisplayName.tsx | 113 +- .../AnimatedUnitagDisplayName.web.tsx | 105 + .../src/components/introCards/IntroCard.tsx | 57 +- .../src/components/menu/ContextMenu.tsx | 12 +- .../nfts/NftViewWithContextMenu.web.tsx | 1 + .../wallet/src/features/fiatOnRamp/api.ts | 23 +- packages/wallet/src/features/gas/hooks.ts | 39 +- .../src/features/nfts/useNftContextMenu.tsx | 2 +- .../SummaryItems/CancelConfirmationView.tsx | 5 +- .../TransactionRequest/NetworkFeeFooter.tsx | 4 +- .../transactions/contexts/SendContext.tsx | 23 +- .../features/transactions/send/GasFeeRow.tsx | 4 +- .../transactions/send/SendReviewDetails.tsx | 43 +- .../transactions/swap/WalletSwapFlow.tsx | 3 +- .../transactions/transactionWatcherSaga.ts | 10 +- .../wallet/src/state/walletMigrationsTests.ts | 39 + yarn.lock | 2867 ++++++++++++----- 280 files changed, 9492 insertions(+), 5278 deletions(-) delete mode 100644 .yarn/patches/@wagmi-core-npm-2.6.16-1baef7c190.patch delete mode 100644 .yarn/patches/@web3-react-coinbase-wallet-npm-8.2.3-9c7073f079.patch delete mode 100644 .yarn/patches/@web3-react-gnosis-safe-npm-8.2.4-a7e2850335.patch delete mode 100644 .yarn/patches/@web3-react-metamask-npm-8.2.4-84b10de2d2.patch delete mode 100644 .yarn/patches/@web3-react-walletconnect-v2-npm-8.5.1-933cac0534.patch delete mode 100644 .yarn/patches/cypress-hardhat-npm-2.5.0-9b9b7d7a28.patch delete mode 100644 apps/mobile/src/app/DataDogProvider.tsx create mode 100644 apps/mobile/src/app/navigation/navigationRef.tsx create mode 100644 apps/mobile/src/features/deepLinking/handleOffRampReturnLinkSaga.ts create mode 100644 apps/mobile/src/features/notifications/hooks/useNotificationsToggle.test.ts create mode 100644 apps/mobile/src/features/notifications/hooks/useNotificationsToggle.ts create mode 100644 apps/mobile/src/features/testnetMode/TestnetSwitchModal.tsx create mode 100644 apps/mobile/src/features/testnetMode/TestnetSwitchModalState.ts create mode 100644 apps/web/.storybook/main.ts create mode 100644 apps/web/.storybook/preview.tsx create mode 100644 apps/web/src/components/Charts/LiquidityRangeInput/constants.ts delete mode 100644 apps/web/src/components/FiatOnrampModal/constants.ts delete mode 100644 apps/web/src/components/FiatOnrampModal/index.tsx delete mode 100644 apps/web/src/components/FiatOnrampModal/utils.test.ts delete mode 100644 apps/web/src/components/FiatOnrampModal/utils.ts create mode 100644 apps/web/src/state/migrations/21.test.ts create mode 100644 apps/web/src/state/migrations/21.ts create mode 100644 packages/ui/src/assets/icons/settings-warning.svg create mode 100644 packages/ui/src/assets/logos/png/monad-logo.png create mode 100644 packages/ui/src/components/button/Button.stories.tsx create mode 100644 packages/ui/src/components/icons/SettingsWarning.tsx create mode 100644 packages/ui/src/storybook/Spore.mdx delete mode 100644 packages/ui/src/storybook/constants.ts delete mode 100644 packages/ui/src/storybook/index.ts create mode 100644 packages/uniswap/src/components/WarningMessage/WarningMessage.tsx create mode 100644 packages/uniswap/src/components/modals/modalConstants.tsx create mode 100644 packages/uniswap/src/features/transactions/settings/selectors.ts create mode 100644 packages/uniswap/src/features/transactions/settings/slice.ts create mode 100644 packages/uniswap/src/features/transactions/swap/form/SwapFormSettingsButton.tsx create mode 100644 packages/uniswap/src/features/transactions/swap/settings/SlippageControl.tsx create mode 100644 packages/uniswap/src/features/transactions/swap/settings/SlippageWarningModal.tsx create mode 100644 packages/uniswap/src/features/transactions/swap/settings/configs/SlippageUpdate.native.tsx create mode 100644 packages/uniswap/src/features/transactions/swap/settings/configs/SlippageUpdate.tsx create mode 100644 packages/uniswap/src/features/transactions/swap/settings/configs/SlippageUpdate.web.tsx create mode 100644 packages/uniswap/src/features/transactions/swap/utils/styleHelpers.ts create mode 100644 packages/utilities/src/react/delayUtils.ts create mode 100644 packages/wallet/src/components/accounts/AnimatedUnitagDisplayName.native.tsx create mode 100644 packages/wallet/src/components/accounts/AnimatedUnitagDisplayName.web.tsx diff --git a/.yarn/patches/@wagmi-core-npm-2.6.16-1baef7c190.patch b/.yarn/patches/@wagmi-core-npm-2.6.16-1baef7c190.patch deleted file mode 100644 index 921345e6881..00000000000 --- a/.yarn/patches/@wagmi-core-npm-2.6.16-1baef7c190.patch +++ /dev/null @@ -1,23 +0,0 @@ -diff --git a/dist/esm/connectors/injected.js b/dist/esm/connectors/injected.js -index 26f420d68ed9a12deea30a3dca195e2bcf3b3c44..70fc93a7db7b9f4db10e71edd73ee81bd0e28f1e 100644 ---- a/dist/esm/connectors/injected.js -+++ b/dist/esm/connectors/injected.js -@@ -405,6 +405,18 @@ export function injected(parameters = {}) { - onChainChanged(chain) { - console.log('[injected] onChainChanged', chain); - const chainId = Number(chain); -+ if (this.id === 'io.metamask') -+ this.getProvider() -+ .then((provider) => -+ provider -+ ?.request({ -+ method: 'wallet_switchEthereumChain', -+ params: [{ chainId: numberToHex(chainId) }], -+ }) -+ .then(() => {}) -+ .catch(() => {}), -+ ) -+ .catch(() => {}) - config.emitter.emit('change', { chainId }); - }, - async onConnect(connectInfo) { diff --git a/.yarn/patches/@web3-react-coinbase-wallet-npm-8.2.3-9c7073f079.patch b/.yarn/patches/@web3-react-coinbase-wallet-npm-8.2.3-9c7073f079.patch deleted file mode 100644 index 2054baa454c..00000000000 --- a/.yarn/patches/@web3-react-coinbase-wallet-npm-8.2.3-9c7073f079.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/dist/index.js b/dist/index.js -index f38d06e2de52b5035560d63d6889dc54d5ca021b..4f8fa194b60c73a901dbce4a742f598b1c95c026 100644 ---- a/dist/index.js -+++ b/dist/index.js -@@ -62,7 +62,7 @@ class CoinbaseWallet extends types_1.Connector { - return __awaiter(this, void 0, void 0, function* () { - if (this.eagerConnection) - return; -- yield (this.eagerConnection = Promise.resolve().then(() => __importStar(require('@coinbase/wallet-sdk'))).then((m) => { -+ yield (this.eagerConnection = Promise.resolve().then(async () => __importStar(await import('@coinbase/wallet-sdk'))).then((m) => { - const _a = this.options, { url } = _a, options = __rest(_a, ["url"]); - this.coinbaseWallet = new m.default(options); - this.provider = this.coinbaseWallet.makeWeb3Provider(url); diff --git a/.yarn/patches/@web3-react-gnosis-safe-npm-8.2.4-a7e2850335.patch b/.yarn/patches/@web3-react-gnosis-safe-npm-8.2.4-a7e2850335.patch deleted file mode 100644 index f4a15fe2120..00000000000 --- a/.yarn/patches/@web3-react-gnosis-safe-npm-8.2.4-a7e2850335.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/dist/index.js b/dist/index.js -index 015a33c37fe87f13f31559d462351acd7ae9bac7..4cd7cdeb4437f30c1c063c0ffb8fd5692a399dbf 100644 ---- a/dist/index.js -+++ b/dist/index.js -@@ -68,8 +68,8 @@ class GnosisSafe extends types_1.Connector { - if (this.eagerConnection) - return; - // kick off import early to minimize waterfalls -- const SafeAppProviderPromise = Promise.resolve().then(() => __importStar(require('@safe-global/safe-apps-provider'))).then(({ SafeAppProvider }) => SafeAppProvider); -- yield (this.eagerConnection = Promise.resolve().then(() => __importStar(require('@safe-global/safe-apps-sdk'))).then((m) => __awaiter(this, void 0, void 0, function* () { -+ const SafeAppProviderPromise = Promise.resolve().then(async () => __importStar(await import('@safe-global/safe-apps-provider'))).then(({ SafeAppProvider }) => SafeAppProvider); -+ yield (this.eagerConnection = Promise.resolve().then(async () => __importStar(await import('@safe-global/safe-apps-sdk'))).then((m) => __awaiter(this, void 0, void 0, function* () { - this.sdk = new m.default(this.options); - const safe = yield Promise.race([ - this.sdk.safe.getInfo(), diff --git a/.yarn/patches/@web3-react-metamask-npm-8.2.4-84b10de2d2.patch b/.yarn/patches/@web3-react-metamask-npm-8.2.4-84b10de2d2.patch deleted file mode 100644 index f22a0f895bc..00000000000 --- a/.yarn/patches/@web3-react-metamask-npm-8.2.4-84b10de2d2.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/dist/index.js b/dist/index.js -index c8476dd9b01c0599dfc545f4c86432081bd0fcec..c0bfce759654232df771724e59a650c92b392f78 100644 ---- a/dist/index.js -+++ b/dist/index.js -@@ -54,7 +54,7 @@ class MetaMask extends types_1.Connector { - return __awaiter(this, void 0, void 0, function* () { - if (this.eagerConnection) - return; -- return (this.eagerConnection = Promise.resolve().then(() => __importStar(require('@metamask/detect-provider'))).then((m) => __awaiter(this, void 0, void 0, function* () { -+ return (this.eagerConnection = Promise.resolve().then(async () => __importStar(await import('@metamask/detect-provider'))).then((m) => __awaiter(this, void 0, void 0, function* () { - var _a, _b; - const provider = yield m.default(this.options); - if (provider) { diff --git a/.yarn/patches/@web3-react-walletconnect-v2-npm-8.5.1-933cac0534.patch b/.yarn/patches/@web3-react-walletconnect-v2-npm-8.5.1-933cac0534.patch deleted file mode 100644 index f42256f5302..00000000000 --- a/.yarn/patches/@web3-react-walletconnect-v2-npm-8.5.1-933cac0534.patch +++ /dev/null @@ -1,28 +0,0 @@ -diff --git a/dist/index.js b/dist/index.js -index 1a36d14c5d7c9ee55b2eccd11216c8adb6839daf..908b8c57a2d8cd565030e34e15c56caf7d182cfd 100644 ---- a/dist/index.js -+++ b/dist/index.js -@@ -84,7 +84,7 @@ class WalletConnect extends types_1.Connector { - return __awaiter(this, void 0, void 0, function* () { - const rpcMap = this.rpcMap ? (0, utils_1.getBestUrlMap)(this.rpcMap, this.timeout) : undefined; - const chainProps = this.getChainProps(this.chains, this.optionalChains, desiredChainId); -- const ethProviderModule = yield Promise.resolve().then(() => __importStar(require('@walletconnect/ethereum-provider'))); -+ const ethProviderModule = yield Promise.resolve().then(async () => __importStar(await import('@walletconnect/ethereum-provider'))); - this.provider = yield ethProviderModule.default.init(Object.assign(Object.assign(Object.assign({}, this.options), chainProps), { rpcMap: yield rpcMap })); - return this.provider - .on('disconnect', this.disconnectListener) -diff --git a/dist/utils.js b/dist/utils.js -index 17539b6f910e65aeaebcc116395dce56ae4ce193..9ea637118844ebbdc55db71009b44849992603d2 100644 ---- a/dist/utils.js -+++ b/dist/utils.js -@@ -62,8 +62,8 @@ function getBestUrl(urls, timeout) { - if (urls.length === 1) - return urls[0]; - const [HttpConnection, JsonRpcProvider] = yield Promise.all([ -- Promise.resolve().then(() => __importStar(require('@walletconnect/jsonrpc-http-connection'))).then(({ HttpConnection }) => HttpConnection), -- Promise.resolve().then(() => __importStar(require('@walletconnect/jsonrpc-provider'))).then(({ JsonRpcProvider }) => JsonRpcProvider), -+ Promise.resolve().then(async () => __importStar(await import('@walletconnect/jsonrpc-http-connection'))).then(({ HttpConnection }) => HttpConnection), -+ Promise.resolve().then(async () => __importStar(await import('@walletconnect/jsonrpc-provider'))).then(({ JsonRpcProvider }) => JsonRpcProvider), - ]); - // the below returns the first url for which there's been a successful call, prioritized by index - return new Promise((resolve) => { diff --git a/.yarn/patches/cypress-hardhat-npm-2.5.0-9b9b7d7a28.patch b/.yarn/patches/cypress-hardhat-npm-2.5.0-9b9b7d7a28.patch deleted file mode 100644 index 63b7c169414..00000000000 --- a/.yarn/patches/cypress-hardhat-npm-2.5.0-9b9b7d7a28.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/lib/browser/eip1193.js b/lib/browser/eip1193.js -index ce028c25a164d8af8d513bc0eae4cf104234f6e8..81ba2f29d379f18c04c57b5a560cc6c4f4b57e0d 100644 ---- a/lib/browser/eip1193.js -+++ b/lib/browser/eip1193.js -@@ -70,6 +70,7 @@ class Eip1193 extends eip1193_bridge_1.Eip1193Bridge { - yield _super.send.call(this, method, params); - // Providers will not "rewind" to an older block number nor notice chain changes, so they must be reset. - this.utils.providers.forEach((provider) => provider.reset()); -+ this.emit('chainChanged', params[0].chainId); - break; - default: - result = yield _super.send.call(this, method, params); diff --git a/RELEASE b/RELEASE index 223f0314dbf..f10d2efac9e 100644 --- a/RELEASE +++ b/RELEASE @@ -1,6 +1,6 @@ IPFS hash of the deployment: -- CIDv0: `QmYVT8bXNHTgPdSTegLQ62Z6f7E51fQbeMvn2nJAxMRGBE` -- CIDv1: `bafybeiew2yawtry3lld6g5ankyq3bsbvjfchxxhboph45u6os6t2babtru` +- CIDv0: `QmP8VRKK9FDri6XhqC8xNCXJTRqbfWmiF7jTdaDBJbt3uv` +- CIDv1: `bafybeialxy3kyi4xjtgo4u3a6k7gpt76j3y77m3cucofzbjxlegxfzufpu` The latest release is always mirrored at [app.uniswap.org](https://app.uniswap.org). @@ -10,15 +10,52 @@ You can also access the Uniswap Interface from an IPFS gateway. Your Uniswap settings are never remembered across different URLs. IPFS gateways: -- https://bafybeiew2yawtry3lld6g5ankyq3bsbvjfchxxhboph45u6os6t2babtru.ipfs.dweb.link/ -- https://bafybeiew2yawtry3lld6g5ankyq3bsbvjfchxxhboph45u6os6t2babtru.ipfs.cf-ipfs.com/ -- [ipfs://QmYVT8bXNHTgPdSTegLQ62Z6f7E51fQbeMvn2nJAxMRGBE/](ipfs://QmYVT8bXNHTgPdSTegLQ62Z6f7E51fQbeMvn2nJAxMRGBE/) +- https://bafybeialxy3kyi4xjtgo4u3a6k7gpt76j3y77m3cucofzbjxlegxfzufpu.ipfs.dweb.link/ +- https://bafybeialxy3kyi4xjtgo4u3a6k7gpt76j3y77m3cucofzbjxlegxfzufpu.ipfs.cf-ipfs.com/ +- [ipfs://QmP8VRKK9FDri6XhqC8xNCXJTRqbfWmiF7jTdaDBJbt3uv/](ipfs://QmP8VRKK9FDri6XhqC8xNCXJTRqbfWmiF7jTdaDBJbt3uv/) -### 5.62.4 (2024-12-16) +## 5.63.0 (2024-12-17) + + +### Features + +* **web:** add indicators for % difference from current price (#14235) 6456766 +* **web:** add more interactivity to range input price chart (#14153) f9c4680 +* **web:** filter v2 unsupported chains from LP creation flow (#14462) 734a4e2 +* **web:** mweb designs for price range input (#14424) 2277e82 +* **web:** pool finder redesign and re-enable on new LP pages (#14451) d55c7ea +* **web:** Revise "unavailable" state for small price charts (#14311) aba0989 ### Bug Fixes -* **web:** fix disabled swap button for previously-dismissed warning tokens (#14560) 2b04e71 +* **web:** 12 16 fix web add monad testnet rpc to web env staging (#14564) 588d8bb +* **web:** check window.__DEV__ cypress fix (#14491) a885720 +* **web:** cherry-pick pagination into staging (#14551) 3920adf +* **web:** cleanup unused legacy FOR modal (#14356) 302b4f3 +* **web:** Conversion API updates (#14550) 242f8da +* **web:** downgrade react-native-web to 0.19.10 (#14473) 010b773 +* **web:** enforce privacy opt out choices (#14374) 9760922 +* **web:** fix broken link for providing lps (#14372) 7c06390 +* **web:** fix current price inversion issue (#14445) 3fe1286 +* **web:** fix disabled swap button for previously-dismissed warning tokens (#14559) 4868b63 +* **web:** fix missing mweb swap - staging (#14580) d8f6631 +* **web:** fix v2 lp create networks (#14578) ef585ef +* **web:** hide un-owned positions (#14447) 742e519 +* **web:** hiding migrate to v4 (#14499) 98825bb +* **web:** lp links open in new tabs - staging (#14571) bdc1de5 +* **web:** modal diet - part ii (#14364) 5e22130 +* **web:** prevent crash when sending on bnb chain (#14355) b47fc90 +* **web:** price range input - prevent scrolling below zero (#14316) e4e37b4 +* **web:** staging cherrypicks - tooltip + position page crash (#14581) d94f7f9 +* **web:** surface imported v2 positions (#14405) a3519b4 +* **web:** truncation issue on mad price text positions (#14582) 78038ed +* **web:** update the create flow to get data from the sdk instead of from the backend (#14380) 50ab440 +* **web:** wrap positions in multichain context (#14466) bc07af4 + + +### Continuous Integration + +* **web:** update sitemaps 721fc2d diff --git a/VERSION b/VERSION index a3f11c0dd6c..732f7aa60d8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -web/5.62.4 \ No newline at end of file +web/5.63.0 \ No newline at end of file diff --git a/apps/extension/.depcheckrc b/apps/extension/.depcheckrc index ed92562bf95..b8b3c787d08 100644 --- a/apps/extension/.depcheckrc +++ b/apps/extension/.depcheckrc @@ -1,17 +1,19 @@ ignores: [ # Dependencies that depcheck thinks are unused but are actually used - "react-native-web", - "jest-environment-jsdom", - "webpack-cli", + 'react-native-web', + 'jest-environment-jsdom', + 'webpack-cli', # Dependencies that depcheck thinks are missing but are actually present or never used ## Internal packages / workspaces - "src", - "tsconfig", + 'src', + 'tsconfig', # Webpack plugins - "@svgr/webpack", - "tamagui-loader", - "esbuild-loader", - "swc-loader", + '@svgr/webpack', + 'tamagui-loader', + 'esbuild-loader', + 'style-loader', + 'css-loader', + 'swc-loader', ## Testing - "@testing-library/dom", + '@testing-library/dom', ] diff --git a/apps/extension/package.json b/apps/extension/package.json index 158e94a6aee..7814d61044d 100644 --- a/apps/extension/package.json +++ b/apps/extension/package.json @@ -67,6 +67,7 @@ "clean-webpack-plugin": "4.0.0", "concurrently": "8.2.2", "copy-webpack-plugin": "11.0.0", + "css-loader": "6.11.0", "esbuild-loader": "3.2.0", "eslint": "8.44.0", "jest": "29.7.0", @@ -77,6 +78,7 @@ "react-refresh": "0.14.0", "serve": "14.2.4", "statsig-js": "4.41.0", + "style-loader": "3.3.2", "swc-loader": "0.2.6", "tamagui-loader": "1.114.4", "typescript": "5.3.3", diff --git a/apps/extension/src/app/datadog.ts b/apps/extension/src/app/datadog.ts index fc6efd19243..2ea7c2d802a 100644 --- a/apps/extension/src/app/datadog.ts +++ b/apps/extension/src/app/datadog.ts @@ -12,7 +12,7 @@ export async function initializeDatadog(appName: string): Promise { const datadogEnabled = Statsig.checkGate(getFeatureFlagName(FeatureFlags.Datadog)) logger.setWalletDatadogEnabled(datadogEnabled) - if (__DEV__ || !datadogEnabled) { + if (!datadogEnabled) { return } diff --git a/apps/extension/src/app/features/dappRequests/requestContent/WrapContent.tsx b/apps/extension/src/app/features/dappRequests/requestContent/WrapContent.tsx index 5762d3a88ed..a7f47740334 100644 --- a/apps/extension/src/app/features/dappRequests/requestContent/WrapContent.tsx +++ b/apps/extension/src/app/features/dappRequests/requestContent/WrapContent.tsx @@ -5,7 +5,7 @@ import { DappRequestStoreItem } from 'src/app/features/dappRequests/slice' import { SendTransactionRequest } from 'src/app/features/dappRequests/types/DappRequestTypes' import { Flex, Text } from 'ui/src' import { useEnabledChains } from 'uniswap/src/features/chains/hooks/useEnabledChains' -import { useGasFeeFormattedAmounts, useTransactionGasFee } from 'uniswap/src/features/gas/hooks' +import { useGasFeeFormattedDisplayAmounts, useTransactionGasFee } from 'uniswap/src/features/gas/hooks' import { useActiveAccountAddressWithThrow, useDisplayName } from 'wallet/src/features/wallet/hooks' export const WrapTransactionDetails = ({ @@ -31,7 +31,7 @@ export const WrapTransactionDetails = ({ const networkFee = useTransactionGasFee(txRequest) - const { gasFeeFormatted } = useGasFeeFormattedAmounts({ + const { gasFeeFormatted } = useGasFeeFormattedDisplayAmounts({ gasFee: networkFee, chainId, placeholder: undefined, diff --git a/apps/extension/src/app/features/settings/SettingsScreen.tsx b/apps/extension/src/app/features/settings/SettingsScreen.tsx index a4af469e930..48337b1f046 100644 --- a/apps/extension/src/app/features/settings/SettingsScreen.tsx +++ b/apps/extension/src/app/features/settings/SettingsScreen.tsx @@ -92,6 +92,7 @@ export function SettingsScreen(): JSX.Element { const fireAnalytic = (): void => { sendAnalyticsEvent(WalletEventName.TestnetModeToggled, { enabled: isChecked, + location: 'settings', }) } diff --git a/apps/extension/src/manifest.json b/apps/extension/src/manifest.json index 64271eebab1..33f57f72dc8 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.12.0", + "version": "1.13.0", "minimum_chrome_version": "116", "icons": { "16": "assets/icon16.png", diff --git a/apps/extension/src/store/migrations.test.ts b/apps/extension/src/store/migrations.test.ts index cbd05dd0391..e41401ef06e 100644 --- a/apps/extension/src/store/migrations.test.ts +++ b/apps/extension/src/store/migrations.test.ts @@ -12,6 +12,7 @@ import { v14Schema, v15Schema, v16Schema, + v17Schema, v1Schema, v2Schema, v3Schema, @@ -48,6 +49,7 @@ import { testMovedUserSettings, testRemoveCreatedOnboardingRedesignAccount, testRemoveHoldToSwap, + testUnchecksumDismissedTokenWarningKeys, testUpdateExploreOrderByType, } from 'wallet/src/state/walletMigrationsTests' @@ -274,4 +276,8 @@ describe('Redux state migrations', () => { it('migrates from v16 to v17', async () => { testRemoveCreatedOnboardingRedesignAccount(migrations[17], v16Schema) }) + + it('migrates from v17 to v18', () => { + testUnchecksumDismissedTokenWarningKeys(migrations[18], v17Schema) + }) }) diff --git a/apps/extension/src/store/migrations.ts b/apps/extension/src/store/migrations.ts index e074421c3a8..1367de1b044 100644 --- a/apps/extension/src/store/migrations.ts +++ b/apps/extension/src/store/migrations.ts @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/explicit-function-return-type */ +import { unchecksumDismissedTokenWarningKeys } from 'uniswap/src/state/uniswapMigrations' import { activatePendingAccounts, addCreatedOnboardingRedesignAccountBehaviorHistory, @@ -42,6 +43,7 @@ export const migrations = { 15: moveCurrencySetting, 16: updateExploreOrderByType, 17: removeCreatedOnboardingRedesignAccountBehaviorHistory, + 18: unchecksumDismissedTokenWarningKeys, } -export const EXTENSION_STATE_VERSION = 17 +export const EXTENSION_STATE_VERSION = 18 diff --git a/apps/mobile/.storybook/storybook.requires.ts b/apps/mobile/.storybook/storybook.requires.ts index 5201a653a29..b6e8c593d2b 100644 --- a/apps/mobile/.storybook/storybook.requires.ts +++ b/apps/mobile/.storybook/storybook.requires.ts @@ -31,6 +31,19 @@ const normalizedStories = [ /^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.stories\.(?:ts|tsx|js|jsx)?)$/ ), }, + { + titlePrefix: "", + directory: "../../packages/ui/src", + files: "**/*.mdx", + importPathMatcher: + /^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.mdx)$/, + // @ts-ignore + req: require.context( + "../../../packages/ui/src", + true, + /^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.mdx)$/ + ), + }, ]; declare global { diff --git a/apps/mobile/android/app/build.gradle b/apps/mobile/android/app/build.gradle index e79271691a0..f8ec19dde60 100644 --- a/apps/mobile/android/app/build.gradle +++ b/apps/mobile/android/app/build.gradle @@ -89,9 +89,9 @@ if (isCI && datadogPropertiesAvailable && !isDetox) { apply from: "../../../../node_modules/@datadog/mobile-react-native/datadog-sourcemaps.gradle" } -def devVersionName = "1.42" -def betaVersionName = "1.42" -def prodVersionName = "1.42" +def devVersionName = "1.43" +def betaVersionName = "1.43" +def prodVersionName = "1.43" android { ndkVersion rootProject.ext.ndkVersion diff --git a/apps/mobile/ios/Uniswap.xcodeproj/project.pbxproj b/apps/mobile/ios/Uniswap.xcodeproj/project.pbxproj index bb9b6982970..0eccb352a9c 100644 --- a/apps/mobile/ios/Uniswap.xcodeproj/project.pbxproj +++ b/apps/mobile/ios/Uniswap.xcodeproj/project.pbxproj @@ -2204,7 +2204,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; @@ -2257,7 +2257,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = schemes.WidgetsCore; @@ -2310,7 +2310,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = schemes.WidgetsCore; @@ -2363,7 +2363,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = schemes.WidgetsCore; @@ -2401,7 +2401,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; @@ -2437,7 +2437,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = schemes.WidgetsCoreTests; @@ -2472,7 +2472,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = schemes.WidgetsCoreTests; @@ -2507,7 +2507,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = schemes.WidgetsCoreTests; @@ -2554,7 +2554,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; @@ -2600,7 +2600,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.widgets; @@ -2646,7 +2646,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.dev.widgets; @@ -2692,7 +2692,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.beta.widgets; @@ -2734,7 +2734,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; @@ -2777,7 +2777,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.WidgetIntentExtension; @@ -2820,7 +2820,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.dev.WidgetIntentExtension; @@ -2863,7 +2863,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.beta.WidgetIntentExtension; @@ -2899,7 +2899,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -2937,7 +2937,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -3137,7 +3137,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; @@ -3181,7 +3181,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.OneSignalNotificationServiceExtension; @@ -3292,7 +3292,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -3363,7 +3363,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.beta.OneSignalNotificationServiceExtension; @@ -3474,7 +3474,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -3545,7 +3545,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.42; + MARKETING_VERSION = 1.43; 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/package.json b/apps/mobile/package.json index 0d86521b298..d17bc474311 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -33,7 +33,7 @@ "firestore:deploy:rules": "firebase deploy --only firestore:rules", "link:assets": "react-native-asset", "graphql:generate:swift": "cd ios && ./Pods/Apollo/apollo-ios-cli generate", - "check:circular": "../../scripts/check-circular-imports.sh ./src/app/App.tsx 8", + "check:circular": "../../scripts/check-circular-imports.sh ./src/app/App.tsx 2", "ios": "yarn ios:prebuild && SKIP_BUNDLING=1 react-native run-ios", "ios:prebuild": "yarn graphql:generate:swift && cd ios/WidgetsCore/MobileSchema && rm -rf !(README.md) && cd ../../.. && yarn graphql:generate:swift && yarn env:local:copy:swift", "ios:smol": "SKIP_BUNDLING=1 react-native run-ios --simulator=\"iPhone SE (3rd generation)\"", @@ -87,11 +87,12 @@ "@shopify/react-native-performance-navigation": "3.0.0", "@shopify/react-native-skia": "1.4.2", "@sparkfabrik/react-native-idfa-aaid": "1.2.0", + "@tanstack/react-query": "5.51.16", "@uniswap/analytics": "1.7.0", "@uniswap/analytics-events": "2.40.0", "@uniswap/client-explore": "0.0.12", "@uniswap/ethers-rs-mobile": "0.0.5", - "@uniswap/sdk-core": "6.0.0", + "@uniswap/sdk-core": "6.1.0", "@walletconnect/core": "2.17.1", "@walletconnect/react-native-compat": "2.17.1", "@walletconnect/utils": "2.17.1", diff --git a/apps/mobile/src/app/App.tsx b/apps/mobile/src/app/App.tsx index f422b6d78c8..21be7e3e89a 100644 --- a/apps/mobile/src/app/App.tsx +++ b/apps/mobile/src/app/App.tsx @@ -15,7 +15,7 @@ import { SafeAreaProvider } from 'react-native-safe-area-context' import { enableFreeze } from 'react-native-screens' import { useDispatch, useSelector } from 'react-redux' import { PersistGate } from 'redux-persist/integration/react' -import { DatadogProviderWrapper } from 'src/app/DataDogProvider' +import { DatadogProviderWrapper } from 'src/app/DatadogProviderWrapper' import { MobileWalletNavigationProvider } from 'src/app/MobileWalletNavigationProvider' import { AppModals } from 'src/app/modals/AppModals' import { NavigationContainer } from 'src/app/navigation/NavigationContainer' diff --git a/apps/mobile/src/app/DataDogProvider.tsx b/apps/mobile/src/app/DataDogProvider.tsx deleted file mode 100644 index 10608710059..00000000000 --- a/apps/mobile/src/app/DataDogProvider.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { - BatchSize, - DatadogProvider, - DatadogProviderConfiguration, - SdkVerbosity, - TrackingConsent, - UploadFrequency, -} from '@datadog/mobile-react-native' -import { ErrorEventMapper } from '@datadog/mobile-react-native/lib/typescript/rum/eventMappers/errorEventMapper' -import { PropsWithChildren, default as React } from 'react' -import { getDatadogEnvironment } from 'src/utils/version' -import { config } from 'uniswap/src/config' -import { isDetoxBuild, isJestRun, localDevDatadogEnabled } from 'utilities/src/environment/constants' -import { logger } from 'utilities/src/logger/logger' - -const ENABLE_DATADOG = localDevDatadogEnabled || !__DEV__ - -const datadogConfig = new DatadogProviderConfiguration( - config.datadogClientToken, - getDatadogEnvironment(), - config.datadogProjectId, - ENABLE_DATADOG, // trackInteractions - ENABLE_DATADOG, // trackResources - ENABLE_DATADOG, // trackErrors - localDevDatadogEnabled ? TrackingConsent.GRANTED : undefined, -) - -Object.assign(datadogConfig, { - site: 'US1', - longTaskThresholdMs: 100, - nativeCrashReportEnabled: true, - verbosity: SdkVerbosity.INFO, - errorEventMapper: (event: ReturnType) => { - // this is Sentry error, which is caused by the not complete closing of their SDK - if (event?.message.includes('Native is disabled')) { - return null - } - return event - }, -}) - -if (localDevDatadogEnabled) { - Object.assign(datadogConfig, { - sessionSamplingRate: 100, - resourceTracingSamplingRate: 100, - uploadFrequency: UploadFrequency.FREQUENT, - batchSize: BatchSize.SMALL, - verbosity: SdkVerbosity.DEBUG, - }) -} - -/** - * Wrapper component to provide Datadog to the app with our mobile app's - * specific configuration. - */ -export function DatadogProviderWrapper({ children }: PropsWithChildren): JSX.Element { - logger.setWalletDatadogEnabled(true) - - if (isDetoxBuild || isJestRun) { - return <>{children} - } - return {children} -} diff --git a/apps/mobile/src/app/DatadogProviderWrapper.tsx b/apps/mobile/src/app/DatadogProviderWrapper.tsx index 10608710059..368e7195fff 100644 --- a/apps/mobile/src/app/DatadogProviderWrapper.tsx +++ b/apps/mobile/src/app/DatadogProviderWrapper.tsx @@ -10,18 +10,16 @@ import { ErrorEventMapper } from '@datadog/mobile-react-native/lib/typescript/ru import { PropsWithChildren, default as React } from 'react' import { getDatadogEnvironment } from 'src/utils/version' import { config } from 'uniswap/src/config' -import { isDetoxBuild, isJestRun, localDevDatadogEnabled } from 'utilities/src/environment/constants' +import { datadogEnabled, isDetoxBuild, isJestRun, localDevDatadogEnabled } from 'utilities/src/environment/constants' import { logger } from 'utilities/src/logger/logger' -const ENABLE_DATADOG = localDevDatadogEnabled || !__DEV__ - const datadogConfig = new DatadogProviderConfiguration( config.datadogClientToken, getDatadogEnvironment(), config.datadogProjectId, - ENABLE_DATADOG, // trackInteractions - ENABLE_DATADOG, // trackResources - ENABLE_DATADOG, // trackErrors + datadogEnabled, // trackInteractions + datadogEnabled, // trackResources + datadogEnabled, // trackErrors localDevDatadogEnabled ? TrackingConsent.GRANTED : undefined, ) diff --git a/apps/mobile/src/app/migrations.test.ts b/apps/mobile/src/app/migrations.test.ts index 07f9a74994b..5f40178538b 100644 --- a/apps/mobile/src/app/migrations.test.ts +++ b/apps/mobile/src/app/migrations.test.ts @@ -83,6 +83,7 @@ import { v79Schema, v7Schema, v80Schema, + v81Schema, v8Schema, v9Schema, } from 'src/app/schema' @@ -125,6 +126,7 @@ import { testMovedUserSettings, testRemoveCreatedOnboardingRedesignAccount, testRemoveHoldToSwap, + testUnchecksumDismissedTokenWarningKeys, testUpdateExploreOrderByType, } from 'wallet/src/state/walletMigrationsTests' import { signerMnemonicAccount } from 'wallet/src/test/fixtures' @@ -1592,4 +1594,8 @@ describe('Redux state migrations', () => { it('migrates from v80 to v81', async () => { testRemoveCreatedOnboardingRedesignAccount(migrations[81], v80Schema) }) + + it('migrates from v81 to v82', () => { + testUnchecksumDismissedTokenWarningKeys(migrations[82], v81Schema) + }) }) diff --git a/apps/mobile/src/app/migrations.ts b/apps/mobile/src/app/migrations.ts index 58a391e55df..dd3810be448 100644 --- a/apps/mobile/src/app/migrations.ts +++ b/apps/mobile/src/app/migrations.ts @@ -16,6 +16,7 @@ import { TransactionStatus, TransactionType, } from 'uniswap/src/features/transactions/types/transactionDetails' +import { unchecksumDismissedTokenWarningKeys } from 'uniswap/src/state/uniswapMigrations' import { getNFTAssetKey } from 'wallet/src/features/nfts/utils' import { Account } from 'wallet/src/features/wallet/accounts/types' import { SwapProtectionSetting } from 'wallet/src/features/wallet/slice' @@ -954,6 +955,8 @@ export const migrations = { 80: updateExploreOrderByType, 81: removeCreatedOnboardingRedesignAccountBehaviorHistory, + + 82: unchecksumDismissedTokenWarningKeys, } -export const MOBILE_STATE_VERSION = 81 +export const MOBILE_STATE_VERSION = 82 diff --git a/apps/mobile/src/app/modals/AppModals.tsx b/apps/mobile/src/app/modals/AppModals.tsx index 8f07874a1be..d71dcfbcd79 100644 --- a/apps/mobile/src/app/modals/AppModals.tsx +++ b/apps/mobile/src/app/modals/AppModals.tsx @@ -21,6 +21,7 @@ import { ExchangeTransferModal } from 'src/features/fiatOnRamp/ExchangeTransferM import { FiatOnRampAggregatorModal } from 'src/features/fiatOnRamp/FiatOnRampAggregatorModal' import { closeModal } from 'src/features/modals/modalSlice' import { ScantasticModal } from 'src/features/scantastic/ScantasticModal' +import { TestnetSwitchModal } from 'src/features/testnetMode/TestnetSwitchModal' import { ReceiveCryptoModal } from 'src/screens/ReceiveCryptoModal' import { SettingsFiatCurrencyModal } from 'src/screens/SettingsFiatCurrencyModal' import { ModalName } from 'uniswap/src/features/telemetry/constants' @@ -119,6 +120,10 @@ export function AppModals(): JSX.Element { + + + + ) } diff --git a/apps/mobile/src/app/navigation/NavigationContainer.tsx b/apps/mobile/src/app/navigation/NavigationContainer.tsx index 7a92b9424fd..fdea0bbca9e 100644 --- a/apps/mobile/src/app/navigation/NavigationContainer.tsx +++ b/apps/mobile/src/app/navigation/NavigationContainer.tsx @@ -1,6 +1,5 @@ import { DdRumReactNavigationTracking } from '@datadog/mobile-react-navigation' import { - createNavigationContainerRef, DefaultTheme, NavigationContainer as NativeNavigationContainer, NavigationContainerRefWithCurrent, @@ -9,6 +8,7 @@ import { SharedEventName } from '@uniswap/analytics-events' import React, { FC, PropsWithChildren, useCallback, useState } from 'react' import { Linking } from 'react-native' import { useDispatch } from 'react-redux' +import { navigationRef } from 'src/app/navigation/navigationRef' import { RootParamList } from 'src/app/navigation/types' import { openDeepLink } from 'src/features/deepLinking/handleDeepLinkSaga' import { DIRECT_LOG_ONLY_SCREENS } from 'src/features/telemetry/directLogScreens' @@ -18,6 +18,7 @@ import { useSporeColors } from 'ui/src' import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import Trace from 'uniswap/src/features/telemetry/Trace' import { MobileNavScreen } from 'uniswap/src/types/screens/mobile' +import { datadogEnabled } from 'utilities/src/environment/constants' import { useAsyncData } from 'utilities/src/react/hooks' import { sleep } from 'utilities/src/time/timing' @@ -25,8 +26,6 @@ interface Props { onReady?: (navigationRef: NavigationContainerRefWithCurrent) => void } -export const navigationRef = createNavigationContainerRef() - /** Wrapped `NavigationContainer` with telemetry tracing. */ export const NavigationContainer: FC> = ({ children, onReady }: PropsWithChildren) => { const colors = useSporeColors() @@ -54,7 +53,7 @@ export const NavigationContainer: FC> = ({ children, on const initialRoute = navigationRef.getCurrentRoute()?.name as MobileNavScreen setRouteName(initialRoute) - if (!__DEV__) { + if (datadogEnabled) { DdRumReactNavigationTracking.startTrackingViews(navigationRef.current) } }} diff --git a/apps/mobile/src/app/navigation/navigation.tsx b/apps/mobile/src/app/navigation/navigation.tsx index 4c3613c6037..5ce3bcac673 100644 --- a/apps/mobile/src/app/navigation/navigation.tsx +++ b/apps/mobile/src/app/navigation/navigation.tsx @@ -1,12 +1,18 @@ -import { NavigationContainer, createNavigationContainerRef } from '@react-navigation/native' +import { DdRumReactNavigationTracking } from '@datadog/mobile-react-navigation' +import { + NavigationContainer, + NavigationContainerRefWithCurrent, + NavigationState, + createNavigationContainerRef, +} from '@react-navigation/native' import { createNativeStackNavigator } from '@react-navigation/native-stack' import { TransitionPresets, createStackNavigator } from '@react-navigation/stack' import React, { useEffect } from 'react' import { DevSettings } from 'react-native' import { useSelector } from 'react-redux' import StorybookUIRoot from 'src/../.storybook' -import { navigationRef } from 'src/app/navigation/NavigationContainer' import { renderHeaderBackButton, renderHeaderBackImage } from 'src/app/navigation/components' +import { navigationRef } from 'src/app/navigation/navigationRef' import { AppStackParamList, AppStackScreenProp, @@ -79,6 +85,7 @@ import { UnitagScreens, UnitagStackParamList, } from 'uniswap/src/types/screens/mobile' +import { datadogEnabled } from 'utilities/src/environment/constants' import { isDevEnv } from 'utilities/src/environment/env' import { OnboardingContextProvider } from 'wallet/src/features/onboarding/OnboardingContext' import { useActiveAccountWithThrow } from 'wallet/src/features/wallet/hooks' @@ -138,6 +145,45 @@ export function WrappedHomeScreen(props: AppStackScreenProp) } export const exploreNavigationRef = createNavigationContainerRef() +const fiatOnRampNavigationRef = createNavigationContainerRef() +const navRefs = [exploreNavigationRef, fiatOnRampNavigationRef, navigationRef] + +/** + * Since we are using multiple navigation containers, we need to start and stop tracking views + * manually since multiple nav containers are not supported by the Datadog RUM. + * + * https://docs.datadoghq.com/real_user_monitoring/mobile_and_tv_monitoring/integrated_libraries/reactnative/#track-view-navigation + */ +const startTracking = ( + navRefToStartTracking: NavigationContainerRefWithCurrent, +): void => { + if (!datadogEnabled) { + return + } + navRefs.forEach((navRef) => { + DdRumReactNavigationTracking.stopTrackingViews(navRef.current) + }) + DdRumReactNavigationTracking.startTrackingViews(navRefToStartTracking.current) +} + +/** + * Since we are using multiple navigation containers, we need to start and stop tracking views + * manually since multiple nav containers are not supported by the Datadog RUM. + * + * https://docs.datadoghq.com/real_user_monitoring/mobile_and_tv_monitoring/integrated_libraries/reactnative/#track-view-navigation + */ +const stopTracking = (state: NavigationState | undefined): void => { + if (!datadogEnabled) { + return + } + const navContainerIsClosing = !state || state.routes.length === 0 + if (navContainerIsClosing) { + navRefs.forEach((navRef) => { + DdRumReactNavigationTracking.stopTrackingViews(navRef.current) + }) + DdRumReactNavigationTracking.startTrackingViews(navigationRef.current) + } +} export function ExploreStackNavigator(): JSX.Element { const colors = useSporeColors() @@ -145,7 +191,7 @@ export function ExploreStackNavigator(): JSX.Element { return ( startTracking(exploreNavigationRef)} > + startTracking(fiatOnRampNavigationRef)} + onStateChange={stopTracking} + > [0]>> function _AssociatedAccountsList({ accounts }: { accounts: Account[] }): JSX.Element { @@ -26,17 +32,27 @@ function _AssociatedAccountsList({ accounts }: { accounts: Account[] }): JSX.Ele .filter((portfolio): portfolio is Portfolio => Boolean(portfolio)) .map((portfolio) => ({ address: portfolio.ownerAddress, - balance: portfolio.tokensTotalDenominatedValue?.value, + balance: portfolio.tokensTotalDenominatedValue?.value ?? 0, })) - .sort((a, b) => (b.balance ?? 0) - (a.balance ?? 0)) + .sort((a, b) => b.balance - a.balance) - // set max height to around 30% screen size, so we always cut the last visible element - // this way user is aware if there are more elements to see const accountsScrollViewHeight = Math.floor((fullHeight * 0.3) / ADDRESS_ROW_HEIGHT) * ADDRESS_ROW_HEIGHT + ADDRESS_ROW_HEIGHT / 2 + spacing.spacing12 // 12 is the ScrollView vertical padding + const renderItem = ({ item, index }: { item: SortedAddressData; index: number }): JSX.Element => { + return ( + + ) + } + return ( - - {sortedAddressesByBalance.map(({ address, balance }, index) => ( - - ))} - + item.address} + renderItem={renderItem} + bounces={false} + contentContainerStyle={[styles.accounts, { paddingBottom: spacing.spacing12 }]} + keyboardShouldPersistTaps="handled" + /> ) } diff --git a/apps/mobile/src/components/accounts/AccountHeader.test.tsx b/apps/mobile/src/components/accounts/AccountHeader.test.tsx index 19e4c626d84..2c7b9224e28 100644 --- a/apps/mobile/src/components/accounts/AccountHeader.test.tsx +++ b/apps/mobile/src/components/accounts/AccountHeader.test.tsx @@ -2,7 +2,7 @@ import * as ExpoClipboard from 'expo-clipboard' import { State } from 'react-native-gesture-handler' import { fireGestureHandler, getByGestureTestId } from 'react-native-gesture-handler/jest-utils' import { MobileState } from 'src/app/mobileReducer' -import { navigationRef } from 'src/app/navigation/NavigationContainer' +import { navigationRef } from 'src/app/navigation/navigationRef' import { AccountHeader } from 'src/components/accounts/AccountHeader' import { fireEvent, render, screen, waitFor, within } from 'src/test/test-utils' import { ModalName } from 'uniswap/src/features/telemetry/constants' diff --git a/apps/mobile/src/components/accounts/AccountHeader.tsx b/apps/mobile/src/components/accounts/AccountHeader.tsx index 9a90df22827..f2a99fb47d4 100644 --- a/apps/mobile/src/components/accounts/AccountHeader.tsx +++ b/apps/mobile/src/components/accounts/AccountHeader.tsx @@ -5,8 +5,9 @@ import Animated, { runOnJS, useAnimatedStyle, useSharedValue, withDelay, withTim import { useDispatch } from 'react-redux' import { navigate } from 'src/app/navigation/rootNavigation' import { openModal } from 'src/features/modals/modalSlice' +import { removePendingSession } from 'src/features/walletConnect/walletConnectSlice' import { Flex, Text, TouchableArea } from 'ui/src' -import { CopyAlt, Settings } from 'ui/src/components/icons' +import { CopyAlt, ScanHome, Settings } from 'ui/src/components/icons' import { AccountType } from 'uniswap/src/features/accounts/types' import { useAvatar } from 'uniswap/src/features/address/avatar' import { pushNotification } from 'uniswap/src/features/notifications/slice' @@ -20,12 +21,16 @@ import { sanitizeAddressText } from 'uniswap/src/utils/addresses' import { setClipboard } from 'uniswap/src/utils/clipboard' import { shortenAddress } from 'utilities/src/addresses' import { isDevEnv } from 'utilities/src/environment/env' +import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants' import { AccountIcon } from 'wallet/src/components/accounts/AccountIcon' import { AnimatedUnitagDisplayName } from 'wallet/src/components/accounts/AnimatedUnitagDisplayName' import useIsFocused from 'wallet/src/features/focus/useIsFocused' import { useActiveAccount, useActiveAccountAddress, useDisplayName } from 'wallet/src/features/wallet/hooks' import { DisplayNameType } from 'wallet/src/features/wallet/types' +// Value comes from https://uniswapteam.slack.com/archives/C083LU9SD9T/p1733425965373019?thread_ts=1733362029.171999&cid=C083LU9SD9T +const SCAN_ICON_ACTIVE_SCALE = 0.72 + const RotatingSettingsIcon = ({ onPressSettings }: { onPressSettings(): void }): JSX.Element => { const isScreenFocused = useIsFocused() const pressProgress = useSharedValue(0) @@ -61,7 +66,7 @@ const RotatingSettingsIcon = ({ onPressSettings }: { onPressSettings(): void }): return ( - + ) @@ -112,6 +117,11 @@ export function AccountHeader(): JSX.Element { }) } } + const onPressScan = useCallback(async () => { + // in case we received a pending session from a previous scan after closing modal + dispatch(removePendingSession()) + dispatch(openModal({ name: ModalName.WalletConnectScan, initialState: ScannerModalState.ScanQr })) + }, [dispatch]) const walletHasName = displayName && displayName?.type !== DisplayNameType.Address const iconSize = 52 @@ -121,50 +131,63 @@ export function AccountHeader(): JSX.Element { {activeAddress && ( - => { - if (isDevEnv()) { - dispatch(openModal({ name: ModalName.Experiments })) - } - }} - onPress={onPressAccountHeader} - > - - - - - {walletHasName ? ( - - - + + => { + if (isDevEnv()) { + dispatch(openModal({ name: ModalName.Experiments })) + } + }} + onPress={onPressAccountHeader} + > + + {walletHasName ? ( + + + + + + ) : ( + + + + {sanitizeAddressText(shortenAddress(activeAddress))} + + + + + )} - ) : ( - - - - {sanitizeAddressText(shortenAddress(activeAddress))} - - - - - )} + + + + + + + )} 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 237ddabfa1b..3d718b0e367 100644 --- a/apps/mobile/src/components/accounts/__snapshots__/AccountHeader.test.tsx.snap +++ b/apps/mobile/src/components/accounts/__snapshots__/AccountHeader.test.tsx.snap @@ -35,306 +35,164 @@ exports[`AccountHeader renders correctly 1`] = ` } > - + - + transform={ + [ + { + "scale": 0.7222222222222222, + }, + ] + } + > + + + - - - - - - - - - - - - - Test Account - - - .uni.eth - - - - @@ -409,94 +229,343 @@ exports[`AccountHeader renders correctly 1`] = ` allowFontScaling={true} maxFontSizeMultiplier={1.4} numberOfLines={1} + onLayout={[Function]} style={ { + "backgroundColor": { + "dynamic": { + "dark": "#131313", + "light": "#FFFFFF", + }, + }, "color": { "dynamic": { - "dark": "#5E5E5E", - "light": "#BFBFBF", + "dark": "#FFFFFF", + "light": "#222222", }, }, "fontFamily": "Basel Grotesk", - "fontSize": 17, + "fontSize": 19, "fontWeight": "400", "lineHeight": 24, + "zIndex": 2, } } suppressHighlighting={true} > - 0x​82D5...3Fa6 + Test Account - + + - + 0x​82D5...3Fa6 + + - + - - + propList={ + [ + "fill", + "stroke", + "strokeWidth", + ] + } + stroke={ + { + "type": 2, + } + } + strokeWidth="0.5" + /> + + + + + + + + + + + + + + + + + + + diff --git a/apps/mobile/src/components/buttons/CopyTextButton.stories.tsx b/apps/mobile/src/components/buttons/CopyTextButton.stories.tsx index 7d1293b5221..41bfdf2397d 100644 --- a/apps/mobile/src/components/buttons/CopyTextButton.stories.tsx +++ b/apps/mobile/src/components/buttons/CopyTextButton.stories.tsx @@ -1,9 +1,8 @@ import type { Meta, StoryObj } from '@storybook/react' import { CopyTextButton } from 'src/components/buttons/CopyTextButton' -import { StorybookTitles } from 'ui/src/storybook' const meta = { - title: StorybookTitles.Atoms, + title: 'Components/Buttons', component: CopyTextButton, } satisfies Meta diff --git a/apps/mobile/src/components/explore/ExploreSections.tsx b/apps/mobile/src/components/explore/ExploreSections.tsx index 99e4ebc6a9b..57e53bb58e5 100644 --- a/apps/mobile/src/components/explore/ExploreSections.tsx +++ b/apps/mobile/src/components/explore/ExploreSections.tsx @@ -3,7 +3,7 @@ import React, { useCallback, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { ListRenderItem, ListRenderItemInfo, StyleSheet } from 'react-native' import { FlatList } from 'react-native-gesture-handler' -import { FadeIn, FadeOut, useAnimatedScrollHandler, useSharedValue } from 'react-native-reanimated' +import { useAnimatedScrollHandler, useSharedValue } from 'react-native-reanimated' import { useSelector } from 'react-redux' import { FavoriteTokensGrid } from 'src/components/explore/FavoriteTokensGrid' import { FavoriteWalletsGrid } from 'src/components/explore/FavoriteWalletsGrid' @@ -13,7 +13,7 @@ import { TokenItemData } from 'src/components/explore/TokenItemData' import { AnimatedBottomSheetFlatList } from 'src/components/layout/AnimatedFlatList' import { AutoScrollProps } from 'src/components/sortableGrid/types' import { getTokenMetadataDisplayType } from 'src/features/explore/utils' -import { AnimatedTouchableArea, Flex, Loader, Text, useSporeColors } from 'ui/src' +import { Flex, Loader, Text, TouchableArea, useSporeColors } from 'ui/src' import { iconSizes, spacing } from 'ui/src/theme' import { BaseCard } from 'uniswap/src/components/BaseCard/BaseCard' import { NetworkLogo } from 'uniswap/src/components/CurrencyLogo/NetworkLogo' @@ -191,7 +191,7 @@ function NetworkPillsRow({ const renderItem: ListRenderItem = useCallback( ({ item }: ListRenderItemInfo) => { return ( - onSelectNetwork(item)}> + onSelectNetwork(item)}> - + ) }, [colors.neutral1.val, onSelectNetwork, selectedNetwork], diff --git a/apps/mobile/src/components/explore/search/SearchResultsSection.tsx b/apps/mobile/src/components/explore/search/SearchResultsSection.tsx index ffcf95732d9..02a31d63c55 100644 --- a/apps/mobile/src/components/explore/search/SearchResultsSection.tsx +++ b/apps/mobile/src/components/explore/search/SearchResultsSection.tsx @@ -176,6 +176,8 @@ export function SearchResultsSection({ return ( diff --git a/apps/mobile/src/components/forceUpgrade/ForceUpgradeModal.tsx b/apps/mobile/src/components/forceUpgrade/ForceUpgradeModal.tsx index 29e6474c1c2..ba4b17d97a1 100644 --- a/apps/mobile/src/components/forceUpgrade/ForceUpgradeModal.tsx +++ b/apps/mobile/src/components/forceUpgrade/ForceUpgradeModal.tsx @@ -1,13 +1,16 @@ -import React, { useEffect, useState } from 'react' +import React, { useEffect, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' +import { StyleSheet } from 'react-native' +import Svg, { Circle } from 'react-native-svg' import { BackButtonView } from 'src/components/layout/BackButtonView' import { SeedPhraseDisplay } from 'src/components/mnemonic/SeedPhraseDisplay' import { APP_STORE_LINK } from 'src/constants/urls' import { UpgradeStatus } from 'src/features/forceUpgrade/types' -import { Flex, Text, TouchableArea, useSporeColors } from 'ui/src' +import { Button, Flex, Image, Text, TouchableArea, isWeb, useSporeColors } from 'ui/src' +import { UNISWAP_LOGO } from 'ui/src/assets' +import { imageSizes } from 'ui/src/theme' import { Modal } from 'uniswap/src/components/modals/Modal' -import { WarningModal } from 'uniswap/src/components/modals/WarningModal/WarningModal' -import { WarningSeverity } from 'uniswap/src/components/modals/WarningModal/types' +import { NewTag } from 'uniswap/src/components/pill/NewTag' import { DynamicConfigs, ForceUpgradeConfigKey } from 'uniswap/src/features/gating/configs' import { useDynamicConfigValue } from 'uniswap/src/features/gating/hooks' import { ModalName } from 'uniswap/src/features/telemetry/constants' @@ -19,7 +22,7 @@ export function ForceUpgradeModal(): JSX.Element { const { t } = useTranslation() const colors = useSporeColors() const forceUpgradeStatusString = useDynamicConfigValue( - DynamicConfigs.MobileForceUpgrade, + DynamicConfigs.ForceUpgrade, ForceUpgradeConfigKey.Status, '' as string, ) @@ -64,26 +67,83 @@ export function ForceUpgradeModal(): JSX.Element { // the force upgrade screen on error, hence we fallback to the global error boundary return ( <> - - - {t('forceUpgrade.description')} - - {mnemonicId && ( - - {t('forceUpgrade.action.recoveryPhrase')} - - )} - + + + + + + + + + + + + + + + {t('forceUpgrade.title')} + + + {t('forceUpgrade.description')} + + + + + + {mnemonicId && ( + + )} + + + {mnemonicId && showSeedPhrase && ( @@ -103,3 +163,48 @@ export function ForceUpgradeModal(): JSX.Element { } const BACK_BUTTON_SIZE = 24 + +function BackgroundDotPattern(): JSX.Element { + const colors = useSporeColors() + const dotGrid = useMemo(() => { + return Array.from({ length: 100 }).map((_, row) => { + return Array.from({ length: 100 }).map((__, col) => { + const x = col * 2 + 1 + const y = row * 2 + 1 + + const distX = Math.abs(x - 50) + const distY = Math.abs(y - 50) + const dist = Math.sqrt(distX * distX + distY * distY) + + if (dist < 45) { + const size = 0.1 + (45 - dist) / 20 + + return + } + return null + }) + }) + }, [colors]) + + return ( + + {dotGrid} + + ) +} + +const styles = StyleSheet.create({ + backgroundPattern: { + bottom: 0, + left: 0, + position: 'absolute', + right: 0, + top: 0, + zIndex: -1, + }, + centered: { + left: '50%', + top: '50%', + transform: [{ translateX: -200 }, { translateY: -200 }], + }, +}) diff --git a/apps/mobile/src/features/deepLinking/handleDeepLinkSaga.test.ts b/apps/mobile/src/features/deepLinking/handleDeepLinkSaga.test.ts index 6b8bc55b5bc..a1f6134ad13 100644 --- a/apps/mobile/src/features/deepLinking/handleDeepLinkSaga.test.ts +++ b/apps/mobile/src/features/deepLinking/handleDeepLinkSaga.test.ts @@ -1,6 +1,6 @@ import { expectSaga } from 'redux-saga-test-plan' import { call } from 'redux-saga/effects' -import { navigationRef } from 'src/app/navigation/NavigationContainer' +import { navigationRef } from 'src/app/navigation/navigationRef' import { handleDeepLink, handleUniswapAppDeepLink, diff --git a/apps/mobile/src/features/deepLinking/handleDeepLinkSaga.ts b/apps/mobile/src/features/deepLinking/handleDeepLinkSaga.ts index b16d66a433c..caec9d54978 100644 --- a/apps/mobile/src/features/deepLinking/handleDeepLinkSaga.ts +++ b/apps/mobile/src/features/deepLinking/handleDeepLinkSaga.ts @@ -15,6 +15,7 @@ import { UNISWAP_URL_SCHEME_WALLETCONNECT_AS_PARAM, UNISWAP_WALLETCONNECT_URL, } from 'src/features/deepLinking/constants' +import { handleOffRampReturnLink } from 'src/features/deepLinking/handleOffRampReturnLinkSaga' import { handleOnRampReturnLink } from 'src/features/deepLinking/handleOnRampReturnLinkSaga' import { handleSwapLink } from 'src/features/deepLinking/handleSwapLinkSaga' import { handleTransactionLink } from 'src/features/deepLinking/handleTransactionLinkSaga' @@ -207,6 +208,7 @@ export function* handleDeepLink(action: ReturnType) { const screen = url.searchParams.get('screen') const userAddress = url.searchParams.get('userAddress') const fiatOnRamp = url.searchParams.get('fiatOnRamp') === 'true' + const fiatOffRamp = url.searchParams.get('fiatOffRamp') === 'true' const activeAccount = yield* select(selectActiveAccount) if (!activeAccount) { @@ -271,6 +273,8 @@ export function* handleDeepLink(action: ReturnType) { case 'transaction': if (fiatOnRamp) { yield* call(handleOnRampReturnLink) + } else if (fiatOffRamp) { + yield* call(handleOffRampReturnLink, url) } else { yield* call(handleTransactionLink) } diff --git a/apps/mobile/src/features/deepLinking/handleOffRampReturnLinkSaga.ts b/apps/mobile/src/features/deepLinking/handleOffRampReturnLinkSaga.ts new file mode 100644 index 00000000000..25f15a694bc --- /dev/null +++ b/apps/mobile/src/features/deepLinking/handleOffRampReturnLinkSaga.ts @@ -0,0 +1,85 @@ +import { navigate } from 'src/app/navigation/rootNavigation' +import { openModal } from 'src/features/modals/modalSlice' +import { call, put } from 'typed-redux-saga' +import { AssetType, TradeableAsset } from 'uniswap/src/entities/assets' +import { UniverseChainId } from 'uniswap/src/features/chains/types' +import { FiatOffRampMetaData, OffRampTransferDetailsResponse } from 'uniswap/src/features/fiatOnRamp/types' +import { ModalName } from 'uniswap/src/features/telemetry/constants' +import { TransactionScreen } from 'uniswap/src/features/transactions/TransactionModal/TransactionModalContext' +import { CurrencyField } from 'uniswap/src/types/currency' +import { MobileScreens } from 'uniswap/src/types/screens/mobile' +import { createTransactionId } from 'uniswap/src/utils/createTransactionId' +import { logger } from 'utilities/src/logger/logger' +import { fetchOffRampTransferDetails } from 'wallet/src/features/fiatOnRamp/api' +import { dismissInAppBrowser } from 'wallet/src/utils/linking' + +export function* handleOffRampReturnLink(url: URL) { + try { + yield* call(_handleOffRampReturnLink, url) + } catch (error) { + // TODO: handle error in UI + // Alert.alert(i18n.t('walletConnect.error.general.title'), i18n.t('walletConnect.error.general.message')) + // yield* put(openModal({ name: ModalName.Send, initialState: initialSendState })) + } +} + +function* _handleOffRampReturnLink(url: URL) { + const externalTransactionId = url.searchParams.get('externalTransactionId') + + if (!externalTransactionId) { + throw new Error('Missing externalTransactionId in fiat offramp deep link') + } + + let offRampTransferDetails: OffRampTransferDetailsResponse | undefined + + try { + offRampTransferDetails = yield* call(fetchOffRampTransferDetails, externalTransactionId) + } catch (error) { + logger.error(error, { + tags: { file: 'handleOffRampReturnLinkSaga', function: 'handleOffRampReturnLink' }, + }) + throw new Error('Failed to fetch offramp transfer details') + } + + if (!offRampTransferDetails) { + throw new Error('Missing offRampTransferDetails in fiat offramp deep link') + } + + const { tokenAddress, baseCurrencyCode, baseCurrencyAmount, depositWalletAddress, logos, provider, chainId } = + offRampTransferDetails + + const currencyTradeableAsset: TradeableAsset = { + address: tokenAddress, + chainId: Number(chainId) as UniverseChainId, + type: AssetType.Currency, + } + + const fiatOffRampMetaData: FiatOffRampMetaData = { + name: provider, + logoUrl: logos.lightLogo, + // TODO: update activity feed once transaction is submitted + onSubmitCallback: () => {}, + moonpayCurrencyCode: baseCurrencyCode, + meldCurrencyCode: baseCurrencyCode, + } + + const txnId = createTransactionId() + + const initialSendState = { + txId: txnId, + [CurrencyField.INPUT]: currencyTradeableAsset, + [CurrencyField.OUTPUT]: null, + exactCurrencyField: CurrencyField.INPUT, + exactAmountToken: baseCurrencyAmount.toString(), + focusOnCurrencyField: null, + recipient: depositWalletAddress, + isFiatInput: false, + showRecipientSelector: false, + fiatOffRampMetaData, + sendScreen: TransactionScreen.Review, + } + + yield* call(navigate, MobileScreens.Home) + yield* put(openModal({ name: ModalName.Send, initialState: initialSendState })) + yield* call(dismissInAppBrowser) +} diff --git a/apps/mobile/src/features/deepLinking/handleSwapLinkSaga.test.ts b/apps/mobile/src/features/deepLinking/handleSwapLinkSaga.test.ts index 704c8942431..fc49c9e4860 100644 --- a/apps/mobile/src/features/deepLinking/handleSwapLinkSaga.test.ts +++ b/apps/mobile/src/features/deepLinking/handleSwapLinkSaga.test.ts @@ -2,12 +2,9 @@ import { URL } from 'react-native-url-polyfill' import { expectSaga } from 'redux-saga-test-plan' import { handleSwapLink } from 'src/features/deepLinking/handleSwapLinkSaga' import { openModal } from 'src/features/modals/modalSlice' -import { DAI, UNI } from 'uniswap/src/constants/tokens' -import { AssetType } from 'uniswap/src/entities/assets' +import { DAI, UNI, USDC_UNICHAIN_SEPOLIA } from 'uniswap/src/constants/tokens' import { UniverseChainId } from 'uniswap/src/features/chains/types' import { ModalName } from 'uniswap/src/features/telemetry/constants' -import { TransactionState } from 'uniswap/src/features/transactions/types/transactionState' -import { CurrencyField } from 'uniswap/src/types/currency' import { signerMnemonicAccount } from 'wallet/src/test/fixtures' const account = signerMnemonicAccount() @@ -29,44 +26,6 @@ const formSwapUrl = ( &amount=${amount}`.trim(), ) -const formTransactionState = ( - chain?: UniverseChainId, - inputAddress?: string, - outputAddress?: string, - currencyField?: string, - amount?: string, -): { - input: { - address: string | undefined - chainId: UniverseChainId | undefined - type: AssetType - } - output: { - address: string | undefined - chainId: UniverseChainId | undefined - type: AssetType - } - exactCurrencyField: string | undefined - exactAmountToken: string | undefined -} => ({ - [CurrencyField.INPUT]: { - address: inputAddress, - chainId: chain, - type: AssetType.Currency, - }, - [CurrencyField.OUTPUT]: { - address: outputAddress, - chainId: chain, - type: AssetType.Currency, - }, - exactCurrencyField: !currencyField - ? currencyField - : currencyField.toLowerCase() === 'output' - ? CurrencyField.OUTPUT - : CurrencyField.INPUT, - exactAmountToken: amount, -}) - const swapUrl = formSwapUrl( account.address, UniverseChainId.Mainnet, @@ -76,6 +35,15 @@ const swapUrl = formSwapUrl( '100', ) +const testnetSwapUrl = formSwapUrl( + account.address, + UniverseChainId.Sepolia, + USDC_UNICHAIN_SEPOLIA.address, + UNI[UniverseChainId.Sepolia].address, + 'input', + '100', +) + const invalidOutputCurrencySwapUrl = formSwapUrl( account.address, UniverseChainId.Mainnet, @@ -121,19 +89,16 @@ const invalidCurrencyFieldSwapUrl = formSwapUrl( '100', ) -const swapFormState = formTransactionState( - UniverseChainId.Mainnet, - DAI.address, - UNI[UniverseChainId.Mainnet].address, - 'input', - '100', -) as TransactionState - describe(handleSwapLink, () => { describe('valid inputs', () => { - it('Navigates to the swap screen with all params if all inputs are valid', () => { + it('Navigates to the swap screen with all params if all inputs are valid; testnet mode aligned', () => { return expectSaga(handleSwapLink, swapUrl) - .put(openModal({ name: ModalName.Swap, initialState: swapFormState })) + .put(openModal({ name: ModalName.Swap })) + .silentRun() + }) + it('Navigates to the swap screen with all params if all inputs are valid; testnet mode not aligned', () => { + return expectSaga(handleSwapLink, testnetSwapUrl) + .put(openModal({ name: ModalName.Swap })) .silentRun() }) }) diff --git a/apps/mobile/src/features/deepLinking/handleSwapLinkSaga.ts b/apps/mobile/src/features/deepLinking/handleSwapLinkSaga.ts index 7896d8cb227..7c9b696ec5f 100644 --- a/apps/mobile/src/features/deepLinking/handleSwapLinkSaga.ts +++ b/apps/mobile/src/features/deepLinking/handleSwapLinkSaga.ts @@ -2,7 +2,8 @@ import { BigNumber } from 'ethers' import { openModal } from 'src/features/modals/modalSlice' import { put } from 'typed-redux-saga' import { AssetType, CurrencyAsset } from 'uniswap/src/entities/assets' -import { SUPPORTED_CHAIN_IDS, UniverseChainId } from 'uniswap/src/features/chains/types' +import { ALL_CHAIN_IDS, SUPPORTED_TESTNET_CHAIN_IDS, UniverseChainId } from 'uniswap/src/features/chains/types' +import { getEnabledChainIdsSaga } from 'uniswap/src/features/settings/saga' import { ModalName } from 'uniswap/src/features/telemetry/constants' import { TransactionState } from 'uniswap/src/features/transactions/types/transactionState' import { CurrencyField } from 'uniswap/src/types/currency' @@ -10,6 +11,16 @@ import { getValidAddress } from 'uniswap/src/utils/addresses' import { currencyIdToAddress, currencyIdToChain } from 'uniswap/src/utils/currencyId' import { logger } from 'utilities/src/logger/logger' +/** + * Opens swap modal with the provided swap link parameters; prompts testnet switch modal if necessary. + * + * Testing deep links: + * Testnet mode – https://uniswap.org/mobile-redirect?screen=swap&userAddress=&inputCurrencyId=41454-0x93EACdB111FF98dE9a8Ac5823d357BBc4842aE63&outputCurrencyId=41454-0xF5A8061bB2C5D9Dc9bC9c5C633D870DAC7bD351e¤cyField=output&amount=100000 + * Prod mode – https://uniswap.org/mobile-redirect?screen=swap&userAddress=&inputCurrencyId=1-0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee&outputCurrencyId=10-0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee¤cyField=output&amount=100000 + * Mixed – https://uniswap.org/mobile-redirect?screen=swap&userAddress=&inputCurrencyId=1-0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee&outputCurrencyId=41454-0xF5A8061bB2C5D9Dc9bC9c5C633D870DAC7bD351e¤cyField=output&amount=100000 + * + * @param url - URL object containing the swap link + */ export function* handleSwapLink(url: URL) { try { const { inputChain, inputAddress, outputChain, outputAddress, exactCurrencyField, exactAmountToken } = @@ -34,7 +45,27 @@ export function* handleSwapLink(url: URL) { exactAmountToken, } + // both should match as of writing because of the check in parseAndValidateSwapParams, + // but we're including an OR gate in case we update to allow only one chain to be passed + const isTestnetChains = + SUPPORTED_TESTNET_CHAIN_IDS.includes(inputChain) || SUPPORTED_TESTNET_CHAIN_IDS.includes(outputChain) + const { isTestnetModeEnabled } = yield* getEnabledChainIdsSaga() + + // prefill modal irrespective of testnet mode alignment yield* put(openModal({ name: ModalName.Swap, initialState: swapFormState })) + + // if testnet mode isn't aligned with assets, prompt testnet switch modal (closes prefilled swap modal if rejected) + if (isTestnetModeEnabled !== isTestnetChains) { + yield* put( + openModal({ + name: ModalName.TestnetSwitchModal, + initialState: { + switchToMode: isTestnetChains ? 'testnet' : 'production', + }, + }), + ) + return + } } catch (error) { logger.error(error, { tags: { file: 'handleSwapLinkSaga', function: 'handleSwapLink' } }) yield* put(openModal({ name: ModalName.Swap })) @@ -77,11 +108,11 @@ const parseAndValidateSwapParams = (url: URL) => { throw new Error('Invalid tokenAddress provided within outputCurrencyId') } - if (!SUPPORTED_CHAIN_IDS.includes(inputChain)) { + if (!ALL_CHAIN_IDS.includes(inputChain)) { throw new Error('Invalid inputCurrencyId. Chain ID is not supported') } - if (!SUPPORTED_CHAIN_IDS.includes(outputChain)) { + if (!ALL_CHAIN_IDS.includes(outputChain)) { throw new Error('Invalid outputCurrencyId. Chain ID is not supported') } @@ -95,6 +126,13 @@ const parseAndValidateSwapParams = (url: URL) => { throw new Error('Invalid currencyField. Must be either `input` or `output`') } + const isInputTestnet = SUPPORTED_TESTNET_CHAIN_IDS.includes(inputChain) + const isOutputTestnet = SUPPORTED_TESTNET_CHAIN_IDS.includes(outputChain) + + if (inputChain && outputChain && isInputTestnet !== isOutputTestnet) { + throw new Error('Cannot swap between testnet and mainnet') + } + const exactCurrencyField = currencyField.toLowerCase() === 'output' ? CurrencyField.OUTPUT : CurrencyField.INPUT return { diff --git a/apps/mobile/src/features/modals/ModalsState.ts b/apps/mobile/src/features/modals/ModalsState.ts index 3b2414a7013..e920d740233 100644 --- a/apps/mobile/src/features/modals/ModalsState.ts +++ b/apps/mobile/src/features/modals/ModalsState.ts @@ -2,10 +2,12 @@ import { ExploreModalState } from 'src/app/modals/ExploreModalState' import { TokenWarningModalState } from 'src/app/modals/TokenWarningModalState' import { RemoveWalletModalState } from 'src/components/RemoveWallet/RemoveWalletModalState' import { ScantasticModalState } from 'src/features/scantastic/ScantasticModalState' +import { TestnetSwitchModalState } from 'src/features/testnetMode/TestnetSwitchModalState' import { FiatOnRampModalState } from 'src/screens/FiatOnRampModalState' import { ReceiveCryptoModalState } from 'src/screens/ReceiveCryptoModalState' import { FORServiceProvider } from 'uniswap/src/features/fiatOnRamp/types' import { ModalName } from 'uniswap/src/features/telemetry/constants' +import { TransactionScreen } from 'uniswap/src/features/transactions/TransactionModal/TransactionModalContext' import { TransactionState } from 'uniswap/src/features/transactions/types/transactionState' import { MobileScreens } from 'uniswap/src/types/screens/mobile' import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants' @@ -33,8 +35,9 @@ export interface ModalsState { [ModalName.RemoveWallet]: AppModalState [ModalName.RestoreWallet]: AppModalState [ModalName.Scantastic]: AppModalState - [ModalName.Send]: AppModalState + [ModalName.Send]: AppModalState [ModalName.Swap]: AppModalState + [ModalName.TestnetSwitchModal]: AppModalState [ModalName.UnitagsIntro]: AppModalState<{ address: Address entryPoint: MobileScreens.Home | MobileScreens.Settings diff --git a/apps/mobile/src/features/modals/modalSlice.ts b/apps/mobile/src/features/modals/modalSlice.ts index 4015fe3bdab..5141095a3de 100644 --- a/apps/mobile/src/features/modals/modalSlice.ts +++ b/apps/mobile/src/features/modals/modalSlice.ts @@ -5,9 +5,11 @@ import { RemoveWalletModalState } from 'src/components/RemoveWallet/RemoveWallet import { ExchangeTransferModalState } from 'src/features/fiatOnRamp/ExchangeTransferModalState' import { ModalsState } from 'src/features/modals/ModalsState' import { ScantasticModalState } from 'src/features/scantastic/ScantasticModalState' +import { TestnetSwitchModalState } from 'src/features/testnetMode/TestnetSwitchModalState' import { FiatOnRampModalState } from 'src/screens/FiatOnRampModalState' import { ReceiveCryptoModalState } from 'src/screens/ReceiveCryptoModalState' import { ModalName } from 'uniswap/src/features/telemetry/constants' +import { TransactionScreen } from 'uniswap/src/features/transactions/TransactionModal/TransactionModalContext' import { TransactionState } from 'uniswap/src/features/transactions/types/transactionState' import { MobileScreens } from 'uniswap/src/types/screens/mobile' import { getKeys } from 'utilities/src/primitives/objects' @@ -60,6 +62,11 @@ type ScantasticModalParams = { initialState: ScantasticModalState } +type TestnetSwitchModalParams = { + name: typeof ModalName.TestnetSwitchModal + initialState?: TestnetSwitchModalState +} + type RemoveWalletModalParams = { name: typeof ModalName.RemoveWallet initialState?: RemoveWalletModalState @@ -74,7 +81,12 @@ type WalletConnectModalParams = { type SwapModalParams = { name: typeof ModalName.Swap; initialState?: TransactionState } -type SendModalParams = { name: typeof ModalName.Send; initialState?: TransactionState } +type SendModalParams = { + name: typeof ModalName.Send + initialState?: TransactionState & { + sendScreen?: TransactionScreen + } +} type UnitagsIntroParams = { name: typeof ModalName.UnitagsIntro @@ -114,6 +126,7 @@ export type OpenModalParams = | ReceiveCryptoModalParams | LanguageSelectorModalParams | ScantasticModalParams + | TestnetSwitchModalParams | RemoveWalletModalParams | SendModalParams | SwapModalParams diff --git a/apps/mobile/src/features/notifications/hooks/useNotificationsToggle.test.ts b/apps/mobile/src/features/notifications/hooks/useNotificationsToggle.test.ts new file mode 100644 index 00000000000..74159f6383f --- /dev/null +++ b/apps/mobile/src/features/notifications/hooks/useNotificationsToggle.test.ts @@ -0,0 +1,206 @@ +import { useDispatch } from 'react-redux' +import { promptPushPermission } from 'src/features/notifications/Onesignal' +import { + NotificationPermission, + useNotificationOSPermissionsEnabled, +} from 'src/features/notifications/hooks/useNotificationOSPermissionsEnabled' +import { useNotificationToggle } from 'src/features/notifications/hooks/useNotificationsToggle' +import { showNotificationSettingsAlert } from 'src/screens/Onboarding/NotificationsSetupScreen' +import { act, renderHook, waitFor } from 'src/test/test-utils' +import { useSelectAccountNotificationSetting } from 'wallet/src/features/wallet/hooks' + +jest.mock('react-redux', () => ({ + ...jest.requireActual('react-redux'), // Keep all other exports + useDispatch: jest.fn(), +})) + +jest.mock('src/features/notifications/Onesignal', () => ({ + promptPushPermission: jest.fn(), +})) + +jest.mock('src/features/notifications/hooks/useNotificationOSPermissionsEnabled', () => ({ + ...jest.requireActual('src/features/notifications/hooks/useNotificationOSPermissionsEnabled'), + useNotificationOSPermissionsEnabled: jest.fn(), +})) + +jest.mock('wallet/src/features/wallet/accounts/editAccountSaga', () => ({ + ...jest.requireActual('wallet/src/features/wallet/accounts/editAccountSaga'), + editAccountActions: { + trigger: jest.fn((payload) => ({ type: 'EDIT_ACCOUNT', payload })), + }, +})) + +jest.mock('src/screens/Onboarding/NotificationsSetupScreen', () => ({ + showNotificationSettingsAlert: jest.fn(), +})) + +jest.mock('src/utils/useAppStateTrigger', () => ({ + useAppStateTrigger: jest.fn(), +})) + +jest.mock('wallet/src/features/wallet/hooks', () => ({ + useSelectAccountNotificationSetting: jest.fn(), +})) + +describe('useNotificationToggle', () => { + const mockAddress = '0xAddress' + const mockDispatch = jest.fn() + const mockUseDispatch = useDispatch as jest.MockedFunction + const mockPermissionPrompt = jest.mocked(promptPushPermission) + const mockSettingsAlert = jest.mocked(showNotificationSettingsAlert) + const mockUseSelectAccountNotificationSetting = jest.mocked(useSelectAccountNotificationSetting) + const mockUseNotificationOSPermissionsQuery = jest.mocked(useNotificationOSPermissionsEnabled) + + beforeEach(() => { + jest.clearAllMocks() + mockUseDispatch.mockReturnValue(mockDispatch) + }) + + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type + function setupHook({ + osPermissionStatus = NotificationPermission.Enabled, + firebaseEnabled = true, + onPermissionChanged, + }: { + osPermissionStatus?: NotificationPermission + firebaseEnabled?: boolean + onPermissionChanged?: (enabled: boolean) => void + } = {}) { + mockUseNotificationOSPermissionsQuery.mockReturnValue(osPermissionStatus) + mockUseSelectAccountNotificationSetting.mockReturnValue(firebaseEnabled) + return renderHook(() => useNotificationToggle({ address: mockAddress, onPermissionChanged })) + } + + describe('initial states', () => { + it('returns enabled when both OS and Firebase are enabled', () => { + const { result } = setupHook({ + osPermissionStatus: NotificationPermission.Enabled, + firebaseEnabled: true, + }) + + expect(result.current.isEnabled).toBe(true) + expect(result.current.isPending).toBe(false) + }) + + it('returns disabled when OS permissions are disabled', () => { + const { result } = setupHook({ + osPermissionStatus: NotificationPermission.Disabled, + firebaseEnabled: true, + }) + + expect(result.current.isEnabled).toBe(false) + expect(result.current.isPending).toBe(false) + }) + + it('returns disabled when Firebase is disabled', () => { + const { result } = setupHook({ + osPermissionStatus: NotificationPermission.Enabled, + firebaseEnabled: false, + }) + + expect(result.current.isEnabled).toBe(false) + expect(result.current.isPending).toBe(false) + }) + }) + + describe('toggle flows', () => { + // For the toggle test + it('handles toggle when OS permissions are enabled', async () => { + const { result } = setupHook({ + osPermissionStatus: NotificationPermission.Enabled, + firebaseEnabled: true, + }) + + await act(async () => { + result.current.toggle() + await new Promise(requestAnimationFrame) + }) + await waitFor(() => { + expect(mockDispatch).toHaveBeenCalled() + expect(result.current.isEnabled).toBe(false) + }) + }) + + it('handles OS permission prompt flow successfully', async () => { + mockPermissionPrompt.mockResolvedValueOnce(true) + + const { result } = setupHook({ + osPermissionStatus: NotificationPermission.Disabled, + firebaseEnabled: false, + }) + + await act(async () => { + result.current.toggle() + await new Promise(requestAnimationFrame) + }) + + await waitFor(() => { + expect(mockPermissionPrompt).toHaveBeenCalled() + expect(mockDispatch).toHaveBeenCalled() + expect(result.current.isEnabled).toBe(true) + }) + }) + + it('handles OS permission prompt flow failure', async () => { + mockPermissionPrompt.mockResolvedValueOnce(false) + + const { result } = setupHook({ + osPermissionStatus: NotificationPermission.Disabled, + firebaseEnabled: false, + }) + + await act(async () => { + result.current.toggle() + await new Promise(requestAnimationFrame) + }) + + await waitFor(() => { + expect(mockPermissionPrompt).toHaveBeenCalled() + expect(mockSettingsAlert).toHaveBeenCalled() + expect(result.current.isEnabled).toBe(false) + expect(result.current.isPending).toBe(false) + }) + }) + }) + + describe('callbacks', () => { + it('calls onPermissionChanged after successful toggle', async () => { + const onPermissionChanged = jest.fn() + + const { result } = setupHook({ + osPermissionStatus: NotificationPermission.Enabled, + firebaseEnabled: false, + onPermissionChanged, + }) + + await act(async () => { + result.current.toggle() + await new Promise(requestAnimationFrame) + }) + + await waitFor(() => { + expect(onPermissionChanged).toHaveBeenCalledWith(true) + }) + }) + }) + + describe('error handling', () => { + it('shows settings alert and resets state on OS permission denial', async () => { + mockPermissionPrompt.mockResolvedValueOnce(false) + + const { result } = setupHook({ + osPermissionStatus: NotificationPermission.Disabled, + }) + + await act(async () => { + result.current.toggle() + await new Promise(requestAnimationFrame) + }) + + await waitFor(() => { + expect(mockSettingsAlert).toHaveBeenCalled() + expect(result.current.isEnabled).toBe(false) + }) + }) + }) +}) diff --git a/apps/mobile/src/features/notifications/hooks/useNotificationsToggle.ts b/apps/mobile/src/features/notifications/hooks/useNotificationsToggle.ts new file mode 100644 index 00000000000..e3c901efcea --- /dev/null +++ b/apps/mobile/src/features/notifications/hooks/useNotificationsToggle.ts @@ -0,0 +1,159 @@ +import { useMutation } from '@tanstack/react-query' +import { useCallback, useEffect, useState } from 'react' +import { useDispatch } from 'react-redux' +import { promptPushPermission } from 'src/features/notifications/Onesignal' +import { + NotificationPermission, + useNotificationOSPermissionsEnabled, +} from 'src/features/notifications/hooks/useNotificationOSPermissionsEnabled' +import { showNotificationSettingsAlert } from 'src/screens/Onboarding/NotificationsSetupScreen' +import { EditAccountAction, editAccountActions } from 'wallet/src/features/wallet/accounts/editAccountSaga' +import { useSelectAccountNotificationSetting } from 'wallet/src/features/wallet/hooks' + +// Wait for next frame to ensure UI updates without flashing +// https://corbt.com/posts/2015/12/22/breaking-up-heavy-processing-in-react-native.html +const waitFrame = async (): Promise => { + await new Promise(requestAnimationFrame) +} + +enum NotificationError { + OsPermissionDenied = 'OS_PERMISSION_DENIED', +} + +/** + * useNotificationToggle + * + * Enabling notifications across different initial states. + * + * What goes into enabling notifications? + * - OS permissions + * - Firebase settings (via redux) + * + * What states can the user be in? + * - Denied notifications at the OS level + * - Enabled notifications at the OS level + * - Denied notifications during onboarding + * - Enabled notifications during onboarding + * - Skipped notifications during onboarding + * + * Situation A: Denied notifications at the OS level + * - User goes to toggle notifications + * - We optimistically enable firebase settings + * - We prompt the user to go to settings and re-enable notifications + * - App is backgrounded and user goes to settings + * - App is foregrounded and we refetch the OS permissions + * - Notifications are enabled + * + * Situation B: User skipped notifications during onboarding + * - User goes to toggle notifications + * - We request the OS permissions + * - Notifications are enabled + * + * Situation C: User has notifications enabled but wants to disable + * - User goes to toggle notifications + * - We disable Firebase settings immediately + * - OS permissions remain enabled but notifications stop + * - User can re-enable without OS prompt + * + * Situation D: User enabled during onboarding but removed OS permissions later + * - User has Firebase enabled but OS permissions are off + * - User goes to toggle notifications + * - We detect mismatched state + * - We maintain Firebase settings as enabled + * - We prompt user to restore OS permissions + * - Normal OS permission flow resumes + */ + +export function useNotificationToggle(props: { address: string; onPermissionChanged?: (enabled: boolean) => void }): { + isEnabled: boolean + isPending: boolean + toggle: () => void +} { + const dispatch = useDispatch() + + // Get real states from different systems + const osPermissionStatus = useNotificationOSPermissionsEnabled() + const reduxPushNotificationsEnabled = useSelectAccountNotificationSetting(props.address) + const isOSPermissionEnabled = osPermissionStatus === NotificationPermission.Enabled + + // Derive real enabled state - only true if both systems are enabled + const isEnabled = isOSPermissionEnabled && reduxPushNotificationsEnabled + + // Optimistic UI state + const [optimisticEnabled, setOptimisticEnabled] = useState(isEnabled) + + // Helper to handle OS permission request and state update + const requestOSPermissions = useCallback(async (): Promise => { + const granted = await promptPushPermission() + if (!granted) { + // first let's enable the redux state (firebase) + // this will ensure that when the user goes to settings and enables notifications + // we're not stuck in a state where notifications are disabled + // and the user has to hit the toggle again + dispatch( + editAccountActions.trigger({ + type: EditAccountAction.TogglePushNotification, + enabled: true, + address: props.address, + }), + ) + // this means the user denied the permission at the system level + // and needs to go to settings to re-enable (boo) + throw new Error(NotificationError.OsPermissionDenied) + } + return true + }, [dispatch, props.address]) + + // Reset optimistic state if real state changes + useEffect(() => { + setOptimisticEnabled(isEnabled) + }, [isEnabled]) + + const mutation = useMutation({ + onMutate: async () => { + // Wait for next frame to ensure UI updates without flashing + await waitFrame() + // Only show optimistic updates when we have OS permissions + if (isOSPermissionEnabled) { + setOptimisticEnabled(!optimisticEnabled) + } + }, + mutationFn: async () => { + const isOsEnabled = isOSPermissionEnabled || (await requestOSPermissions()) + + // After this point, we're guaranteed to have requested OS permissions + // If we just obtained permissions, we want to enable notifications + // Otherwise, we're toggling the current redux state + const shouldEnable = isOsEnabled ? !reduxPushNotificationsEnabled : true + + dispatch( + editAccountActions.trigger({ + type: EditAccountAction.TogglePushNotification, + enabled: shouldEnable, + address: props.address, + }), + ) + return shouldEnable + }, + onError: (error) => { + if (error.message === NotificationError.OsPermissionDenied) { + // user will need to go to settings to re-enable notifications + // when they come back, the real state will be refetched and the UI will update automatically + showNotificationSettingsAlert() + setOptimisticEnabled(false) + } + }, + onSuccess: (enabled) => { + // setState will bail if the value is the same as the current state + // so we can safely call it without conditionals + setOptimisticEnabled(enabled) + props.onPermissionChanged?.(enabled) + }, + }) + + return { + isEnabled: optimisticEnabled, + isPending: mutation.isPending, + toggle: () => mutation.mutate(), + } +} diff --git a/apps/mobile/src/features/onboarding/OnboardingScreen.tsx b/apps/mobile/src/features/onboarding/OnboardingScreen.tsx index 860fb9f4709..97f9a6b8e3f 100644 --- a/apps/mobile/src/features/onboarding/OnboardingScreen.tsx +++ b/apps/mobile/src/features/onboarding/OnboardingScreen.tsx @@ -41,6 +41,8 @@ export function OnboardingScreen({ const headerHeight = useHeaderHeight() const insets = useAppInsets() const media = useMedia() + // TODO(WALL-5483): remove this once we improve seed recovery screen design on smaller devices + const showIcon = !media.short const gapSize = media.short ? '$none' : '$spacing16' @@ -82,7 +84,7 @@ export function OnboardingScreen({ > {/* Text content */} - {Icon && ( + {showIcon && Icon && ( diff --git a/apps/mobile/src/features/send/SendFlow.tsx b/apps/mobile/src/features/send/SendFlow.tsx index 3d369b24154..c6bd3e68362 100644 --- a/apps/mobile/src/features/send/SendFlow.tsx +++ b/apps/mobile/src/features/send/SendFlow.tsx @@ -44,16 +44,20 @@ export function SendFlow(): JSX.Element { onClose={onClose} > - + ) } -function CurrentScreen(): JSX.Element { - const { screen } = useTransactionModalContext() +function CurrentScreen({ screenOverride }: { screenOverride?: TransactionScreen }): JSX.Element { + const { screen, setScreen } = useTransactionModalContext() const { recipient } = useSendContext() + if (screenOverride) { + setScreen(screenOverride) + } + // If no recipient, force full screen recipient select. Need to render this outside of `SendFormScreen` to ensure that // the modals are rendered correctly, and animations can properly measure the available space for the decimal pad. if (!recipient) { diff --git a/apps/mobile/src/features/testnetMode/TestnetSwitchModal.tsx b/apps/mobile/src/features/testnetMode/TestnetSwitchModal.tsx new file mode 100644 index 00000000000..d6717246ef0 --- /dev/null +++ b/apps/mobile/src/features/testnetMode/TestnetSwitchModal.tsx @@ -0,0 +1,59 @@ +import React from 'react' +import { useTranslation } from 'react-i18next' +import { useDispatch, useSelector } from 'react-redux' +import { closeModal } from 'src/features/modals/modalSlice' +import { selectModalState } from 'src/features/modals/selectModalState' +import { Wrench } from 'ui/src/components/icons' +import { WarningModal } from 'uniswap/src/components/modals/WarningModal/WarningModal' +import { WarningSeverity } from 'uniswap/src/components/modals/WarningModal/types' +import { setIsTestnetModeEnabled } from 'uniswap/src/features/settings/slice' +import { ModalName, WalletEventName } from 'uniswap/src/features/telemetry/constants' +import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' + +export function TestnetSwitchModal(): JSX.Element { + const dispatch = useDispatch() + const { t } = useTranslation() + + const modalState = useSelector(selectModalState(ModalName.TestnetSwitchModal)) + + const { switchToMode } = modalState.initialState ?? {} + + const onToggleTestnetMode = (): void => { + dispatch(closeModal({ name: ModalName.TestnetSwitchModal })) + dispatch(setIsTestnetModeEnabled(switchToMode === 'testnet')) + + sendAnalyticsEvent(WalletEventName.TestnetModeToggled, { + enabled: switchToMode === 'testnet', + location: 'deep_link_modal', + }) + } + + const onReject = (): void => { + dispatch(closeModal({ name: ModalName.Swap })) + dispatch(closeModal({ name: ModalName.TestnetSwitchModal })) + } + + const toTestnetModeDescription = t('testnet.modal.swapDeepLink.description.toTestnetMode') + const toProdModeDescription = t('testnet.modal.swapDeepLink.description.toProdMode') + + const toTestnetModeTitle = t('testnet.modal.swapDeepLink.title.toTestnetMode') + const toProdModeTitle = t('testnet.modal.swapDeepLink.title.toProdMode') + + return ( + } + acknowledgeButtonTheme="primary" + // only show if swap form state is provided + modalName={ModalName.TestnetSwitchModal} + severity={WarningSeverity.None} + title={switchToMode === 'production' ? toProdModeTitle : toTestnetModeTitle} + onAcknowledge={onToggleTestnetMode} + onClose={onReject} + onReject={onReject} + /> + ) +} diff --git a/apps/mobile/src/features/testnetMode/TestnetSwitchModalState.ts b/apps/mobile/src/features/testnetMode/TestnetSwitchModalState.ts new file mode 100644 index 00000000000..41a6e21f576 --- /dev/null +++ b/apps/mobile/src/features/testnetMode/TestnetSwitchModalState.ts @@ -0,0 +1,3 @@ +export interface TestnetSwitchModalState { + switchToMode: 'testnet' | 'production' +} diff --git a/apps/mobile/src/features/walletConnect/utils.ts b/apps/mobile/src/features/walletConnect/utils.ts index 2c8471e7c85..533a0961f7c 100644 --- a/apps/mobile/src/features/walletConnect/utils.ts +++ b/apps/mobile/src/features/walletConnect/utils.ts @@ -159,26 +159,19 @@ export const parseTransactionRequest = ( } } -function isUtf8(str: string): boolean { +export function decodeMessage(value: string): string { try { - const decoded = new TextDecoder('utf-8').decode(new TextEncoder().encode(str)) + if (utils.isHexString(value)) { + const decoded = utils.toUtf8String(value) + if (decoded?.trim()) { + return decoded + } + } - // if the encoded -> decoded string matches the original string (ie no chars swapped), - // then it's valid utf-8 - return decoded === str + return value } catch { - return false - } -} - -export function decodeMessage(value: string): string { - if (utils.isHexString(value) && isUtf8(value)) { - const decoded = utils.toUtf8String(value) - if (decoded?.trim()) { - return decoded - } + return value } - return value } /** diff --git a/apps/mobile/src/screens/ExploreScreen.tsx b/apps/mobile/src/screens/ExploreScreen.tsx index 710ed9d5ccf..7e86a4c4b07 100644 --- a/apps/mobile/src/screens/ExploreScreen.tsx +++ b/apps/mobile/src/screens/ExploreScreen.tsx @@ -53,6 +53,8 @@ export function ExploreScreen(): JSX.Element { const [isSearchMode, setIsSearchMode] = useState(false) const textInputRef = useRef(null) const [selectedChain, setSelectedChain] = useState(null) + // TODO(WALL-5482): investigate list rendering performance/scrolling issue + const canRenderList = useRenderNextFrame(!isSearchMode) const onSearchChangeText = (newSearchFilter: string): void => { setSearchQuery(newSearchFilter) @@ -132,8 +134,56 @@ export function ExploreScreen(): JSX.Element { )} ) : ( - isSheetReady && + isSheetReady && canRenderList && )} ) } + +/** + * A hook that safely handles mounting/unmounting using requestAnimationFrame. + * This can help prevent common React Native issues with rendering and gestures + * by ensuring elements mount on the next frame. (not ideal, but better than nothing) + */ +const useRenderNextFrame = (condition: boolean): boolean => { + const [canRender, setCanRender] = useState(false) + const rafRef = useRef() + const mountedRef = useRef(true) + + const conditionRef = useRef(condition) + + // clean up on unmount to prevent memory leaks + useEffect(() => { + return () => { + mountedRef.current = false + if (rafRef.current) { + cancelAnimationFrame(rafRef.current) + } + } + }, []) + + // schedule render for next frame if we should mount + useEffect(() => { + conditionRef.current = condition + + if (condition) { + rafRef.current = requestAnimationFrame(() => { + // By the time this callback runs, 'condition' might have changed + // since RAF executes in the next frame, so we store the condition in a ref + if (mountedRef.current && conditionRef.current) { + setCanRender(true) + } + }) + } else { + setCanRender(false) + } + + return () => { + if (rafRef.current) { + cancelAnimationFrame(rafRef.current) + } + } + }, [condition]) + + return canRender +} diff --git a/apps/mobile/src/screens/FiatOnRampConnecting.tsx b/apps/mobile/src/screens/FiatOnRampConnecting.tsx index 4ad7e94e11f..8e526d28038 100644 --- a/apps/mobile/src/screens/FiatOnRampConnecting.tsx +++ b/apps/mobile/src/screens/FiatOnRampConnecting.tsx @@ -106,7 +106,7 @@ export function FiatOnRampConnectingScreen({ navigation }: Props): JSX.Element | refundWalletAddress: activeAccountAddress, externalCustomerId: activeAccountAddress, externalSessionId: externalTransactionId, - redirectUrl: `${uniswapUrls.redirectUrlBase}?screen=transaction&fiatOffRamp=true&userAddress=${activeAccountAddress}`, + redirectUrl: `${uniswapUrls.redirectUrlBase}?screen=transaction&fiatOffRamp=true&userAddress=${activeAccountAddress}&externalTransactionId=${externalTransactionId}`, } : skipToken, ) diff --git a/apps/mobile/src/screens/FiatOnRampScreen.tsx b/apps/mobile/src/screens/FiatOnRampScreen.tsx index 14a0045050e..003a9966bd1 100644 --- a/apps/mobile/src/screens/FiatOnRampScreen.tsx +++ b/apps/mobile/src/screens/FiatOnRampScreen.tsx @@ -366,6 +366,14 @@ export function FiatOnRampScreen({ navigation }: Props): JSX.Element { }) const onSelectCurrency = (currency: FORCurrencyOrBalance): void => { + if (isTokenInputMode) { + resetAmount() + } else { + setSelectedQuote(undefined) + // This is done for formatting reasons. The existing value may change if max decimals of new currency is different + onChangeValue(value, 'changeAsset') + } + setShowTokenSelector(false) if (isSupportedFORCurrency(currency)) { setQuoteCurrency(currency) @@ -427,14 +435,18 @@ export function FiatOnRampScreen({ navigation }: Props): JSX.Element { } }, [navigateToSwapFlow, unsupportedCurrency]) - const onPillToggle = (option: string | number): void => { - setIsOffRamp(option === RampToggle.SELL) - + const resetAmount = useCallback(() => { setValue('') setFiatAmount(0) setTokenAmount(0) valueRef.current = '' resetSelection({ start: 0 }) + setSelectedQuote(undefined) + }, [setValue, setFiatAmount, setTokenAmount, valueRef, resetSelection, setSelectedQuote]) + + const onPillToggle = (option: string | number): void => { + setIsOffRamp(option === RampToggle.SELL) + resetAmount() setQuoteCurrency(defaultCurrency) sendAnalyticsEvent(FiatOffRampEventName.FORBuySellToggled, { diff --git a/apps/mobile/src/screens/HomeScreen.tsx b/apps/mobile/src/screens/HomeScreen.tsx index 4b934ca32bd..97d1ac6c8a6 100644 --- a/apps/mobile/src/screens/HomeScreen.tsx +++ b/apps/mobile/src/screens/HomeScreen.tsx @@ -15,7 +15,6 @@ import Animated, { useDerivedValue, useSharedValue, } from 'react-native-reanimated' -import { SvgProps } from 'react-native-svg' import { SceneRendererProps, TabBar } from 'react-native-tab-view' import { useDispatch, useSelector } from 'react-redux' import { NavBar, SWAP_BUTTON_HEIGHT } from 'src/app/navigation/NavBar' @@ -45,16 +44,12 @@ import { openModal } from 'src/features/modals/modalSlice' import { selectSomeModalOpen } from 'src/features/modals/selectSomeModalOpen' import { AIAssistantOverlay } from 'src/features/openai/AIAssistantOverlay' import { useWalletRestore } from 'src/features/wallet/hooks' -import { removePendingSession } from 'src/features/walletConnect/walletConnectSlice' import { HomeScreenTabIndex } from 'src/screens/HomeScreenTabIndex' import { useHapticFeedback } from 'src/utils/haptics/useHapticFeedback' import { hideSplashScreen } from 'src/utils/splashScreen' import { useOpenBackupReminderModal } from 'src/utils/useOpenBackupReminderModal' -import { Flex, Text, TouchableArea, useMedia, useSporeColors } from 'ui/src' -import ReceiveIcon from 'ui/src/assets/icons/arrow-down-circle.svg' -import BuyIcon from 'ui/src/assets/icons/buy.svg' -import ScanIcon from 'ui/src/assets/icons/scan-home.svg' -import SendIcon from 'ui/src/assets/icons/send-action.svg' +import { Flex, GeneratedIcon, Text, TouchableArea, useMedia, useSporeColors } from 'ui/src' +import { ArrowDownCircle, Buy, SendAction } from 'ui/src/components/icons' import { AnimatedFlex } from 'ui/src/components/layout/AnimatedFlex' import { useDeviceDimensions } from 'ui/src/hooks/useDeviceDimensions' import { iconSizes, spacing } from 'ui/src/theme' @@ -376,12 +371,6 @@ export function HomeScreen(props?: AppStackScreenProp): JSX. await hapticFeedback.light() }, [hapticFeedback]) - const onPressScan = useCallback(async () => { - // in case we received a pending session from a previous scan after closing modal - dispatch(removePendingSession()) - dispatch(openModal({ name: ModalName.WalletConnectScan, initialState: ScannerModalState.ScanQr })) - await triggerHaptics() - }, [dispatch, triggerHaptics]) const onPressSend = useCallback(async () => { dispatch(openModal({ name: ModalName.Send })) await triggerHaptics() @@ -400,11 +389,6 @@ export function HomeScreen(props?: AppStackScreenProp): JSX. // Hide actions when active account isn't a signer account. const isSignerAccount = activeAccount.type === AccountType.SignerMnemonic - // Necessary to declare these as direct dependencies due to race condition with initializing react-i18next and useMemo - const buyLabel = t('home.label.buy') - const sendLabel = t('home.label.send') - const receiveLabel = t('home.label.receive') - const scanLabel = t('home.label.scan') const [isTestnetWarningModalOpen, setIsTestnetWarningModalOpen] = useState(false) @@ -425,41 +409,34 @@ export function HomeScreen(props?: AppStackScreenProp): JSX. ) }, [dispatch, isTestnetModeEnabled, disableForKorea, triggerHaptics]) + // Necessary to declare these as direct dependencies due to race condition with initializing react-i18next and useMemo + const buyLabel = t('home.label.buy') + const sendLabel = t('home.label.send') + const receiveLabel = t('home.label.receive') + const actions = useMemo( (): QuickAction[] => [ { - Icon: BuyIcon, + Icon: Buy, eventName: MobileEventName.FiatOnRampQuickActionButtonPressed, - iconScale: 1.2, label: buyLabel, name: ElementName.Buy, - sentryLabel: 'BuyActionButton', onPress: onPressBuy, }, { - Icon: SendIcon, - iconScale: 1.1, + Icon: SendAction, label: sendLabel, name: ElementName.Send, - sentryLabel: 'SendActionButton', onPress: onPressSend, }, { - Icon: ReceiveIcon, + Icon: ArrowDownCircle, label: receiveLabel, name: ElementName.Receive, - sentryLabel: 'ReceiveActionButton', onPress: onPressReceive, }, - { - Icon: ScanIcon, - label: scanLabel, - name: ElementName.WalletConnectScan, - sentryLabel: 'ScanActionButton', - onPress: onPressScan, - }, ], - [buyLabel, sendLabel, scanLabel, receiveLabel, onPressBuy, onPressScan, onPressSend, onPressReceive], + [buyLabel, sendLabel, receiveLabel, onPressBuy, onPressSend, onPressReceive], ) // This hooks handles the logic for when to open the BackupReminderModal @@ -479,12 +456,7 @@ export function HomeScreen(props?: AppStackScreenProp): JSX. const contentHeader = useMemo(() => { return ( - + ): JSX. onClose={handleTestnetWarningModalClose} /> - + {isSignerAccount ? ( - + ) : ( - + - + {viewOnlyLabel} @@ -797,69 +769,51 @@ export function HomeScreen(props?: AppStackScreenProp): JSX. } type QuickAction = { - Icon: React.FC + /* Icon to display for the action */ + Icon: GeneratedIcon + /* Event name to log when the action is triggered */ eventName?: MobileEventName - iconScale?: number + /* Label to display for the action */ label: string + /* Name of the element to log when the action is triggered */ name: ElementNameType - sentryLabel: string + /* Callback to execute when the action is triggered */ onPress: () => void } +/** + * CTA buttons that appear at top of the screen showing actions such as + * "Send", "Receive", "Buy" etc. + */ function QuickActions({ actions }: { actions: QuickAction[] }): JSX.Element { + const colors = useSporeColors() + const iconSize = iconSizes.icon24 + const contentColor = colors.accent1.val + const activeScale = 0.96 + return ( - {actions.map((action) => ( - + {actions.map(({ eventName, name, label, Icon, onPress }) => ( + + + + + + {label} + + + + ))} ) } - -function ActionButton({ - eventName, - name, - Icon, - onPress, - flex, - activeScale = 0.96, - iconScale = 1, -}: { - eventName?: MobileEventName - name: ElementNameType - label: string - Icon: React.FC - onPress: () => void - flex: number - activeScale?: number - iconScale?: number -}): JSX.Element { - const colors = useSporeColors() - const media = useMedia() - const iconSize = media.short ? iconSizes.icon24 : iconSizes.icon28 - - return ( - - - - - - - - ) -} diff --git a/apps/mobile/src/screens/Import/OnDeviceRecoveryScreen.tsx b/apps/mobile/src/screens/Import/OnDeviceRecoveryScreen.tsx index 68a845df2a3..0e5e06d3fb1 100644 --- a/apps/mobile/src/screens/Import/OnDeviceRecoveryScreen.tsx +++ b/apps/mobile/src/screens/Import/OnDeviceRecoveryScreen.tsx @@ -29,6 +29,7 @@ import { TestID } from 'uniswap/src/test/fixtures/testIDs' import { ImportType, OnboardingEntryPoint } from 'uniswap/src/types/onboarding' import { OnboardingScreens } from 'uniswap/src/types/screens/mobile' import { areAddressesEqual } from 'uniswap/src/utils/addresses' +import { getCloudProviderName } from 'uniswap/src/utils/cloud-backup/getCloudProviderName' import { logger } from 'utilities/src/logger/logger' import { useTimeout } from 'utilities/src/time/timing' import { useOnboardingContext } from 'wallet/src/features/onboarding/OnboardingContext' @@ -249,7 +250,9 @@ export function OnDeviceRecoveryScreen({ } diff --git a/apps/mobile/src/screens/SettingsScreen.tsx b/apps/mobile/src/screens/SettingsScreen.tsx index 7b73bbbf7f2..dbbe247e3ca 100644 --- a/apps/mobile/src/screens/SettingsScreen.tsx +++ b/apps/mobile/src/screens/SettingsScreen.tsx @@ -111,6 +111,7 @@ export function SettingsScreen(): JSX.Element { const fireAnalytic = (): void => sendAnalyticsEvent(WalletEventName.TestnetModeToggled, { enabled: newIsTestnetMode, + location: 'settings', }) setTimeout(() => { diff --git a/apps/mobile/src/screens/SettingsWallet.tsx b/apps/mobile/src/screens/SettingsWallet.tsx index f277caad24a..66afd8077aa 100644 --- a/apps/mobile/src/screens/SettingsWallet.tsx +++ b/apps/mobile/src/screens/SettingsWallet.tsx @@ -1,6 +1,6 @@ -import { useFocusEffect, useNavigation } from '@react-navigation/core' +import { useNavigation } from '@react-navigation/core' import { NativeStackScreenProps } from '@react-navigation/native-stack' -import React, { useCallback, useEffect, useState } from 'react' +import React, { memo, useEffect } from 'react' import { useTranslation } from 'react-i18next' import { ListRenderItemInfo, SectionList } from 'react-native' import { SvgProps } from 'react-native-svg' @@ -20,12 +20,7 @@ import { import { BackHeader } from 'src/components/layout/BackHeader' import { Screen } from 'src/components/layout/Screen' import { openModal } from 'src/features/modals/modalSlice' -import { promptPushPermission } from 'src/features/notifications/Onesignal' -import { - NotificationPermission, - useNotificationOSPermissionsEnabled, -} from 'src/features/notifications/hooks/useNotificationOSPermissionsEnabled' -import { showNotificationSettingsAlert } from 'src/screens/Onboarding/NotificationsSetupScreen' +import { useNotificationToggle } from 'src/features/notifications/hooks/useNotificationsToggle' import { Button, Flex, Switch, Text, useSporeColors } from 'ui/src' import NotificationIcon from 'ui/src/assets/icons/bell.svg' import GlobalIcon from 'ui/src/assets/icons/global.svg' @@ -40,11 +35,14 @@ import { useUnitagByAddress } from 'uniswap/src/features/unitags/hooks' import { TestID } from 'uniswap/src/test/fixtures/testIDs' import { MobileScreens, UnitagScreens } from 'uniswap/src/types/screens/mobile' import { AddressDisplay } from 'wallet/src/components/accounts/AddressDisplay' -import { EditAccountAction, editAccountActions } from 'wallet/src/features/wallet/accounts/editAccountSaga' -import { useAccounts, useSelectAccountNotificationSetting } from 'wallet/src/features/wallet/hooks' +import { useAccounts } from 'wallet/src/features/wallet/hooks' type Props = NativeStackScreenProps +const onPermissionChanged = (enabled: boolean): void => { + sendAnalyticsEvent(MobileEventName.NotificationsToggled, { enabled }) +} + // Specific design request not in standard sizing type const UNICON_ICON_SIZE = 56 @@ -64,10 +62,6 @@ export function SettingsWallet({ const readonly = currentAccount?.type === AccountType.Readonly const navigation = useNavigation() - const notificationOSPermission = useNotificationOSPermissionsEnabled() - const notificationsEnabledOnFirebase = useSelectAccountNotificationSetting(address) - const [notificationSwitchEnabled, setNotificationSwitchEnabled] = useState(notificationsEnabledOnFirebase) - const showEditProfile = !readonly useEffect(() => { @@ -77,47 +71,6 @@ export function SettingsWallet({ } }, [currentAccount, navigation]) - // Need to trigger a state update when the user backgrounds the app to enable notifications and then returns to this screen - useFocusEffect( - useCallback( - () => - setNotificationSwitchEnabled( - notificationsEnabledOnFirebase && notificationOSPermission === NotificationPermission.Enabled, - ), - [notificationOSPermission, notificationsEnabledOnFirebase], - ), - ) - - const onChangeNotificationSettings = async (enabled: boolean): Promise => { - sendAnalyticsEvent(MobileEventName.NotificationsToggled, { enabled }) - - if (notificationOSPermission === NotificationPermission.Enabled) { - dispatch( - editAccountActions.trigger({ - type: EditAccountAction.TogglePushNotification, - enabled, - address, - }), - ) - setNotificationSwitchEnabled(enabled) - } else { - const arePushNotificationsEnabled = await promptPushPermission() - - if (arePushNotificationsEnabled) { - dispatch( - editAccountActions.trigger({ - type: EditAccountAction.TogglePushNotification, - enabled: true, - address, - }), - ) - setNotificationSwitchEnabled(enabled) - } else { - showNotificationSettingsAlert() - } - } - } - const iconProps: SvgProps = { color: colors.neutral2.get(), height: iconSizes.icon24, @@ -141,14 +94,7 @@ export function SettingsWallet({ data: [ ...(showEditProfile ? [] : [editNicknameSectionOption]), { - action: ( - - ), + action: , text: t('settings.setting.wallet.notifications.title'), icon: , }, @@ -267,3 +213,13 @@ function AddressDisplayHeader({ address }: { address: Address }): JSX.Element { ) } + +const NotificationsSwitch: React.FC<{ address: Address }> = memo(({ address }) => { + const { isEnabled, isPending, toggle } = useNotificationToggle({ + address, + onPermissionChanged, + }) + return +}) + +NotificationsSwitch.displayName = 'NotificationsSwitch' diff --git a/apps/mobile/src/test/render.tsx b/apps/mobile/src/test/render.tsx index 144fb1f89fe..07ad7b52898 100644 --- a/apps/mobile/src/test/render.tsx +++ b/apps/mobile/src/test/render.tsx @@ -12,7 +12,7 @@ import { import React, { PropsWithChildren } from 'react' import { MobileWalletNavigationProvider } from 'src/app/MobileWalletNavigationProvider' import type { MobileState } from 'src/app/mobileReducer' -import { navigationRef } from 'src/app/navigation/NavigationContainer' +import { navigationRef } from 'src/app/navigation/navigationRef' import { store as appStore, persistedReducer } from 'src/app/store' import { BlankUrlProvider } from 'uniswap/src/contexts/UrlContext' import { Resolvers } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' diff --git a/apps/web/.depcheckrc b/apps/web/.depcheckrc index 51d548ce02b..8c4c1f18535 100644 --- a/apps/web/.depcheckrc +++ b/apps/web/.depcheckrc @@ -13,6 +13,7 @@ ignores: [ 'process', 'madge', # Dependencies that depcheck thinks are missing but are actually present or never used + 'stories', ## package.json scripts 'esbuild-register', ## GraphQL @@ -30,6 +31,17 @@ ignores: [ '@babel/preset-env', 'eslint-plugin-import', 'terser-webpack-plugin', + ## Storybook + '@svgr/webpack', + 'ts-loader', + '@chromatic-com/storybook', + '@storybook/addon-essentials', + '@storybook/addon-interactions', + '@storybook/addon-onboarding', + '@storybook/blocks', + '@storybook/preset-create-react-app', + 'eslint-plugin-storybook', + 'prop-types', ## Testing '@types/testing-library__cypress', ## i18n diff --git a/apps/web/.env b/apps/web/.env index 8dec521b23f..96f506e8adf 100644 --- a/apps/web/.env +++ b/apps/web/.env @@ -15,6 +15,7 @@ REACT_APP_QUICKNODE_BASE_RPC_URL="" REACT_APP_QUICKNODE_BLAST_RPC_URL="" REACT_APP_QUICKNODE_BNB_RPC_URL="" REACT_APP_QUICKNODE_CELO_RPC_URL="" +REACT_APP_QUICKNODE_MONAD_TESTNET_RPC_URL="" REACT_APP_QUICKNODE_OP_RPC_URL="" REACT_APP_QUICKNODE_POLYGON_RPC_URL="" REACT_APP_MOONPAY_API="https://api.moonpay.com" diff --git a/apps/web/.eslintignore b/apps/web/.eslintignore index 4f714642634..2cd488e0b43 100644 --- a/apps/web/.eslintignore +++ b/apps/web/.eslintignore @@ -3,3 +3,4 @@ babel.config.js jest.config.js metro.config.js node_modules +.storybook/stories diff --git a/apps/web/.eslintrc.js b/apps/web/.eslintrc.js index 632b9b31856..236302231ed 100644 --- a/apps/web/.eslintrc.js +++ b/apps/web/.eslintrc.js @@ -8,7 +8,7 @@ rulesDirPlugin.RULES_DIR = 'eslint_rules' module.exports = { root: true, - extends: ['@uniswap/eslint-config/react'], + extends: ['@uniswap/eslint-config/react', 'plugin:storybook/recommended'], plugins: ['rulesdir'], rules: { diff --git a/apps/web/.gitignore b/apps/web/.gitignore index e71747f7c4c..9ae70a016f8 100644 --- a/apps/web/.gitignore +++ b/apps/web/.gitignore @@ -54,3 +54,5 @@ cypress/screenshots .vercel .wrangler + +*storybook.log diff --git a/apps/web/.storybook/main.ts b/apps/web/.storybook/main.ts new file mode 100644 index 00000000000..1ef2c002d7d --- /dev/null +++ b/apps/web/.storybook/main.ts @@ -0,0 +1,71 @@ +import type { StorybookConfig } from '@storybook/react-webpack5' + +import { dirname, join, resolve } from 'path' + +/** + * This function is used to resolve the absolute path of a package. + * It is needed in projects that use Yarn PnP or are set up within a monorepo. + */ +function getAbsolutePath(value: string): any { + return dirname(require.resolve(join(value, 'package.json'))) +} +const config: StorybookConfig = { + stories: ['../../../packages/ui/**/*.stories.?(ts|tsx)', '../../../packages/ui/**/*.mdx'], + addons: [ + getAbsolutePath('@storybook/preset-create-react-app'), + getAbsolutePath('@storybook/addon-onboarding'), + getAbsolutePath('@storybook/addon-essentials'), + getAbsolutePath('@chromatic-com/storybook'), + getAbsolutePath('@storybook/addon-interactions'), + ], + framework: { + name: getAbsolutePath('@storybook/react-webpack5'), + options: {}, + }, + staticDirs: ['../public'], + webpackFinal: (config) => { + // This modifies the existing image rule to exclude `.svg` files + // since we handle those with `@svgr/webpack`. + const imageRule = + config?.module?.rules && + config.module.rules.find((rule) => { + if (rule && typeof rule !== 'string' && rule.test instanceof RegExp) { + return rule.test.test('.svg') + } + + return + }) + + if (imageRule && typeof imageRule !== 'string') { + imageRule.exclude = /\.svg$/i + } + + config?.module?.rules && + config.module.rules.push({ + test: /\.svg$/i, + use: ['@svgr/webpack'], + }) + + config?.module?.rules && + config.module.rules.push({ + test: /\.tsx?$/, + use: 'ts-loader', + exclude: /node_modules/, + }) + + config.resolve ??= {} + + config.resolve = { + ...config.resolve, + alias: { + ...config?.resolve?.alias, + 'react-native$': 'react-native-web', + }, + } + + config.resolve.modules = [resolve(__dirname, '../src'), 'node_modules'] + + return config + }, +} +export default config diff --git a/apps/web/.storybook/preview.tsx b/apps/web/.storybook/preview.tsx new file mode 100644 index 00000000000..cf3573878ce --- /dev/null +++ b/apps/web/.storybook/preview.tsx @@ -0,0 +1,23 @@ +import type { Preview } from '@storybook/react' +import { TamaguiProvider } from '../src/theme/tamaguiProvider' + +const preview: Preview = { + decorators: [ + (Story) => ( + + {/* 👇 Decorators in Storybook also accept a function. Replace with Story() to enable it */} + + + ), + ], + parameters: { + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i, + }, + }, + }, +} + +export default preview diff --git a/apps/web/craco.config.cjs b/apps/web/craco.config.cjs index 19f85c7cc09..eb0212912fd 100644 --- a/apps/web/craco.config.cjs +++ b/apps/web/craco.config.cjs @@ -5,7 +5,7 @@ const { execSync } = require('child_process') const { readFileSync } = require('fs') const MiniCssExtractPlugin = require('mini-css-extract-plugin') const path = require('path') -const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin') +const ModuleScopePlugin = require(path.resolve(__dirname, '..', '..','node_modules/react-scripts/node_modules/react-dev-utils/ModuleScopePlugin')) const { IgnorePlugin, ProvidePlugin, DefinePlugin } = require('webpack') const { RetryChunkLoadPlugin } = require('webpack-retry-chunk-load-plugin') const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer') diff --git a/apps/web/package.json b/apps/web/package.json index e6fce74791b..43660261910 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -30,7 +30,9 @@ "test:cloud": "yarn jest functions --config=functions/jest.config.json", "cypress:open": "cypress open --browser chrome --e2e", "cypress:run": "cypress run --browser chrome --e2e", - "deduplicate": "yarn-deduplicate --strategy=highest" + "deduplicate": "yarn-deduplicate --strategy=highest", + "storybook:run": "storybook dev -p 6006", + "storybook:build": "storybook build" }, "husky": { "hooks": { @@ -70,10 +72,19 @@ }, "devDependencies": { "@babel/preset-env": "7.23.3", + "@chromatic-com/storybook": "3.2.2", "@cloudflare/workers-types": "4.20231025.0", "@craco/craco": "7.1.0", "@crowdin/cli": "3.14.0", "@ethersproject/experimental": "5.7.0", + "@storybook/addon-essentials": "8.4.2", + "@storybook/addon-interactions": "8.4.2", + "@storybook/addon-onboarding": "8.4.2", + "@storybook/blocks": "8.4.2", + "@storybook/preset-create-react-app": "8.4.2", + "@storybook/react": "8.4.2", + "@storybook/react-webpack5": "8.4.2", + "@storybook/test": "8.4.2", "@swc/core": "1.3.72", "@swc/jest": "0.2.29", "@swc/plugin-styled-components": "1.5.97", @@ -114,12 +125,14 @@ "concurrently": "8.2.2", "cypress": "12.17.4", "cypress-hardhat": "2.5.3", + "depcheck": "1.4.7", "dotenv": "16.0.3", "dotenv-cli": "7.1.0", "esbuild-register": "3.6.0", "eslint": "8.44.0", "eslint-plugin-import": "2.27.5", "eslint-plugin-rulesdir": "0.2.2", + "eslint-plugin-storybook": "0.8.0", "hardhat": "2.22.16", "husky": "8.0.3", "jest": "29.7.0", @@ -133,11 +146,13 @@ "path-browserify": "1.0.1", "postinstall-postinstall": "2.1.0", "process": "0.11.10", + "prop-types": "15.8.1", "react-scripts": "5.0.1", "resize-observer-polyfill": "1.5.1", "serve": "14.2.4", "source-map-explorer": "2.5.3", "start-server-and-test": "2.0.0", + "storybook": "8.4.2", "swc-loader": "0.2.6", "terser": "5.24.0", "terser-webpack-plugin": "5.3.9", @@ -172,6 +187,7 @@ "@sentry/core": "7.80.0", "@sentry/react": "7.80.0", "@sentry/types": "7.80.0", + "@svgr/webpack": "8.0.1", "@tamagui/core": "1.114.4", "@tamagui/portal": "1.114.4", "@tamagui/react-native-svg": "1.114.4", @@ -189,7 +205,7 @@ "@uniswap/permit2-sdk": "1.3.0", "@uniswap/redux-multicall": "1.1.8", "@uniswap/router-sdk": "1.15.0", - "@uniswap/sdk-core": "6.0.0", + "@uniswap/sdk-core": "6.1.0", "@uniswap/smart-order-router": "3.17.3", "@uniswap/token-lists": "1.0.0-beta.33", "@uniswap/uniswapx-sdk": "2.1.0-beta.18", @@ -269,6 +285,7 @@ "styled-components": "5.3.11", "tamagui": "1.114.4", "tiny-invariant": "1.3.1", + "ts-loader": "9.5.1", "typed-redux-saga": "1.5.0", "ui": "workspace:^", "uniswap": "workspace:^", diff --git a/apps/web/public/pools-sitemap.xml b/apps/web/public/pools-sitemap.xml index 8cb698084a0..17cd6ec1e94 100644 --- a/apps/web/public/pools-sitemap.xml +++ b/apps/web/public/pools-sitemap.xml @@ -7215,4 +7215,134 @@ 2024-12-06T22:01:49.956Z 0.8 + + https://app.uniswap.org/explore/pools/ethereum/0xc4ce8e63921b8b6cbdb8fcb6bd64cc701fb926f2 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x9febc984504356225405e26833608b17719c82ae + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x59c38b6775ded821f010dbd30ecabdcf84e04756 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x2aeee741fa1e21120a21e57db9ee545428e683c9 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/ethereum/0x67324985b5014b36b960273353deb3d96f2f18c2 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x2aeee741fa1e21120a21e57db9ee545428e683c9 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/arbitrum/0x67324985b5014b36b960273353deb3d96f2f18c2 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0x2aeee741fa1e21120a21e57db9ee545428e683c9 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/optimism/0x67324985b5014b36b960273353deb3d96f2f18c2 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0xcec31e540163ddf45a394e00b11ae442ddc0d704 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x7f9121b4f4e040fd066e9dc5c250cf9b4338d5bc + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x2aeee741fa1e21120a21e57db9ee545428e683c9 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/polygon/0x67324985b5014b36b960273353deb3d96f2f18c2 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x316f12517630903035a0e0b4d6e617593ee432ba + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x61928bf5f2895b682ecc9b13957aa5a5fe040cc0 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x9399da51c1a85e64cce4b30b554875d2b89b2445 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x0962a51e121aa8371cd4bb0458b7e5a08c1cbd29 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0xfbb6eed8e7aa03b138556eedaf5d271a5e1e43ef + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x2aeee741fa1e21120a21e57db9ee545428e683c9 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/base/0x67324985b5014b36b960273353deb3d96f2f18c2 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x913a4ed1636c474e6451b5e9249d94046a24bb33 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x8e3ecc0b261f1a4db62321090575eb299844f077 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x2aeee741fa1e21120a21e57db9ee545428e683c9 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/bnb/0x67324985b5014b36b960273353deb3d96f2f18c2 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x2aeee741fa1e21120a21e57db9ee545428e683c9 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/pools/celo/0x67324985b5014b36b960273353deb3d96f2f18c2 + 2024-12-13T21:22:32.347Z + 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 c15b7bd1992..34370852127 100644 --- a/apps/web/public/tokens-sitemap.xml +++ b/apps/web/public/tokens-sitemap.xml @@ -8385,4 +8385,249 @@ 2024-12-07T02:42:16.799Z 0.8 + + https://app.uniswap.org/explore/tokens/ethereum/0x9cdf242ef7975d8c68d5c1f5b6905801699b1940 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xadd39272e83895e7d3f244f696b7a25635f34234 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x0000000000c5dc95539589fbd24be07c6c14eca4 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xcab254f1a32343f11ab41fbde90ecb410cde348a + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x95ed629b028cf6aadd1408bb988c6d1daabe4767 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xa6c0c097741d55ecd9a3a7def3a8253fd022ceb9 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xd888a5460fffa4b14340dd9fe2710cbabd520659 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x683989afc948477fd38567f8327f501562c955ac + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x946fb08103b400d1c79e07acccdef5cfd26cd374 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x7076de6ff1d91e00be7e92458089c833de99e22e + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xadf7c35560035944e805d98ff17d58cde2449389 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x62b9c7356a2dc64a1969e19c23e4f579f9810aa7 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xd19b72e027cd66bde41d8f60a13740a26c4be8f3 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0x66a1e37c9b0eaddca17d3662d6c05f4decf3e110 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/ethereum/0xf477ac7719e2e659001455cdda0cc8f3ad10b604 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xe16e2548a576ad448fb014bbe85284d7f3542df5 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0x330bd769382cfc6d50175903434ccc8d206dcae5 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/arbitrum/0xb08d8becab1bf76a9ce3d2d5fa946f65ec1d3e83 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/optimism/0x8b21e9b7daf2c4325bf3d18c1beb79a347fe902a + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0xd9a9b4d466747e1ebcb7aeb42784452f40452367 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x306fd3e7b169aa4ee19412323e1a5995b8c1a1f4 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/polygon/0x9cb74c8032b007466865f060ad2c46145d45553d + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x333333c465a19c85f85c6cfbed7b16b0b26e3333 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xb9a5f238dc61eebe820060226c8143cd24624771 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xc48cddc6f2650bdb13dcf6681f61ba07209b5299 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xfb42da273158b0f642f59f2ba7cc1d5457481677 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x6f35720b272bf23832852b13ae9888c706e1a379 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x4498cd8ba045e00673402353f5a4347562707e7d + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x1035ae3f87a91084c6c5084d0615cc6121c5e228 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x3639e6f4c224ebd1bf6373c3d97917d33e0492bb + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x8bfac1b375bf2894d6f12fb2eb48b1c1a7916789 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xd27c288fd69f228e0c02f79e5ecadff962e05a2b + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x62ff28a01abd2484adb18c61f78f30fb2e4a6fdb + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x315b8c9a1123c10228d469551033440441b41f0b + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x1d008f50fb828ef9debbbeae1b71fffe929bf317 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xeec468333ccc16d4bf1cef497a56cf8c0aae4ca3 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x20dd04c17afd5c9a8b3f2cdacaa8ee7907385bef + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x25e0a7767d03461eaf88b47cd9853722fe05dfd3 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x22af33fe49fd1fa80c7149773dde5890d3c76f3b + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xbc1852f8940991d91bd2b09a5abb5e7b8092a16c + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x06a63c498ef95ad1fa4fff841955e512b4b2198a + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xeb6d78148f001f3aa2f588997c5e102e489ad341 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xa4dc5a82839a148ff172b5b8ba9d52e681fd2261 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xef22cb48b8483df6152e1423b19df5553bbd818b + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0xf83759099dc88f75fc83de854c41e0d9e83ada9b + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/base/0x844c03892863b0e3e00e805e41b34527044d5c72 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0xc9de725a4be9ab74b136c29d4731d6bebd7122e8 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x59e69094398afbea632f8bd63033bdd2443a3be1 + 2024-12-13T21:22:32.347Z + 0.8 + + + https://app.uniswap.org/explore/tokens/bnb/0x15f9eb4b9beafa9db35341c5694c0b6573809808 + 2024-12-13T21:22:32.347Z + 0.8 + \ No newline at end of file diff --git a/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/__snapshots__/CancelOrdersDialog.test.tsx.snap b/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/__snapshots__/CancelOrdersDialog.test.tsx.snap index ace2b75ed15..0d166ca2f84 100644 --- a/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/__snapshots__/CancelOrdersDialog.test.tsx.snap +++ b/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/__snapshots__/CancelOrdersDialog.test.tsx.snap @@ -7,42 +7,6 @@ exports[`CancelOrdersDialog should render limit order text 1`] = ` min-width: 0; } -.c7 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 4px; -} - -.c18 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - gap: 12px; -} - .c12 { color: #222222; -webkit-letter-spacing: -0.01em; @@ -226,6 +190,42 @@ exports[`CancelOrdersDialog should render limit order text 1`] = ` background-color: transparent; } +.c7 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 4px; +} + +.c18 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + gap: 12px; +} + .c5 { width: -webkit-fit-content; width: -moz-fit-content; @@ -626,42 +626,6 @@ exports[`CancelOrdersDialog should render order cancel correctly 1`] = ` min-width: 0; } -.c7 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 4px; -} - -.c18 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - gap: 12px; -} - .c12 { color: #222222; -webkit-letter-spacing: -0.01em; @@ -845,6 +809,42 @@ exports[`CancelOrdersDialog should render order cancel correctly 1`] = ` background-color: transparent; } +.c7 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 4px; +} + +.c18 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + gap: 12px; +} + .c5 { width: -webkit-fit-content; width: -moz-fit-content; diff --git a/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/__snapshots__/OffchainActivityModal.test.tsx.snap b/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/__snapshots__/OffchainActivityModal.test.tsx.snap index 6ce2c28549d..599221e9ea3 100644 --- a/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/__snapshots__/OffchainActivityModal.test.tsx.snap +++ b/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/__snapshots__/OffchainActivityModal.test.tsx.snap @@ -7,42 +7,6 @@ exports[`OrderContent should render without error, filled order 1`] = ` min-width: 0; } -.c2 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 12px; -} - -.c11 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between; - gap: 12px; -} - .c6 { color: #222222; -webkit-letter-spacing: -0.01em; @@ -93,6 +57,42 @@ exports[`OrderContent should render without error, filled order 1`] = ` background-color: #22222212; } +.c2 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 12px; +} + +.c11 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; + gap: 12px; +} + .c0 { display: -webkit-box; display: -webkit-flex; @@ -463,42 +463,6 @@ exports[`OrderContent should render without error, limit order 1`] = ` min-width: 0; } -.c2 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 12px; -} - -.c11 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between; - gap: 12px; -} - .c6 { color: #222222; -webkit-letter-spacing: -0.01em; @@ -621,6 +585,42 @@ exports[`OrderContent should render without error, limit order 1`] = ` background-color: transparent; } +.c2 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 12px; +} + +.c11 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; + gap: 12px; +} + .c0 { display: -webkit-box; display: -webkit-flex; @@ -1035,42 +1035,6 @@ exports[`OrderContent should render without error, open order 1`] = ` min-width: 0; } -.c2 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 12px; -} - -.c11 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between; - gap: 12px; -} - .c6 { color: #222222; -webkit-letter-spacing: -0.01em; @@ -1174,6 +1138,42 @@ exports[`OrderContent should render without error, open order 1`] = ` background-color: transparent; } +.c2 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 12px; +} + +.c11 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; + gap: 12px; +} + .c0 { display: -webkit-box; display: -webkit-flex; diff --git a/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/parseRemote.tsx b/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/parseRemote.tsx index 0d444503712..927a3bbddca 100644 --- a/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/parseRemote.tsx +++ b/apps/web/src/components/AccountDrawer/MiniPortfolio/Activity/parseRemote.tsx @@ -125,6 +125,11 @@ function callsV4PositionManagerContract(assetActivity: TransactionActivity) { return false } + // monad testnet does not have v4 support + if (supportedChain === UniverseChainId.MonadTestnet) { + return false + } + return isSameAddress(assetActivity.details.to, CHAIN_TO_ADDRESSES_MAP[supportedChain].v4PositionManagerAddress) } function callsPositionManagerContract(assetActivity: TransactionActivity) { diff --git a/apps/web/src/components/AccountDrawer/MiniPortfolio/Limits/__snapshots__/LimitDetailActivityRow.test.tsx.snap b/apps/web/src/components/AccountDrawer/MiniPortfolio/Limits/__snapshots__/LimitDetailActivityRow.test.tsx.snap index 2e610add542..4f5231548c7 100644 --- a/apps/web/src/components/AccountDrawer/MiniPortfolio/Limits/__snapshots__/LimitDetailActivityRow.test.tsx.snap +++ b/apps/web/src/components/AccountDrawer/MiniPortfolio/Limits/__snapshots__/LimitDetailActivityRow.test.tsx.snap @@ -7,6 +7,29 @@ exports[`LimitDetailActivityRow should render with valid details 1`] = ` min-width: 0; } +.c5 { + color: #7D7D7D; + -webkit-letter-spacing: -0.01em; + -moz-letter-spacing: -0.01em; + -ms-letter-spacing: -0.01em; + letter-spacing: -0.01em; +} + +.c10 { + color: #222222; + -webkit-letter-spacing: -0.01em; + -moz-letter-spacing: -0.01em; + -ms-letter-spacing: -0.01em; + letter-spacing: -0.01em; +} + +.c11 { + -webkit-letter-spacing: -0.01em; + -moz-letter-spacing: -0.01em; + -ms-letter-spacing: -0.01em; + letter-spacing: -0.01em; +} + .c1 { width: 100%; display: -webkit-box; @@ -42,29 +65,6 @@ exports[`LimitDetailActivityRow should render with valid details 1`] = ` gap: 4px; } -.c5 { - color: #7D7D7D; - -webkit-letter-spacing: -0.01em; - -moz-letter-spacing: -0.01em; - -ms-letter-spacing: -0.01em; - letter-spacing: -0.01em; -} - -.c10 { - color: #222222; - -webkit-letter-spacing: -0.01em; - -moz-letter-spacing: -0.01em; - -ms-letter-spacing: -0.01em; - letter-spacing: -0.01em; -} - -.c11 { - -webkit-letter-spacing: -0.01em; - -moz-letter-spacing: -0.01em; - -ms-letter-spacing: -0.01em; - letter-spacing: -0.01em; -} - .c6 { display: -webkit-box; display: -webkit-flex; diff --git a/apps/web/src/components/AccountDrawer/__snapshots__/index.test.tsx.snap b/apps/web/src/components/AccountDrawer/__snapshots__/index.test.tsx.snap index baee4aaab7c..4263b47ce17 100644 --- a/apps/web/src/components/AccountDrawer/__snapshots__/index.test.tsx.snap +++ b/apps/web/src/components/AccountDrawer/__snapshots__/index.test.tsx.snap @@ -39,6 +39,95 @@ exports[`AccountDrawer tests AccountDrawer default styles 1`] = ` flex: 1; } +.c36 { + color: #7D7D7D; + -webkit-letter-spacing: -0.01em; + -moz-letter-spacing: -0.01em; + -ms-letter-spacing: -0.01em; + letter-spacing: -0.01em; +} + +.c37 { + -webkit-text-decoration: none; + text-decoration: none; + cursor: pointer; + -webkit-transition-duration: 125ms; + transition-duration: 125ms; + color: #FC72FF; + stroke: #FC72FF; + font-weight: 500; +} + +.c37:hover { + opacity: 0.6; +} + +.c37:active { + opacity: 0.4; +} + +.c4 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.c10 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 16px; +} + +.c11 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 12px; +} + +.c26 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 12px; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; +} + .c8 { width: 100%; display: -webkit-box; @@ -158,95 +247,6 @@ exports[`AccountDrawer tests AccountDrawer default styles 1`] = ` margin: !important; } -.c36 { - color: #7D7D7D; - -webkit-letter-spacing: -0.01em; - -moz-letter-spacing: -0.01em; - -ms-letter-spacing: -0.01em; - letter-spacing: -0.01em; -} - -.c37 { - -webkit-text-decoration: none; - text-decoration: none; - cursor: pointer; - -webkit-transition-duration: 125ms; - transition-duration: 125ms; - color: #FC72FF; - stroke: #FC72FF; - font-weight: 500; -} - -.c37:hover { - opacity: 0.6; -} - -.c37:active { - opacity: 0.4; -} - -.c4 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c10 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 16px; -} - -.c11 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 12px; -} - -.c26 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 12px; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; -} - .c32 { display: -webkit-box; display: -webkit-flex; diff --git a/apps/web/src/components/Button/buttons.tsx b/apps/web/src/components/Button/buttons.tsx index a0f242a36f7..79af9e98acd 100644 --- a/apps/web/src/components/Button/buttons.tsx +++ b/apps/web/src/components/Button/buttons.tsx @@ -1,8 +1,6 @@ -import { RowBetween } from 'components/deprecated/Row' import styled, { DefaultTheme } from 'lib/styled-components' import { darken } from 'polished' import { forwardRef } from 'react' -import { ChevronDown } from 'react-feather' import { ButtonProps as ButtonPropsOriginal, Button as RebassButton } from 'rebass/styled-components' export { default as LoadingButtonSpinner } from './LoadingButtonSpinner' @@ -306,17 +304,6 @@ export function ButtonError({ error, ...rest }: { error?: boolean } & BaseButton } } -export function ButtonDropdownLight({ disabled = false, children, ...rest }: { disabled?: boolean } & ButtonProps) { - return ( - - -
{children}
- -
-
- ) -} - export enum ButtonSize { small, medium, diff --git a/apps/web/src/components/Charts/ActiveLiquidityChart/ActiveLiquidityChart2.tsx b/apps/web/src/components/Charts/ActiveLiquidityChart/ActiveLiquidityChart2.tsx index 52f27004bb5..6ae9d2482d2 100644 --- a/apps/web/src/components/Charts/ActiveLiquidityChart/ActiveLiquidityChart2.tsx +++ b/apps/web/src/components/Charts/ActiveLiquidityChart/ActiveLiquidityChart2.tsx @@ -1,4 +1,4 @@ -import { Currency } from '@uniswap/sdk-core' +import { Currency, Percent } from '@uniswap/sdk-core' import { AxisRight } from 'components/Charts/ActiveLiquidityChart/AxisRight' import { Brush2 } from 'components/Charts/ActiveLiquidityChart/Brush2' import { HorizontalArea } from 'components/Charts/ActiveLiquidityChart/HorizontalArea' @@ -7,7 +7,9 @@ import { TickTooltip } from 'components/Charts/ActiveLiquidityChart/TickTooltip' import { ChartEntry } from 'components/LiquidityChartRangeInput/types' import { max as getMax, scaleLinear } from 'd3' import { useEffect, useMemo, useRef, useState } from 'react' -import { useSporeColors } from 'ui/src' +import { Flex, Text, useSporeColors } from 'ui/src' +import { opacify } from 'ui/src/theme' +import { useFormatter } from 'utils/formatNumbers' const xAccessor = (d: ChartEntry) => d.activeLiquidity const yAccessor = (d: ChartEntry) => d.price0 @@ -53,6 +55,11 @@ function findClosestElementBinarySearch(data: ChartEntry[], target?: number) { return closestElement } +function scaleToInteger(a: number, precision = 18) { + const scaleFactor = Math.pow(10, precision) + return Math.round(a * scaleFactor) +} + /** * A horizontal version of the active liquidity area chart, which uses the * x-y coordinate plane to show the data, but with the axes flipped so lower @@ -69,6 +76,8 @@ export function ActiveLiquidityChart2({ brushDomain, onBrushDomainChange, disableBrushInteraction, + showDiffIndicators, + isMobile, }: { id?: string currency0: Currency @@ -80,10 +89,13 @@ export function ActiveLiquidityChart2({ max?: number } disableBrushInteraction?: boolean + showDiffIndicators?: boolean dimensions: { width: number; height: number; contentWidth: number; axisLabelPaneWidth: number } brushDomain?: [number, number] onBrushDomainChange: (domain: [number, number], mode: string | undefined) => void + isMobile?: boolean }) { + const { formatPercent } = useFormatter() const colors = useSporeColors() const svgRef = useRef(null) const [hoverY, setHoverY] = useState() @@ -124,6 +136,9 @@ export function ActiveLiquidityChart2({ } }, [brushDomain, onBrushDomainChange, yScale]) + const southHandleInView = brushDomain && yScale(brushDomain[0]) >= 0 && yScale(brushDomain[0]) <= height + const northHandleInView = brushDomain && yScale(brushDomain[1]) >= 0 && yScale(brushDomain[1]) <= height + return ( <> {hoverY && hoveredTick && ( @@ -138,6 +153,42 @@ export function ActiveLiquidityChart2({ currency1={currency1} /> )} + {showDiffIndicators && ( + <> + {southHandleInView && ( + + + {formatPercent(new Percent(scaleToInteger(brushDomain[0] - current), scaleToInteger(current)))} + + + )} + {northHandleInView && ( + + + {formatPercent(new Percent(scaleToInteger(brushDomain[1] - current), scaleToInteger(current)))} + + + )} + + )} @@ -209,14 +260,16 @@ export function ActiveLiquidityChart2({ /> )} - + {isMobile ? null : ( + + )} { + const { formatNumber } = useFormatter() const tickValues = useMemo(() => { const minCoordinate = min ? yScale(min) : undefined const maxCoordinate = max ? yScale(max) : undefined @@ -76,7 +78,18 @@ export const AxisRight = ({ return ( - + + formatNumber({ + input: d as number, + type: NumberType.TokenQuantityStats, + }), + )} + height={height} + yScale={yScale} + /> ) } diff --git a/apps/web/src/components/Charts/ActiveLiquidityChart/Brush2.tsx b/apps/web/src/components/Charts/ActiveLiquidityChart/Brush2.tsx index 9bc28b29e2e..88ecfc9a835 100644 --- a/apps/web/src/components/Charts/ActiveLiquidityChart/Brush2.tsx +++ b/apps/web/src/components/Charts/ActiveLiquidityChart/Brush2.tsx @@ -68,13 +68,17 @@ export const Brush2 = ({ // keep local and external brush extent in sync // i.e. snap to ticks on brush end + const [brushInProgress, setBrushInProgress] = useState(false) useEffect(() => { + if (brushInProgress) { + return + } setLocalBrushExtent(brushExtent) - }, [brushExtent]) + }, [brushExtent, brushInProgress]) // initialize the brush useEffect(() => { - if (!brushRef.current) { + if (!brushRef.current || brushInProgress) { return } @@ -90,8 +94,14 @@ export const Brush2 = ({ ]) .handleSize(30) .filter(() => interactive) + .filter((event) => { + // Allow interactions only if the event target is part of the brush selection or handles + const target = event.target as SVGElement + return target.classList.contains('selection') || target.classList.contains('handle') + }) .on('brush', (event: D3BrushEvent) => { const { selection } = event + setBrushInProgress(true) if (!selection) { setLocalBrushExtent(null) @@ -116,6 +126,7 @@ export const Brush2 = ({ setBrushExtent(priceExtent, mode) } setLocalBrushExtent(priceExtent) + setBrushInProgress(false) }) brushBehavior.current(select(brushRef.current)) @@ -126,6 +137,8 @@ export const Brush2 = ({ .call(brushBehavior.current.move as any, scaledExtent) } + select(brushRef.current).selectAll('.overlay').attr('cursor', 'default') + // brush linear gradient select(brushRef.current) .selectAll('.selection') @@ -133,7 +146,7 @@ export const Brush2 = ({ .attr('fill-opacity', '0.1') .attr('fill', `url(#${id}-gradient-selection)`) .attr('cursor', 'grab') - }, [brushExtent, id, height, interactive, previousBrushExtent, yScale, width, setBrushExtent]) + }, [brushExtent, id, height, interactive, previousBrushExtent, yScale, width, setBrushExtent, brushInProgress]) // respond to yScale changes only useEffect(() => { diff --git a/apps/web/src/components/Charts/ActiveLiquidityChart/HorizontalArea.tsx b/apps/web/src/components/Charts/ActiveLiquidityChart/HorizontalArea.tsx index 4ae58933129..1b46fadfd94 100644 --- a/apps/web/src/components/Charts/ActiveLiquidityChart/HorizontalArea.tsx +++ b/apps/web/src/components/Charts/ActiveLiquidityChart/HorizontalArea.tsx @@ -3,7 +3,6 @@ import { ScaleLinear } from 'd3' import styled from 'lib/styled-components' const Bar = styled.rect<{ fill?: string }>` - opacity: 0.5; stroke: ${({ fill, theme }) => fill ?? theme.accent1}; fill: ${({ fill, theme }) => fill ?? theme.accent1}; ` diff --git a/apps/web/src/components/Charts/LiquidityPositionRangeChart/LiquidityPositionRangeChart.tsx b/apps/web/src/components/Charts/LiquidityPositionRangeChart/LiquidityPositionRangeChart.tsx index 88fa63f1d39..b7f4d50ce6c 100644 --- a/apps/web/src/components/Charts/LiquidityPositionRangeChart/LiquidityPositionRangeChart.tsx +++ b/apps/web/src/components/Charts/LiquidityPositionRangeChart/LiquidityPositionRangeChart.tsx @@ -12,7 +12,6 @@ import { } from 'components/Charts/ChartModel' import { PriceChartData } from 'components/Charts/PriceChart' import { PriceChartType, formatTickMarks } from 'components/Charts/utils' -import { MissingDataIcon } from 'components/Table/icons' import { DataQuality } from 'components/Tokens/TokenDetails/ChartSection/util' import { usePoolPriceChartData } from 'hooks/usePoolPriceChartData' import { useTheme } from 'lib/styled-components' @@ -25,12 +24,11 @@ import { } from 'pages/Pool/Positions/create/utils' import { useLayoutEffect, useMemo, useRef, useState } from 'react' import { opacify } from 'theme/utils' -import { Flex, FlexProps, Shine, TamaguiElement, Text, assertWebElement } from 'ui/src' +import { Flex, FlexProps, Shine, TamaguiElement, assertWebElement } from 'ui/src' import { LoadingPriceCurve } from 'ui/src/components/icons/LoadingPriceCurve' import { HistoryDuration } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { getChainInfo } from 'uniswap/src/features/chains/chainInfo' import { UniverseChainId } from 'uniswap/src/features/chains/types' -import { useTranslation } from 'uniswap/src/i18n' const CHART_HEIGHT = 52 export const CHART_WIDTH = 224 @@ -115,7 +113,7 @@ export class LPPriceChartModel extends ChartModel { Math.pow(10, params.positionPriceLower.baseCurrency.decimals), ), ) - ?.toSignificant(params.positionPriceLower.baseCurrency.decimals) ?? 0, + ?.toSignificant(params.positionPriceLower.baseCurrency.decimals || 6) ?? 0, ) this.positionRangeMax = typeof params.positionPriceUpper === 'number' @@ -128,7 +126,7 @@ export class LPPriceChartModel extends ChartModel { Math.pow(10, params.positionPriceUpper.baseCurrency.decimals), ), ) - ?.toSignificant(params.positionPriceUpper.baseCurrency.decimals) ?? 0, + ?.toSignificant(params.positionPriceUpper.baseCurrency.decimals || 6) ?? 0, ) if (isEffectivelyInfinity(this.positionRangeMin)) { @@ -392,7 +390,6 @@ export function LiquidityPositionRangeChart({ grow = false, }: LiquidityPositionRangeChartProps) { const theme = useTheme() - const { t } = useTranslation() const isV2 = version === ProtocolVersion.V2 const isV3 = version === ProtocolVersion.V3 const isV4 = version === ProtocolVersion.V4 @@ -477,14 +474,7 @@ export function LiquidityPositionRangeChart({ overflow="hidden" > {priceData.loading && } - {dataUnavailable && ( - - - - {t('common.dataUnavailable')} - - - )} + {dataUnavailable && } {shouldRenderChart && ( diff --git a/apps/web/src/components/Charts/LiquidityRangeInput/LiquidityRangeInput.tsx b/apps/web/src/components/Charts/LiquidityRangeInput/LiquidityRangeInput.tsx index 8dd3fc69999..cef5fe0eb76 100644 --- a/apps/web/src/components/Charts/LiquidityRangeInput/LiquidityRangeInput.tsx +++ b/apps/web/src/components/Charts/LiquidityRangeInput/LiquidityRangeInput.tsx @@ -4,9 +4,11 @@ import { Currency } from '@uniswap/sdk-core' import { ActiveLiquidityChart2 } from 'components/Charts/ActiveLiquidityChart/ActiveLiquidityChart2' import { Chart } from 'components/Charts/ChartModel' import { LPPriceChartModel } from 'components/Charts/LiquidityPositionRangeChart/LiquidityPositionRangeChart' +import { useRangeInputSizes } from 'components/Charts/LiquidityRangeInput/constants' import { ChartErrorView } from 'components/Charts/LoadingState' import { getCandlestickPriceBounds } from 'components/Charts/PriceChart/utils' import { PriceChartType } from 'components/Charts/utils' +import { DropdownSelector } from 'components/DropdownSelector' import { useDensityChartData } from 'components/LiquidityChartRangeInput/hooks' import { DataQuality } from 'components/Tokens/TokenDetails/ChartSection/util' import { usePoolPriceChartData } from 'hooks/usePoolPriceChartData' @@ -15,23 +17,19 @@ import { getCurrencyWithWrap, getSortedCurrenciesTupleWithWrap, } from 'pages/Pool/Positions/create/utils' -import { useMemo, useState } from 'react' +import { useEffect, useMemo, useRef, useState } from 'react' +import { ClickableTamaguiStyle } from 'theme/components' import { Button, Flex, SegmentedControl, SegmentedControlOption, Shine, Text, useSporeColors } from 'ui/src' import { HorizontalDensityChart } from 'ui/src/components/icons/HorizontalDensityChart' import { LoadingPriceCurve } from 'ui/src/components/icons/LoadingPriceCurve' +import { RotatableChevron } from 'ui/src/components/icons/RotatableChevron' +import { RotateLeft } from 'ui/src/components/icons/RotateLeft' import { SearchMinus } from 'ui/src/components/icons/SearchMinus' import { SearchPlus } from 'ui/src/components/icons/SearchPlus' import { HistoryDuration } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { getChainInfo } from 'uniswap/src/features/chains/chainInfo' import { useTranslation } from 'uniswap/src/i18n' - -const RIGHT_AXIS_WIDTH = 64 -const CHART_CONTAINER_WIDTH = 452 + RIGHT_AXIS_WIDTH -const LIQUIDITY_CHART_WIDTH = 68 -const INTER_CHART_PADDING = 12 -const CHART_HEIGHT = 164 -const BOTTOM_AXIS_HEIGHT = 46 -const loadedPriceChartWidth = CHART_CONTAINER_WIDTH - LIQUIDITY_CHART_WIDTH - INTER_CHART_PADDING - RIGHT_AXIS_WIDTH +import { isMobileWeb } from 'utilities/src/platform' /** * Chart input for selecting the min/max prices for a liquidity position. @@ -99,27 +97,47 @@ export function LiquidityRangeInput({ return { dataMin, dataMax } }, [priceData.entries]) + const [midPrice, setMidPrice] = useState() + const [showDiffIndicators, setShowDiffIndicators] = useState(false) + + useEffect(() => { + if (priceData.entries.length > 0) { + setMidPrice(priceData.entries[priceData.entries.length - 1]?.value) + } + }, [priceData.entries]) + + const scrollIncrement = (dataMax - dataMin) / 10 + // Sets the min/max prices of the price axis manually, which is used to center the current price and zoom in/out. const { minVisiblePrice, maxVisiblePrice } = useMemo(() => { - const currentPrice = priceData.entries[priceData.entries.length - 1]?.value + if (!midPrice) { + return { + minVisiblePrice: dataMin, + maxVisiblePrice: dataMax, + } + } + const mostRecentPrice = priceData.entries[priceData.entries.length - 1]?.value // Calculate the default range based on the current price. - const maxSpread = Math.max(currentPrice - dataMin, dataMax - currentPrice) + const maxSpread = Math.max(mostRecentPrice - dataMin, dataMax - mostRecentPrice) // Initial unscaled range to fit all values with the current price centered const initialRange = 2 * maxSpread const newRange = initialRange / zoomFactor return { - minVisiblePrice: currentPrice - newRange / 2, - maxVisiblePrice: currentPrice + newRange / 2, + minVisiblePrice: midPrice - newRange / 2, + maxVisiblePrice: midPrice + newRange / 2, } - }, [dataMax, dataMin, priceData.entries, zoomFactor]) + }, [dataMax, dataMin, midPrice, priceData.entries, zoomFactor]) + + const containerRef = useRef(null) + const sizes = useRangeInputSizes(containerRef.current?.clientWidth) const priceChartParams = useMemo(() => { return { data: priceData.entries, stale: priceData.dataQuality === DataQuality.STALE, type: PriceChartType.LINE, - height: CHART_HEIGHT, + height: sizes.chartHeight, color: colors.accent1.val, currentPriceLineColor: colors.neutral2.val, showXAxis: true, @@ -127,20 +145,22 @@ export function LiquidityRangeInput({ maxVisiblePrice, setBoundaryPrices, isReversed, - disableExtendedTimeScale: true, + disableExtendedTimeScale: !isMobileWeb, + allowScrollInteractions: false, priceScaleMargins: { top: 0, bottom: 0, }, } as const }, [ + priceData.entries, + priceData.dataQuality, + sizes.chartHeight, colors.accent1.val, colors.neutral2.val, - isReversed, - priceData.dataQuality, - priceData.entries, - maxVisiblePrice, minVisiblePrice, + maxVisiblePrice, + isReversed, ]) const { formattedData, isLoading: liquidityDataLoading } = useDensityChartData({ @@ -158,28 +178,87 @@ export function LiquidityRangeInput({ }, [formattedData]) const timePeriodOptions = useMemo(() => { - const options: SegmentedControlOption[] = [ - [HistoryDuration.Day, t('token.priceExplorer.timeRangeLabel.day')], - [HistoryDuration.Week, t('token.priceExplorer.timeRangeLabel.week')], - [HistoryDuration.Month, t('token.priceExplorer.timeRangeLabel.month')], - [HistoryDuration.Year, t('token.priceExplorer.timeRangeLabel.year')], + const options: Array & { verboseDisplay: JSX.Element }> = [ + [ + HistoryDuration.Day, + t('token.priceExplorer.timeRangeLabel.day'), + t('token.priceExplorer.timeRangeLabel.day.verbose'), + ], + [ + HistoryDuration.Week, + t('token.priceExplorer.timeRangeLabel.week'), + t('token.priceExplorer.timeRangeLabel.week.verbose'), + ], + [ + HistoryDuration.Month, + t('token.priceExplorer.timeRangeLabel.month'), + t('token.priceExplorer.timeRangeLabel.month.verbose'), + ], + [ + HistoryDuration.Year, + t('token.priceExplorer.timeRangeLabel.year'), + t('token.priceExplorer.timeRangeLabel.year.verbose'), + ], [HistoryDuration.Max, t('token.priceExplorer.timeRangeLabel.all')], ].map((timePeriod) => ({ value: timePeriod[0] as HistoryDuration, display: {timePeriod[1]}, + verboseDisplay: {timePeriod[2] ?? timePeriod[1]}, })) return { options, selected: selectedHistoryDuration, } }, [selectedHistoryDuration, t]) + const [createDropdownOpen, setCreateDropdownOpen] = useState(false) const showChartErrorView = (!priceData.loading && priceData.entries.length === 0) || (!liquidityDataLoading && !sortedFormattedData) + useEffect(() => { + const container = containerRef.current + if (container && !disableBrushInteraction) { + let lastCall = 0 + const throttleDelayMs = 50 + + const listener = (event: WheelEvent) => { + event.preventDefault() + event.stopPropagation() + + const now = Date.now() + if (now - lastCall >= throttleDelayMs) { + lastCall = now + + if (event.deltaY < 0) { + setMidPrice((prevMidPrice) => (prevMidPrice ? prevMidPrice + scrollIncrement : undefined)) + } else if (event.deltaY > 0 && minVisiblePrice > 0) { + setMidPrice((prevMidPrice) => (prevMidPrice ? prevMidPrice - scrollIncrement : undefined)) + } + } + } + + container.addEventListener('wheel', listener) + + return () => { + container.removeEventListener('wheel', listener) + } + } + return undefined + }, [disableBrushInteraction, midPrice, minVisiblePrice, scrollIncrement]) + return ( - - + { + setShowDiffIndicators(true) + }} + onMouseLeave={() => { + setShowDiffIndicators(false) + }} + > + {showChartErrorView && ( @@ -188,21 +267,34 @@ export function LiquidityRangeInput({ )} {(priceData.loading || showChartErrorView) && (!priceData.entries || priceData.entries.length === 0) && ( - + )} - + {showChartErrorView ? null : ( + + )} - + {(liquidityDataLoading || priceData.loading) && ( - + )} {sortedFormattedData && !liquidityDataLoading && !priceData.loading && boundaryPrices && ( @@ -225,74 +317,147 @@ export function LiquidityRangeInput({ max: boundaryPrices[1], }} disableBrushInteraction={disableBrushInteraction} + showDiffIndicators={showDiffIndicators} brushDomain={minPrice && maxPrice ? [minPrice, maxPrice] : undefined} dimensions={{ - width: CHART_CONTAINER_WIDTH, - height: CHART_HEIGHT, - contentWidth: LIQUIDITY_CHART_WIDTH, - axisLabelPaneWidth: RIGHT_AXIS_WIDTH, + width: sizes.chartContainerWidth, + height: sizes.chartHeight, + contentWidth: sizes.liquidityChartWidth, + axisLabelPaneWidth: sizes.rightAxisWidth, }} - onBrushDomainChange={function (domain: [number, number]): void { + onBrushDomainChange={function (domain: [number, number], mode?: string): void { + // You can zoom out far enough to set an invalid range, so we prevent that here. if (domain[0] < 0) { return - } else { - setMinPrice(domain[0]) - setMaxPrice(domain[1]) } + // While scrolling we receive updates to the range because the yScale changes, + // but we can filter them out because they have an undefined "mode". + // The initial range suggestion also comes with an undefined "mode", so we allow that here. + const hasValidRange = + minPrice !== undefined && + maxPrice !== undefined && + minPrice < maxPrice && + minPrice >= 0 && + maxPrice >= 0 + if (!mode && hasValidRange) { + return + } + setMinPrice(domain[0]) + setMaxPrice(domain[1]) }} currency0={currency0} currency1={currency1} + isMobile={isMobileWeb} /> )} - - { - setSelectedHistoryDuration(option) - setZoomFactor(1) - setBoundaryPrices(undefined) - }} - /> - - - + + + {isMobileWeb ? ( + + {timePeriodOptions.options.find((p) => p.value === timePeriodOptions.selected)?.display} + + + } + buttonStyle={{ + borderWidth: 0, + p: 0, + }} + dropdownStyle={{ + width: 160, + }} + internalMenuItems={ + <> + {timePeriodOptions.options.map((p) => ( + { + setSelectedHistoryDuration(p.value) + setZoomFactor(1) + setBoundaryPrices(undefined) + }} + > + {p.verboseDisplay} + + ))} + + } + hideChevron={true} + isOpen={createDropdownOpen} + toggleOpen={() => { + setCreateDropdownOpen((prev) => !prev) + }} + /> + ) : ( + { + setSelectedHistoryDuration(option) + setZoomFactor(1) + setBoundaryPrices(undefined) + }} + /> + )} + + + + diff --git a/apps/web/src/components/Charts/LiquidityRangeInput/constants.ts b/apps/web/src/components/Charts/LiquidityRangeInput/constants.ts new file mode 100644 index 00000000000..565a96009b9 --- /dev/null +++ b/apps/web/src/components/Charts/LiquidityRangeInput/constants.ts @@ -0,0 +1,39 @@ +import { isMobileWeb } from 'utilities/src/platform' + +const RIGHT_AXIS_WIDTH = 64 +const CHART_CONTAINER_WIDTH = 452 + RIGHT_AXIS_WIDTH +const LIQUIDITY_CHART_WIDTH = 68 +const INTER_CHART_PADDING = 12 +const CHART_HEIGHT = 164 +const BOTTOM_AXIS_HEIGHT = 28 +const loadedPriceChartWidth = CHART_CONTAINER_WIDTH - LIQUIDITY_CHART_WIDTH - INTER_CHART_PADDING - RIGHT_AXIS_WIDTH + +const desktopSizes = { + rightAxisWidth: RIGHT_AXIS_WIDTH, + chartContainerWidth: CHART_CONTAINER_WIDTH, + liquidityChartWidth: LIQUIDITY_CHART_WIDTH, + interChartPadding: INTER_CHART_PADDING, + chartHeight: CHART_HEIGHT, + bottomAxisHeight: BOTTOM_AXIS_HEIGHT, + loadedPriceChartWidth, +} + +const mobileSizes = { + rightAxisWidth: 0, + chartContainerWidth: 290, + liquidityChartWidth: 48, + interChartPadding: 0, + chartHeight: CHART_HEIGHT, + bottomAxisHeight: BOTTOM_AXIS_HEIGHT, + loadedPriceChartWidth: 290, +} + +export function useRangeInputSizes(parentWidth?: number) { + return isMobileWeb + ? { + ...mobileSizes, + chartContainerWidth: parentWidth ?? mobileSizes.chartContainerWidth, + loadedPriceChartWidth: parentWidth ?? mobileSizes.loadedPriceChartWidth, + } + : desktopSizes +} diff --git a/apps/web/src/components/ConfirmSwapModal/__snapshots__/Pending.test.tsx.snap b/apps/web/src/components/ConfirmSwapModal/__snapshots__/Pending.test.tsx.snap index b463ae2cfa8..1e1b2e7d0c4 100644 --- a/apps/web/src/components/ConfirmSwapModal/__snapshots__/Pending.test.tsx.snap +++ b/apps/web/src/components/ConfirmSwapModal/__snapshots__/Pending.test.tsx.snap @@ -50,41 +50,6 @@ exports[`Pending - classic trade titles renders classic trade correctly, with ap min-height: 24px; } -.c13 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - gap: 8px; -} - -.c15 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; -} - .c10 { color: #222222; -webkit-letter-spacing: -0.01em; @@ -120,6 +85,41 @@ exports[`Pending - classic trade titles renders classic trade correctly, with ap opacity: 0.4; } +.c13 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + gap: 8px; +} + +.c15 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; +} + .c0 { display: -webkit-box; display: -webkit-flex; @@ -372,41 +372,6 @@ exports[`Pending - classic trade titles renders classic trade correctly, with ap min-height: 24px; } -.c13 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - gap: 8px; -} - -.c15 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; -} - .c10 { color: #222222; -webkit-letter-spacing: -0.01em; @@ -442,6 +407,41 @@ exports[`Pending - classic trade titles renders classic trade correctly, with ap opacity: 0.4; } +.c13 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + gap: 8px; +} + +.c15 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; +} + .c0 { display: -webkit-box; display: -webkit-flex; @@ -714,6 +714,22 @@ exports[`Pending - classic trade titles renders classic trade correctly, with ap min-height: 24px; } +.c12 { + color: #222222; + -webkit-letter-spacing: -0.01em; + -moz-letter-spacing: -0.01em; + -ms-letter-spacing: -0.01em; + letter-spacing: -0.01em; +} + +.c13 { + color: #7D7D7D; + -webkit-letter-spacing: -0.01em; + -moz-letter-spacing: -0.01em; + -ms-letter-spacing: -0.01em; + letter-spacing: -0.01em; +} + .c15 { width: 100%; display: -webkit-box; @@ -749,22 +765,6 @@ exports[`Pending - classic trade titles renders classic trade correctly, with ap justify-content: center; } -.c12 { - color: #222222; - -webkit-letter-spacing: -0.01em; - -moz-letter-spacing: -0.01em; - -ms-letter-spacing: -0.01em; - letter-spacing: -0.01em; -} - -.c13 { - color: #7D7D7D; - -webkit-letter-spacing: -0.01em; - -moz-letter-spacing: -0.01em; - -ms-letter-spacing: -0.01em; - letter-spacing: -0.01em; -} - .c0 { display: -webkit-box; display: -webkit-flex; @@ -1003,6 +1003,22 @@ exports[`Pending - uniswapX trade titles renders limit order correctly, with app min-width: 0; } +.c10 { + color: #222222; + -webkit-letter-spacing: -0.01em; + -moz-letter-spacing: -0.01em; + -ms-letter-spacing: -0.01em; + letter-spacing: -0.01em; +} + +.c11 { + color: #7D7D7D; + -webkit-letter-spacing: -0.01em; + -moz-letter-spacing: -0.01em; + -ms-letter-spacing: -0.01em; + letter-spacing: -0.01em; +} + .c13 { width: 100%; display: -webkit-box; @@ -1021,22 +1037,6 @@ exports[`Pending - uniswapX trade titles renders limit order correctly, with app gap: 8px; } -.c10 { - color: #222222; - -webkit-letter-spacing: -0.01em; - -moz-letter-spacing: -0.01em; - -ms-letter-spacing: -0.01em; - letter-spacing: -0.01em; -} - -.c11 { - color: #7D7D7D; - -webkit-letter-spacing: -0.01em; - -moz-letter-spacing: -0.01em; - -ms-letter-spacing: -0.01em; - letter-spacing: -0.01em; -} - .c0 { display: -webkit-box; display: -webkit-flex; @@ -1272,41 +1272,6 @@ exports[`Pending - uniswapX trade titles renders limit order correctly, with app min-height: 24px; } -.c13 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - gap: 8px; -} - -.c15 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; -} - .c10 { color: #222222; -webkit-letter-spacing: -0.01em; @@ -1342,6 +1307,41 @@ exports[`Pending - uniswapX trade titles renders limit order correctly, with app opacity: 0.4; } +.c13 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + gap: 8px; +} + +.c15 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; +} + .c0 { display: -webkit-box; display: -webkit-flex; @@ -1614,6 +1614,22 @@ exports[`Pending - uniswapX trade titles renders limit order correctly, with app min-height: 24px; } +.c12 { + color: #222222; + -webkit-letter-spacing: -0.01em; + -moz-letter-spacing: -0.01em; + -ms-letter-spacing: -0.01em; + letter-spacing: -0.01em; +} + +.c13 { + color: #7D7D7D; + -webkit-letter-spacing: -0.01em; + -moz-letter-spacing: -0.01em; + -ms-letter-spacing: -0.01em; + letter-spacing: -0.01em; +} + .c15 { width: 100%; display: -webkit-box; @@ -1649,22 +1665,6 @@ exports[`Pending - uniswapX trade titles renders limit order correctly, with app justify-content: center; } -.c12 { - color: #222222; - -webkit-letter-spacing: -0.01em; - -moz-letter-spacing: -0.01em; - -ms-letter-spacing: -0.01em; - letter-spacing: -0.01em; -} - -.c13 { - color: #7D7D7D; - -webkit-letter-spacing: -0.01em; - -moz-letter-spacing: -0.01em; - -ms-letter-spacing: -0.01em; - letter-spacing: -0.01em; -} - .c0 { display: -webkit-box; display: -webkit-flex; diff --git a/apps/web/src/components/Dialog/__snapshots__/Dialog.test.tsx.snap b/apps/web/src/components/Dialog/__snapshots__/Dialog.test.tsx.snap index 1da97ab5a08..b068ac30e96 100644 --- a/apps/web/src/components/Dialog/__snapshots__/Dialog.test.tsx.snap +++ b/apps/web/src/components/Dialog/__snapshots__/Dialog.test.tsx.snap @@ -7,42 +7,6 @@ exports[` renders different button types 1`] = ` min-width: 0; } -.c7 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 4px; -} - -.c16 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - gap: 12px; -} - .c12 { color: #222222; -webkit-letter-spacing: -0.01em; @@ -226,6 +190,42 @@ exports[` renders different button types 1`] = ` background-color: transparent; } +.c7 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 4px; +} + +.c16 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + gap: 12px; +} + .c5 { width: -webkit-fit-content; width: -moz-fit-content; @@ -568,42 +568,6 @@ exports[` renders the Dialog component correctly 1`] = ` min-width: 0; } -.c7 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 4px; -} - -.c16 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - gap: 12px; -} - .c12 { color: #222222; -webkit-letter-spacing: -0.01em; @@ -729,6 +693,42 @@ exports[` renders the Dialog component correctly 1`] = ` background-color: transparent; } +.c7 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 4px; +} + +.c16 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + gap: 12px; +} + .c5 { width: -webkit-fit-content; width: -moz-fit-content; diff --git a/apps/web/src/components/FeatureFlagModal/FeatureFlagModal.tsx b/apps/web/src/components/FeatureFlagModal/FeatureFlagModal.tsx index ae363746bf7..c623581790b 100644 --- a/apps/web/src/components/FeatureFlagModal/FeatureFlagModal.tsx +++ b/apps/web/src/components/FeatureFlagModal/FeatureFlagModal.tsx @@ -253,6 +253,7 @@ export default function FeatureFlagModal() { + diff --git a/apps/web/src/components/FiatOnrampModal/constants.ts b/apps/web/src/components/FiatOnrampModal/constants.ts deleted file mode 100644 index 8163c5649ea..00000000000 --- a/apps/web/src/components/FiatOnrampModal/constants.ts +++ /dev/null @@ -1,19 +0,0 @@ -export const MOONPAY_SUPPORTED_CURRENCY_CODES = [ - 'eth', - 'eth_arbitrum', - 'eth_optimism', - 'eth_polygon', - 'eth_base', - 'weth', - 'wbtc', - 'matic_polygon', - 'polygon', - 'usdc_arbitrum', - 'usdc_optimism', - 'usdc_polygon', - 'usdc_base', - 'usdc', - 'usdt', -] as const - -export type MoonpaySupportedCurrencyCode = (typeof MOONPAY_SUPPORTED_CURRENCY_CODES)[number] diff --git a/apps/web/src/components/FiatOnrampModal/index.tsx b/apps/web/src/components/FiatOnrampModal/index.tsx deleted file mode 100644 index f84e02083dc..00000000000 --- a/apps/web/src/components/FiatOnrampModal/index.tsx +++ /dev/null @@ -1,185 +0,0 @@ -import Circle from 'assets/images/blue-loader.svg' -import { MOONPAY_SUPPORTED_CURRENCY_CODES } from 'components/FiatOnrampModal/constants' -import { getDefaultCurrencyCode, parsePathParts } from 'components/FiatOnrampModal/utils' -import { useAccount } from 'hooks/useAccount' -import styled, { useTheme } from 'lib/styled-components' -import { useCallback, useEffect, useState } from 'react' -import { useHref } from 'react-router-dom' -import { useCloseModal, useModalIsOpen } from 'state/application/hooks' -import { ApplicationModal } from 'state/application/reducer' -import { CustomLightSpinner, ThemedText } from 'theme/components' -import { useIsDarkMode } from 'theme/components/ThemeToggle' -import { Modal } from 'uniswap/src/components/modals/Modal' -import { useUrlContext } from 'uniswap/src/contexts/UrlContext' -import { getChainInfo } from 'uniswap/src/features/chains/chainInfo' -import { ModalName } from 'uniswap/src/features/telemetry/constants' -import { Trans } from 'uniswap/src/i18n' -import { logger } from 'utilities/src/logger/logger' -import { getChainIdFromChainUrlParam } from 'utils/chainParams' - -const MOONPAY_DARK_BACKGROUND = '#1c1c1e' -const Wrapper = styled.div<{ isDarkMode: boolean }>` - // #1c1c1e is the background color for the darkmode moonpay iframe as of 2/16/2023 - background-color: ${({ isDarkMode, theme }) => (isDarkMode ? MOONPAY_DARK_BACKGROUND : theme.white)}; - border-radius: 20px; - box-shadow: ${({ theme }) => theme.deprecated_deepShadow}; - display: flex; - flex-flow: column nowrap; - margin: 0; - flex: 1 1; - min-width: 375px; - position: relative; - width: 100%; -` - -const ErrorText = styled(ThemedText.BodyPrimary)` - color: ${({ theme }) => theme.critical}; - margin: auto !important; - text-align: center; - width: 90%; -` -const StyledIframe = styled.iframe<{ isDarkMode: boolean }>` - // #1c1c1e is the background color for the darkmode moonpay iframe as of 2/16/2023 - background-color: ${({ isDarkMode, theme }) => (isDarkMode ? MOONPAY_DARK_BACKGROUND : theme.white)}; - border-radius: 12px; - bottom: 0; - left: 0; - height: calc(100% - 16px); - margin: 8px; - padding: 0; - position: absolute; - right: 0; - top: 0; - width: calc(100% - 16px); -` -const StyledSpinner = styled(CustomLightSpinner)` - bottom: 0; - left: 0; - margin: auto; - position: absolute; - right: 0; - top: 0; -` - -const MoonpayTextWrapper = styled.div` - position: absolute; - bottom: 20px; - margin: auto; - left: 0; - right: 0; - width: 100%; - text-align: center; -` - -export default function FiatOnrampModal() { - const account = useAccount() - const theme = useTheme() - const isDarkMode = useIsDarkMode() - const closeModal = useCloseModal() - const fiatOnrampModalOpen = useModalIsOpen(ApplicationModal.FIAT_ONRAMP) - - const { chainId, tokenAddress } = parsePathParts(location.pathname) - const chainInfo = chainId ? getChainInfo(chainId) : undefined - const { useParsedQueryString } = useUrlContext() - const parsedChainName = useParsedQueryString().chain - const queryChainId = typeof parsedChainName === 'string' ? getChainIdFromChainUrlParam(parsedChainName) : undefined - const queryChainInfo = queryChainId ? getChainInfo(queryChainId) : undefined - const accountChainInfo = account.chainId ? getChainInfo(account.chainId) : undefined - - const [signedIframeUrl, setSignedIframeUrl] = useState(null) - const [error, setError] = useState(null) - const [loading, setLoading] = useState(false) - - const swapUrl = useHref('/swap') - - const fetchSignedIframeUrl = useCallback(async () => { - if (!account.isConnected) { - setError('Please connect an account before making a purchase.') - return - } - setLoading(true) - setError(null) - try { - const signedIframeUrlFetchEndpoint = process.env.REACT_APP_MOONPAY_LINK as string - const res = await fetch(signedIframeUrlFetchEndpoint, { - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - method: 'POST', - body: JSON.stringify({ - theme: isDarkMode ? 'dark' : 'light', - colorCode: theme.accent1, - defaultCurrencyCode: getDefaultCurrencyCode( - tokenAddress, - chainInfo?.backendChain.chain ?? queryChainInfo?.backendChain.chain ?? accountChainInfo?.backendChain.chain, - ), - redirectUrl: swapUrl, - walletAddresses: JSON.stringify( - MOONPAY_SUPPORTED_CURRENCY_CODES.reduce( - (acc, currencyCode) => ({ - ...acc, - [currencyCode]: account.address, - }), - {}, - ), - ), - }), - }) - const { url } = await res.json() - setSignedIframeUrl(url) - } catch (e) { - logger.info('FiatOnrampModal', 'fetchSingedIframeUrl', 'there was an error fetching the link', e) - setError(e.toString()) - } finally { - setLoading(false) - } - }, [ - account.address, - account.isConnected, - accountChainInfo?.backendChain.chain, - chainInfo?.backendChain.chain, - isDarkMode, - queryChainInfo?.backendChain.chain, - swapUrl, - theme.accent1, - tokenAddress, - ]) - - useEffect(() => { - fetchSignedIframeUrl() - }, [fetchSignedIframeUrl]) - - return ( - closeModal()}> - - {error ? ( - <> - - - - - -
- {error} -
- - ) : loading ? ( - - ) : ( - - )} -
- - - - - -
- ) -} diff --git a/apps/web/src/components/FiatOnrampModal/utils.test.ts b/apps/web/src/components/FiatOnrampModal/utils.test.ts deleted file mode 100644 index ead2021ec65..00000000000 --- a/apps/web/src/components/FiatOnrampModal/utils.test.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { WETH9 } from '@uniswap/sdk-core' -import { getDefaultCurrencyCode, parsePathParts } from 'components/FiatOnrampModal/utils' -import { NATIVE_CHAIN_ID } from 'constants/tokens' -import { - MATIC_MAINNET, - USDC_ARBITRUM, - USDC_MAINNET, - USDC_OPTIMISM, - USDC_POLYGON, - USDT, - WBTC, - WETH_POLYGON, -} from 'uniswap/src/constants/tokens' -import { Chain } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' -import { UniverseChainId } from 'uniswap/src/features/chains/types' - -describe('getDefaultCurrencyCode', () => { - it('NATIVE/arbitrum should return the correct currency code', () => { - expect(getDefaultCurrencyCode(NATIVE_CHAIN_ID, Chain.Arbitrum)).toBe('eth_arbitrum') - }) - it('NATIVE/optimism should return the correct currency code', () => { - expect(getDefaultCurrencyCode(NATIVE_CHAIN_ID, Chain.Optimism)).toBe('eth_optimism') - }) - it('WETH/polygon should return the correct currency code', () => { - expect(getDefaultCurrencyCode(WETH_POLYGON.address, Chain.Polygon)).toBe('eth_polygon') - }) - it('WETH/ethereum should return the correct currency code', () => { - expect(getDefaultCurrencyCode(WETH9[UniverseChainId.Mainnet].address, Chain.Ethereum)).toBe('weth') - }) - it('WBTC/ethereum should return the correct currency code', () => { - expect(getDefaultCurrencyCode(WBTC.address, Chain.Ethereum)).toBe('wbtc') - }) - it('NATIVE/polygon should return the correct currency code', () => { - expect(getDefaultCurrencyCode(NATIVE_CHAIN_ID, Chain.Polygon)).toBe('matic_polygon') - }) - it('MATIC/ethereum should return the correct currency code', () => { - expect(getDefaultCurrencyCode(MATIC_MAINNET.address, Chain.Ethereum)).toBe('polygon') - }) - it('USDC/arbitrum should return the correct currency code', () => { - expect(getDefaultCurrencyCode(USDC_ARBITRUM.address, Chain.Arbitrum)).toBe('usdc_arbitrum') - }) - it('USDC/optimism should return the correct currency code', () => { - expect(getDefaultCurrencyCode(USDC_OPTIMISM.address, Chain.Optimism)).toBe('usdc_optimism') - }) - it('USDC/polygon should return the correct currency code', () => { - expect(getDefaultCurrencyCode(USDC_POLYGON.address, Chain.Polygon)).toBe('usdc_polygon') - }) - it('native/ethereum should return the correct currency code', () => { - expect(getDefaultCurrencyCode(NATIVE_CHAIN_ID, Chain.Ethereum)).toBe('eth') - }) - it('usdc/ethereum should return the correct currency code', () => { - expect(getDefaultCurrencyCode(USDC_MAINNET.address, Chain.Ethereum)).toBe('usdc') - }) - it('usdt/ethereum should return the correct currency code', () => { - expect(getDefaultCurrencyCode(USDT.address, Chain.Ethereum)).toBe('usdt') - }) - it('chain/token mismatch should default to eth', () => { - expect(getDefaultCurrencyCode(USDC_ARBITRUM.address, Chain.Ethereum)).toBe('eth') - expect(getDefaultCurrencyCode(USDC_OPTIMISM.address, Chain.Ethereum)).toBe('eth') - expect(getDefaultCurrencyCode(USDC_POLYGON.address, Chain.Ethereum)).toBe('eth') - expect(getDefaultCurrencyCode(MATIC_MAINNET.address, Chain.Arbitrum)).toBe('eth') - }) -}) - -describe('parseLocation', () => { - it('should parse the URL correctly', () => { - expect(parsePathParts('/tokens/ethereum/0x2260fac5e5542a773aa44fbcfedf7c193bc2c599')).toEqual({ - chainId: UniverseChainId.Mainnet, - tokenAddress: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', - }) - expect(parsePathParts('tokens/ethereum/0x2260fac5e5542a773aa44fbcfedf7c193bc2c599')).toEqual({ - chainId: UniverseChainId.Mainnet, - tokenAddress: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', - }) - expect(parsePathParts('/swap')).toEqual({ - chainId: undefined, - tokenAddress: undefined, - }) - }) -}) diff --git a/apps/web/src/components/FiatOnrampModal/utils.ts b/apps/web/src/components/FiatOnrampModal/utils.ts deleted file mode 100644 index b59a26a70aa..00000000000 --- a/apps/web/src/components/FiatOnrampModal/utils.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { WETH9 } from '@uniswap/sdk-core' -import { MoonpaySupportedCurrencyCode } from 'components/FiatOnrampModal/constants' -import { - MATIC_MAINNET, - USDC_ARBITRUM, - USDC_BASE, - USDC_MAINNET, - USDC_OPTIMISM, - USDC_POLYGON, - USDT, - WBTC, - WETH_POLYGON, -} from 'uniswap/src/constants/tokens' -import { Chain } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' -import { GqlChainId, UniverseChainId } from 'uniswap/src/features/chains/types' -import { getChainIdFromChainUrlParam } from 'utils/chainParams' - -type MoonpaySupportedChain = Chain.Ethereum | Chain.Polygon | Chain.Arbitrum | Chain.Optimism | Chain.Base -const moonPaySupportedChains = [Chain.Ethereum, Chain.Polygon, Chain.Arbitrum, Chain.Optimism, Chain.Base] -const isMoonpaySupportedChain = (chain?: Chain): chain is MoonpaySupportedChain => - !!chain && moonPaySupportedChains.includes(chain) - -const CURRENCY_CODES: { - [K in MoonpaySupportedChain]: { - [key: string]: MoonpaySupportedCurrencyCode - native: MoonpaySupportedCurrencyCode - } -} = { - [Chain.Ethereum]: { - [WETH9[UniverseChainId.Mainnet]?.address.toLowerCase()]: 'weth', - [USDC_MAINNET.address.toLowerCase()]: 'usdc', - [USDT.address.toLowerCase()]: 'usdt', - [WBTC.address.toLowerCase()]: 'wbtc', - [MATIC_MAINNET.address.toLowerCase()]: 'polygon', - native: 'eth', - }, - [Chain.Arbitrum]: { - [USDC_ARBITRUM.address.toLowerCase()]: 'usdc_arbitrum', - native: 'eth_arbitrum', - }, - [Chain.Optimism]: { - [USDC_OPTIMISM.address.toLowerCase()]: 'usdc_optimism', - native: 'eth_optimism', - }, - [Chain.Polygon]: { - [USDC_POLYGON.address.toLowerCase()]: 'usdc_polygon', - [WETH_POLYGON.address.toLowerCase()]: 'eth_polygon', - native: 'matic_polygon', - }, - [Chain.Base]: { - [USDC_BASE.address.toLowerCase()]: 'usdc_base', - native: 'eth_base', - }, -} - -export function getDefaultCurrencyCode(address?: string, gqlChain?: GqlChainId): MoonpaySupportedCurrencyCode { - if (!gqlChain) { - return 'eth' - } - if (!address) { - return isMoonpaySupportedChain(gqlChain) ? CURRENCY_CODES[gqlChain]?.native : 'eth' - } - if (isMoonpaySupportedChain(gqlChain)) { - const code = CURRENCY_CODES[gqlChain]?.[address.toLowerCase()] - return code ?? 'eth' - } - return 'eth' -} - -/** - * You should use useParams() from react-router-dom instead of this function if possible. - * This function is only used in the case where we need to parse the path outside the scope of the router. - */ -export function parsePathParts(pathname: string) { - const pathParts = pathname.split('/') - // Matches the /tokens// path. - const chainSlug = pathParts.length > 2 ? pathParts[pathParts.length - 2] : undefined - const chainId = getChainIdFromChainUrlParam(chainSlug) - const tokenAddress = pathParts.length > 2 ? pathParts[pathParts.length - 1] : undefined - return { chainId, tokenAddress } -} diff --git a/apps/web/src/components/Liquidity/LiquidityModalHeader.test.tsx b/apps/web/src/components/Liquidity/LiquidityModalHeader.test.tsx index 8c61b9ad1d5..7bb215340c3 100644 --- a/apps/web/src/components/Liquidity/LiquidityModalHeader.test.tsx +++ b/apps/web/src/components/Liquidity/LiquidityModalHeader.test.tsx @@ -2,13 +2,14 @@ import { LiquidityModalHeader } from 'components/Liquidity/LiquidityModalHeader' import { WebUniswapProvider } from 'components/Web3Provider/WebUniswapContext' import { act, fireEvent, render } from 'test-utils/render' import { TransactionSettingsContextProvider } from 'uniswap/src/features/transactions/settings/contexts/TransactionSettingsContext' +import { TransactionSettingKey } from 'uniswap/src/features/transactions/settings/slice' describe('LiquidityModalHeader', () => { it('should render with given title and call close callback', () => { const onClose = jest.fn() const { getByText, getByTestId } = render( - + , diff --git a/apps/web/src/components/Liquidity/LiquidityPositionFeeStats.tsx b/apps/web/src/components/Liquidity/LiquidityPositionFeeStats.tsx index 8ab13029ac1..d8a1aa17138 100644 --- a/apps/web/src/components/Liquidity/LiquidityPositionFeeStats.tsx +++ b/apps/web/src/components/Liquidity/LiquidityPositionFeeStats.tsx @@ -7,7 +7,7 @@ import { MouseoverTooltip } from 'components/Tooltip' import { useScreenSize } from 'hooks/screenSize/useScreenSize' import { TextLoader } from 'pages/Pool/Positions/shared' import { Dispatch, SetStateAction } from 'react' -import { ClickableTamaguiStyle } from 'theme/components' +import { ClickableTamaguiStyle, EllipsisTamaguiStyle } from 'theme/components' import { Flex, Text, styled } from 'ui/src' import { ArrowUpDown } from 'ui/src/components/icons/ArrowUpDown' import { InfoCircleFilled } from 'ui/src/components/icons/InfoCircleFilled' @@ -168,8 +168,17 @@ export function LiquidityPositionFeeStats({ - - {maxPrice} {tokenASymbol} / {tokenBSymbol} + + + {maxPrice} + + + {tokenASymbol} / {tokenBSymbol} + ` `}; ` -const FindPoolTabsText = styled(ThemedText.H1Small)` - position: absolute; - left: 50%; - transform: translateX(-50%); -` - const StyledArrowLeft = styled(ArrowLeft)` color: ${({ theme }) => theme.neutral1}; ` -export function FindPoolTabs({ origin }: { origin: string }) { - return ( - - - - - - - - - - - ) -} - const AddRemoveTitleText = styled(ThemedText.H1Small)<{ $center: boolean }>` flex: 1; margin: auto; diff --git a/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsStatsButtons.test.tsx.snap b/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsStatsButtons.test.tsx.snap index d118e1c3973..3456ddbb932 100644 --- a/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsStatsButtons.test.tsx.snap +++ b/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsStatsButtons.test.tsx.snap @@ -131,37 +131,6 @@ exports[`PoolDetailsStatsButton renders both buttons correctly 1`] = ` border-radius: 4px; } -.c1 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c10 { - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between; -} - -.c12 { - position: relative; - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; -} - .c4 { -webkit-letter-spacing: -0.01em; -moz-letter-spacing: -0.01em; @@ -314,6 +283,37 @@ exports[`PoolDetailsStatsButton renders both buttons correctly 1`] = ` grid-row-gap: 4px; } +.c1 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.c10 { + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; +} + +.c12 { + position: relative; + width: -webkit-fit-content; + width: -moz-fit-content; + width: fit-content; +} + .c28 { display: inline-block; height: inherit; diff --git a/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsTransactionTable.test.tsx.snap b/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsTransactionTable.test.tsx.snap index 3745754d997..942a57bb081 100644 --- a/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsTransactionTable.test.tsx.snap +++ b/apps/web/src/components/Pools/PoolDetails/__snapshots__/PoolDetailsTransactionTable.test.tsx.snap @@ -51,24 +51,6 @@ exports[`PoolDetailsTransactionsTable renders data filled state 1`] = ` min-width: 0; } -.c2 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 4px; -} - .c8 { display: inline-block; height: inherit; @@ -114,6 +96,24 @@ exports[`PoolDetailsTransactionsTable renders data filled state 1`] = ` position: relative; } +.c2 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 4px; +} + .c14 { color: #7D7D7D; stroke: #7D7D7D; @@ -483,24 +483,6 @@ exports[`PoolDetailsTransactionsTable renders error state 1`] = ` min-width: 0; } -.c2 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 4px; -} - .c3 { height: 16px; width: 16px; @@ -534,6 +516,24 @@ exports[`PoolDetailsTransactionsTable renders error state 1`] = ` position: relative; } +.c2 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 4px; +} + .c0 { min-height: 256px; } @@ -1299,24 +1299,6 @@ exports[`PoolDetailsTransactionsTable renders loading state 1`] = ` min-width: 0; } -.c2 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 4px; -} - .c3 { height: 16px; width: 16px; @@ -1350,6 +1332,24 @@ exports[`PoolDetailsTransactionsTable renders loading state 1`] = ` position: relative; } +.c2 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 4px; +} + .c0 { min-height: 256px; } diff --git a/apps/web/src/components/TopLevelModals/index.tsx b/apps/web/src/components/TopLevelModals/index.tsx index 461b7ff3b8b..621192722e6 100644 --- a/apps/web/src/components/TopLevelModals/index.tsx +++ b/apps/web/src/components/TopLevelModals/index.tsx @@ -4,7 +4,6 @@ import { AddressQRModal } from 'components/AddressQRModal' import { Banners } from 'components/Banner/shared/Banners' import ConnectedAccountBlocked from 'components/ConnectedAccountBlocked' import FeatureFlagModal from 'components/FeatureFlagModal/FeatureFlagModal' -import FiatOnrampModal from 'components/FiatOnrampModal' import { GetTheAppModal } from 'components/NavBar/DownloadApp/Modal' import { PrivacyChoicesModal } from 'components/PrivacyChoices' import { PrivacyPolicyModal } from 'components/PrivacyPolicy' @@ -69,7 +68,6 @@ export default function TopLevelModals() { - {account.address && } {account.address && } diff --git a/apps/web/src/components/swap/__snapshots__/SwapDetails.test.tsx.snap b/apps/web/src/components/swap/__snapshots__/SwapDetails.test.tsx.snap index 6deb0dd199c..2c7fdeaf314 100644 --- a/apps/web/src/components/swap/__snapshots__/SwapDetails.test.tsx.snap +++ b/apps/web/src/components/swap/__snapshots__/SwapDetails.test.tsx.snap @@ -31,77 +31,6 @@ exports[`SwapDetails.tsx matches base snapshot, test trade exact input 1`] = ` border-radius: 4px; } -.c13 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 8px; -} - -.c16 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 4px; -} - -.c19 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c20 { - -webkit-flex-wrap: wrap; - -ms-flex-wrap: wrap; - flex-wrap: wrap; -} - -.c20 > * { - margin: !important; -} - -.c17 { - position: relative; - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - margin: -xs; -} - .c5 { color: #7D7D7D; -webkit-letter-spacing: -0.01em; @@ -227,6 +156,77 @@ exports[`SwapDetails.tsx matches base snapshot, test trade exact input 1`] = ` gap: 8px; } +.c13 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 8px; +} + +.c16 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 4px; +} + +.c19 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.c20 { + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; +} + +.c20 > * { + margin: !important; +} + +.c17 { + position: relative; + width: -webkit-fit-content; + width: -moz-fit-content; + width: fit-content; + margin: -xs; +} + .c15 { -webkit-filter: none; filter: none; @@ -675,51 +675,6 @@ exports[`SwapDetails.tsx renders a preview trade while disabling submission 1`] border-radius: 4px; } -.c13 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 8px; -} - -.c16 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c17 { - -webkit-flex-wrap: wrap; - -ms-flex-wrap: wrap; - flex-wrap: wrap; -} - -.c17 > * { - margin: !important; -} - .c5 { color: #7D7D7D; -webkit-letter-spacing: -0.01em; @@ -845,6 +800,51 @@ exports[`SwapDetails.tsx renders a preview trade while disabling submission 1`] gap: 8px; } +.c13 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 8px; +} + +.c16 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.c17 { + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; +} + +.c17 > * { + margin: !important; +} + .c15 { -webkit-animation: fAQEyV 1.5s infinite; animation: fAQEyV 1.5s infinite; diff --git a/apps/web/src/components/swap/__snapshots__/SwapHeader.test.tsx.snap b/apps/web/src/components/swap/__snapshots__/SwapHeader.test.tsx.snap index ce223214b95..f9613d1f740 100644 --- a/apps/web/src/components/swap/__snapshots__/SwapHeader.test.tsx.snap +++ b/apps/web/src/components/swap/__snapshots__/SwapHeader.test.tsx.snap @@ -8,6 +8,27 @@ exports[`SwapHeader.tsx matches base snapshot 1`] = ` min-width: 0; } +.c6 { + outline: none; + border: none; + font-size: inherit; + padding: 0; + margin: 0; + background: none; + cursor: pointer; + -webkit-transition-duration: 125ms; + transition-duration: 125ms; + -webkit-transition-timing-function: ease-in-out; + transition-timing-function: ease-in-out; + -webkit-transition-property: opacity,color,background-color; + transition-property: opacity,color,background-color; +} + +.c6:focus { + -webkit-text-decoration: underline; + text-decoration: underline; +} + .c1 { width: 100%; display: -webkit-box; @@ -39,27 +60,6 @@ exports[`SwapHeader.tsx matches base snapshot 1`] = ` width: fit-content; } -.c6 { - outline: none; - border: none; - font-size: inherit; - padding: 0; - margin: 0; - background: none; - cursor: pointer; - -webkit-transition-duration: 125ms; - transition-duration: 125ms; - -webkit-transition-timing-function: ease-in-out; - transition-timing-function: ease-in-out; - -webkit-transition-property: opacity,color,background-color; - transition-property: opacity,color,background-color; -} - -.c6:focus { - -webkit-text-decoration: underline; - text-decoration: underline; -} - .c12 { height: 24px; width: 24px; diff --git a/apps/web/src/hooks/useContract.ts b/apps/web/src/hooks/useContract.ts index bc32103d1fc..c3f1f3e740a 100644 --- a/apps/web/src/hooks/useContract.ts +++ b/apps/web/src/hooks/useContract.ts @@ -218,7 +218,10 @@ export function useV4NFTPositionManagerContract( const chainIdToUse = chainId ?? account.chainId const contract = useContract( - chainIdToUse ? CHAIN_TO_ADDRESSES_MAP[chainIdToUse].v4PositionManagerAddress : undefined, + // monad testnet does not have v4 support + chainIdToUse && chainIdToUse !== UniverseChainId.MonadTestnet + ? CHAIN_TO_ADDRESSES_MAP[chainIdToUse].v4PositionManagerAddress + : undefined, NFTPositionManagerABI, withSignerIfPossible, chainIdToUse, diff --git a/apps/web/src/pages/IncreaseLiquidity/IncreaseLiquidityModal.tsx b/apps/web/src/pages/IncreaseLiquidity/IncreaseLiquidityModal.tsx index d4e078c6af7..447087824f0 100644 --- a/apps/web/src/pages/IncreaseLiquidity/IncreaseLiquidityModal.tsx +++ b/apps/web/src/pages/IncreaseLiquidity/IncreaseLiquidityModal.tsx @@ -13,6 +13,7 @@ import { Modal } from 'uniswap/src/components/modals/Modal' import { MIN_AUTO_SLIPPAGE_TOLERANCE } from 'uniswap/src/constants/transactions' import { ModalName } from 'uniswap/src/features/telemetry/constants' import { TransactionSettingsContextProvider } from 'uniswap/src/features/transactions/settings/contexts/TransactionSettingsContext' +import { TransactionSettingKey } from 'uniswap/src/features/transactions/settings/slice' import { useTranslation } from 'uniswap/src/i18n' function IncreaseLiquidityModalInner() { @@ -64,7 +65,10 @@ function IncreaseLiquidityModalInner() { export function IncreaseLiquidityModal() { return ( - + diff --git a/apps/web/src/pages/Landing/sections/Hero.tsx b/apps/web/src/pages/Landing/sections/Hero.tsx index f3bdd0942dc..d201ac4571e 100644 --- a/apps/web/src/pages/Landing/sections/Hero.tsx +++ b/apps/web/src/pages/Landing/sections/Hero.tsx @@ -4,7 +4,7 @@ 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, useCallback, useMemo } from 'react' import { ChevronDown } from 'react-feather' import { useNavigate } from 'react-router-dom' import { serializeSwapStateToURLParameters } from 'state/swap/hooks' @@ -25,9 +25,13 @@ export function Hero({ scrollToRef, transition }: HeroProps) { const initialInputCurrency = useCurrency('ETH', UniverseChainId.Mainnet) const navigate = useNavigate() const { t } = useTranslation() - - const translateY = -scrollPosition / 7 - const opacityY = 1 - scrollPosition / 1000 + const { translateY, opacityY } = useMemo( + () => ({ + translateY: !media.sm ? -scrollPosition / 7 : 0, + opacityY: !media.sm ? 1 - scrollPosition / 1000 : 1, + }), + [media.sm, scrollPosition], + ) const swapRedirectCallback = useCallback( ({ inputCurrency, outputCurrency, typedValue, independentField, chainId }: Parameters[0]) => { diff --git a/apps/web/src/pages/LegacyPool/redirects.tsx b/apps/web/src/pages/LegacyPool/redirects.tsx index 54a3140f90a..8d43bd304d9 100644 --- a/apps/web/src/pages/LegacyPool/redirects.tsx +++ b/apps/web/src/pages/LegacyPool/redirects.tsx @@ -32,11 +32,6 @@ export function LegacyPoolV2Redirects() { // /pool/v2/find export function PoolFinderRedirects() { - const isLPRedesignEnabled = useFeatureFlag(FeatureFlags.LPRedesign) - - if (isLPRedesignEnabled) { - return - } return } diff --git a/apps/web/src/pages/Pool/Positions/create/CreatePosition.tsx b/apps/web/src/pages/Pool/Positions/create/CreatePosition.tsx index 1b515f9984d..212fb89633b 100644 --- a/apps/web/src/pages/Pool/Positions/create/CreatePosition.tsx +++ b/apps/web/src/pages/Pool/Positions/create/CreatePosition.tsx @@ -45,6 +45,7 @@ import { useFeatureFlag, useFeatureFlagWithLoading } from 'uniswap/src/features/ import Trace from 'uniswap/src/features/telemetry/Trace' import { InterfacePageNameLocal, SectionName } from 'uniswap/src/features/telemetry/constants' import { TransactionSettingsContextProvider } from 'uniswap/src/features/transactions/settings/contexts/TransactionSettingsContext' +import { TransactionSettingKey } from 'uniswap/src/features/transactions/settings/slice' import { SwapFormSettings } from 'uniswap/src/features/transactions/swap/form/SwapFormSettings' import { Deadline } from 'uniswap/src/features/transactions/swap/settings/configs/Deadline' import { Trans, useTranslation } from 'uniswap/src/i18n' @@ -385,7 +386,7 @@ export default function CreatePosition() { return ( - + - + diff --git a/apps/web/src/pages/Pool/Positions/create/RangeSelectionStep.tsx b/apps/web/src/pages/Pool/Positions/create/RangeSelectionStep.tsx index 1e254f92250..c9031590f9e 100644 --- a/apps/web/src/pages/Pool/Positions/create/RangeSelectionStep.tsx +++ b/apps/web/src/pages/Pool/Positions/create/RangeSelectionStep.tsx @@ -493,6 +493,9 @@ export const SelectPriceRangeStep = ({ gap="$gap12" borderTopLeftRadius="$rounded20" borderTopRightRadius="$rounded20" + $lg={{ + px: '$spacing8', + }} > {!creatingPoolOrPair && !isPriceRangeInputV2Enabled && ( @@ -534,7 +537,7 @@ export const SelectPriceRangeStep = ({ /> )} - + void }) => { +export 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) @@ -260,6 +261,12 @@ export function SelectTokensStep({ }, [mostUsedFeeTier, defaultFeeTierSelected, setPositionState, trace]) const { chains } = useEnabledChains() + const supportedChains = useMemo(() => { + // some chains are not supported for v2 pools, so we need to filter them out + return protocolVersion === ProtocolVersion.V2 + ? chains.filter((chain) => SUPPORTED_V2POOL_CHAIN_IDS.includes(chain)) + : undefined + }, [chains, protocolVersion]) return ( @@ -314,7 +321,7 @@ export function SelectTokensStep({ borderColor="$surface3" > - + {isDynamicFeeTier(fee) ? ( @@ -326,17 +333,21 @@ export function SelectTokensStep({ )} {fee.feeAmount === mostUsedFeeTier?.fee.feeAmount ? ( - - - - - + + + + + + + ) : feeTiers.find((tier) => tier.value.feeAmount === fee.feeAmount) ? null : ( @@ -433,11 +444,7 @@ export function SelectTokensStep({ isOpen={currencySearchInputState !== undefined} onDismiss={() => setCurrencySearchInputState(undefined)} onCurrencySelect={handleCurrencySelect} - chainIds={ - protocolVersion === ProtocolVersion.V2 - ? chains.filter((chain) => SUPPORTED_V2POOL_CHAIN_IDS.includes(chain)) - : undefined - } + chainIds={supportedChains} /> ) diff --git a/apps/web/src/pages/Pool/Positions/create/shared.tsx b/apps/web/src/pages/Pool/Positions/create/shared.tsx index a7c5490d04c..84c35853dc3 100644 --- a/apps/web/src/pages/Pool/Positions/create/shared.tsx +++ b/apps/web/src/pages/Pool/Positions/create/shared.tsx @@ -20,6 +20,9 @@ export const Container = styled(Flex, { borderColor: '$surface3', overflow: 'hidden', width: '100%', + $lg: { + p: '$spacing16', + }, }) export function AdvancedButton({ diff --git a/apps/web/src/pages/Pool/index.tsx b/apps/web/src/pages/Pool/index.tsx index f927c1fe2a0..e1884798044 100644 --- a/apps/web/src/pages/Pool/index.tsx +++ b/apps/web/src/pages/Pool/index.tsx @@ -5,6 +5,7 @@ import V4_HOOK from 'assets/images/v4Hooks.png' import { useAccountDrawer } from 'components/AccountDrawer/MiniPortfolio/hooks' import { Pool as PoolIcon } from 'components/Icons/Pool' import { LiquidityPositionCard, LiquidityPositionCardLoader } from 'components/Liquidity/LiquidityPositionCard' +import { PositionInfo } from 'components/Liquidity/types' import { getPositionUrl, parseRestPosition } from 'components/Liquidity/utils' import { TopPoolTable, sortAscendingAtom, sortMethodAtom } from 'components/Pools/PoolTable/PoolTable' import { OrderDirection } from 'graphql/data/util' @@ -15,10 +16,10 @@ import { PositionsHeader } from 'pages/Pool/Positions/PositionsHeader' import { TopPools } from 'pages/Pool/Positions/TopPools' import { ExternalArrowLink } from 'pages/Pool/Positions/shared' import { useEffect, useMemo, useState } from 'react' -import { ChevronLeft, ChevronRight } from 'react-feather' import { Link, Navigate, useNavigate } from 'react-router-dom' import { useTopPools } from 'state/explore/topPools' import { usePendingLPTransactionsChangeListener } from 'state/transactions/hooks' +import { useRequestPositionsForSavedPairs } from 'state/user/hooks' import { ClickableTamaguiStyle } from 'theme/components' import { Anchor, Button, Flex, Text, useMedia, useSporeColors } from 'ui/src' import { InfoCircleFilled } from 'ui/src/components/icons/InfoCircleFilled' @@ -27,7 +28,7 @@ import { iconSizes } from 'ui/src/theme' import { uniswapUrls } from 'uniswap/src/constants/urls' import { ALL_NETWORKS_ARG } from 'uniswap/src/data/rest/base' import { useExploreStatsQuery } from 'uniswap/src/data/rest/exploreStats' -import { useGetPositionsQuery } from 'uniswap/src/data/rest/getPositions' +import { useGetPositionsInfiniteQuery } from 'uniswap/src/data/rest/getPositions' import { useEnabledChains } from 'uniswap/src/features/chains/hooks/useEnabledChains' import { UniverseChainId } from 'uniswap/src/features/chains/types' import { FeatureFlags } from 'uniswap/src/features/gating/flags' @@ -36,7 +37,7 @@ import Trace from 'uniswap/src/features/telemetry/Trace' import { InterfacePageNameLocal } from 'uniswap/src/features/telemetry/constants' import { Trans, useTranslation } from 'uniswap/src/i18n' -const PAGE_SIZE = 8 +const PAGE_SIZE = 25 function EmptyPositionsView({ chainId, isConnected }: { chainId?: UniverseChainId | null; isConnected: boolean }) { const colors = useSporeColors() @@ -129,7 +130,13 @@ function EmptyPositionsView({ chainId, isConnected }: { chainId?: UniverseChainI function LearnMoreTile({ img, text, link }: { img: string; text: string; link?: string }) { return ( - + { if (isV4DataEnabled) { @@ -177,26 +183,42 @@ export default function Pool() { } }, [isV4DataEnabled, setVersionFilter]) - const { data, isPlaceholderData, refetch, isLoading } = useGetPositionsQuery( - { - address, - chainIds: chainFilter ? [chainFilter] : currentModeChains, - positionStatuses: statusFilter, - protocolVersions: versionFilter, - }, - !isConnected, - ) + const { data, isPlaceholderData, refetch, isLoading, fetchNextPage, hasNextPage, isFetching } = + useGetPositionsInfiniteQuery( + { + address, + chainIds: chainFilter ? [chainFilter] : currentModeChains, + positionStatuses: statusFilter, + protocolVersions: versionFilter, + pageSize: PAGE_SIZE, + pageToken: '', + }, + !isConnected, + ) + + const loadedPositions = useMemo(() => { + return data?.pages.flatMap((positionsResponse) => positionsResponse.positions) || [] + }, [data]) + + const savedPositions = useRequestPositionsForSavedPairs() + const isLoadingPositions = !!account.address && (isLoading || !data) + const combinedPositions = useMemo(() => { + return [...loadedPositions, ...(savedPositions.map((p) => p.data?.position) ?? [])] + .map(parseRestPosition) + .filter((position): position is PositionInfo => !!position) + }, [loadedPositions, savedPositions]) + usePendingLPTransactionsChangeListener(refetch) - const currentPageItems = useMemo(() => { - const start = currentPage * PAGE_SIZE - return (data?.positions.slice(start, start + PAGE_SIZE) ?? []).map((position) => parseRestPosition(position)) - }, [currentPage, data?.positions]) + const loadMorePositions = () => { + if (hasNextPage && !isFetching) { + fetchNextPage() + } + } - const pageCount = data?.positions ? Math.ceil(data?.positions.length / PAGE_SIZE) : undefined - const showingEmptyPositions = !isLoadingPositions && currentPageItems.length === 0 + const showingEmptyPositions = !isLoadingPositions && combinedPositions.length === 0 if (!isLoadingFeatureFlag && !lpRedesignEnabled) { return @@ -243,24 +265,22 @@ export default function Pool() { }} /> {!isLoadingPositions ? ( - currentPageItems.length > 0 ? ( + combinedPositions.length > 0 ? ( - {currentPageItems.map((position) => { - return ( - position && ( - - - - ) - ) + {combinedPositions.map((position) => { + return position ? ( + + + + ) : null })} ) : ( @@ -273,6 +293,13 @@ export default function Pool() { ))} )} + {hasNextPage && ( + + + + )} {!statusFilter.includes(PositionStatus.CLOSED) && !closedCTADismissed && account.address && ( )} - {!!pageCount && pageCount > 1 && data?.positions && ( - - { - setCurrentPage(Math.max(currentPage - 1, 0)) - }} - /> - {Array.from({ length: pageCount > 5 ? 3 : pageCount }).map((_, index) => { - const isSelected = currentPage === index - return ( - setCurrentPage(index)} - > - {index + 1} - - ) - })} - {pageCount > 5 && ( - - ... - - )} - {pageCount > 5 && ( - setCurrentPage(pageCount - 1)} - > - {pageCount} - - )} - { - setCurrentPage(Math.min(currentPage + 1, pageCount - 1)) - }} - /> - - )} + + + {t('pool.import.link.description')} + + + + {t('pool.import.positions.v2')} + + + {!media.xl && !showingEmptyPositions && !isLoading && } diff --git a/apps/web/src/pages/PoolFinder/index.tsx b/apps/web/src/pages/PoolFinder/index.tsx index b80a2d0e569..28bf202b518 100644 --- a/apps/web/src/pages/PoolFinder/index.tsx +++ b/apps/web/src/pages/PoolFinder/index.tsx @@ -1,56 +1,43 @@ import { InterfacePageName } from '@uniswap/analytics-events' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' -import { ButtonDropdownLight } from 'components/Button/buttons' -import { BlueCard, LightCard } from 'components/Card/cards' -import CurrencyLogo from 'components/Logo/CurrencyLogo' -import { FindPoolTabs } from 'components/NavigationTabs' -import { MinimalPositionCard } from 'components/PositionCard' +import { useAccountDrawer } from 'components/AccountDrawer/MiniPortfolio/hooks' +import { BreadcrumbNavContainer, BreadcrumbNavLink } from 'components/BreadcrumbNav' +import { DoubleCurrencyLogo } from 'components/Logo/DoubleLogo' import CurrencySearchModal from 'components/SearchModal/CurrencySearchModal' -import { SwitchLocaleLink } from 'components/SwitchLocaleLink' import { V2Unsupported } from 'components/V2Unsupported' -import { AutoColumn, ColumnCenter } from 'components/deprecated/Column' -import Row from 'components/deprecated/Row' import { useAccount } from 'hooks/useAccount' import { useNetworkSupportsV2 } from 'hooks/useNetworkSupportsV2' -import { PairState, useV2Pair } from 'hooks/useV2Pairs' +import { useTotalSupply } from 'hooks/useTotalSupply' +import { useV2Pair } from 'hooks/useV2Pairs' import JSBI from 'jsbi' -import AppBody from 'pages/App/AppBody' -import { Dots } from 'pages/LegacyPool/styled' -import { useCallback, useEffect, useState } from 'react' -import { Plus } from 'react-feather' -import { useLocation } from 'react-router-dom' -import { Text } from 'rebass' +import ms from 'ms' +import { CurrencySelector } from 'pages/Pool/Positions/create/SelectTokenStep' +import { useEffect, useState } from 'react' +import { ArrowLeft } from 'react-feather' import { useTokenBalance } from 'state/connection/hooks' import { usePairAdder } from 'state/user/hooks' -import { StyledInternalLink, ThemedText } from 'theme/components' +import { PositionField } from 'types/position' +import { Button, Flex, Text } from 'ui/src' import { nativeOnChain } from 'uniswap/src/constants/tokens' import Trace from 'uniswap/src/features/telemetry/Trace' -import { Trans } from 'uniswap/src/i18n' -import { currencyId } from 'utils/currencyId' - -enum Fields { - TOKEN0 = 0, - TOKEN1 = 1, -} - -function useQuery() { - return new URLSearchParams(useLocation().search) -} +import { useUSDCValue } from 'uniswap/src/features/transactions/swap/hooks/useUSDCPrice' +import { Trans, useTranslation } from 'uniswap/src/i18n' +import { NumberType, useFormatter } from 'utils/formatNumbers' export default function PoolFinder() { - const query = useQuery() - const account = useAccount() + const { t } = useTranslation() + const accountDrawer = useAccountDrawer() + const { formatCurrencyAmount } = useFormatter() + const [success, setSuccess] = useState(false) - const [showSearch, setShowSearch] = useState(false) - const [activeField, setActiveField] = useState(Fields.TOKEN1) - - const [currency0, setCurrency0] = useState(() => - account.chainId ? nativeOnChain(account.chainId) : null, + const [currency0, setCurrency0] = useState(() => + account.chainId ? nativeOnChain(account.chainId) : undefined, ) - const [currency1, setCurrency1] = useState(null) + const [currency1, setCurrency1] = useState() + const [currencySearchInputState, setCurrencySearchInputState] = useState(undefined) - const [pairState, pair] = useV2Pair(currency0 ?? undefined, currency1 ?? undefined) + const [, pair] = useV2Pair(currency0, currency1) const addPair = usePairAdder() useEffect(() => { if (pair) { @@ -58,40 +45,26 @@ export default function PoolFinder() { } }, [pair, addPair]) - const validPairNoLiquidity: boolean = - pairState === PairState.NOT_EXISTS || - Boolean( - pairState === PairState.EXISTS && - pair && - JSBI.equal(pair.reserve0.quotient, JSBI.BigInt(0)) && - JSBI.equal(pair.reserve1.quotient, JSBI.BigInt(0)), - ) - const position: CurrencyAmount | undefined = useTokenBalance(account.address, pair?.liquidityToken) const hasPosition = Boolean(position && JSBI.greaterThan(position.quotient, JSBI.BigInt(0))) - const handleCurrencySelect = useCallback( - (currency: Currency) => { - if (activeField === Fields.TOKEN0) { - setCurrency0(currency) - } else { - setCurrency1(currency) - } - }, - [activeField], - ) + const userPoolBalance = useTokenBalance(account.address, pair?.liquidityToken) + const totalPoolTokens = useTotalSupply(pair?.liquidityToken) - const handleSearchDismiss = useCallback(() => { - setShowSearch(false) - }, [setShowSearch]) + const [token0Deposited, token1Deposited] = + !!pair && + !!totalPoolTokens && + !!userPoolBalance && + // this condition is a short-circuit in the case where useTokenBalance updates sooner than useTotalSupply + JSBI.greaterThanOrEqual(totalPoolTokens.quotient, userPoolBalance.quotient) + ? [ + pair.getLiquidityValue(pair.token0, totalPoolTokens, userPoolBalance, false), + pair.getLiquidityValue(pair.token1, totalPoolTokens, userPoolBalance, false), + ] + : [undefined, undefined] - const prerequisiteMessage = ( - - - {!account.isConnected ? : } - - - ) + const token0UsdValue = useUSDCValue(token0Deposited) + const token1UsdValue = useUSDCValue(token1Deposited) const networkSupportsV2 = useNetworkSupportsV2() if (!networkSupportsV2) { @@ -100,137 +73,119 @@ export default function PoolFinder() { return ( - <> - - - - - - - - - - - { - setShowSearch(true) - setActiveField(Fields.TOKEN0) - }} + + + + + + + + {t('pool.import.positions.v2')} + + + {t('pool.selectPair')} + + {t('pool.import.positions.v2.selectPair.description')} + + + setCurrencySearchInputState(PositionField.TOKEN0)} + /> + setCurrencySearchInputState(PositionField.TOKEN1)} + /> + + {currency0 && currency1 && account.isConnected ? ( + <> + + {t('poolFinder.availablePools')} + + + {hasPosition + ? t('poolFinder.availablePools.found.description') + : t('poolFinder.availablePools.notFound.description')} + + + ) : null} + {hasPosition && pair && token0UsdValue && token1UsdValue && ( + - {currency0 ? ( - - - - {currency0.symbol} - - - ) : ( - - + + + + {currency0?.symbol}/{currency1?.symbol} - )} - - - - - - - { - setShowSearch(true) - setActiveField(Fields.TOKEN1) - }} - > - {currency1 ? ( - - - - {currency1.symbol} - - - ) : ( - - - - )} - - - {hasPosition && ( - + - - + + {formatCurrencyAmount({ + amount: token0UsdValue.add(token1UsdValue), + type: NumberType.FiatTokenQuantity, + })} - - - - - - - )} - - {currency0 && currency1 ? ( - pairState === PairState.EXISTS ? ( - hasPosition && pair ? ( - - ) : ( - - - - - - - - - - - - - ) - ) : validPairNoLiquidity ? ( - - - - - - - - - - - ) : pairState === PairState.INVALID ? ( - - - - - - - - ) : pairState === PairState.LOADING ? ( - - - - - - - - - ) : null - ) : ( - prerequisiteMessage - )} - - - - - - + + {t('position.value')} + + + + )} + {!account.isConnected ? ( + + ) : ( + + )} + + + setCurrencySearchInputState(undefined)} + onCurrencySelect={(currency) => { + if (currencySearchInputState === PositionField.TOKEN0) { + setCurrency0(currency) + } else if (currencySearchInputState === PositionField.TOKEN1) { + setCurrency1(currency) + } + setCurrencySearchInputState(undefined) + }} + /> + ) } diff --git a/apps/web/src/pages/RemoveLiquidity/RemoveLiquidityModal.tsx b/apps/web/src/pages/RemoveLiquidity/RemoveLiquidityModal.tsx index 0f83b767e40..f1bc6dbc24e 100644 --- a/apps/web/src/pages/RemoveLiquidity/RemoveLiquidityModal.tsx +++ b/apps/web/src/pages/RemoveLiquidity/RemoveLiquidityModal.tsx @@ -14,6 +14,7 @@ import { Modal } from 'uniswap/src/components/modals/Modal' import { MIN_AUTO_SLIPPAGE_TOLERANCE } from 'uniswap/src/constants/transactions' import { ModalName } from 'uniswap/src/features/telemetry/constants' import { TransactionSettingsContextProvider } from 'uniswap/src/features/transactions/settings/contexts/TransactionSettingsContext' +import { TransactionSettingKey } from 'uniswap/src/features/transactions/settings/slice' import { useTranslation } from 'uniswap/src/i18n' function RemoveLiquidityModalInner() { @@ -53,7 +54,10 @@ function RemoveLiquidityModalInner() { export function RemoveLiquidityModal() { return ( - + diff --git a/apps/web/src/pages/Swap/Send/__snapshots__/NewAddressSpeedBump.test.tsx.snap b/apps/web/src/pages/Swap/Send/__snapshots__/NewAddressSpeedBump.test.tsx.snap index b189e37c524..a85a867a338 100644 --- a/apps/web/src/pages/Swap/Send/__snapshots__/NewAddressSpeedBump.test.tsx.snap +++ b/apps/web/src/pages/Swap/Send/__snapshots__/NewAddressSpeedBump.test.tsx.snap @@ -7,60 +7,6 @@ exports[`NewAddressSpeedBumpModal should not render identicon if account has no min-width: 0; } -.c7 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 4px; -} - -.c18 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - gap: 4px; -} - -.c19 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - gap: 12px; -} - .c12 { color: #222222; -webkit-letter-spacing: -0.01em; @@ -186,6 +132,60 @@ exports[`NewAddressSpeedBumpModal should not render identicon if account has no background-color: transparent; } +.c7 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 4px; +} + +.c18 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + gap: 4px; +} + +.c19 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + gap: 12px; +} + .c5 { width: -webkit-fit-content; width: -moz-fit-content; 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 84298a6ea50..d1c14b08bf9 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 @@ -61,84 +61,6 @@ exports[`SendCurrencyInputform renders input in fiat correctly 1`] = ` width: 100%; } -.c5 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c12 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - gap: 4px; -} - -.c19 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 12px; -} - -.c25 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 4px; -} - -.c16 { - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between; -} - .c14 { color: #CECECE; -webkit-letter-spacing: -0.01em; @@ -227,6 +149,84 @@ exports[`SendCurrencyInputform renders input in fiat correctly 1`] = ` justify-content: flex-start; } +.c5 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.c12 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + gap: 4px; +} + +.c19 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 12px; +} + +.c25 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 4px; +} + +.c16 { + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; +} + .c6 { position: relative; max-width: 100%; @@ -624,84 +624,6 @@ exports[`SendCurrencyInputform renders input in token amount correctly 1`] = ` width: 100%; } -.c5 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c11 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - gap: 4px; -} - -.c18 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 12px; -} - -.c24 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 4px; -} - -.c15 { - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between; -} - .c13 { color: #CECECE; -webkit-letter-spacing: -0.01em; @@ -790,6 +712,84 @@ exports[`SendCurrencyInputform renders input in token amount correctly 1`] = ` justify-content: flex-start; } +.c5 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.c11 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + gap: 4px; +} + +.c18 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 12px; +} + +.c24 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 4px; +} + +.c15 { + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; +} + .c6 { position: relative; max-width: 100%; @@ -1171,84 +1171,6 @@ exports[`SendCurrencyInputform should render placeholder values 1`] = ` width: 100%; } -.c5 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c12 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - gap: 4px; -} - -.c19 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 12px; -} - -.c25 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 4px; -} - -.c16 { - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between; -} - .c14 { color: #CECECE; -webkit-letter-spacing: -0.01em; @@ -1337,6 +1259,84 @@ exports[`SendCurrencyInputform should render placeholder values 1`] = ` justify-content: flex-start; } +.c5 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.c12 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + gap: 4px; +} + +.c19 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 12px; +} + +.c25 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 4px; +} + +.c16 { + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; +} + .c6 { position: relative; max-width: 100%; diff --git a/apps/web/src/pages/Swap/Send/__snapshots__/SendReviewModal.test.tsx.snap b/apps/web/src/pages/Swap/Send/__snapshots__/SendReviewModal.test.tsx.snap index a585b5fe8f1..41b262fb595 100644 --- a/apps/web/src/pages/Swap/Send/__snapshots__/SendReviewModal.test.tsx.snap +++ b/apps/web/src/pages/Swap/Send/__snapshots__/SendReviewModal.test.tsx.snap @@ -99,61 +99,6 @@ exports[`SendCurrencyInputform should render input in fiat correctly 1`] = ` border-radius: 4px; } -.c7 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 4px; -} - -.c12 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between; -} - -.c24 { - width: -webkit-min-content; - width: -moz-min-content; - width: min-content; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 4px; -} - .c14 { color: #7D7D7D; -webkit-letter-spacing: -0.01em; @@ -301,6 +246,61 @@ exports[`SendCurrencyInputform should render input in fiat correctly 1`] = ` outline: none; } +.c7 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 4px; +} + +.c12 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; +} + +.c24 { + width: -webkit-min-content; + width: -moz-min-content; + width: min-content; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 4px; +} + .c5 { width: -webkit-fit-content; width: -moz-fit-content; @@ -725,61 +725,6 @@ exports[`SendCurrencyInputform should render input in token amount correctly 1`] border-radius: 4px; } -.c7 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 4px; -} - -.c12 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between; -} - -.c24 { - width: -webkit-min-content; - width: -moz-min-content; - width: min-content; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 4px; -} - .c14 { color: #7D7D7D; -webkit-letter-spacing: -0.01em; @@ -927,6 +872,61 @@ exports[`SendCurrencyInputform should render input in token amount correctly 1`] outline: none; } +.c7 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 4px; +} + +.c12 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; +} + +.c24 { + width: -webkit-min-content; + width: -moz-min-content; + width: min-content; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 4px; +} + .c5 { width: -webkit-fit-content; width: -moz-fit-content; diff --git a/apps/web/src/pages/Swap/Send/__snapshots__/SmartContractSpeedbump.test.tsx.snap b/apps/web/src/pages/Swap/Send/__snapshots__/SmartContractSpeedbump.test.tsx.snap index e5dfb1eb473..30f8c21f8b8 100644 --- a/apps/web/src/pages/Swap/Send/__snapshots__/SmartContractSpeedbump.test.tsx.snap +++ b/apps/web/src/pages/Swap/Send/__snapshots__/SmartContractSpeedbump.test.tsx.snap @@ -7,42 +7,6 @@ exports[`SmartContractSpeedBumpModal should render correctly 1`] = ` min-width: 0; } -.c7 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; - gap: 4px; -} - -.c18 { - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - padding: 0; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - gap: 12px; -} - .c14 { color: #222222; -webkit-letter-spacing: -0.01em; @@ -168,6 +132,42 @@ exports[`SmartContractSpeedBumpModal should render correctly 1`] = ` background-color: transparent; } +.c7 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 4px; +} + +.c18 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + gap: 12px; +} + .c5 { width: -webkit-fit-content; width: -moz-fit-content; diff --git a/apps/web/src/pages/Swap/index.tsx b/apps/web/src/pages/Swap/index.tsx index ded233946e2..3ada862e760 100644 --- a/apps/web/src/pages/Swap/index.tsx +++ b/apps/web/src/pages/Swap/index.tsx @@ -36,6 +36,7 @@ import { InterfaceEventNameLocal } from 'uniswap/src/features/telemetry/constant import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { SwapRedirectFn } from 'uniswap/src/features/transactions/TransactionModal/TransactionModalContext' import { TransactionSettingsContextProvider } from 'uniswap/src/features/transactions/settings/contexts/TransactionSettingsContext' +import { TransactionSettingKey } from 'uniswap/src/features/transactions/settings/slice' import { SwapFlow } from 'uniswap/src/features/transactions/swap/SwapFlow' import { SwapFormContextProvider, SwapFormState } from 'uniswap/src/features/transactions/swap/contexts/SwapFormContext' import { useSwapPrefilledState } from 'uniswap/src/features/transactions/swap/hooks/useSwapPrefilledState' @@ -46,6 +47,7 @@ import { currencyToAsset } from 'uniswap/src/features/transactions/swap/utils/as import { useTranslation } from 'uniswap/src/i18n' import { CurrencyField } from 'uniswap/src/types/currency' import { SwapTab } from 'uniswap/src/types/screens/interface' +import { isTestEnv } from 'utilities/src/environment/env' import noop from 'utilities/src/react/noop' export function getIsReviewableQuote( @@ -168,10 +170,13 @@ export function Swap({ selectingCurrencyField: isSwapTokenSelectorOpen ? CurrencyField.OUTPUT : undefined, }) - if (universalSwapFlow || isTestnetModeEnabled || isLoading) { + // TODO(WEB-5078): Remove this once we upgrade swap e2e tests to use the new swap flow + const waitForLoading = isLoading && !isTestEnv() + + if (universalSwapFlow || isTestnetModeEnabled || waitForLoading) { return ( - + { + beforeEach(() => { + jest.spyOn(console, 'warn').mockImplementation(() => {}) + }) + + const migrator = createMigrate( + { + 1: migration1, + 2: migration2, + 3: migration3, + 4: migration4, + 5: migration5, + 6: migration6, + 7: migration7, + 8: migration8, + 9: migration9, + 10: migration10, + 11: migration11, + 12: migration12, + 13: migration13, + 14: migration14, + 15: migration15, + 16: migration16, + 17: migration17, + 18: migration18, + 19: migration19, + 20: migration20, + 21: migration21, + }, + { debug: false }, + ) + + it('should convert uppercase token warning addresses to lowercase', async () => { + const state: PersistAppStateV21 = { + tokens: { + dismissedTokenWarnings: { + '1': { + '0x1234567890123456789012345678901234567890': { + address: '0x1234567890123456789012345678901234567890', + chainId: UniverseChainId.Mainnet, + symbol: 'TEST', + name: 'Test Token', + decimals: 18, + }, + }, + }, + }, + _persist: { + version: 20, + rehydrated: true, + }, + } + + const result: any = await migrator(state, 21) + expect(result.tokens?.dismissedTokenWarnings['1']).toHaveProperty('0x1234567890123456789012345678901234567890') + expect(result._persist.version).toEqual(21) + }) + + it('should handle undefined tokens state', async () => { + const state = { + _persist: { + version: 20, + rehydrated: true, + }, + } + const result: any = await migrator(state, 21) + expect(result.tokens?.dismissedTokenWarnings).toBeUndefined() + expect(result._persist.version).toEqual(21) + }) + + it('should handle empty dismissedTokenWarnings object', async () => { + const state: PersistAppStateV21 = { + tokens: { + dismissedTokenWarnings: {}, + }, + _persist: { + version: 20, + rehydrated: true, + }, + } + const result: any = await migrator(state, 21) + expect(result.tokens?.dismissedTokenWarnings).toEqual({}) + expect(result._persist.version).toEqual(21) + }) + + it('should skip invalid addresses', async () => { + const state: PersistAppStateV21 = { + tokens: { + dismissedTokenWarnings: { + '1': { + '0x1234567890123456789012345678901234567890': { + address: '0x1234567890123456789012345678901234567890', + chainId: UniverseChainId.Mainnet, + symbol: 'TEST', + name: 'Test Token', + decimals: 18, + }, + 'invalid-address': { + address: 'invalid-address', + chainId: UniverseChainId.Mainnet, + symbol: 'TEST', + name: 'Test Token', + decimals: 18, + }, + }, + }, + }, + _persist: { + version: 20, + rehydrated: true, + }, + } + const result: any = await migrator(state, 21) + expect(Object.keys(result.tokens?.dismissedTokenWarnings['1'])).toHaveLength(1) + expect(result.tokens?.dismissedTokenWarnings['1']).toHaveProperty('0x1234567890123456789012345678901234567890') + expect(result.tokens?.dismissedTokenWarnings['1']).not.toHaveProperty('invalid-address') + expect(result._persist.version).toEqual(21) + }) +}) diff --git a/apps/web/src/state/migrations/21.ts b/apps/web/src/state/migrations/21.ts new file mode 100644 index 00000000000..735d43de488 --- /dev/null +++ b/apps/web/src/state/migrations/21.ts @@ -0,0 +1,18 @@ +import { PersistState } from 'redux-persist' +import { TokensState } from 'uniswap/src/features/tokens/slice/slice' +import { unchecksumDismissedTokenWarningKeys } from 'uniswap/src/state/uniswapMigrations' + +export type PersistAppStateV21 = { + _persist: PersistState + tokens?: TokensState +} + +export const migration21 = (state: PersistAppStateV21 | undefined) => { + if (!state) { + return undefined + } + return { + ...unchecksumDismissedTokenWarningKeys(state), + _persist: { ...state._persist, version: 21 }, + } +} diff --git a/apps/web/src/state/reducerTypeTest.ts b/apps/web/src/state/reducerTypeTest.ts index 761d0692239..41d17ad816e 100644 --- a/apps/web/src/state/reducerTypeTest.ts +++ b/apps/web/src/state/reducerTypeTest.ts @@ -34,6 +34,7 @@ import { SearchHistoryState } from 'uniswap/src/features/search/searchHistorySli import { UserSettingsState } from 'uniswap/src/features/settings/slice' import { TimingState } from 'uniswap/src/features/timing/slice' import { TokensState } from 'uniswap/src/features/tokens/slice/slice' +import { transactionSettingsReducer } from 'uniswap/src/features/transactions/settings/slice' import { TransactionsState } from 'uniswap/src/features/transactions/slice' const forAggregatorApi = getFiatOnRampAggregatorApi() @@ -84,6 +85,7 @@ type ExpectedAppState = CombinedState<{ readonly timing: TimingState readonly tokens: TokensState readonly transactions: TransactionsState + readonly transactionSettings: ReturnType readonly userSettings: UserSettingsState }> diff --git a/apps/web/src/state/routing/types.ts b/apps/web/src/state/routing/types.ts index 98c7e1e9350..d7d91b52ee7 100644 --- a/apps/web/src/state/routing/types.ts +++ b/apps/web/src/state/routing/types.ts @@ -908,6 +908,7 @@ export enum SwapRouterNativeAssets { BNB = 'BNB', AVAX = 'AVAX', ETH = 'ETH', + MON = 'MON', } export enum URAQuoteType { diff --git a/apps/web/src/state/user/hooks.tsx b/apps/web/src/state/user/hooks.tsx index be2a59a75a0..c781a6e4656 100644 --- a/apps/web/src/state/user/hooks.tsx +++ b/apps/web/src/state/user/hooks.tsx @@ -20,6 +20,7 @@ import { TokenSortableField, useTopTokensQuery, } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' +import { useGetPositionsForPairs } from 'uniswap/src/data/rest/getPositions' import { useEnabledChains } from 'uniswap/src/features/chains/hooks/useEnabledChains' import { useSupportedChainId } from 'uniswap/src/features/chains/hooks/useSupportedChainId' import { isL2ChainId, toGraphQLChain } from 'uniswap/src/features/chains/utils' @@ -254,3 +255,9 @@ export function useTrackedTokenPairs(): [Token, Token][] { return Object.keys(keyed).map((key) => keyed[key]) }, [combinedList]) } + +export function useRequestPositionsForSavedPairs() { + const savedSerializedPairs = useAppSelector(({ user: { pairs } }) => pairs) + const account = useAccount() + return useGetPositionsForPairs(savedSerializedPairs, account.address) +} diff --git a/config/jest-presets/jest/globals.js b/config/jest-presets/jest/globals.js index e09031bda0a..0613f198f80 100644 --- a/config/jest-presets/jest/globals.js +++ b/config/jest-presets/jest/globals.js @@ -21,6 +21,7 @@ module.exports = { QUICKNODE_AVAX_RPC_URL: 'https://api.uniswap.org', QUICKNODE_BASE_RPC_URL: 'https://api.uniswap.org', QUICKNODE_CELO_RPC_URL: 'https://api.uniswap.org', + QUICKNODE_MONAD_TESTNET_RPC_URL: 'https://api.uniswap.org', QUICKNODE_OP_RPC_URL: 'https://api.uniswap.org', QUICKNODE_POLYGON_RPC_URL: 'https://api.uniswap.org', QUICKNODE_WORLDCHAIN_RPC_URL: 'https://api.uniswap.org', diff --git a/package.json b/package.json index dffc8efa88d..f0cc67cc0db 100644 --- a/package.json +++ b/package.json @@ -55,16 +55,11 @@ "@tamagui/animations-moti@1.92.0": "patch:@tamagui/animations-moti@npm%3A1.92.0#./.yarn/patches/@tamagui-animations-moti-npm-1.92.0-a8dde990ec.patch", "@tanstack/react-query@5.51.16": "patch:@tanstack/react-query@npm%3A5.51.16#./.yarn/patches/@tanstack-react-query-npm-5.51.16-8fa6414eca.patch", "@uniswap/router-sdk": "1.14.3", - "@uniswap/sdk-core": "6.0.0", + "@uniswap/sdk-core": "6.1.0", "@uniswap/v2-sdk": "4.6.1", "@vercel/og@0.5.8": "patch:@vercel/og@npm%3A0.5.8#./.yarn/patches/@vercel-og-npm-0.5.8-83a79f2744.patch", "@walletconnect/ethereum-provider": "2.17.1", - "@web3-react/coinbase-wallet@8.2.3": "patch:@web3-react/coinbase-wallet@npm%3A8.2.3#./.yarn/patches/@web3-react-coinbase-wallet-npm-8.2.3-9c7073f079.patch", - "@web3-react/gnosis-safe@8.2.4": "patch:@web3-react/gnosis-safe@npm%3A8.2.4#./.yarn/patches/@web3-react-gnosis-safe-npm-8.2.4-a7e2850335.patch", - "@web3-react/metamask@8.2.4": "patch:@web3-react/metamask@npm%3A8.2.4#./.yarn/patches/@web3-react-metamask-npm-8.2.4-84b10de2d2.patch", - "@web3-react/walletconnect-v2@8.5.1": "patch:@web3-react/walletconnect-v2@npm%3A8.5.1#./.yarn/patches/@web3-react-walletconnect-v2-npm-8.5.1-933cac0534.patch", "@xmldom/xmldom": "0.7.7", - "cypress-hardhat@2.5.0": "patch:cypress-hardhat@npm%3A2.5.0#./.yarn/patches/cypress-hardhat-npm-2.5.0-9b9b7d7a28.patch", "cypress": "13.7.3", "detox@20.23.0": "patch:detox@npm%3A20.23.0#./.yarn/patches/detox-npm-20.23.0-6d61110e63.patch", "elliptic": "6.5.7", diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index 954a5cf00db..7c0b20d9037 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -43,7 +43,7 @@ "eslint-plugin-react-native": "4.1.0", "eslint-plugin-security": "1.5.0", "eslint-plugin-spellcheck": "0.0.20", - "eslint-plugin-storybook": "0.11.1", + "eslint-plugin-storybook": "0.8.0", "eslint-plugin-unused-imports": "2.0.0" }, "peerDependencies": { diff --git a/packages/ui/package.json b/packages/ui/package.json index c4bd7b33111..1fc469e74d0 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -6,6 +6,7 @@ "@react-native-masked-view/masked-view": "0.2.9", "@shopify/flash-list": "1.6.3", "@shopify/react-native-skia": "1.4.2", + "@storybook/react": "8.4.2", "@tamagui/animations-react-native": "1.114.4", "@tamagui/font-inter": "1.114.4", "@tamagui/helpers-icon": "1.114.4", diff --git a/packages/ui/src/assets/icons/scan-home.svg b/packages/ui/src/assets/icons/scan-home.svg index ae77a85b9fa..cefd89b5fbc 100644 --- a/packages/ui/src/assets/icons/scan-home.svg +++ b/packages/ui/src/assets/icons/scan-home.svg @@ -1,3 +1,3 @@ - - - \ No newline at end of file + + + diff --git a/packages/ui/src/assets/icons/settings-warning.svg b/packages/ui/src/assets/icons/settings-warning.svg new file mode 100644 index 00000000000..3ab52cfd058 --- /dev/null +++ b/packages/ui/src/assets/icons/settings-warning.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/ui/src/assets/index.ts b/packages/ui/src/assets/index.ts index e7523fa044e..b0454cb254a 100644 --- a/packages/ui/src/assets/index.ts +++ b/packages/ui/src/assets/index.ts @@ -4,6 +4,7 @@ export const OPTIMISM_LOGO = require('./logos/png/optimism-logo.png') export const ARBITRUM_LOGO = require('./logos/png/arbitrum-logo.png') export const BASE_LOGO = require('./logos/png/base-logo.png') export const BNB_LOGO = require('./logos/png/bnb-logo.png') +export const MONAD_LOGO = require('./logos/png/monad-logo.png') export const POLYGON_LOGO = require('./logos/png/polygon-logo.png') export const BLAST_LOGO = require('./logos/png/blast-logo.png') export const AVALANCHE_LOGO = require('./logos/png/avalanche-logo.png') diff --git a/packages/ui/src/assets/logos/png/monad-logo.png b/packages/ui/src/assets/logos/png/monad-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..051f75add07994b7ea5ba4cff7c72850f6a16023 GIT binary patch literal 5414 zcmV+>71`>EP)z{8E; zM|9P#Y)LlA611fLsmeNEgvS#BGY;H+l$j^9vJ`>f`P8&aUFt4tOMh6hON!{ZwY2EI zwAlZa3#I77k~()^J2QsO{DQe@;rB zIzfLkN#nTHQ5OV)0s;<*cC))o*6z4p&uL20K8T`YQpw?VXYQCl5J145!_hV|w_8M} zNo9z31cS(&sC4%~ou}snyafXGlwPzoTV!dKYD6h@03rJe1ne1i(&T0G2^W#wuifoV ztkaECx@?FSHWO=PVg+uc#tHYs2r zN`ZhYq+jRm_4~NuU?D55)-d5!9T0E@ zNJ*FTg0#9iAmEZ|H?LR8&{qj9 z97Nz8yx+RngUehkaH;bF0Y5;09P&u&=^@`iO8q!Up~t}W?wr*p5N~~OO3h=KADcIL z24jGLN6@c#zoXu*9~QAO_B-n0(LlgMaJ}nZn+^f5aBZf&_GWj7z&%g{_vsx(=pNw& zk>_A5<~<-_>X}ts?;>Rm1DIRCh(3j8vx?8|LcHMsbL$sT3;4t4?MpVR2uA>e1Ljtb zXa&rMh^6#^K+wc)ZbexGW3oyfu}*G9C19+)5ssqcRLyV1bfPI50b?vO5|lb~ZKkzY z9O@_pj5bkR#MEXIFJOo_PGS+UXcrni-gt?nS1eY*yyle;;1hbh(bDe~pR}8o%On($ z0_Fh?G6v!W%p$o+oV^nQ5hq}NP#Dkv!|*#HacWDHfH7SK9zx>OmKYbh_h3wm0C*JL z+Wy?wB>{*KFvJTcM}~-l7cj&NrYC$62Q6TT7tBuBA`Vu-5HBc>a77%XfFWK`JYkAB zH~~Yvpgh78aZmz=ctQDuCE{QN4DptWQgrVAc}m9oV-t0*sq20v*}-^2>7t>=lKa}K zd%;DHB;F?+5eFe)z9|9A)(huCDRpdA`mI59n)ldUwiv-sOS+I1CF^fL&mEHIcrReg zHW!MEsP>SwJ>Kp-J*64=@an2*mD(f0gdk$C1L;DLR;o&WZocl=@=CxE?__YAYz!Tmq;c%S zE@X(fdb|;E|9a08>}`G=7OqQ^cYQQh#D54Yb(X5eiZ9FKz1hgoyDrMhdBrS$@F?`Za}dV&`b7&j?vUi6~zVO0Nxn?3?rE*s1l%9g_)g#_l7u^e z&B-}?Bl>m>t<{UV20dyKFxo};ktp1|^bSC1{;-xhRae`fN96*Bcz?ltMXSw*RN>x5 zx~av_@>b8ksJgvWc^fIQ$ybP%E}ZNB`t9e1XEBJEdDnS*;QWq#5(?kLl-TYORZOJ< z&KzfJmnmL&Vs+`G*!QL2#2Qs~$nXRdP-m2SjxbNo0W zsE3`7?dx|HeLz~hs)E0xU64-&pcxafMgFah@`Y<`ef>^|3P zzU)GhNDQtt6})G<5CIFXdr|9Fi1YyurpS7@kQ!Lq?v6z9vcrs8w^~w_Zjj&s4~FYu z)(jQE%n?}VIZup1)<}Evy5)Woyi2Q30rxJ=Bw&$q&PtulsdO#&Q$uy*Qt9sztQo%G z3~!cHdZrZGiC0+a?2Iba@b3DIC{bzcD_bjIan>EvQ%7K7sq=-k#@YM4H3IlTd-L)@ z`bFZ*EUl%fA~2`U+RE7X%Z?zALPEU$k?JRW5Jr64jz=v&W#h+_GnIhlq|WA$?R=!n ze!{gOn~5Z!#ao+9mCa6^Ld!{=%`Ofggh3>R7KhWdNn4f^MPMPRGuOKt5N|-lVQ9IS zLSK0(YLfqCA_0e?nHE`Ip?a zrh|xc;%4l zdG3|UKMm##yZ5iIa_y3P)P)XtToU4yM+`fq`{Ww4d^7@wYFt6QGT{Rz(syX}$z^Cg zC}57hp&D08cX1#=C{~#biU2mW9-Gj5P{4D6_I&x~Ke)|uiKwkak4zB0mlw|A z9B%}uG=>q&?8d`~+Dc;uoJ={JSvN^64>odQio&j~G&U0+Dd2XqyBy+PB96YOdm{o- zcuWMgHptr7D*HEqXh0MmA>iy{~!=A(bU4fT1uIKxiB`aK&H?U zekm4sm}sJ~wa*7;mhS!IDtz%$@6xDGO{CFL6Gs$YY^2>xvpoS@{U-^*q}^o#(Gp7( zwwf}{4r<_K62jmI1My;2dPu^t*7hQBf7|2|31RSqfp{_WgqNdBpUPY0a#5$0O51q9 zILTU0AdmhYDe)UDxm?uBD0x>_m;_Nca$?wEX%s!zq$KuEt@tY`!NYJA){0I^FqX`c z`x(s=$pdLLa1qLgPNQA){X<);WF7!`U=0a~1L-X#%d2PI??MIqYgz@wi!w&?mX^h- zF8B_F#kur)oj}ywCJP57*vw)9i~ZrO)_)O*nyjUyl++#J&ZtvXuGRj?PF)ZQLg%AZ zCSVf#>C|Jy9w87HnVBUq(^TqQ8*BedlCiW5GYhyELEL<_we*j++DgAeXmNOt5Qq?M zk4YF#z-QW!>}i!gTZqDOBQcFm5+~qR?}i!>APPs1wdxxMjwSnde`&#;n;9b9sSDym+3?$@N~?pxzyB1l*lCqv5QU@0 zMc{J^7L(nIH)?+LiSM@T-1!qL*DH0Ufd87g(} z-w)i|BP4F*Y$S-nATX3t2mk2}Uj5{^1O3wX2>k?6I7%9n1Upijj4+yi6L3tIB_j&Q zhq(>&?kpF5Plux~GkT>?G%Y1W;n+|K1-Yfgj?v^u0V4_niL{!ROV-jl1qMgoew+6< z#xJ!)6b8bWvpUERYghYjjQiSH0V4_nNwha_wgQd52cv4=0S~T~O&?IcC=i83^RfBA z=k6f~IpdH#k_kU3;ND?>8%0}58U2-jIC^z&PD4K%y*3Ah=DH4vg_Vqh9@PLgkTH;e_w3Ym&XI9;O7a`s$Qs)6v2{_xY8%J+A`-CUp6&DKZC1t|=K|Hi*^su~9Tz;r^y;Tgod--6fd`~&K8jQt zhF1M>%ADBli74^TkU9^TNx(f<+T?CJ2aC1O+nd)d0=2+L0Xb#n=Rks(C3PM!Qwlwx zy?N!FTD3*8xtP=D#jJnfAU~WkyQq64v*Tg+w?99bIh&X%0uSH;52fgwWP=H<3TZd5 zR}*vdL!x-I+Z75BFH?wsvlC0I%c->NdN`ZVy2eG}CBjkn{npJM8R9d%B3pQgGexN& z3K1~#rt`0}C|XN~zM?l=4((=lnR~mEjH+SW&-S{=GOREGGug32GKVA^^o9$DKM+4` zU4JEGf}Ul5jI3o;@MK@10%lVEq$#}~=II|Cb|{8HtsCOPxk=!<_f|CuKayLB3q1@U z>*A9kB(#QMvInB)Ukol<29we2>pD{~f|+{8bugZl(ZMJ@0y8nx!@NU_r-BGf44)qA z_jQ*k0*bDC@BP22M55>qYg)T|;W8Kxn^aD;d(s9n9;TRn?>I^oFw@?;5jR0I#6_y- zpCOeVPw&{@&7Sl+cNi|S-hN(qMkP{83VoMUrE9`Xt=_Z{7)fsoQoczwOg86SV88c) zKc{^9rq*{73=aR_C(d;F7g~2;uopxnQ;C3?53jD8Rw>E-Q_MVit+n=Ads3Jt5a#MJ(Rz9^VSZ%Ty|0#ziR6rWVif^2!&A0IqXCY+e88-~1Q#e0cwGe&rimD@~yX zWOWiZ^5s5s(e-fOpxTMK&b`aPajxTe*CJp>x-%_t)DprSO;wKb$UmEEf`4GEjo2me zJZhQP8xactSh(3PaATs_2R;exIM*fK?9Zo~X>VS(+~9v5F_sz?7WwhukO^R3sz@k;w{?)(m8lo)#Yt6>HFHaB1W4sqI6N89(={H|BnKz~W z)U-=o>Mm%}}{~V$%kPyVn1R-EX{>Wty7P3|PZ%yW0QzJVFVW_)kNH3}Mc8Rq9 z!@XY1l5a4mpZZ56^Ae1JnOH;&>LeWTGC>KLfrvqQge6`kH~}*dF({t!#LEOJUnP3IXK*V5n!WAzQw163i7)(#t;$?ytFar^T$q8S)j0gcU5HZM)4Dm8z1k6Ch z;Bn-Lmk}jkCW1Sdz?6hC9ytl(1kA)RI}Ij7qIemR0%rP05&7O;4Ee{+1!=S9^O3+= z5G!DYmjYPZIKtq6w0M0OzX(JNn329?3yj9+H8@2gUcd}Q92c>Om+@vVbeXi=gS=H{ zMeyEfFu* z2W^79F%XP`r>o)@R2&8k(a0i%%E2sEaH2-d5B)X4BAX#5mTG!F`}%2 zhq=>cIwjyW$~~i7J^upY?STk91db&7Oq@>hLqNbIfVt%#%G%d&XS{w!A`tKxU~c(A z?*h2)TI^=kI3VB$fVovON}bKAbPe_Hcp%^$U~;PtQ19jeE_4p~MdBKaKowl@-!;UW z4@BSzKuTRMsCOp^5qJW6{o?r-MCOn{!I(qt??Swjfe1V$Xf+iEr_8%(5lsgKJOfCn zX9Fqo>>!1nfnO=L-6t?1b{{G8>>vUc1n;8OR_`DhKZ@uzuT_HxToCU%PY<#K5iq#M z!z*v}{4rBE97JI=DD?2?h!>^oUhW?FsZ5o0GDFW)lnA&DhC3tnNWocci9ghU{C1HRVQCvjl4`A!@{*H-9?@22N1Al zw40a9$|gI$2^qrm6A0K-d`YdfqGO}XK7{Kh5U}SAgshbQvqIO}8B)fXQ%^cDr~C#2 z4v2R1dR1F`X)LW$@m#nx`3z}tSU|u5(rVg8O;@YR(DICtnMLbT + +type Story = StoryObj + +export const VariantSmall: Story = { + args: { + children: 'Hello, world!', + size: 'small', + }, +} + +export const VariantMedium: Story = { + args: { + children: 'Hello, world!', + size: 'medium', + }, +} + +export const VariantLarge: Story = { + args: { + children: 'Hello, world!', + size: 'large', + }, +} + +export default meta diff --git a/packages/ui/src/components/icons/ScanHome.tsx b/packages/ui/src/components/icons/ScanHome.tsx index 262a790235f..d41ecf8ca46 100644 --- a/packages/ui/src/components/icons/ScanHome.tsx +++ b/packages/ui/src/components/icons/ScanHome.tsx @@ -6,13 +6,14 @@ import { createIcon } from '../factories/createIcon' export const [ScanHome, AnimatedScanHome] = createIcon({ name: 'ScanHome', getIcon: (props) => ( - + ), + defaultFill: '#7D7D7D', }) diff --git a/packages/ui/src/components/icons/SettingsWarning.tsx b/packages/ui/src/components/icons/SettingsWarning.tsx new file mode 100644 index 00000000000..075e3638a11 --- /dev/null +++ b/packages/ui/src/components/icons/SettingsWarning.tsx @@ -0,0 +1,25 @@ +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 [SettingsWarning, AnimatedSettingsWarning] = createIcon({ + name: 'SettingsWarning', + getIcon: (props) => ( + + + + + ), + defaultFill: '#FF0000', +}) diff --git a/packages/ui/src/components/icons/exported.ts b/packages/ui/src/components/icons/exported.ts index 971b7ef7fd5..50c54db5172 100644 --- a/packages/ui/src/components/icons/exported.ts +++ b/packages/ui/src/components/icons/exported.ts @@ -185,6 +185,7 @@ export * from './SelectIcon' export * from './SendAction' export * from './SendRoundedAirplane' export * from './Settings' +export * from './SettingsWarning' export * from './Share' export * from './ShieldCheck' export * from './ShieldQuestion' diff --git a/packages/ui/src/components/switch/Switch.tsx b/packages/ui/src/components/switch/Switch.tsx index 6065afc07df..8f39c8eb0c9 100644 --- a/packages/ui/src/components/switch/Switch.tsx +++ b/packages/ui/src/components/switch/Switch.tsx @@ -31,6 +31,7 @@ export function Switch({ onCheckedChange: onCheckedChangeProp, disabled, variant, + disabledStyle, ...rest }: SwitchProps): JSX.Element { const [checked, setChecked] = useState(checkedProp) @@ -56,8 +57,10 @@ export function Switch({ const THUMB_PADDING = getTokenValue('$spacing4') const TRACK_HEIGHT = THUMB_HEIGHT + THUMB_PADDING * 2 + const isDisabledStyling = disabled && !checked + const frameBackgroundColor = ((): ColorTokens => { - if (disabled) { + if (isDisabledStyling) { return '$surface3' } if (isBranded) { @@ -67,7 +70,7 @@ export function Switch({ })() const thumbBackgroundColor = ((): ColorTokens => { - if (disabled) { + if (isDisabledStyling) { if (isBranded) { return checked ? '$neutral2' : '$neutral3' } @@ -80,7 +83,7 @@ export function Switch({ })() const iconColor = ((): string => { - if (disabled) { + if (isDisabledStyling) { return colors.white.val } return isBranded ? colors.accent1.val : colors.neutral1.val @@ -122,6 +125,10 @@ export function Switch({ minWidth="$spacing60" p="$spacing4" pointerEvents={disabled ? 'none' : 'auto'} + disabledStyle={{ + ...(checked && { opacity: 0.6 }), + ...disabledStyle, + }} onCheckedChange={disabled ? undefined : onCheckedChange} {...rest} > diff --git a/packages/ui/src/storybook/Spore.mdx b/packages/ui/src/storybook/Spore.mdx new file mode 100644 index 00000000000..b865d6d7a3e --- /dev/null +++ b/packages/ui/src/storybook/Spore.mdx @@ -0,0 +1,92 @@ +import { Meta } from '@storybook/blocks' + +export const RightArrow = () => ( + + + +) + + + +
+
+ # 🍄 Explore the Spore Library + + The Spore Library is a comprehensive collection of design components and resources that streamline your UI development process. Dive into the guides below to learn how to integrate Spore into your projects and enhance your design workflow. + +
+
+
+

Design System

+

Discover the principles and guidelines that form the foundation of the Spore design system.

+ Learn more in Figma +
+
+

Component Library

+

Access a wide range of reusable components that adhere to the Spore design standards.

+ Explore components in Figma +
+ +
+
+ + diff --git a/packages/ui/src/storybook/constants.ts b/packages/ui/src/storybook/constants.ts deleted file mode 100644 index 56f803f8da6..00000000000 --- a/packages/ui/src/storybook/constants.ts +++ /dev/null @@ -1,5 +0,0 @@ -export enum StorybookTitles { - Atoms = 'atoms', - Molecules = 'molecules', - Organisms = 'organisms', -} diff --git a/packages/ui/src/storybook/index.ts b/packages/ui/src/storybook/index.ts deleted file mode 100644 index f87cf0102a1..00000000000 --- a/packages/ui/src/storybook/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './constants' diff --git a/packages/ui/src/theme/color/colors.ts b/packages/ui/src/theme/color/colors.ts index 8f35842d12a..94a2d79656c 100644 --- a/packages/ui/src/theme/color/colors.ts +++ b/packages/ui/src/theme/color/colors.ts @@ -138,6 +138,10 @@ export const networkColors = { light: '#222222', dark: '#FCFF52', }, + monad: { + light: '#836EF9', + dark: '#836EF9', + }, worldchain: { light: '#222222', dark: '#FFFFFF', @@ -326,6 +330,9 @@ export const colorsLight = { // Testnets chain_11155111: networkColors.ethereum.light, chain_1301: networkColors.unichain.light, + chain_41454: networkColors.monad.light, + + pinkThemed: colors.pinkLight, } export type ColorKeys = keyof typeof colorsLight @@ -409,4 +416,7 @@ export const colorsDark = { // Testnets chain_11155111: networkColors.ethereum.dark, chain_1301: networkColors.unichain.dark, + chain_41454: networkColors.monad.dark, + + pinkThemed: colors.pinkDark, } diff --git a/packages/uniswap/package.json b/packages/uniswap/package.json index f4a45171f6a..c31e54265e5 100644 --- a/packages/uniswap/package.json +++ b/packages/uniswap/package.json @@ -45,7 +45,7 @@ "@uniswap/client-pools": "0.0.9", "@uniswap/permit2-sdk": "1.3.0", "@uniswap/router-sdk": "1.15.0", - "@uniswap/sdk-core": "6.0.0", + "@uniswap/sdk-core": "6.1.0", "@uniswap/uniswapx-sdk": "2.1.0-beta.18", "@uniswap/v2-sdk": "4.7.0", "@uniswap/v3-sdk": "3.19.0", diff --git a/packages/uniswap/src/assets/chainLogos.tsx b/packages/uniswap/src/assets/chainLogos.tsx index 15ac4ed7983..a19dfd2c885 100644 --- a/packages/uniswap/src/assets/chainLogos.tsx +++ b/packages/uniswap/src/assets/chainLogos.tsx @@ -53,6 +53,12 @@ export const UNIVERSE_CHAIN_LOGO = { logoDark: BlockExplorer, }, } as const satisfies UniverseChainLogoInfo, + [UniverseChainId.MonadTestnet]: { + explorer: { + logoLight: BlockExplorer, + logoDark: BlockExplorer, + }, + } as const satisfies UniverseChainLogoInfo, [UniverseChainId.Optimism]: { explorer: { logoLight: OpEtherscanLogoLight, diff --git a/packages/uniswap/src/components/WarningMessage/WarningMessage.tsx b/packages/uniswap/src/components/WarningMessage/WarningMessage.tsx new file mode 100644 index 00000000000..f7d077a280a --- /dev/null +++ b/packages/uniswap/src/components/WarningMessage/WarningMessage.tsx @@ -0,0 +1,32 @@ +import { ColorTokens, Flex, Text, Tooltip } from 'ui/src' +import { AlertTriangleFilled } from 'ui/src/components/icons/AlertTriangleFilled' + +interface WarningMessageProps { + warningMessage: string + color: ColorTokens + tooltipText?: string +} + +export function WarningMessage({ warningMessage, color, tooltipText }: WarningMessageProps): JSX.Element { + const warningContent = ( + + + + {warningMessage} + + + ) + + if (tooltipText) { + return ( + + {warningContent} + + {tooltipText} + + + ) + } + + return warningContent +} diff --git a/packages/uniswap/src/components/dropdowns/ActionSheetDropdown.test.tsx b/packages/uniswap/src/components/dropdowns/ActionSheetDropdown.test.tsx index 6dbf01ca45e..0c060919d94 100644 --- a/packages/uniswap/src/components/dropdowns/ActionSheetDropdown.test.tsx +++ b/packages/uniswap/src/components/dropdowns/ActionSheetDropdown.test.tsx @@ -110,7 +110,9 @@ describe(ActionSheetDropdown, () => { fireEvent.press(option, ON_PRESS_EVENT_PAYLOAD) - // Should call the onPress function of the option - expect(options[2]?.onPress).toHaveBeenCalledTimes(1) + await waitFor(() => { + // Should call the onPress function of the option + expect(options[2]?.onPress).toHaveBeenCalledTimes(1) + }) }) }) diff --git a/packages/uniswap/src/components/dropdowns/ActionSheetDropdown.tsx b/packages/uniswap/src/components/dropdowns/ActionSheetDropdown.tsx index 34d2b51c18d..bc40f3567f5 100644 --- a/packages/uniswap/src/components/dropdowns/ActionSheetDropdown.tsx +++ b/packages/uniswap/src/components/dropdowns/ActionSheetDropdown.tsx @@ -11,6 +11,7 @@ import { Scrollbar } from 'uniswap/src/components/misc/Scrollbar' import { MenuItemProp } from 'uniswap/src/components/modals/ActionSheetModal' import { useAppInsets } from 'uniswap/src/hooks/useAppInsets' import { isAndroid, isInterface, isTouchable } from 'utilities/src/platform' +import { executeWithFrameDelay } from 'utilities/src/react/delayUtils' import { useTimeout } from 'utilities/src/time/timing' const DEFAULT_MIN_WIDTH = 225 @@ -357,10 +358,11 @@ function DropdownContent({ hoverable borderRadius="$rounded8" onPress={(event) => { - onPress() - if (closeOnSelect) { - handleClose?.(event) - } + executeWithFrameDelay(() => { + if (closeOnSelect) { + handleClose?.(event) + } + }, onPress) }} > {render()} diff --git a/packages/uniswap/src/components/gas/NetworkFee.test.tsx b/packages/uniswap/src/components/gas/NetworkFee.test.tsx index 1835f62b16c..38d7a55a570 100644 --- a/packages/uniswap/src/components/gas/NetworkFee.test.tsx +++ b/packages/uniswap/src/components/gas/NetworkFee.test.tsx @@ -7,7 +7,7 @@ jest.mock('uniswap/src/features/gas/hooks', () => { useFormattedUniswapXGasFeeInfo: jest.fn(() => undefined), useUSDValue: (_chainId: UniverseChainId, gasFee: string): string => gasFee, useGasFeeHighRelativeToValue: jest.fn(() => false), - useGasFeeFormattedAmounts: jest.fn(() => ({ + useGasFeeFormattedDisplayAmounts: jest.fn(() => ({ gasFeeFormatted: '$1', gasFeeUSD: '$500.00', })), diff --git a/packages/uniswap/src/components/gas/NetworkFee.tsx b/packages/uniswap/src/components/gas/NetworkFee.tsx index 1de2bca5c0a..52091c762f0 100644 --- a/packages/uniswap/src/components/gas/NetworkFee.tsx +++ b/packages/uniswap/src/components/gas/NetworkFee.tsx @@ -8,7 +8,7 @@ import { IndicativeLoadingWrapper } from 'uniswap/src/components/misc/Indicative import { UniverseChainId } from 'uniswap/src/features/chains/types' import { useFormattedUniswapXGasFeeInfo, - useGasFeeFormattedAmounts, + useGasFeeFormattedDisplayAmounts, useGasFeeHighRelativeToValue, } from 'uniswap/src/features/gas/hooks' import { GasFeeResult } from 'uniswap/src/features/gas/types' @@ -31,7 +31,7 @@ export function NetworkFee({ }): JSX.Element { const { t } = useTranslation() - const { gasFeeFormatted, gasFeeUSD } = useGasFeeFormattedAmounts({ + const { gasFeeFormatted, gasFeeUSD } = useGasFeeFormattedDisplayAmounts({ gasFee, chainId, placeholder: '-', diff --git a/packages/uniswap/src/components/modals/Modal.native.tsx b/packages/uniswap/src/components/modals/Modal.native.tsx index f230d87c1a9..a3b4ac2d1b3 100644 --- a/packages/uniswap/src/components/modals/Modal.native.tsx +++ b/packages/uniswap/src/components/modals/Modal.native.tsx @@ -17,6 +17,7 @@ import { borderRadii, spacing } from 'ui/src/theme' import { BottomSheetContextProvider } from 'uniswap/src/components/modals/BottomSheetContext' import { HandleBar } from 'uniswap/src/components/modals/HandleBar' import { ModalProps } from 'uniswap/src/components/modals/ModalProps' +import { BSM_ANIMATION_CONFIGS, IS_SHEET_READY_DELAY } from 'uniswap/src/components/modals/modalConstants' import Trace from 'uniswap/src/features/telemetry/Trace' import { useAppInsets } from 'uniswap/src/hooks/useAppInsets' import { useKeyboardLayout } from 'uniswap/src/utils/useKeyboardLayout' @@ -207,7 +208,7 @@ function BottomSheetModalContents({ // We consider the sheet to be "ready" as soon as it starts animating from the bottom to the top. // We add a short delay given that this callback is called when the sheet is "about to" animate. if (!isSheetReady && fromIndex === -1 && toIndex === 0) { - setTimeout(() => setIsSheetReady(true), 50) + setTimeout(() => setIsSheetReady(true), IS_SHEET_READY_DELAY) } }, [hideKeyboardOnDismiss, hideKeyboardOnSwipeDown, isSheetReady], @@ -267,6 +268,7 @@ function BottomSheetModalContents({ snapPoints={snapPoints} stackBehavior={stackBehavior} topInset={renderBehindTopInset ? 0 : insets.top} + animationConfigs={BSM_ANIMATION_CONFIGS} onAnimate={onAnimate} onDismiss={onClose} > diff --git a/packages/uniswap/src/components/modals/Modal.web.tsx b/packages/uniswap/src/components/modals/Modal.web.tsx index bf724f7adbc..ba2998040c2 100644 --- a/packages/uniswap/src/components/modals/Modal.web.tsx +++ b/packages/uniswap/src/components/modals/Modal.web.tsx @@ -64,7 +64,7 @@ export function Modal({ adaptToSheet={isInterface} alignment={alignment} backgroundColor={backgroundColor} - height={height ?? (fullScreen ? '100%' : undefined)} + height={fullScreen ? '100%' : undefined} isOpen={isModalOpen} justifyContent={justifyContent} m="$none" diff --git a/packages/uniswap/src/components/modals/modalConstants.tsx b/packages/uniswap/src/components/modals/modalConstants.tsx new file mode 100644 index 00000000000..23b3f4a9b7e --- /dev/null +++ b/packages/uniswap/src/components/modals/modalConstants.tsx @@ -0,0 +1,29 @@ +import { BottomSheetModal } from '@gorhom/bottom-sheet' +import { ComponentProps } from 'react' +import { Easing } from 'react-native-reanimated' +import { isIOS } from 'utilities/src/platform' + +/** + * iOS animation config. Based on default values from + * the gorhom/bottom-sheet library. + */ +const ANIMATION_CONFIGS_IOS = { + damping: 500, + stiffness: 1500, + mass: 1.5, + overshootClamping: true, + restDisplacementThreshold: 10, + restSpeedThreshold: 10, +} satisfies ComponentProps['animationConfigs'] + +/**apps/mobile/src/components/explore/ExploreSections.tsx + * Android animation config. Based on default values from + * the gorhom/bottom-sheet library. + */ +const ANIMATION_CONFIGS_ANDROID = { + duration: 200, + easing: Easing.out(Easing.exp), +} satisfies ComponentProps['animationConfigs'] + +export const IS_SHEET_READY_DELAY = 100 +export const BSM_ANIMATION_CONFIGS = isIOS ? ANIMATION_CONFIGS_IOS : ANIMATION_CONFIGS_ANDROID diff --git a/packages/uniswap/src/components/pill/NewTag.tsx b/packages/uniswap/src/components/pill/NewTag.tsx index 22deeb05f2c..55e3885e95e 100644 --- a/packages/uniswap/src/components/pill/NewTag.tsx +++ b/packages/uniswap/src/components/pill/NewTag.tsx @@ -1,23 +1,35 @@ import { memo } from 'react' -import { Flex, Text } from 'ui/src' +import { ColorTokens, Flex, FlexProps, Text } from 'ui/src' import { useTranslation } from 'uniswap/src/i18n' -function _NewTag(): JSX.Element { +interface NewTagProps { + backgroundColor?: ColorTokens + textColor?: ColorTokens + ml?: FlexProps['ml'] + exclamation?: boolean +} + +function _NewTag({ + backgroundColor = '$accent2Hovered', + textColor = '$accent1Hovered', + ml = '$spacing6', + exclamation = false, +}: NewTagProps): JSX.Element { const { t } = useTranslation() return ( - - {t('common.new')} + + {exclamation ? t('common.new.exclamation') : t('common.new')} diff --git a/packages/uniswap/src/config.ts b/packages/uniswap/src/config.ts index d0bdc03955e..03c42266f28 100644 --- a/packages/uniswap/src/config.ts +++ b/packages/uniswap/src/config.ts @@ -16,6 +16,7 @@ import { QUICKNODE_BNB_RPC_URL, QUICKNODE_CELO_RPC_URL, QUICKNODE_MAINNET_RPC_URL, + QUICKNODE_MONAD_TESTNET_RPC_URL, QUICKNODE_OP_RPC_URL, QUICKNODE_POLYGON_RPC_URL, QUICKNODE_SEPOLIA_RPC_URL, @@ -68,6 +69,7 @@ export interface Config { quicknodeZkSyncRpcUrl: string quicknodeWorldChainRpcUrl: string quicknodeUnichainSepoliaRpcUrl: string + quicknodeMonadTestnetRpcUrl: string quicknodeMainnetRpcUrl: string quicknodeSepoliaRpcUrl: string tradingApiKey: string @@ -113,6 +115,10 @@ const _config: Config = { process.env.REACT_APP_QUICKNODE_BNB_RPC_URL || process.env.QUICKNODE_BNB_RPC_URL || QUICKNODE_BNB_RPC_URL, quicknodeCeloRpcUrl: process.env.REACT_APP_QUICKNODE_CELO_RPC_URL || process.env.QUICKNODE_CELO_RPC_URL || QUICKNODE_CELO_RPC_URL, + quicknodeMonadTestnetRpcUrl: + process.env.REACT_APP_QUICKNODE_MONAD_TESTNET_RPC_URL || + process.env.QUICKNODE_MONAD_TESTNET_RPC_URL || + QUICKNODE_MONAD_TESTNET_RPC_URL, quicknodeOpRpcUrl: process.env.REACT_APP_QUICKNODE_OP_RPC_URL || process.env.QUICKNODE_OP_RPC_URL || QUICKNODE_OP_RPC_URL, quicknodePolygonRpcUrl: diff --git a/packages/uniswap/src/constants/routing.ts b/packages/uniswap/src/constants/routing.ts index 2382b63159f..824805e5790 100644 --- a/packages/uniswap/src/constants/routing.ts +++ b/packages/uniswap/src/constants/routing.ts @@ -31,6 +31,7 @@ import { USDT_ARBITRUM_ONE, USDT_AVALANCHE, USDT_BSC, + USDT_MONAD_TESTNET, USDT_OPTIMISM, USDT_POLYGON, WBTC, @@ -104,6 +105,12 @@ export const COMMON_BASES: ChainCurrencyList = { [UniverseChainId.Celo]: [nativeOnChain(UniverseChainId.Celo), USDC_CELO].map(buildPartialCurrencyInfo), + [UniverseChainId.MonadTestnet]: [ + nativeOnChain(UniverseChainId.MonadTestnet), + WRAPPED_NATIVE_CURRENCY[UniverseChainId.MonadTestnet] as Token, + USDT_MONAD_TESTNET, + ].map(buildPartialCurrencyInfo), + [UniverseChainId.Optimism]: [ nativeOnChain(UniverseChainId.Optimism), OP, diff --git a/packages/uniswap/src/constants/tokens.ts b/packages/uniswap/src/constants/tokens.ts index d42064b46d8..20352706110 100644 --- a/packages/uniswap/src/constants/tokens.ts +++ b/packages/uniswap/src/constants/tokens.ts @@ -3,6 +3,14 @@ import { Currency, NativeCurrency, Token, UNI_ADDRESSES, WETH9 } from '@uniswap/ import invariant from 'tiny-invariant' import { UniverseChainId } from 'uniswap/src/features/chains/types' +export const USDT_MONAD_TESTNET = new Token( + UniverseChainId.MonadTestnet, + '0xfBC2D240A5eD44231AcA3A9e9066bc4b33f01149', + 6, + 'USDT', + 'Tether USD', +) + export const USDC_SEPOLIA = new Token( UniverseChainId.Sepolia, '0x1c7d4b196cb0c7b01d743fbc6116a902379c7238', @@ -407,6 +415,13 @@ export const WRAPPED_NATIVE_CURRENCY: { [chainId: number]: Token } = { 'CELO', 'Celo native asset', ), + [UniverseChainId.MonadTestnet]: new Token( + UniverseChainId.MonadTestnet, + '0x93EACdB111FF98dE9a8Ac5823d357BBc4842aE63', + 18, + 'WMON', + 'Wrapped MON', + ), [UniverseChainId.Optimism]: new Token( UniverseChainId.Optimism, '0x4200000000000000000000000000000000000006', @@ -553,6 +568,33 @@ class AvaxNativeCurrency extends NativeCurrency { } } +function isMonadTestnet(chainId: number): chainId is UniverseChainId.MonadTestnet { + return chainId === UniverseChainId.MonadTestnet +} + +// can reuse for monad mainnet when we add support +class MonadTestnetNativeCurrency extends NativeCurrency { + equals(other: Currency): boolean { + return other.isNative && other.chainId === this.chainId + } + + get wrapped(): Token { + if (!isMonadTestnet(this.chainId)) { + throw new Error('Not monad testnet') + } + const wrapped = WRAPPED_NATIVE_CURRENCY[this.chainId] + invariant(wrapped instanceof Token) + return wrapped + } + + public constructor(chainId: number) { + if (!isMonadTestnet(chainId)) { + throw new Error('Not monad testnet') + } + super(chainId, 18, 'MON', 'MON') + } +} + class ExtendedEther extends NativeCurrency { public get wrapped(): Token { const wrapped = WRAPPED_NATIVE_CURRENCY[this.chainId] @@ -591,6 +633,8 @@ export function nativeOnChain(chainId: number): NativeCurrency | Token { nativeCurrency = new BscNativeCurrency(chainId) } else if (isAvalanche(chainId)) { nativeCurrency = new AvaxNativeCurrency(chainId) + } else if (isMonadTestnet(chainId)) { + nativeCurrency = new MonadTestnetNativeCurrency(chainId) } else { nativeCurrency = ExtendedEther.onChain(chainId) } diff --git a/packages/uniswap/src/constants/transactions.ts b/packages/uniswap/src/constants/transactions.ts index 1f3f2b8c84e..7b24b8f8d5c 100644 --- a/packages/uniswap/src/constants/transactions.ts +++ b/packages/uniswap/src/constants/transactions.ts @@ -2,7 +2,8 @@ export const TRANSACTION_CANCELLATION_GAS_FACTOR = 1.2 // Increase gas price off // Slippage tolerances are percentages (ex. 5 = 5% slippage tolerance) export const MIN_AUTO_SLIPPAGE_TOLERANCE = 0.5 export const MAX_AUTO_SLIPPAGE_TOLERANCE = 5.5 -export const MAX_CUSTOM_SLIPPAGE_TOLERANCE = 50 +export const MAX_CUSTOM_SLIPPAGE_TOLERANCE = 100 +export const SLIPPAGE_CRITICAL_TOLERANCE = 20 export const MAX_CUSTOM_DEADLINE = 3 * 24 * 60 // 3 days in minutes diff --git a/packages/uniswap/src/data/graphql/uniswap-data-api/schema.graphql b/packages/uniswap/src/data/graphql/uniswap-data-api/schema.graphql index c0e6da1a1c8..7087c2bdcf5 100644 --- a/packages/uniswap/src/data/graphql/uniswap-data-api/schema.graphql +++ b/packages/uniswap/src/data/graphql/uniswap-data-api/schema.graphql @@ -188,6 +188,7 @@ enum Chain { ZORA ZKSYNC ASTROCHAIN_SEPOLIA + MONAD_TESTNET WORLDCHAIN UNKNOWN_CHAIN } diff --git a/packages/uniswap/src/data/rest/conversionTracking/constants.ts b/packages/uniswap/src/data/rest/conversionTracking/constants.ts index 1882eb90847..0417be15d9a 100644 --- a/packages/uniswap/src/data/rest/conversionTracking/constants.ts +++ b/packages/uniswap/src/data/rest/conversionTracking/constants.ts @@ -48,7 +48,7 @@ export const PERSONAL3_CONVERSION_URL = 'https://www.persona3.tech/events/attrib const REDDIT_PIXEL_ID = 't2_tic7kuip' export const REDDIT_CONVERSION_URL = `https://ads-api.reddit.com/api/v2.0/conversions/events/${REDDIT_PIXEL_ID}` -const GOOGLE_CUSTOMER_ID = '987-182-6344' +const GOOGLE_CUSTOMER_ID = '9871826344' export const GOOGLE_CONVERSION_URL = `https://googleads.googleapis.com/v18/customers/${GOOGLE_CUSTOMER_ID}:uploadClickConversions` export const GOOGLE_CONVERSION_EVENTS = { diff --git a/packages/uniswap/src/data/rest/conversionTracking/tracking.ts b/packages/uniswap/src/data/rest/conversionTracking/tracking.ts index fbab958a067..f87d5892117 100644 --- a/packages/uniswap/src/data/rest/conversionTracking/tracking.ts +++ b/packages/uniswap/src/data/rest/conversionTracking/tracking.ts @@ -87,9 +87,6 @@ const buildGoogleProxyRequest = ({ gclid: lead.id, conversionDateTime: addJitter(new Date()), conversionAction: eventId, - conversionValue: 1.0, - conversionCode: 'USD', - conversionEnvironment: 'WEB', }, ], }), diff --git a/packages/uniswap/src/data/rest/conversionTracking/useConversionTracking.ts b/packages/uniswap/src/data/rest/conversionTracking/useConversionTracking.ts index d36f6a457a4..05c055461f4 100644 --- a/packages/uniswap/src/data/rest/conversionTracking/useConversionTracking.ts +++ b/packages/uniswap/src/data/rest/conversionTracking/useConversionTracking.ts @@ -13,6 +13,8 @@ import { useConversionProxy } from 'uniswap/src/data/rest/conversionTracking/use import { getExternalConversionLeadsCookie } from 'uniswap/src/data/rest/conversionTracking/utils' import { FeatureFlags } from 'uniswap/src/features/gating/flags' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' +import { UniswapEventName } from 'uniswap/src/features/telemetry/constants' +import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { useAccount } from 'wagmi' const conversionLeadsAtom = atomWithStorage(CONVERSION_LEADS_STORAGE_KEY, []) @@ -42,7 +44,7 @@ export function useConversionTracking(): UseConversionTracking { const conversionProxy = useConversionProxy() const trackConversion = useCallback( - ({ platformIdType, eventId, eventName }: TrackConversionArgs) => { + async ({ platformIdType, eventId, eventName }: TrackConversionArgs) => { const lead = conversionLeads.find(({ type }) => type === platformIdType) // Prevent triggering events under the following conditions: @@ -64,17 +66,31 @@ export function useConversionTracking(): UseConversionTracking { const proxyRequest = buildProxyRequest({ lead, address: account.address, eventId, eventName }) - conversionProxy.mutate(proxyRequest, { - onSuccess: () => { - setConversionLeads((leads: ConversionLead[]) => [ - ...leads.filter(({ id }) => lead.id !== id), - { - ...lead, - executedEvents: lead.executedEvents.concat([eventId]), - }, - ]) - }, - }) + try { + const response = await conversionProxy.mutateAsync(proxyRequest) + + // Prevent success handler if the underlying request is bad + if (response.status !== 200) { + throw new Error() + } + + setConversionLeads((leads: ConversionLead[]) => [ + ...leads.filter(({ id }) => lead.id !== id), + { + ...lead, + executedEvents: lead.executedEvents.concat([eventId]), + }, + ]) + + sendAnalyticsEvent(UniswapEventName.ConversionEventSubmitted, { + id: lead.id, + eventId, + eventName, + platformIdType, + }) + } catch (e) { + // Note: The request will be retried until it exists in executedEvents + } }, // TODO: Investigate why conversionProxy as a dependency causes a rendering loop // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/packages/uniswap/src/data/rest/getPositions.ts b/packages/uniswap/src/data/rest/getPositions.ts index 017e6b136da..0756eb5379a 100644 --- a/packages/uniswap/src/data/rest/getPositions.ts +++ b/packages/uniswap/src/data/rest/getPositions.ts @@ -1,11 +1,26 @@ /* eslint-disable no-restricted-imports */ import { PartialMessage } from '@bufbuild/protobuf' import { ConnectError } from '@connectrpc/connect' -import { useQuery } from '@connectrpc/connect-query' -import { UseQueryResult, keepPreviousData } 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 { createQueryOptions, useInfiniteQuery, useQuery } from '@connectrpc/connect-query' +import { + InfiniteData, + UseInfiniteQueryResult, + UseQueryResult, + keepPreviousData, + useQueries, +} from '@tanstack/react-query' +import { getPosition, listPositions } from '@uniswap/client-pools/dist/pools/v1/api-PoolsService_connectquery' +import { + GetPositionResponse, + ListPositionsRequest, + ListPositionsResponse, +} from '@uniswap/client-pools/dist/pools/v1/api_pb' +import { ProtocolVersion } from '@uniswap/client-pools/dist/pools/v1/types_pb' +import { Pair } from '@uniswap/v2-sdk' +import { useMemo } from 'react' import { uniswapGetTransport } from 'uniswap/src/data/rest/base' +import { SerializedToken } from 'uniswap/src/features/tokens/slice/types' +import { deserializeToken } from 'uniswap/src/utils/currency' export function useGetPositionsQuery( input?: PartialMessage, @@ -17,3 +32,64 @@ export function useGetPositionsQuery( placeholderData: keepPreviousData, }) } + +export function useGetPositionsInfiniteQuery( + input: PartialMessage & { pageToken: string }, + disabled?: boolean, +): UseInfiniteQueryResult, ConnectError> { + return useInfiniteQuery(listPositions, input, { + transport: uniswapGetTransport, + enabled: !!input && !disabled, + pageParamKey: 'pageToken', + getNextPageParam: (lastPage) => lastPage.nextPageToken, + placeholderData: keepPreviousData, + }) +} + +export function useGetPositionsForPairs( + serializedPairs: { + [chainId: number]: { + [key: string]: { token0: SerializedToken; token1: SerializedToken } + } + }, + account?: Address, +): UseQueryResult[] { + const positionsQueryOptions = useMemo(() => { + return Object.keys(serializedPairs || {}) + .flatMap((chainId) => { + const pairsForChain = serializedPairs[Number(chainId)] + if (!pairsForChain) { + return [] + } + return Object.keys(pairsForChain).map((pairId) => { + const pair = pairsForChain[pairId] + if (!pair) { + return undefined + } + const [token0, token1] = [deserializeToken(pair.token0), deserializeToken(pair.token1)] + const pairAddress = Pair.getAddress(token0, token1) + return createQueryOptions( + getPosition, + account + ? { + chainId: Number(chainId), + protocolVersion: ProtocolVersion.V2, + pairAddress, + owner: account, + } + : undefined, + { transport: uniswapGetTransport }, + ) + }) + }) + .filter(isDefined) + }, [serializedPairs, account]) + + return useQueries({ + queries: positionsQueryOptions, + }) +} + +function isDefined(value: T | undefined): value is T { + return value !== undefined +} diff --git a/packages/uniswap/src/data/tradingApi/api.json b/packages/uniswap/src/data/tradingApi/api.json index 28611dcc852..b257f03ee84 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_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_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 `simulateTransaction` 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 `simulateTransaction` 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 `simulateTransaction` 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":"Decrease LP position calldata","description":"The response will also have the transaction to decrease the position for the corresponding pool. If the parameter `simulateTransaction` is set to `true`, then the response will include the gas fees for the decrease transaction.","operationId":"decrease_lp_position","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecreaseLPPositionRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/DecreaseLPPositionSuccess200"},"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 `simulateTransaction` 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"}}}},"/lp/migrate":{"post":{"tags":["Liquidity"],"summary":"Migrate LP position calldata","description":"The response will also have the transaction to migrate the position for the corresponding pool. If the parameter `simulateTransaction` is set to `true`, then the response will include the gas fees for the migrate transaction.","operationId":"migrate_lp_position","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MigrateLPPositionRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/MigrateLPPositionSuccess200"},"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"}}}},"DecreaseLPPositionSuccess200":{"description":"Decrease LP Position successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecreaseLPPositionResponse"}}}},"ClaimLPFeesSuccess200":{"description":"Claim LP Fees successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimLPFeesResponse"}}}},"MigrateLPPositionSuccess200":{"description":"Migrate LP Position successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MigrateLPPositionResponse"}}}},"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}$"},"Position":{"type":"object","properties":{"pool":{"$ref":"#/components/schemas/Pool"},"tickLower":{"type":"number"},"tickUpper":{"type":"number"}},"required":["pool"]},"Pool":{"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"]},"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"},{"$ref":"#/components/schemas/PriorityQuote"}]},"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":{"enum":["ResourceNotFound","QuoteAmountTooLowError"],"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,1301,480]},"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","Priority"]},"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"]},"PriorityInput":{"type":"object","properties":{"amount":{"type":"string"},"token":{"type":"string"},"mpsPerPriorityFeeWei":{"type":"string"}},"required":["amount","token","mpsPerPriorityFeeWei"]},"PriorityOutput":{"type":"object","properties":{"amount":{"type":"string"},"token":{"type":"string"},"recipient":{"type":"string"},"mpsPerPriorityFeeWei":{"type":"string"}},"required":["amount","token","recipient","mpsPerPriorityFeeWei"]},"PriorityOrderInfo":{"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"},"auctionStartBlock":{"type":"string"},"baselinePriorityFeeWei":{"type":"string"},"input":{"$ref":"#/components/schemas/PriorityInput"},"outputs":{"type":"array","items":{"$ref":"#/components/schemas/PriorityOutput"}},"cosigner":{"$ref":"#/components/schemas/Address"}},"required":["chainId","nonce","reactor","swapper","deadline","validationContract","validationData","auctionStartBlock","baselinePriorityFeeWei","input","outputs","cosigner"]},"PriorityQuote":{"type":"object","properties":{"encodedOrder":{"type":"string"},"orderId":{"type":"string"},"orderInfo":{"$ref":"#/components/schemas/PriorityOrderInfo"},"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"},"expectedAmountIn":{"type":"string"},"expectedAmountOut":{"type":"string"}},"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","PRIORITY"]},"Quote":{"oneOf":[{"$ref":"#/components/schemas/DutchQuote"},{"$ref":"#/components/schemas/ClassicQuote"},{"$ref":"#/components/schemas/WrapUnwrapQuote"},{"$ref":"#/components/schemas/DutchQuoteV2"},{"$ref":"#/components/schemas/BridgeQuote"},{"$ref":"#/components/schemas/PriorityQuote"}]},"CheckApprovalLPRequest":{"type":"object","properties":{"protocol":{"$ref":"#/components/schemas/ProtocolItems"},"token0":{"$ref":"#/components/schemas/Address"},"token1":{"$ref":"#/components/schemas/Address"},"positionToken":{"$ref":"#/components/schemas/Address"},"chainId":{"$ref":"#/components/schemas/ChainId"},"walletAddress":{"$ref":"#/components/schemas/Address"},"amount0":{"type":"string"},"amount1":{"type":"string"},"positionAmount":{"type":"string"},"simulateTransaction":{"type":"boolean"}}},"CheckApprovalLPResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"token0Approval":{"$ref":"#/components/schemas/TransactionRequest"},"token1Approval":{"$ref":"#/components/schemas/TransactionRequest"},"positionTokenApproval":{"$ref":"#/components/schemas/TransactionRequest"},"permitData":{"$ref":"#/components/schemas/NullablePermit"},"gasFeeToken0Approval":{"type":"string"},"gasFeeToken1Approval":{"type":"string"},"gasFeePositionTokenApproval":{"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"},{"$ref":"#/components/schemas/V4PoolInRoute"}]}}},"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"}}},"V4PoolInRoute":{"type":"object","properties":{"type":{"type":"string","default":"v4-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"},"tickSpacing":{"type":"string"},"hooks":{"type":"string"},"amountIn":{"type":"string"},"amountOut":{"type":"string"}},"required":["type","address","tokenIn","tokenOut","sqrtRatioX96","liquidity","tickCurrent","fee","tickSpacing","hooks"]},"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","PRIORITY"]},"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","SIMULATION_UNAVAILABLE"]},"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":{"protocol":{"$ref":"#/components/schemas/ProtocolItems"},"position":{"$ref":"#/components/schemas/Position"},"walletAddress":{"$ref":"#/components/schemas/Address"},"chainId":{"$ref":"#/components/schemas/ChainId"},"initialPrice":{"type":"string"},"poolLiquidity":{"type":"string"},"currentTick":{"type":"number"},"sqrtRatioX96":{"type":"string"},"amount0":{"type":"string"},"amount1":{"type":"string"},"slippageTolerance":{"type":"number"},"deadline":{"type":"number"},"signature":{"type":"string","description":"The signed permit."},"batchPermitData":{"allOf":[{"$ref":"#/components/schemas/Permit"}]},"simulateTransaction":{"type":"boolean"}}},"CreateLPPositionResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"create":{"$ref":"#/components/schemas/TransactionRequest"},"gasFee":{"type":"string"}}},"IncreaseLPPositionRequest":{"type":"object","properties":{"protocol":{"$ref":"#/components/schemas/ProtocolItems"},"tokenId":{"type":"number"},"position":{"$ref":"#/components/schemas/Position"},"poolLiquidity":{"type":"string"},"currentTick":{"type":"number"},"sqrtRatioX96":{"type":"string"},"walletAddress":{"$ref":"#/components/schemas/Address"},"chainId":{"$ref":"#/components/schemas/ChainId"},"amount0":{"type":"string"},"amount1":{"type":"string"},"slippageTolerance":{"type":"number"},"deadline":{"type":"number"},"signature":{"type":"string","description":"The signed permit."},"batchPermitData":{"allOf":[{"$ref":"#/components/schemas/Permit"}]},"simulateTransaction":{"type":"boolean"}}},"IncreaseLPPositionResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"increase":{"$ref":"#/components/schemas/TransactionRequest"},"gasFee":{"type":"string"}}},"DecreaseLPPositionRequest":{"type":"object","properties":{"protocol":{"$ref":"#/components/schemas/ProtocolItems"},"tokenId":{"type":"number"},"position":{"$ref":"#/components/schemas/Position"},"walletAddress":{"$ref":"#/components/schemas/Address"},"chainId":{"$ref":"#/components/schemas/ChainId"},"liquidityPercentageToDecrease":{"type":"number"},"liquidity0":{"type":"string"},"liquidity1":{"type":"string"},"slippageTolerance":{"type":"number"},"poolLiquidity":{"type":"string"},"currentTick":{"type":"number"},"sqrtRatioX96":{"type":"string"},"positionLiquidity":{"type":"string"},"expectedTokenOwed0RawAmount":{"type":"string"},"expectedTokenOwed1RawAmount":{"type":"string"},"collectAsWETH":{"type":"boolean"},"deadline":{"type":"number"},"simulateTransaction":{"type":"boolean"}}},"DecreaseLPPositionResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"decrease":{"$ref":"#/components/schemas/TransactionRequest"},"gasFee":{"type":"string"}}},"ClaimLPFeesRequest":{"type":"object","properties":{"protocol":{"$ref":"#/components/schemas/ProtocolItems"},"tokenId":{"type":"number"},"position":{"$ref":"#/components/schemas/Position"},"walletAddress":{"$ref":"#/components/schemas/Address"},"chainId":{"$ref":"#/components/schemas/ChainId"},"expectedTokenOwed0RawAmount":{"type":"string"},"expectedTokenOwed1RawAmount":{"type":"string"},"collectAsWETH":{"type":"boolean"},"simulateTransaction":{"type":"boolean"}}},"ClaimLPFeesResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"claim":{"$ref":"#/components/schemas/TransactionRequest"},"gasFee":{"type":"string"}}},"MigrateLPPositionRequest":{"type":"object","properties":{"tokenId":{"type":"number"},"walletAddress":{"$ref":"#/components/schemas/Address"},"chainId":{"$ref":"#/components/schemas/ChainId"},"inputProtocol":{"$ref":"#/components/schemas/ProtocolItems"},"inputPosition":{"$ref":"#/components/schemas/Position"},"inputPoolLiquidity":{"type":"string"},"inputCurrentTick":{"type":"number"},"inputSqrtRatioX96":{"type":"string"},"inputPositionLiquidity":{"type":"string"},"signature":{"type":"string"},"amount0":{"type":"string"},"amount1":{"type":"string"},"outputProtocol":{"$ref":"#/components/schemas/ProtocolItems"},"outputPosition":{"$ref":"#/components/schemas/Position"},"initialPrice":{"type":"string"},"outputPoolLiquidity":{"type":"string"},"outputCurrentTick":{"type":"number"},"outputSqrtRatioX96":{"type":"string"},"expectedTokenOwed0RawAmount":{"type":"string"},"expectedTokenOwed1RawAmount":{"type":"string"},"slippageTolerance":{"type":"number"},"deadline":{"type":"number"},"signatureDeadline":{"type":"number"},"simulateTransaction":{"type":"boolean","default":false}},"required":["tokenId","chainId","walletAddress","inputProtocol","inputPosition","inputPoolLiquidity","inputCurrentTick","inputSqrtRatioX96","inputPositionLiquidity","amount0","amount1","outputProtocol","outputPosition","expectedTokenOwed0RawAmount","expectedTokenOwed1RawAmount"]},"MigrateLPPositionResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"migrate":{"$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_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_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 `simulateTransaction` 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 `simulateTransaction` 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 `simulateTransaction` 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":"Decrease LP position calldata","description":"The response will also have the transaction to decrease the position for the corresponding pool. If the parameter `simulateTransaction` is set to `true`, then the response will include the gas fees for the decrease transaction.","operationId":"decrease_lp_position","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecreaseLPPositionRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/DecreaseLPPositionSuccess200"},"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 `simulateTransaction` 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"}}}},"/lp/migrate":{"post":{"tags":["Liquidity"],"summary":"Migrate LP position calldata","description":"The response will also have the transaction to migrate the position for the corresponding pool. If the parameter `simulateTransaction` is set to `true`, then the response will include the gas fees for the migrate transaction.","operationId":"migrate_lp_position","security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MigrateLPPositionRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/MigrateLPPositionSuccess200"},"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"}}}},"DecreaseLPPositionSuccess200":{"description":"Decrease LP Position successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecreaseLPPositionResponse"}}}},"ClaimLPFeesSuccess200":{"description":"Claim LP Fees successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimLPFeesResponse"}}}},"MigrateLPPositionSuccess200":{"description":"Migrate LP Position successful.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MigrateLPPositionResponse"}}}},"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}$"},"Position":{"type":"object","properties":{"pool":{"$ref":"#/components/schemas/Pool"},"tickLower":{"type":"number"},"tickUpper":{"type":"number"}},"required":["pool"]},"Pool":{"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"]},"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"},{"$ref":"#/components/schemas/PriorityQuote"}]},"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":{"enum":["ResourceNotFound","QuoteAmountTooLowError"],"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,1301,480]},"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","Priority"]},"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"]},"PriorityInput":{"type":"object","properties":{"amount":{"type":"string"},"token":{"type":"string"},"mpsPerPriorityFeeWei":{"type":"string"}},"required":["amount","token","mpsPerPriorityFeeWei"]},"PriorityOutput":{"type":"object","properties":{"amount":{"type":"string"},"token":{"type":"string"},"recipient":{"type":"string"},"mpsPerPriorityFeeWei":{"type":"string"}},"required":["amount","token","recipient","mpsPerPriorityFeeWei"]},"PriorityOrderInfo":{"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"},"auctionStartBlock":{"type":"string"},"baselinePriorityFeeWei":{"type":"string"},"input":{"$ref":"#/components/schemas/PriorityInput"},"outputs":{"type":"array","items":{"$ref":"#/components/schemas/PriorityOutput"}},"cosigner":{"$ref":"#/components/schemas/Address"}},"required":["chainId","nonce","reactor","swapper","deadline","validationContract","validationData","auctionStartBlock","baselinePriorityFeeWei","input","outputs","cosigner"]},"PriorityQuote":{"type":"object","properties":{"encodedOrder":{"type":"string"},"orderId":{"type":"string"},"orderInfo":{"$ref":"#/components/schemas/PriorityOrderInfo"},"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"},"expectedAmountIn":{"type":"string"},"expectedAmountOut":{"type":"string"}},"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","PRIORITY"]},"Quote":{"oneOf":[{"$ref":"#/components/schemas/DutchQuote"},{"$ref":"#/components/schemas/ClassicQuote"},{"$ref":"#/components/schemas/WrapUnwrapQuote"},{"$ref":"#/components/schemas/DutchQuoteV2"},{"$ref":"#/components/schemas/BridgeQuote"},{"$ref":"#/components/schemas/PriorityQuote"}]},"CheckApprovalLPRequest":{"type":"object","properties":{"protocol":{"$ref":"#/components/schemas/ProtocolItems"},"token0":{"$ref":"#/components/schemas/Address"},"token1":{"$ref":"#/components/schemas/Address"},"positionToken":{"$ref":"#/components/schemas/Address"},"chainId":{"$ref":"#/components/schemas/ChainId"},"walletAddress":{"$ref":"#/components/schemas/Address"},"amount0":{"type":"string"},"amount1":{"type":"string"},"positionAmount":{"type":"string"},"simulateTransaction":{"type":"boolean"}}},"CheckApprovalLPResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"token0Approval":{"$ref":"#/components/schemas/TransactionRequest"},"token1Approval":{"$ref":"#/components/schemas/TransactionRequest"},"positionTokenApproval":{"$ref":"#/components/schemas/TransactionRequest"},"permitData":{"$ref":"#/components/schemas/NullablePermit"},"gasFeeToken0Approval":{"type":"string"},"gasFeeToken1Approval":{"type":"string"},"gasFeePositionTokenApproval":{"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"},{"$ref":"#/components/schemas/V4PoolInRoute"}]}}},"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"}}},"V4PoolInRoute":{"type":"object","properties":{"type":{"type":"string","default":"v4-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"},"tickSpacing":{"type":"string"},"hooks":{"type":"string"},"amountIn":{"type":"string"},"amountOut":{"type":"string"}},"required":["type","address","tokenIn","tokenOut","sqrtRatioX96","liquidity","tickCurrent","fee","tickSpacing","hooks"]},"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","PRIORITY"]},"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","SIMULATION_UNAVAILABLE","SLIPPAGE_TOO_LOW"]},"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":{"protocol":{"$ref":"#/components/schemas/ProtocolItems"},"position":{"$ref":"#/components/schemas/Position"},"walletAddress":{"$ref":"#/components/schemas/Address"},"chainId":{"$ref":"#/components/schemas/ChainId"},"initialPrice":{"type":"string"},"poolLiquidity":{"type":"string"},"currentTick":{"type":"number"},"sqrtRatioX96":{"type":"string"},"amount0":{"type":"string"},"amount1":{"type":"string"},"slippageTolerance":{"type":"number"},"deadline":{"type":"number"},"signature":{"type":"string","description":"The signed permit."},"batchPermitData":{"allOf":[{"$ref":"#/components/schemas/Permit"}]},"simulateTransaction":{"type":"boolean"}}},"CreateLPPositionResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"create":{"$ref":"#/components/schemas/TransactionRequest"},"gasFee":{"type":"string"}}},"IncreaseLPPositionRequest":{"type":"object","properties":{"protocol":{"$ref":"#/components/schemas/ProtocolItems"},"tokenId":{"type":"number"},"position":{"$ref":"#/components/schemas/Position"},"poolLiquidity":{"type":"string"},"currentTick":{"type":"number"},"sqrtRatioX96":{"type":"string"},"walletAddress":{"$ref":"#/components/schemas/Address"},"chainId":{"$ref":"#/components/schemas/ChainId"},"amount0":{"type":"string"},"amount1":{"type":"string"},"slippageTolerance":{"type":"number"},"deadline":{"type":"number"},"signature":{"type":"string","description":"The signed permit."},"batchPermitData":{"allOf":[{"$ref":"#/components/schemas/Permit"}]},"simulateTransaction":{"type":"boolean"}}},"IncreaseLPPositionResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"increase":{"$ref":"#/components/schemas/TransactionRequest"},"gasFee":{"type":"string"}}},"DecreaseLPPositionRequest":{"type":"object","properties":{"protocol":{"$ref":"#/components/schemas/ProtocolItems"},"tokenId":{"type":"number"},"position":{"$ref":"#/components/schemas/Position"},"walletAddress":{"$ref":"#/components/schemas/Address"},"chainId":{"$ref":"#/components/schemas/ChainId"},"liquidityPercentageToDecrease":{"type":"number"},"liquidity0":{"type":"string"},"liquidity1":{"type":"string"},"slippageTolerance":{"type":"number"},"poolLiquidity":{"type":"string"},"currentTick":{"type":"number"},"sqrtRatioX96":{"type":"string"},"positionLiquidity":{"type":"string"},"expectedTokenOwed0RawAmount":{"type":"string"},"expectedTokenOwed1RawAmount":{"type":"string"},"collectAsWETH":{"type":"boolean"},"deadline":{"type":"number"},"simulateTransaction":{"type":"boolean"}}},"DecreaseLPPositionResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"decrease":{"$ref":"#/components/schemas/TransactionRequest"},"gasFee":{"type":"string"}}},"ClaimLPFeesRequest":{"type":"object","properties":{"protocol":{"$ref":"#/components/schemas/ProtocolItems"},"tokenId":{"type":"number"},"position":{"$ref":"#/components/schemas/Position"},"walletAddress":{"$ref":"#/components/schemas/Address"},"chainId":{"$ref":"#/components/schemas/ChainId"},"expectedTokenOwed0RawAmount":{"type":"string"},"expectedTokenOwed1RawAmount":{"type":"string"},"collectAsWETH":{"type":"boolean"},"simulateTransaction":{"type":"boolean"}}},"ClaimLPFeesResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"claim":{"$ref":"#/components/schemas/TransactionRequest"},"gasFee":{"type":"string"}}},"MigrateLPPositionRequest":{"type":"object","properties":{"tokenId":{"type":"number"},"walletAddress":{"$ref":"#/components/schemas/Address"},"chainId":{"$ref":"#/components/schemas/ChainId"},"inputProtocol":{"$ref":"#/components/schemas/ProtocolItems"},"inputPosition":{"$ref":"#/components/schemas/Position"},"inputPoolLiquidity":{"type":"string"},"inputCurrentTick":{"type":"number"},"inputSqrtRatioX96":{"type":"string"},"inputPositionLiquidity":{"type":"string"},"signature":{"type":"string"},"amount0":{"type":"string"},"amount1":{"type":"string"},"outputProtocol":{"$ref":"#/components/schemas/ProtocolItems"},"outputPosition":{"$ref":"#/components/schemas/Position"},"initialPrice":{"type":"string"},"outputPoolLiquidity":{"type":"string"},"outputCurrentTick":{"type":"number"},"outputSqrtRatioX96":{"type":"string"},"expectedTokenOwed0RawAmount":{"type":"string"},"expectedTokenOwed1RawAmount":{"type":"string"},"slippageTolerance":{"type":"number"},"deadline":{"type":"number"},"signatureDeadline":{"type":"number"},"simulateTransaction":{"type":"boolean","default":false}},"required":["tokenId","chainId","walletAddress","inputProtocol","inputPosition","inputPoolLiquidity","inputCurrentTick","inputSqrtRatioX96","inputPositionLiquidity","amount0","amount1","outputProtocol","outputPosition","expectedTokenOwed0RawAmount","expectedTokenOwed1RawAmount"]},"MigrateLPPositionResponse":{"type":"object","properties":{"requestId":{"$ref":"#/components/schemas/RequestId"},"migrate":{"$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 diff --git a/packages/uniswap/src/data/tradingApi/types.ts b/packages/uniswap/src/data/tradingApi/types.ts index ccc73569b90..0f66d89544a 100644 --- a/packages/uniswap/src/data/tradingApi/types.ts +++ b/packages/uniswap/src/data/tradingApi/types.ts @@ -9,6 +9,7 @@ export enum FeeType { export interface GasStrategy { limitInflationFactor: number + displayLimitInflationFactor: number priceInflationFactor: number percentileThresholdFor1559Fee: number minPriorityFeeGwei?: number | null diff --git a/packages/uniswap/src/features/chains/chainInfo.ts b/packages/uniswap/src/features/chains/chainInfo.ts index 3df43d91775..1cd55eea8d3 100644 --- a/packages/uniswap/src/features/chains/chainInfo.ts +++ b/packages/uniswap/src/features/chains/chainInfo.ts @@ -8,6 +8,7 @@ import { BNB_LOGO, CELO_LOGO, ETHEREUM_LOGO, + MONAD_LOGO, OPTIMISM_LOGO, POLYGON_LOGO, UNICHAIN_SEPOLIA_LOGO, @@ -37,6 +38,7 @@ import { USDC_ZKSYNC, USDC_ZORA, USDT, + USDT_MONAD_TESTNET, } from 'uniswap/src/constants/tokens' import { Chain as BackendChainId } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { @@ -484,6 +486,67 @@ export const UNIVERSE_CHAIN_INFO: Record = { address: '0x471EcE3750Da237f93B8E339c536989b8978a438', }, } as const satisfies UniverseChainInfo, + [UniverseChainId.MonadTestnet]: { + id: UniverseChainId.MonadTestnet, + testnet: true, + sdkId: UniswapSDKChainId.MONAD_TESTNET, + assetRepoNetworkName: undefined, + backendChain: { + chain: BackendChainId.MonadTestnet as GqlChainId, + backendSupported: true, + isSecondaryChain: false, + nativeTokenBackendAddress: undefined, + }, + bridge: undefined, + chainPriority: 0, + docs: 'https://docs.monad.xyz/', + helpCenterUrl: undefined, + label: 'Monad Testnet', + logo: MONAD_LOGO, + name: 'Monad Testnet', + nativeCurrency: { + name: 'Monad', + symbol: 'MON', + decimals: 18, + address: DEFAULT_NATIVE_ADDRESS, + logo: MONAD_LOGO, + }, + networkLayer: NetworkLayer.L1, + pendingTransactionsRetryOptions: undefined, + statusPage: undefined, + supportsInterfaceClientSideRouting: true, + supportsGasEstimates: true, + urlParam: 'monad_testnet', + rpcUrls: { + [RPCType.Public]: { + http: [config.quicknodeMonadTestnetRpcUrl], + }, + [RPCType.Default]: { + http: [config.quicknodeMonadTestnetRpcUrl], + }, + [RPCType.Interface]: { + http: [config.quicknodeMonadTestnetRpcUrl], + }, + }, + wrappedNativeCurrency: { + name: 'Wrapped Monad', + symbol: 'WMON', + decimals: 18, + address: '0x93EACdB111FF98dE9a8Ac5823d357BBc4842aE63', + }, + blockPerMainnetEpochForChainId: 1, + blockWaitMsBeforeWarning: undefined, + elementName: ElementName.ChainMonadTestnet, + explorer: { + name: 'Monad Explorer', + url: 'https://monadscan.xyz/', + }, + infoLink: 'https://app.uniswap.org/explore', + infuraPrefix: undefined, + interfaceName: 'monad', + spotPriceStablecoinAmount: CurrencyAmount.fromRawAmount(USDT_MONAD_TESTNET, 10_000e6), + stablecoins: [USDT_MONAD_TESTNET], + }, [UniverseChainId.Optimism]: { ...optimism, id: UniverseChainId.Optimism, diff --git a/packages/uniswap/src/features/chains/hooks/useFeatureFlaggedChainIds.ts b/packages/uniswap/src/features/chains/hooks/useFeatureFlaggedChainIds.ts index c722cc13a23..f05d52a1ec4 100644 --- a/packages/uniswap/src/features/chains/hooks/useFeatureFlaggedChainIds.ts +++ b/packages/uniswap/src/features/chains/hooks/useFeatureFlaggedChainIds.ts @@ -1,6 +1,8 @@ import { useMemo } from 'react' import { UniverseChainId } from 'uniswap/src/features/chains/types' import { filterChainIdsByFeatureFlag } from 'uniswap/src/features/chains/utils' +import { FeatureFlags } from 'uniswap/src/features/gating/flags' +import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' // Used to feature flag chains. If a chain is not included in the object, it is considered enabled by default. export function useFeatureFlaggedChainIds(): UniverseChainId[] { @@ -8,5 +10,13 @@ export function useFeatureFlaggedChainIds(): UniverseChainId[] { // Example: [ChainId.BLAST]: useFeatureFlag(FeatureFlags.BLAST) // IMPORTANT: Don't forget to also update getEnabledChainIdsSaga - return useMemo(() => filterChainIdsByFeatureFlag({}), []) + const monadTestnetEnabled = useFeatureFlag(FeatureFlags.MonadTestnet) + + return useMemo( + () => + filterChainIdsByFeatureFlag({ + [UniverseChainId.MonadTestnet]: monadTestnetEnabled, + }), + [monadTestnetEnabled], + ) } diff --git a/packages/uniswap/src/features/chains/types.ts b/packages/uniswap/src/features/chains/types.ts index 2d6cb03c3ef..598881852a7 100644 --- a/packages/uniswap/src/features/chains/types.ts +++ b/packages/uniswap/src/features/chains/types.ts @@ -18,6 +18,7 @@ export enum UniverseChainId { Blast = UniswapSDKChainId.BLAST, Bnb = UniswapSDKChainId.BNB, Celo = UniswapSDKChainId.CELO, + MonadTestnet = UniswapSDKChainId.MONAD_TESTNET, Optimism = UniswapSDKChainId.OPTIMISM, Polygon = UniswapSDKChainId.POLYGON, Sepolia = UniswapSDKChainId.SEPOLIA, @@ -42,7 +43,11 @@ export const SUPPORTED_CHAIN_IDS: UniverseChainId[] = [ UniverseChainId.Zksync, ] -export const SUPPORTED_TESTNET_CHAIN_IDS: UniverseChainId[] = [UniverseChainId.Sepolia, UniverseChainId.UnichainSepolia] +export const SUPPORTED_TESTNET_CHAIN_IDS: UniverseChainId[] = [ + UniverseChainId.Sepolia, + UniverseChainId.UnichainSepolia, + UniverseChainId.MonadTestnet, +] // This order is used as a fallback for chain ordering but will otherwise defer to useOrderedChainIds export const ALL_CHAIN_IDS: UniverseChainId[] = [...SUPPORTED_CHAIN_IDS, ...SUPPORTED_TESTNET_CHAIN_IDS] @@ -106,7 +111,7 @@ export interface UniverseChainInfo extends WagmiChain { readonly elementName: ElementNameType readonly explorer: { name: string - url: string + url: `${string}/` apiURL?: string } readonly rpcUrls: { diff --git a/packages/uniswap/src/features/chains/utils.test.ts b/packages/uniswap/src/features/chains/utils.test.ts index a1962127e8e..3300748115b 100644 --- a/packages/uniswap/src/features/chains/utils.test.ts +++ b/packages/uniswap/src/features/chains/utils.test.ts @@ -169,8 +169,8 @@ describe('getEnabledChains', () => { featureFlaggedChainIds: SUPPORTED_TESTNET_CHAIN_IDS, }), ).toEqual({ - chains: [UniverseChainId.Sepolia, UniverseChainId.UnichainSepolia], - gqlChains: [Chain.AstrochainSepolia, Chain.EthereumSepolia], + chains: [UniverseChainId.Sepolia, UniverseChainId.UnichainSepolia, UniverseChainId.MonadTestnet], + gqlChains: [Chain.AstrochainSepolia, Chain.MonadTestnet, Chain.EthereumSepolia], defaultChainId: UniverseChainId.Sepolia, isTestnetModeEnabled: true, }) diff --git a/packages/uniswap/src/features/chains/utils.ts b/packages/uniswap/src/features/chains/utils.ts index a17ce46975a..a2a226b0606 100644 --- a/packages/uniswap/src/features/chains/utils.ts +++ b/packages/uniswap/src/features/chains/utils.ts @@ -93,6 +93,8 @@ export function fromGraphQLChain(chain: Chain | string | undefined): UniverseCha return UniverseChainId.Blast case Chain.Celo: return UniverseChainId.Celo + case Chain.MonadTestnet: + return UniverseChainId.MonadTestnet case Chain.Optimism: return UniverseChainId.Optimism case Chain.Polygon: @@ -132,6 +134,8 @@ export function fromUniswapWebAppLink(network: string | null): UniverseChainId | return UniverseChainId.Bnb case Chain.Celo.toLowerCase(): return UniverseChainId.Celo + case Chain.MonadTestnet.toLowerCase(): + return UniverseChainId.MonadTestnet case Chain.Optimism.toLowerCase(): return UniverseChainId.Optimism case Chain.Polygon.toLowerCase(): @@ -167,6 +171,8 @@ export function toUniswapWebAppLink(chainId: UniverseChainId): string | null { return Chain.Bnb.toLowerCase() case UniverseChainId.Celo: return Chain.Celo.toLowerCase() + case UniverseChainId.MonadTestnet: + return Chain.MonadTestnet.toLowerCase() case UniverseChainId.Optimism: return Chain.Optimism.toLowerCase() case UniverseChainId.Polygon: diff --git a/packages/uniswap/src/features/fiatOnRamp/types.ts b/packages/uniswap/src/features/fiatOnRamp/types.ts index 222ba0e5d92..1d8f4579a95 100644 --- a/packages/uniswap/src/features/fiatOnRamp/types.ts +++ b/packages/uniswap/src/features/fiatOnRamp/types.ts @@ -165,38 +165,37 @@ export type FORTransferWidgetUrlRequest = { // /offramp-transfer-details -export type OffRampTransferDetailsRequest = { - requestSource?: string - transferProviderDetails: - | { - value: MoonpayOffRampTransferDetailsRequest - case: 'moonpayDetails' - } - | { - value: MeldOffRampTransferDetailsRequest - case: 'meldDetails' - } - | { - case: undefined - value?: undefined - } -} +export type OffRampTransferDetailsRequest = MoonpayOffRampTransferDetailsRequest | MeldOffRampTransferDetailsRequest +// TODO: verify that this is needed and BE cannot also use a sessionId type MoonpayOffRampTransferDetailsRequest = { - baseCurrencyCode: string - baseCurrencyAmount: number - depositWalletAddress: string - depositWalletAddressTag?: string + moonpayDetails: { + baseCurrencyCode: string + baseCurrencyAmount: number + depositWalletAddress: string + depositWalletAddressTag?: string + } } type MeldOffRampTransferDetailsRequest = { - sessionId: string + meldDetails: { + sessionId: string + } } export type OffRampTransferDetailsResponse = { + chainId: string + provider: string + tokenAddress: string baseCurrencyCode: string baseCurrencyAmount: number depositWalletAddress: string + logos: { + darkLogo: string + lightLogo: string + darkFullLogo: string + lightFullLogo: string + } depositWalletAddressTag?: string } @@ -241,6 +240,14 @@ export type FiatOnRampCurrency = { meldCurrencyCode?: string } +export interface FiatOffRampMetaData { + name: string + logoUrl: string + onSubmitCallback: () => void + meldCurrencyCode?: string + moonpayCurrencyCode?: string +} + export enum InitialQuoteSelection { MostRecent, Best, diff --git a/packages/uniswap/src/features/gas/hooks.ts b/packages/uniswap/src/features/gas/hooks.ts index 15b58f0d9cd..019528ad691 100644 --- a/packages/uniswap/src/features/gas/hooks.ts +++ b/packages/uniswap/src/features/gas/hooks.ts @@ -1,5 +1,5 @@ import { Currency, CurrencyAmount } from '@uniswap/sdk-core' -import { providers } from 'ethers/lib/ethers' +import { BigNumber, providers } from 'ethers/lib/ethers' import { useEffect, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import { isWeb } from 'ui/src' @@ -39,6 +39,7 @@ import { ONE_SECOND_MS } from 'utilities/src/time/time' // The default "Urgent" strategy that was previously hardcoded in the gas service export const DEFAULT_GAS_STRATEGY: GasStrategy = { limitInflationFactor: 1.15, + displayLimitInflationFactor: 1.15, priceInflationFactor: 1.5, percentileThresholdFor1559Fee: 75, minPriorityFeeGwei: 2, @@ -96,15 +97,38 @@ export function useShadowGasStrategies(chainId: number | undefined, type: GasStr }, [isLoading, chainId, type]) } -// Function to find the name of a gas strategy based on the GasEstimate -export function findGasStrategyName(gasEstimate: GasEstimate, type: GasStrategyType): string | undefined { - const gasStrategies = Statsig.getConfig(DynamicConfigs.GasStrategies).value as GasStrategies +/** + * Converts a gas fee calculated with the provided gas strategy to a display value. + * When calculating the gas fee, the gas limit is multiplied by the `limitInflationFactor`, + * but in the vast majority of cases, the transaction uses only the originally estimated gas limit. + * We use the `displayLimitInflationFactor` to calculate the display value, which can be + * different from the `limitInflationFactor` so that the gas fee displayed is more accurate. + * + * More info: https://www.notion.so/uniswaplabs/Gas-Limit-Experiment-14ac52b2548b80ea932ff2edfdab6683 + * + * @param gasFee - The gas fee value to convert. + * @param gasStrategy - The gas strategy used to calculate the gas fee. + * @returns The display value of the gas fee. + */ +export function convertGasFeeToDisplayValue( + gasFee: string | undefined, + gasStrategy: GasStrategy | undefined, +): string | undefined { + if (!gasFee || !gasStrategy || gasStrategy.limitInflationFactor === 0) { + return gasFee + } - const matchingStrategy = gasStrategies.strategies.find( - (s) => s.conditions.types === type && areEqualGasStrategies(s.strategy, gasEstimate.strategy), - ) + const PRECISION = 1_000_000 + const { displayLimitInflationFactor, limitInflationFactor } = gasStrategy + + // Scale the inflation factors to integers + const scaledDisplayFactor = Math.round(displayLimitInflationFactor * PRECISION) + const scaledLimitFactor = Math.round(limitInflationFactor * PRECISION) - return matchingStrategy?.conditions.name + return BigNumber.from(gasFee) + .mul(BigNumber.from(scaledDisplayFactor)) + .div(BigNumber.from(scaledLimitFactor)) + .toString() } export function useTransactionGasFee( @@ -153,6 +177,8 @@ export function useTransactionGasFee( const gasUseEstimate = (await provider.estimateGas({ from: account?.address, ...tx })).toNumber() * 10e9 setClientsideGasEstimate({ value: gasUseEstimate.toString(), + // These estimates don't inflate the gas limit, so we can use the same value for display + displayValue: gasUseEstimate.toString(), isLoading: false, error: null, }) @@ -160,6 +186,8 @@ export function useTransactionGasFee( // provider.estimateGas will error if the account doesn't have sufficient ETH balance, but we should show an estimated cost anyway setClientsideGasEstimate({ value: fallbackGasLimit?.toString(), + // These estimates don't inflate the gas limit, so we can use the same value for display + displayValue: fallbackGasLimit?.toString(), isLoading: false, error: fallbackGasLimit ? null : (e as Error), }) @@ -194,6 +222,7 @@ export function useTransactionGasFee( return { value: activeEstimate.gasFee, + displayValue: convertGasFeeToDisplayValue(activeEstimate.gasFee, activeGasStrategy), isLoading, error: error ?? null, params: extractGasFeeParams(activeEstimate), @@ -356,7 +385,7 @@ type GasFeeFormattedAmounts = T extends string * If no placeholder is defined, the response can be null. If a placeholder is defined, * the gas fee amount will always be a string. */ -export function useGasFeeFormattedAmounts({ +export function useGasFeeFormattedDisplayAmounts({ gasFee, chainId, placeholder, @@ -366,7 +395,7 @@ export function useGasFeeFormattedAmounts({ placeholder: T }): GasFeeFormattedAmounts { const { convertFiatAmountFormatted, formatNumberOrString } = useLocalizationContext() - const { value: gasFeeUSD, isLoading: gasFeeUSDIsLoading } = useUSDValueOfGasFee(chainId, gasFee?.value) + const { value: gasFeeUSD, isLoading: gasFeeUSDIsLoading } = useUSDValueOfGasFee(chainId, gasFee?.displayValue) // In testnet mode, use native currency values as USD pricing may be unreliable const { isTestnetModeEnabled } = useEnabledChains() @@ -374,7 +403,7 @@ export function useGasFeeFormattedAmounts({ const nativeCurrency = NativeCurrency.onChain(chainId) const nativeCurrencyAmount = getCurrencyAmount({ currency: nativeCurrency, - value: gasFee?.value, + value: gasFee?.displayValue, valueType: ValueType.Raw, }) @@ -389,7 +418,7 @@ export function useGasFeeFormattedAmounts({ const gasFeeFormatted = useMemo(() => { // Gas fee not available - if (!gasFee?.value) { + if (!gasFee?.displayValue) { return emptyState } @@ -404,7 +433,7 @@ export function useGasFeeFormattedAmounts({ emptyState, fiatAmountFormatted, gasFee?.isLoading, - gasFee?.value, + gasFee?.displayValue, gasFeeUSD, gasFeeUSDIsLoading, isTestnetModeEnabled, diff --git a/packages/uniswap/src/features/gas/types.ts b/packages/uniswap/src/features/gas/types.ts index 7d1a5f25ddc..1d34a00757b 100644 --- a/packages/uniswap/src/features/gas/types.ts +++ b/packages/uniswap/src/features/gas/types.ts @@ -19,6 +19,7 @@ export function areEqualGasStrategies(a?: GasStrategy, b?: GasStrategy): boolean return false } + // displayLimitInflationFactor is not returned by the server, so it's ignored here return ( a.limitInflationFactor === b.limitInflationFactor && a.priceInflationFactor === b.priceInflationFactor && @@ -39,6 +40,7 @@ export type GasFeeResponse = { export type GasFeeResult = { value?: string + displayValue?: string isLoading: boolean error: SerializedError | FetchError | Error | null params?: TransactionLegacyFeeParams | TransactionEip1559FeeParams diff --git a/packages/uniswap/src/features/gas/useMaxAmountSpend.ts b/packages/uniswap/src/features/gas/useMaxAmountSpend.ts index aef71a5dbf1..ba20dec2dcd 100644 --- a/packages/uniswap/src/features/gas/useMaxAmountSpend.ts +++ b/packages/uniswap/src/features/gas/useMaxAmountSpend.ts @@ -45,6 +45,7 @@ function useGetMinAmount(chainId?: UniverseChainId, txType?: TransactionType): J const MIN_POLYGON_FOR_GAS = useMinPolygonForGas(txType) const MIN_AVALANCHE_FOR_GAS = useMinAvalancheForGas(txType) const MIN_CELO_FOR_GAS = useMinCeloForGas(txType) + const MIN_MON_FOR_GAS = useMinMonForGas(txType) const MIN_L2_FOR_GAS = useMinGenericL2ForGas(txType) if (!chainId) { @@ -62,6 +63,8 @@ function useGetMinAmount(chainId?: UniverseChainId, txType?: TransactionType): J return MIN_AVALANCHE_FOR_GAS case UniverseChainId.Celo: return MIN_CELO_FOR_GAS + case UniverseChainId.MonadTestnet: + return MIN_MON_FOR_GAS case UniverseChainId.ArbitrumOne: case UniverseChainId.Optimism: case UniverseChainId.Base: @@ -111,6 +114,12 @@ export function useMinCeloForGas(txType?: TransactionType): JSBI { ) } +export function useMinMonForGas(txType?: TransactionType): JSBI { + return useCalculateMinForGas( + isSend(txType) ? SwapConfigKey.MonSendMinGasAmount : SwapConfigKey.MonSwapMinGasAmount, + isSend(txType) ? 150 : 20, + ) +} export function useMinGenericL2ForGas(txType?: TransactionType): JSBI { return useCalculateMinForGas( isSend(txType) ? SwapConfigKey.GenericL2SendMinGasAmount : SwapConfigKey.GenericL2SwapMinGasAmount, diff --git a/packages/uniswap/src/features/gas/utils.ts b/packages/uniswap/src/features/gas/utils.ts index 09ed57e9062..e3d7fe175c5 100644 --- a/packages/uniswap/src/features/gas/utils.ts +++ b/packages/uniswap/src/features/gas/utils.ts @@ -1,4 +1,13 @@ import { CurrencyAmount, NativeCurrency } from '@uniswap/sdk-core' +import { GasEstimate } from 'uniswap/src/data/tradingApi/types' +import { areEqualGasStrategies } from 'uniswap/src/features/gas/types' +import { + DynamicConfigs, + GasStrategies, + GasStrategyType, + GasStrategyWithConditions, +} from 'uniswap/src/features/gating/configs' +import { Statsig } from 'uniswap/src/features/gating/sdk/statsig' import { ValueType, getCurrencyAmount } from 'uniswap/src/features/tokens/getCurrencyAmount' function getNativeCurrencyTotalSpend( @@ -28,3 +37,14 @@ export function hasSufficientFundsIncludingGas(params: { const totalSpend = getNativeCurrencyTotalSpend(transactionAmount, gasFee, nativeCurrencyBalance?.currency) return !totalSpend || !nativeCurrencyBalance?.lessThan(totalSpend) } + +// Function to find the name of a gas strategy based on the GasEstimate +export function findLocalGasStrategy( + gasEstimate: GasEstimate, + type: GasStrategyType, +): GasStrategyWithConditions | undefined { + const gasStrategies = Statsig.getConfig(DynamicConfigs.GasStrategies).value as GasStrategies + return gasStrategies.strategies.find( + (s) => s.conditions.types === type && areEqualGasStrategies(s.strategy, gasEstimate.strategy), + ) +} diff --git a/packages/uniswap/src/features/gating/configs.ts b/packages/uniswap/src/features/gating/configs.ts index 4e32a228e7b..fe50e9267d4 100644 --- a/packages/uniswap/src/features/gating/configs.ts +++ b/packages/uniswap/src/features/gating/configs.ts @@ -12,7 +12,7 @@ export enum DynamicConfigs { // Wallet HomeScreenExploreTokens = 'home_screen_explore_tokens', - MobileForceUpgrade = 'force_upgrade', + ForceUpgrade = 'force_upgrade', OnDeviceRecovery = 'on_device_recovery', UwuLink = 'uwulink_config', GasStrategies = 'gas_strategy', @@ -41,6 +41,8 @@ export enum SwapConfigKey { AvalancheSendMinGasAmount = 'avalancheSendMinGasAmount', CeloSwapMinGasAmount = 'celoSwapMinGasAmount', CeloSendMinGasAmount = 'celoSendMinGasAmount', + MonSwapMinGasAmount = 'monSwapMinGasAmount', + MonSendMinGasAmount = 'monSendMinGasAmount', GenericL2SwapMinGasAmount = 'genericL2SwapMinGasAmount', GenericL2SendMinGasAmount = 'genericL2SendMinGasAmount', } @@ -113,7 +115,7 @@ export type DynamicConfigKeys = { // Wallet [DynamicConfigs.HomeScreenExploreTokens]: HomeScreenExploreTokensConfigKey - [DynamicConfigs.MobileForceUpgrade]: ForceUpgradeConfigKey + [DynamicConfigs.ForceUpgrade]: ForceUpgradeConfigKey [DynamicConfigs.OnDeviceRecovery]: OnDeviceRecoveryConfigKey [DynamicConfigs.UwuLink]: UwuLinkConfigKey [DynamicConfigs.MainnetPrivateRpc]: MainnetPrivateRpcConfigKey diff --git a/packages/uniswap/src/features/gating/flags.ts b/packages/uniswap/src/features/gating/flags.ts index 9f198e0e18c..b1fcce2cc02 100644 --- a/packages/uniswap/src/features/gating/flags.ts +++ b/packages/uniswap/src/features/gating/flags.ts @@ -15,6 +15,7 @@ export enum FeatureFlags { UniswapX, UniswapXPriorityOrders, V4Swap, + MonadTestnet, // Wallet DisableFiatOnRampKorea, @@ -66,6 +67,7 @@ export enum FeatureFlags { export const SHARED_FEATURE_FLAG_NAMES = new Map([ [FeatureFlags.Datadog, 'datadog'], [FeatureFlags.IndicativeSwapQuotes, 'indicative-quotes'], + [FeatureFlags.MonadTestnet, 'monad_testnet'], [FeatureFlags.PortionFields, 'portion-fields'], [FeatureFlags.SharedSwapArbitrumUniswapXExperiment, 'shared_swap_arbitrum_uniswapx_experiment'], [FeatureFlags.TokenProtection, 'token_protection'], diff --git a/packages/uniswap/src/features/settings/saga.ts b/packages/uniswap/src/features/settings/saga.ts index 65600ec4577..7a0a79306f1 100644 --- a/packages/uniswap/src/features/settings/saga.ts +++ b/packages/uniswap/src/features/settings/saga.ts @@ -1,11 +1,18 @@ import { call, select } from 'typed-redux-saga' +import { UniverseChainId } from 'uniswap/src/features/chains/types' import { filterChainIdsByFeatureFlag, getEnabledChains } from 'uniswap/src/features/chains/utils' +import { FeatureFlags } from 'uniswap/src/features/gating/flags' +import { getFeatureFlag } from 'uniswap/src/features/gating/hooks' import { selectIsTestnetModeEnabled } from 'uniswap/src/features/settings/selectors' export function* getEnabledChainIdsSaga() { const isTestnetModeEnabled = yield* select(selectIsTestnetModeEnabled) - const featureFlaggedChainIds = filterChainIdsByFeatureFlag({}) + const monadTestnetEnabled = getFeatureFlag(FeatureFlags.MonadTestnet) + + const featureFlaggedChainIds = filterChainIdsByFeatureFlag({ + [UniverseChainId.MonadTestnet]: monadTestnetEnabled, + }) return yield* call(getEnabledChains, { isTestnetModeEnabled, diff --git a/packages/uniswap/src/features/telemetry/constants/trace.ts b/packages/uniswap/src/features/telemetry/constants/trace.ts index 561814e85de..d920e3e4a6c 100644 --- a/packages/uniswap/src/features/telemetry/constants/trace.ts +++ b/packages/uniswap/src/features/telemetry/constants/trace.ts @@ -90,6 +90,7 @@ export const ModalName = { SendReview: 'send-review-modal', SendWarning: 'send-warning-modal', SlippageInfo: 'slippage-info-modal', + SlippageWarningModal: 'slippage-warning-modal', StorageWarning: 'storage-warning-modal', Swap: 'swap-modal', SwapError: 'swap-error-modal', @@ -156,6 +157,7 @@ export const ElementName = { ChainAvalanche: 'chain-avalanche', ChainBase: 'chain-base', ChainBlast: 'chain-blast', + ChainMonadTestnet: 'chain-monad-testnet', ChainWorldChain: 'chain-world-chain', ChainZora: 'chain-zora', ChainZkSync: 'chain-zksync', diff --git a/packages/uniswap/src/features/telemetry/constants/uniswap.ts b/packages/uniswap/src/features/telemetry/constants/uniswap.ts index b2c5ad1f626..785aeba68e9 100644 --- a/packages/uniswap/src/features/telemetry/constants/uniswap.ts +++ b/packages/uniswap/src/features/telemetry/constants/uniswap.ts @@ -2,4 +2,5 @@ export enum UniswapEventName { BalancesReport = 'Balances Report', BalancesReportPerChain = 'Balances Report Per Chain', TokenSelected = 'Token Selected', + ConversionEventSubmitted = 'Conversion Event Submitted', } diff --git a/packages/uniswap/src/features/telemetry/types.ts b/packages/uniswap/src/features/telemetry/types.ts index f1c53d206ee..f61e0a447d1 100644 --- a/packages/uniswap/src/features/telemetry/types.ts +++ b/packages/uniswap/src/features/telemetry/types.ts @@ -24,6 +24,7 @@ import { import { Protocol } from '@uniswap/router-sdk' import { TokenOptionSection } from 'uniswap/src/components/TokenSelector/types' import { NftStandard } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' +import { TransactionFailureReason } from 'uniswap/src/data/tradingApi/__generated__' import { UniverseChainId } from 'uniswap/src/features/chains/types' import { FiatCurrency } from 'uniswap/src/features/fiatCurrency/constants' import { @@ -70,6 +71,7 @@ export type GasEstimateAccuracyProperties = { name?: string out_of_gas: boolean timed_out: boolean + display_limit_inflation_factor?: number } export type PendingTransactionTimeoutProperties = { @@ -154,6 +156,7 @@ export type SwapTradeBaseProperties = { // Legacy props only used on web. We might be able to delete these after we delete the old swap flow. method?: 'ROUTING_API' | 'QUICK_ROUTE' | 'CLIENT_SIDE_FALLBACK' offchain_order_type?: 'Dutch' | 'Dutch_V2' | 'Limit' | 'Dutch_V1_V2' | 'Priority' + simulation_failure_reasons?: TransactionFailureReason[] } & ITraceContext type BaseSwapTransactionResultProperties = { @@ -180,6 +183,7 @@ type BaseSwapTransactionResultProperties = { submitViaPrivateRpc?: boolean protocol?: Protocol transactedUSDValue?: number + simulation_failure_reasons?: TransactionFailureReason[] } type ClassicSwapTransactionResultProperties = BaseSwapTransactionResultProperties @@ -285,7 +289,7 @@ export enum DappRequestCardLoggingName { } export type FORAmountEnteredProperties = ITraceContext & { - source: 'chip' | 'textInput' + source: 'chip' | 'textInput' | 'changeAsset' amountUSD?: number } @@ -716,6 +720,7 @@ export type UniverseEventProperties = { txRequest?: EthersTransactionRequest client_block_number?: number isAutoSlippage?: boolean + simulationFailureReasons?: TransactionFailureReason[] } & SwapTradeBaseProperties [SwapEventName.SWAP_FIRST_ACTION]: { time_to_first_swap_action?: number @@ -747,6 +752,12 @@ export type UniverseEventProperties = { total_balances_usd_per_chain: Record wallet: string } + [UniswapEventName.ConversionEventSubmitted]: { + id: string + eventId: string + eventName: string + platformIdType: string + } [UniswapEventName.TokenSelected]: | (ITraceContext & AssetDetailsBaseProperties & @@ -842,6 +853,7 @@ export type UniverseEventProperties = { SwapTradeBaseProperties [WalletEventName.TestnetModeToggled]: { enabled: boolean + location: 'settings' | 'deep_link_modal' } [WalletEventName.TestnetEvent]: { originalEventName: string diff --git a/packages/uniswap/src/features/tokens/slice/hooks.ts b/packages/uniswap/src/features/tokens/slice/hooks.ts index af0c3c863bd..f49084066bc 100644 --- a/packages/uniswap/src/features/tokens/slice/hooks.ts +++ b/packages/uniswap/src/features/tokens/slice/hooks.ts @@ -4,6 +4,7 @@ import { useDispatch, useSelector } from 'react-redux' import { dismissedWarningTokensSelector } from 'uniswap/src/features/tokens/slice/selectors' import { dismissTokenWarning } from 'uniswap/src/features/tokens/slice/slice' import { BasicTokenInfo, isBasicTokenInfo } from 'uniswap/src/features/tokens/slice/types' +import { getValidAddress } from 'uniswap/src/utils/addresses' import { serializeToken } from 'uniswap/src/utils/currency' export function useDismissedTokenWarnings(info: Maybe): { @@ -15,8 +16,12 @@ export function useDismissedTokenWarnings(info: Maybe const isBasicInfo = isBasicTokenInfo(info) + const lowercasedAddress = getValidAddress( + isBasicInfo ? info.address : info?.isToken ? info?.address : undefined, + false, + ) const tokenWarningDismissed = Boolean( - (isBasicInfo || info?.isToken) && dismissedTokens && dismissedTokens[info.chainId]?.[info.address], + info && lowercasedAddress && dismissedTokens && dismissedTokens[info.chainId]?.[lowercasedAddress], ) const onDismissTokenWarning = useCallback(() => { diff --git a/packages/uniswap/src/features/tokens/slice/slice.ts b/packages/uniswap/src/features/tokens/slice/slice.ts index a536ca19dcb..8b7a30fb8cc 100644 --- a/packages/uniswap/src/features/tokens/slice/slice.ts +++ b/packages/uniswap/src/features/tokens/slice/slice.ts @@ -1,5 +1,6 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit' import { BasicTokenInfo, SerializedToken, SerializedTokenMap } from 'uniswap/src/features/tokens/slice/types' +import { getValidAddress } from 'uniswap/src/utils/addresses' export interface TokensState { dismissedTokenWarnings: SerializedTokenMap @@ -19,8 +20,11 @@ const slice = createSlice({ } = action.payload const { token } = action.payload state.dismissedTokenWarnings[chainId] = state.dismissedTokenWarnings[chainId] || {} - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - state.dismissedTokenWarnings[chainId]![address] = token + const lowercasedAddress = getValidAddress(address, false) + if (lowercasedAddress) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + state.dismissedTokenWarnings[chainId]![lowercasedAddress] = token + } }, resetDismissedWarnings: (state) => { state.dismissedTokenWarnings = {} diff --git a/packages/uniswap/src/features/transactions/InsufficientNativeTokenWarning/useInsufficientNativeTokenWarning.tsx b/packages/uniswap/src/features/transactions/InsufficientNativeTokenWarning/useInsufficientNativeTokenWarning.tsx index 602567c76ae..75857262965 100644 --- a/packages/uniswap/src/features/transactions/InsufficientNativeTokenWarning/useInsufficientNativeTokenWarning.tsx +++ b/packages/uniswap/src/features/transactions/InsufficientNativeTokenWarning/useInsufficientNativeTokenWarning.tsx @@ -75,10 +75,10 @@ export function useInsufficientNativeTokenWarning({ return null } - const supportedChainId = toSupportedChainId(nativeCurrency?.chainId) + const supportedChainId = toSupportedChainId(nativeCurrency.chainId) if (!supportedChainId) { - throw new Error(`Unsupported chain ID: ${nativeCurrency?.chainId}`) + throw new Error(`Unsupported chain ID: ${nativeCurrency.chainId}`) } const networkName = getChainLabel(supportedChainId) diff --git a/packages/uniswap/src/features/transactions/TransactionDetails/TransactionDetails.tsx b/packages/uniswap/src/features/transactions/TransactionDetails/TransactionDetails.tsx index b6c8e8474b3..877bd6da882 100644 --- a/packages/uniswap/src/features/transactions/TransactionDetails/TransactionDetails.tsx +++ b/packages/uniswap/src/features/transactions/TransactionDetails/TransactionDetails.tsx @@ -2,13 +2,14 @@ import { SwapEventName } from '@uniswap/analytics-events' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { PropsWithChildren, ReactNode, useState } from 'react' import { useTranslation } from 'react-i18next' -import { AnimatePresence, Flex, Separator, Text, TouchableArea } from 'ui/src' +import { AnimatePresence, Button, Flex, Popover, Separator, Text, TouchableArea } from 'ui/src' import { AlertTriangleFilled } from 'ui/src/components/icons/AlertTriangleFilled' import { AnglesMaximize } from 'ui/src/components/icons/AnglesMaximize' import { AnglesMinimize } from 'ui/src/components/icons/AnglesMinimize' import { NetworkFee } from 'uniswap/src/components/gas/NetworkFee' import { getAlertColor } from 'uniswap/src/components/modals/WarningModal/getAlertColor' import { Warning } from 'uniswap/src/components/modals/WarningModal/types' +import { TransactionFailureReason } from 'uniswap/src/data/tradingApi/__generated__' import { UniverseChainId } from 'uniswap/src/features/chains/types' import { GasFeeResult } from 'uniswap/src/features/gas/types' import { FeatureFlags } from 'uniswap/src/features/gating/flags' @@ -22,9 +23,12 @@ import { TokenWarningProps, } from 'uniswap/src/features/transactions/TransactionDetails/types' import { EstimatedTime } from 'uniswap/src/features/transactions/swap/review/EstimatedTime' +import { TransactionSettingsModal } from 'uniswap/src/features/transactions/swap/settings/TransactionSettingsModal' +import { SlippageUpdate } from 'uniswap/src/features/transactions/swap/settings/configs/SlippageUpdate' import { UniswapXGasBreakdown } from 'uniswap/src/features/transactions/swap/types/swapTxAndGasInfo' import { SwapFee as SwapFeeType } from 'uniswap/src/features/transactions/swap/types/trade' import { openUri } from 'uniswap/src/utils/linking' +import { isInterface } from 'utilities/src/platform' interface TransactionDetailsProps { banner?: ReactNode @@ -52,8 +56,10 @@ interface TransactionDetailsProps { RoutingInfo?: JSX.Element RateInfo?: JSX.Element transactionUSDValue?: Maybe> + txSimulationErrors?: TransactionFailureReason[] } +// eslint-disable-next-line complexity export function TransactionDetails({ banner, children, @@ -76,6 +82,7 @@ export function TransactionDetails({ indicative = false, isSwap, transactionUSDValue, + txSimulationErrors, isBridgeTrade, AccountDetails, estimatedBridgingTime, @@ -93,9 +100,22 @@ export function TransactionDetails({ setShowChildren(!showChildren) } + // Used to show slippage settings on mobile, where the modal needs to be added outside of the conditional expected failure banner + const [showSlippageSettings, setShowSlippageSettings] = useState(false) + const showExpectedFailureBanner = + isSwap && + ((showGasFeeError && gasFee.error) || + txSimulationErrors?.includes(TransactionFailureReason.SIMULATION_ERROR) || + txSimulationErrors?.includes(TransactionFailureReason.SLIPPAGE_TOO_LOW)) + return ( - {showGasFeeError && gasFee.error && } + {showExpectedFailureBanner && ( + setShowSlippageSettings(true)} + /> + )} {!showWarning && banner && {banner}} {children && showSeparatorToggle ? ( )} + {isSwap && ( + setShowSlippageSettings(false)} + /> + )} ) } @@ -231,24 +259,87 @@ const TransactionWarning = ({ ) } -const GasFeeError = ({ warning }: { warning?: Warning }): JSX.Element => { +const ExpectedFailureBanner = ({ + txFailureReasons, + onSlippageEditPress, +}: { + txFailureReasons?: TransactionFailureReason[] + onSlippageEditPress?: () => void +}): JSX.Element => { const { t } = useTranslation() - const warningColor = getAlertColor(warning?.severity) + + const showSlippageWarning = txFailureReasons?.includes(TransactionFailureReason.SLIPPAGE_TOO_LOW) return ( - - - {t('swap.warning.expectedFailure')} - + + + + + {t('swap.warning.expectedFailure.titleMay')} + + {showSlippageWarning && ( + + {t('swap.warning.expectedFailure.increaseSlippage')} + + )} + + + {showSlippageWarning && } ) } + +const SlippageEdit = ({ + onWalletSlippageEditPress: onSlippageEditPress, +}: { + onWalletSlippageEditPress?: () => void +}): JSX.Element => { + const { t } = useTranslation() + const [showInterfaceSlippageSettings, setShowInterfaceSlippageSettings] = useState(false) + const editButton = ( + + ) + + if (!isInterface) { + return editButton + } + + // Web needs to use a popover, so we need to wrap both the button and the modal in a popover + return ( + { + if (!open && isInterface) { + setShowInterfaceSlippageSettings(false) + } + }} + > + {editButton} + setShowInterfaceSlippageSettings(false)} + /> + + ) +} diff --git a/packages/uniswap/src/features/transactions/settings/contexts/TransactionSettingsContext.tsx b/packages/uniswap/src/features/transactions/settings/contexts/TransactionSettingsContext.tsx index adade5e6edf..b96e5ba9ee4 100644 --- a/packages/uniswap/src/features/transactions/settings/contexts/TransactionSettingsContext.tsx +++ b/packages/uniswap/src/features/transactions/settings/contexts/TransactionSettingsContext.tsx @@ -1,70 +1,60 @@ -import { createContext, ReactNode, useCallback, useContext, useMemo, useState } from 'react' +import { createContext, ReactNode, useCallback, useContext, useEffect, useMemo } from 'react' +import { useDispatch, useSelector } from 'react-redux' +import { ProtocolItems } from 'uniswap/src/data/tradingApi/__generated__' import { FeatureFlags } from 'uniswap/src/features/gating/flags' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' -import { DEFAULT_CUSTOM_DEADLINE } from 'uniswap/src/features/transactions/swap/settings/useDeadlineSettings' +import { selectTransactionSettings } from 'uniswap/src/features/transactions/settings/selectors' import { - DEFAULT_PROTOCOL_OPTIONS, - FrontendSupportedProtocol, -} from 'uniswap/src/features/transactions/swap/utils/protocols' + setTransactionSettings, + TransactionSettingKey, + TransactionSettingsState, +} from 'uniswap/src/features/transactions/settings/slice' import { logContextUpdate } from 'utilities/src/logger/contextEnhancer' -export type TransactionSettingsState = { - autoSlippageTolerance?: number - customSlippageTolerance?: number - customDeadline?: number - selectedProtocols: FrontendSupportedProtocol[] -} - -type TransactionSettingsContextState = { +export type TransactionSettingsContextState = { updateTransactionSettings: (newState: Partial) => void } & TransactionSettingsState -export const getDefaultState = ({ - autoSlippageTolerance, -}: Partial): TransactionSettingsState => ({ - customDeadline: DEFAULT_CUSTOM_DEADLINE, - autoSlippageTolerance, - selectedProtocols: DEFAULT_PROTOCOL_OPTIONS, -}) - export const TransactionSettingsContext = createContext(undefined) export function TransactionSettingsContextProvider({ + settingKey, children, autoSlippageTolerance, -}: { children: ReactNode } & Partial): JSX.Element { - const defaultState = useMemo(() => getDefaultState({ autoSlippageTolerance }), [autoSlippageTolerance]) - const [transactionSettings, setTransactionSettings] = useState(defaultState) +}: { + children: ReactNode + settingKey: TransactionSettingKey + autoSlippageTolerance?: TransactionSettingsState['autoSlippageTolerance'] +}): JSX.Element { + const appDispatch = useDispatch() + const transactionSettings = useSelector(selectTransactionSettings(settingKey)) const datadogEnabled = useFeatureFlag(FeatureFlags.Datadog) const updateTransactionSettings = useCallback( - (newState: Parameters[0]): void => { - setTransactionSettings((prevState) => { - const updatedState = { ...prevState, ...newState } - - logContextUpdate('TransactionSettingsContext', updatedState, datadogEnabled) - - return updatedState - }) + (newState: Partial): void => { + appDispatch(setTransactionSettings({ settingKey, ...newState })) }, - [setTransactionSettings, datadogEnabled], + [settingKey, appDispatch], ) + useEffect(() => { + logContextUpdate('TransactionSettingsContext', transactionSettings, datadogEnabled) + }, [transactionSettings, datadogEnabled]) + + useEffect(() => { + updateTransactionSettings({ autoSlippageTolerance }) + }, [autoSlippageTolerance, updateTransactionSettings]) + const state = useMemo( (): TransactionSettingsContextState => ({ - autoSlippageTolerance: transactionSettings.autoSlippageTolerance, - customSlippageTolerance: transactionSettings.customSlippageTolerance, - customDeadline: transactionSettings.customDeadline, - selectedProtocols: transactionSettings.selectedProtocols, + ...transactionSettings, updateTransactionSettings, + selectedProtocols: transactionSettings.isOnlyV2Allowed + ? [ProtocolItems.V2] + : transactionSettings.selectedProtocols, + isOnlyV2Allowed: transactionSettings.isOnlyV2Allowed, }), - [ - transactionSettings.customSlippageTolerance, - transactionSettings.customDeadline, - transactionSettings.autoSlippageTolerance, - transactionSettings.selectedProtocols, - updateTransactionSettings, - ], + [transactionSettings, updateTransactionSettings], ) return {children} diff --git a/packages/uniswap/src/features/transactions/settings/selectors.ts b/packages/uniswap/src/features/transactions/settings/selectors.ts new file mode 100644 index 00000000000..6afc0d2d25c --- /dev/null +++ b/packages/uniswap/src/features/transactions/settings/selectors.ts @@ -0,0 +1,8 @@ +import { TransactionSettingKey, TransactionSettingsState } from 'uniswap/src/features/transactions/settings/slice' +import { UniswapState } from 'uniswap/src/state/uniswapReducer' + +export function selectTransactionSettings( + key: TransactionSettingKey, +): (state: UniswapState) => TransactionSettingsState { + return (state) => state.transactionSettings[key] +} diff --git a/packages/uniswap/src/features/transactions/settings/slice.ts b/packages/uniswap/src/features/transactions/settings/slice.ts new file mode 100644 index 00000000000..1431ffd16ba --- /dev/null +++ b/packages/uniswap/src/features/transactions/settings/slice.ts @@ -0,0 +1,55 @@ +import { createSlice, PayloadAction } from '@reduxjs/toolkit' +import { DEFAULT_CUSTOM_DEADLINE } from 'uniswap/src/features/transactions/swap/settings/useDeadlineSettings' +import { + DEFAULT_PROTOCOL_OPTIONS, + FrontendSupportedProtocol, +} from 'uniswap/src/features/transactions/swap/utils/protocols' + +// The settingKey is used to identify the settings slice in the redux store +// TransactionSettings components are shared between swap and lp, but we want +// to keep the custom settings themselves separate. +export enum TransactionSettingKey { + Swap = 'swap', + LP = 'lp', +} + +export interface TransactionSettingsState { + autoSlippageTolerance?: number + customSlippageTolerance?: number + customDeadline?: number + selectedProtocols: FrontendSupportedProtocol[] + isOnlyV2Allowed: boolean + slippageWarningModalSeen: boolean +} + +export const initialTransactionSettingsState: TransactionSettingsState = { + customDeadline: DEFAULT_CUSTOM_DEADLINE, + selectedProtocols: DEFAULT_PROTOCOL_OPTIONS, + isOnlyV2Allowed: false, + slippageWarningModalSeen: false, +} + +const slice = createSlice({ + name: 'transactionSettings', + initialState: { + [TransactionSettingKey.Swap]: initialTransactionSettingsState, + [TransactionSettingKey.LP]: initialTransactionSettingsState, + }, + reducers: { + setTransactionSettings: ( + state, + { payload }: PayloadAction & { settingKey: TransactionSettingKey }>, + ) => { + if (!payload.settingKey) { + throw new Error('TransactionSettingsState settingKey not provided') + } + + const { settingKey, ...settings } = payload + Object.assign(state[settingKey], settings) + }, + }, +}) + +export const { setTransactionSettings } = slice.actions + +export const transactionSettingsReducer = slice.reducer diff --git a/packages/uniswap/src/features/transactions/swap/analytics.ts b/packages/uniswap/src/features/transactions/swap/analytics.ts index dc49034e5c8..d7a0f581519 100644 --- a/packages/uniswap/src/features/transactions/swap/analytics.ts +++ b/packages/uniswap/src/features/transactions/swap/analytics.ts @@ -8,7 +8,7 @@ import { LocalizationContextState, useLocalizationContext } from 'uniswap/src/fe import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' import { SwapRouting, SwapTradeBaseProperties } from 'uniswap/src/features/telemetry/types' import { ValueType, getCurrencyAmount } from 'uniswap/src/features/tokens/getCurrencyAmount' -import { TransactionSettingsState } from 'uniswap/src/features/transactions/settings/contexts/TransactionSettingsContext' +import { TransactionSettingsContextState } from 'uniswap/src/features/transactions/settings/contexts/TransactionSettingsContext' import { DerivedSwapInfo } from 'uniswap/src/features/transactions/swap/types/derivedSwapInfo' import { Trade } from 'uniswap/src/features/transactions/swap/types/trade' import { SwapEventType, timestampTracker } from 'uniswap/src/features/transactions/swap/utils/SwapEventTimestampTracker' @@ -137,6 +137,7 @@ export function getBaseTradeAnalyticsProperties({ token_out_amount_min: trade.minimumAmountOut(slippagePercent).toExact(), token_in_detected_tax: parseFloat(trade.inputTax.toFixed(2)), token_out_detected_tax: parseFloat(trade.outputTax.toFixed(2)), + simulation_failure_reasons: isClassic(trade) ? trade.quote?.quote.txFailureReasons : undefined, } } @@ -146,7 +147,7 @@ export function getBaseTradeAnalyticsPropertiesFromSwapInfo({ formatter, trace, }: { - transactionSettings: TransactionSettingsState + transactionSettings: TransactionSettingsContextState derivedSwapInfo: DerivedSwapInfo formatter: LocalizationContextState trace: ITraceContext diff --git a/packages/uniswap/src/features/transactions/swap/form/SwapFormScreen.tsx b/packages/uniswap/src/features/transactions/swap/form/SwapFormScreen.tsx index 9a5eacd6c06..e3c70c77bca 100644 --- a/packages/uniswap/src/features/transactions/swap/form/SwapFormScreen.tsx +++ b/packages/uniswap/src/features/transactions/swap/form/SwapFormScreen.tsx @@ -22,6 +22,7 @@ import { getAlertColor } from 'uniswap/src/components/modals/WarningModal/getAle import { WarningSeverity } from 'uniswap/src/components/modals/WarningModal/types' import { MAX_FIAT_INPUT_DECIMALS } from 'uniswap/src/constants/transactions' import { usePrefetchSwappableTokens } from 'uniswap/src/data/apiClients/tradingApi/useTradingApiSwappableTokensQuery' +import { UniverseChainId } from 'uniswap/src/features/chains/types' import { CurrencyInfo } from 'uniswap/src/features/dataApi/types' import { ElementName, SectionName } from 'uniswap/src/features/telemetry/constants' import Trace from 'uniswap/src/features/telemetry/Trace' @@ -189,6 +190,15 @@ function SwapFormContent({ wrapCallback }: { wrapCallback?: WrapCallback }): JSX // eslint-disable-next-line react-hooks/exhaustive-deps }, []) + const { updateTransactionSettings } = useTransactionSettingsContext() + useEffect(() => { + if (derivedSwapInfo.chainId === UniverseChainId.MonadTestnet) { + updateTransactionSettings({ isOnlyV2Allowed: true }) + } else { + updateTransactionSettings({ isOnlyV2Allowed: false }) + } + }, [derivedSwapInfo.chainId, updateTransactionSettings]) + const exactFieldIsInput = exactCurrencyField === CurrencyField.INPUT const exactFieldIsOutput = exactCurrencyField === CurrencyField.OUTPUT const derivedCurrencyField = exactFieldIsInput ? CurrencyField.OUTPUT : CurrencyField.INPUT diff --git a/packages/uniswap/src/features/transactions/swap/form/SwapFormSettings.tsx b/packages/uniswap/src/features/transactions/swap/form/SwapFormSettings.tsx index a9e68c7eabc..0a211371884 100644 --- a/packages/uniswap/src/features/transactions/swap/form/SwapFormSettings.tsx +++ b/packages/uniswap/src/features/transactions/swap/form/SwapFormSettings.tsx @@ -1,19 +1,19 @@ -import { useCallback, useState } from 'react' +import { useCallback, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' -import { ColorTokens, Flex, FlexProps, Popover, Text, TouchableArea, isWeb, useSporeColors } from 'ui/src' +import { ColorTokens, Flex, FlexProps, Popover, Text, TouchableArea } from 'ui/src' import { Eye } from 'ui/src/components/icons/Eye' -import { Settings } from 'ui/src/components/icons/Settings' import { IconSizeTokens, iconSizes } from 'ui/src/theme' import { useAccountMeta } from 'uniswap/src/contexts/UniswapContext' import { AccountType } from 'uniswap/src/features/accounts/types' -import { useLocalizationContext } from 'uniswap/src/features/language/LocalizationContext' import { ViewOnlyModal } from 'uniswap/src/features/transactions/modals/ViewOnlyModal' import { useTransactionSettingsContext } from 'uniswap/src/features/transactions/settings/contexts/TransactionSettingsContext' +import { SwapFormSettingsButton } from 'uniswap/src/features/transactions/swap/form/SwapFormSettingsButton' +import SlippageWarningModal from 'uniswap/src/features/transactions/swap/settings/SlippageWarningModal' import { TransactionSettingsModal } from 'uniswap/src/features/transactions/swap/settings/TransactionSettingsModal' import { SwapSettingConfig } from 'uniswap/src/features/transactions/swap/settings/configs/types' -import { TestID } from 'uniswap/src/test/fixtures/testIDs' +import { useSlippageSettings } from 'uniswap/src/features/transactions/swap/settings/useSlippageSettings' import { dismissNativeKeyboard } from 'utilities/src/device/keyboard' -import { isInterface, isMobileApp } from 'utilities/src/platform' +import { isExtension, isInterface, isMobileApp, isMobileWeb } from 'utilities/src/platform' export function SwapFormSettings({ settings, @@ -35,14 +35,15 @@ export function SwapFormSettings({ isBridgeTrade?: boolean }): JSX.Element { const { t } = useTranslation() - const { formatPercent } = useLocalizationContext() - const colors = useSporeColors() const account = useAccountMeta() - const { customSlippageTolerance } = useTransactionSettingsContext() + const { customSlippageTolerance, slippageWarningModalSeen, updateTransactionSettings } = + useTransactionSettingsContext() + const { autoSlippageTolerance } = useSlippageSettings() const [showTransactionSettingsModal, setShowSettingsModal] = useState(false) const [showViewOnlyModal, setShowViewOnlyModal] = useState(false) + const [showSlippageWarningModal, setShowSlippageWarningModal] = useState(false) const onPressSwapSettings = useCallback((): void => { setShowSettingsModal(true) @@ -53,7 +54,24 @@ export function SwapFormSettings({ setShowViewOnlyModal(true) }, []) - const onCloseSettingsModal = useCallback(() => setShowSettingsModal(false), []) + const onCloseSettingsModal = useCallback(() => { + const shouldShowSlippageWarning = + !slippageWarningModalSeen && customSlippageTolerance && customSlippageTolerance >= 20 + + if (shouldShowSlippageWarning) { + // Leave swap settings modal open for mobile app (to layer modals), but close for web apps + if (!isMobileApp) { + setShowSettingsModal(false) + } + // Delay showing the slippage warning modal to avoid conflict with popover dismissal for a smoother UX + setTimeout(() => { + setShowSlippageWarningModal(true) + updateTransactionSettings({ slippageWarningModalSeen: true }) + }, 80) + } else { + setShowSettingsModal(false) + } + }, [slippageWarningModalSeen, customSlippageTolerance, updateTransactionSettings]) const isViewOnlyWallet = account?.type === AccountType.Readonly @@ -62,6 +80,13 @@ export function SwapFormSettings({ const showCustomSlippage = customSlippageTolerance && !isBridgeTrade + const showSettingsIconTooltip = useMemo(() => { + const meetsPlatformConditions = (isInterface || isExtension) && !isMobileWeb + const exceedsSlippageTolerance = !!customSlippageTolerance && customSlippageTolerance > autoSlippageTolerance + + return meetsPlatformConditions && exceedsSlippageTolerance && !showTransactionSettingsModal + }, [customSlippageTolerance, showTransactionSettingsModal, autoSlippageTolerance]) + return ( setShowViewOnlyModal(false)} /> @@ -75,7 +100,7 @@ export function SwapFormSettings({ onPress={onPressViewOnlyModal} > - + {t('swap.header.viewOnly')} @@ -87,34 +112,22 @@ export function SwapFormSettings({ { + onOpenChange={(open: boolean) => { // Only close on interface because SwapSettings are rendered in a modal on mobile/extension // and when click is triggered inside extension Modal it causes onOpenChange to trigger if (!open && isInterface) { - setShowSettingsModal(false) + onCloseSettingsModal() } }} > - - - - {showCustomSlippage ? ( - - {formatPercent(customSlippageTolerance)} - - ) : null} - - - - + )} + setShowSlippageWarningModal(false)} /> ) } diff --git a/packages/uniswap/src/features/transactions/swap/form/SwapFormSettingsButton.tsx b/packages/uniswap/src/features/transactions/swap/form/SwapFormSettingsButton.tsx new file mode 100644 index 00000000000..4c9ac4f19a1 --- /dev/null +++ b/packages/uniswap/src/features/transactions/swap/form/SwapFormSettingsButton.tsx @@ -0,0 +1,92 @@ +import { useMemo } from 'react' +import { useTranslation } from 'react-i18next' +import { ColorTokens, Flex, isWeb, Popover, Text, Tooltip, TouchableArea } from 'ui/src' +import { Settings } from 'ui/src/components/icons/Settings' +import { SettingsWarning } from 'ui/src/components/icons/SettingsWarning' +import { IconSizeTokens } from 'ui/src/theme' +import { SLIPPAGE_CRITICAL_TOLERANCE } from 'uniswap/src/constants/transactions' +import { useLocalizationContext } from 'uniswap/src/features/language/LocalizationContext' +import { useSlippageSettings } from 'uniswap/src/features/transactions/swap/settings/useSlippageSettings' +import { getSlippageWarningColor } from 'uniswap/src/features/transactions/swap/utils/styleHelpers' +import { TestID } from 'uniswap/src/test/fixtures/testIDs' + +const getSettingsIconBackgroundColor = (autoSlippageTolerance: number, slippageTolerance?: number): ColorTokens => { + if (!slippageTolerance) { + return '$transparent' + } + if (slippageTolerance >= SLIPPAGE_CRITICAL_TOLERANCE) { + return '$statusCritical2' + } + if (slippageTolerance > autoSlippageTolerance) { + return '$statusWarning2' + } + return '$surface3' +} + +interface SwapFormSettingsButtonProps { + showCustomSlippage: boolean + showTooltip: boolean + customSlippageTolerance?: number + onPress: () => void + iconColor?: ColorTokens + iconSize?: IconSizeTokens +} + +export function SwapFormSettingsButton({ + showCustomSlippage, + showTooltip, + customSlippageTolerance, + onPress, + iconColor, + iconSize, +}: SwapFormSettingsButtonProps): JSX.Element { + const { t } = useTranslation() + const { formatPercent } = useLocalizationContext() + const { autoSlippageTolerance } = useSlippageSettings() + + // Icon settings (background color, content color, and component) based on slippage tolerance + const { backgroundColor, contentColor, IconComponent } = useMemo(() => { + const iconBackgroundColor = getSettingsIconBackgroundColor(autoSlippageTolerance, customSlippageTolerance) + const fillColor = getSlippageWarningColor(customSlippageTolerance ?? 0, autoSlippageTolerance, iconColor) + const SettingsIconComponent = + customSlippageTolerance && customSlippageTolerance > SLIPPAGE_CRITICAL_TOLERANCE ? SettingsWarning : Settings + + return { backgroundColor: iconBackgroundColor, contentColor: fillColor, IconComponent: SettingsIconComponent } + }, [customSlippageTolerance, iconColor, autoSlippageTolerance]) + + const content = ( + + + + {showCustomSlippage && ( + + {formatPercent(customSlippageTolerance)} + + )} + + + + + ) + + if (showTooltip) { + return ( + + {content} + + {t('swap.settings.slippage.warning.hover')} + + + ) + } + + return content +} diff --git a/packages/uniswap/src/features/transactions/swap/form/footer/GasTradeRow.tsx b/packages/uniswap/src/features/transactions/swap/form/footer/GasTradeRow.tsx index c3238ca04cc..86c77cf4000 100644 --- a/packages/uniswap/src/features/transactions/swap/form/footer/GasTradeRow.tsx +++ b/packages/uniswap/src/features/transactions/swap/form/footer/GasTradeRow.tsx @@ -12,7 +12,7 @@ import { Warning } from 'uniswap/src/components/modals/WarningModal/types' import { useEnabledChains } from 'uniswap/src/features/chains/hooks/useEnabledChains' import { useFormattedUniswapXGasFeeInfo, - useGasFeeFormattedAmounts, + useGasFeeFormattedDisplayAmounts, useGasFeeHighRelativeToValue, } from 'uniswap/src/features/gas/hooks' import { FormattedUniswapXGasFeeInfo, GasFeeResult } from 'uniswap/src/features/gas/types' @@ -49,7 +49,7 @@ export function useDebouncedGasInfo(): DebouncedGasInfo { chainId, ) - const { gasFeeFormatted, gasFeeUSD } = useGasFeeFormattedAmounts({ + const { gasFeeFormatted, gasFeeUSD } = useGasFeeFormattedDisplayAmounts({ gasFee, chainId, placeholder: undefined, diff --git a/packages/uniswap/src/features/transactions/swap/hooks/useSwapTxAndGasInfo.ts b/packages/uniswap/src/features/transactions/swap/hooks/useSwapTxAndGasInfo.ts index 247aeea9609..920cbf753e0 100644 --- a/packages/uniswap/src/features/transactions/swap/hooks/useSwapTxAndGasInfo.ts +++ b/packages/uniswap/src/features/transactions/swap/hooks/useSwapTxAndGasInfo.ts @@ -69,8 +69,8 @@ export function useSwapTxAndGasInfo({ const orderParams = signature ? { signature, quote: trade.quote.quote, routing: Routing.DUTCH_V2 } : undefined const gasFeeBreakdown: UniswapXGasBreakdown = { classicGasUseEstimateUSD: trade.quote.quote.classicGasUseEstimateUSD, - approvalCost: tokenApprovalInfo?.gasFee, - wrapCost: swapTxInfo.gasFeeResult.value, + approvalCost: tokenApprovalInfo?.displayGasFee, + wrapCost: swapTxInfo.gasFeeResult.displayValue, inputTokenSymbol: trade.inputAmount.currency.wrapped.symbol, } @@ -157,7 +157,7 @@ function getTotalGasFee( // For UniswapX orders with no wrap and no approval, show total gas fee as 0. if (isGaslessSwap && noApprovalNeeded) { - return { value: '0', error, isLoading } + return { value: '0', displayValue: '0', error, isLoading } } // If user is disconnected, we don't have approval info, so use swapGasResult only for gas estimation @@ -169,9 +169,14 @@ function getTotalGasFee( // - If errors exist on swap or approval requests. // - If we don't have both the approval and transaction gas fees. if (approvalGasFeeMissing || swapGasFeeMissing || blockingUnknownApprovalStatus || error) { - return { value: undefined, error, isLoading } + return { value: undefined, displayValue: undefined, error, isLoading } } const value = sumGasFees([swapGasResult.value, tokenApprovalInfo.gasFee, tokenApprovalInfo.cancelGasFee]) - return { value, error, isLoading } + const displayValue = sumGasFees([ + swapGasResult.displayValue, + tokenApprovalInfo.displayGasFee, + tokenApprovalInfo.displayCancelGasFee, + ]) + return { value, displayValue, error, isLoading } } 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 32c8ba6f997..316222c10a7 100644 --- a/packages/uniswap/src/features/transactions/swap/hooks/useTokenApprovalInfo.test.ts +++ b/packages/uniswap/src/features/transactions/swap/hooks/useTokenApprovalInfo.test.ts @@ -87,6 +87,7 @@ describe('useTokenApprovalInfo', () => { maxPriorityFeePerGas: '400000', }, gasFee: '200000', + displayGasFee: '200000', gasEstimates: mockGasEstimates, cancelTxRequest: null, }) diff --git a/packages/uniswap/src/features/transactions/swap/hooks/useTokenApprovalInfo.ts b/packages/uniswap/src/features/transactions/swap/hooks/useTokenApprovalInfo.ts index cb8e0393f37..613d7ef15b4 100644 --- a/packages/uniswap/src/features/transactions/swap/hooks/useTokenApprovalInfo.ts +++ b/packages/uniswap/src/features/transactions/swap/hooks/useTokenApprovalInfo.ts @@ -4,7 +4,11 @@ import { useCheckApprovalQuery } from 'uniswap/src/data/apiClients/tradingApi/us import { ApprovalRequest, Routing } from 'uniswap/src/data/tradingApi/__generated__/index' import { AccountMeta } from 'uniswap/src/features/accounts/types' import { UniverseChainId } from 'uniswap/src/features/chains/types' -import { useActiveGasStrategy, useShadowGasStrategies } from 'uniswap/src/features/gas/hooks' +import { + convertGasFeeToDisplayValue, + useActiveGasStrategy, + useShadowGasStrategies, +} from 'uniswap/src/features/gas/hooks' import { areEqualGasStrategies } from 'uniswap/src/features/gas/types' import { ApprovalAction, TokenApprovalInfo } from 'uniswap/src/features/transactions/swap/types/trade' import { isUniswapX } from 'uniswap/src/features/transactions/swap/utils/routing' @@ -29,7 +33,9 @@ export interface TokenApprovalInfoParams { interface TokenApprovalGasInfo { gasFee?: string + displayGasFee?: string cancelGasFee?: string + displayCancelGasFee?: string gasEstimates?: GasFeeEstimates isLoading: boolean } @@ -52,6 +58,9 @@ export function useTokenApprovalInfo(params: TokenApprovalInfoParams): TokenAppr const currencyOut = currencyOutAmount?.currency const tokenOutAddress = getTokenAddressForApi(currencyOut) + const activeGasStrategy = useActiveGasStrategy(chainId, 'general') + const shadowGasStrategies = useShadowGasStrategies(chainId, 'general') + const approvalRequestArgs: ApprovalRequest | undefined = useMemo(() => { const tokenInChainId = toTradingApiSupportedChainId(chainId) const tokenOutChainId = toTradingApiSupportedChainId(currencyOut?.chainId) @@ -71,17 +80,25 @@ export function useTokenApprovalInfo(params: TokenApprovalInfoParams): TokenAppr includeGasInfo: true, tokenOut: tokenOutAddress, tokenOutChainId, + gasStrategies: [activeGasStrategy, ...(shadowGasStrategies ?? [])], } - }, [address, amount, chainId, currencyIn, currencyOut?.chainId, isBridge, tokenInAddress, tokenOutAddress]) + }, [ + activeGasStrategy, + address, + amount, + chainId, + currencyIn, + currencyOut?.chainId, + isBridge, + tokenInAddress, + tokenOutAddress, + shadowGasStrategies, + ]) const shouldSkip = skip || !approvalRequestArgs || isWrap || !address - const activeGasStrategy = useActiveGasStrategy(chainId, 'general') - const shadowGasStrategies = useShadowGasStrategies(chainId, 'general') const { data, isLoading, error } = useCheckApprovalQuery({ - params: shouldSkip - ? undefined - : { ...approvalRequestArgs, gasStrategies: [activeGasStrategy, ...(shadowGasStrategies ?? [])] }, + params: shouldSkip ? undefined : approvalRequestArgs, staleTime: 15 * ONE_SECOND_MS, immediateGcTime: ONE_MINUTE_MS, }) @@ -115,16 +132,7 @@ export function useTokenApprovalInfo(params: TokenApprovalInfoParams): TokenAppr isLoading, } } - if (data.approval && data.cancel) { - return { - action: ApprovalAction.RevokeAndPermit2Approve, - txRequest: data.approval, - gasFee: data.gasFee, - cancelTxRequest: data.cancel, - cancelGasFee: data.cancelGasFee, - isLoading, - } - } + if (data.approval) { const activeEstimate = data.gasEstimates?.find((e) => areEqualGasStrategies(e.strategy, activeGasStrategy)) @@ -136,10 +144,25 @@ export function useTokenApprovalInfo(params: TokenApprovalInfoParams): TokenAppr } } + if (data.cancel) { + return { + action: ApprovalAction.RevokeAndPermit2Approve, + txRequest: data.approval, + gasFee: data.gasFee, + displayGasFee: convertGasFeeToDisplayValue(data.gasFee, activeGasStrategy), + cancelTxRequest: data.cancel, + cancelGasFee: data.cancelGasFee, + displayCancelGasFee: convertGasFeeToDisplayValue(data.cancelGasFee, activeGasStrategy), + isLoading, + gasEstimates, + } + } + return { action: ApprovalAction.Permit2Approve, txRequest: data.approval, gasFee: data.gasFee, + displayGasFee: convertGasFeeToDisplayValue(data.gasFee, activeGasStrategy), gasEstimates, cancelTxRequest: null, isLoading, diff --git a/packages/uniswap/src/features/transactions/swap/hooks/useTransactionRequestInfo.ts b/packages/uniswap/src/features/transactions/swap/hooks/useTransactionRequestInfo.ts index 3b53abff428..290d0f95973 100644 --- a/packages/uniswap/src/features/transactions/swap/hooks/useTransactionRequestInfo.ts +++ b/packages/uniswap/src/features/transactions/swap/hooks/useTransactionRequestInfo.ts @@ -11,7 +11,12 @@ import { TransactionFailureReason, } from 'uniswap/src/data/tradingApi/__generated__/index' import { AccountMeta } from 'uniswap/src/features/accounts/types' -import { useActiveGasStrategy, useShadowGasStrategies, useTransactionGasFee } from 'uniswap/src/features/gas/hooks' +import { + convertGasFeeToDisplayValue, + useActiveGasStrategy, + useShadowGasStrategies, + useTransactionGasFee, +} from 'uniswap/src/features/gas/hooks' import { GasFeeResult, areEqualGasStrategies } from 'uniswap/src/features/gas/types' import { DynamicConfigs, SwapConfigKey } from 'uniswap/src/features/gating/configs' import { FeatureFlags } from 'uniswap/src/features/gating/flags' @@ -54,6 +59,7 @@ export interface TransactionRequestInfo { gasFeeResult: GasFeeResult gasEstimate: SwapGasFeeEstimation swapRequestArgs: CreateSwapRequest | undefined + simulationFailureReasons?: TransactionFailureReason[] } export function useTransactionRequestInfo({ @@ -152,7 +158,11 @@ export function useTransactionRequestInfo({ // Wrap gas cost should not change significantly between trades, so we can use the last value if current is unavailable. const wrapGasFee: GasFeeResult = useMemo( - () => ({ ...currentWrapGasFee, value: currentWrapGasFee.value ?? wrapGasFeeRef.current.value }), + () => ({ + ...currentWrapGasFee, + value: currentWrapGasFee.value ?? wrapGasFeeRef.current.value, + displayValue: currentWrapGasFee.displayValue ?? wrapGasFeeRef.current.displayValue, + }), [currentWrapGasFee], ) @@ -183,11 +193,20 @@ export function useTransactionRequestInfo({ }) // We use the gasFee estimate from quote, as its more accurate - const swapGasFee = swapQuote?.gasFee + const swapGasFee = useMemo( + () => ({ + value: swapQuote?.gasFee, + displayValue: convertGasFeeToDisplayValue(swapQuote?.gasFee, activeGasStrategy), + }), + [swapQuote?.gasFee, activeGasStrategy], + ) // This is a case where simulation fails on backend, meaning txn is expected to fail + const simulationFailureReasons = isClassicQuote(swapQuote) ? swapQuote?.txFailureReasons : undefined const simulationError = - isClassicQuote(swapQuote) && swapQuote?.txFailureReasons?.includes(TransactionFailureReason.SIMULATION_ERROR) + simulationFailureReasons?.includes(TransactionFailureReason.SIMULATION_ERROR) || + simulationFailureReasons?.includes(TransactionFailureReason.SLIPPAGE_TOO_LOW) + const gasEstimateError = useMemo( () => (simulationError ? new Error(UNKNOWN_SIM_ERROR) : error), [simulationError, error], @@ -195,7 +214,8 @@ export function useTransactionRequestInfo({ const gasFeeResult = useMemo( () => ({ - value: isWrapApplicable ? wrapGasFee.value : swapGasFee, + value: isWrapApplicable ? wrapGasFee.value : swapGasFee.value, + displayValue: isWrapApplicable ? wrapGasFee.displayValue : swapGasFee.displayValue, isLoading: isWrapApplicable ? wrapGasFee.isLoading : isSwapLoading, error: isWrapApplicable ? wrapGasFee.error : gasEstimateError, }), @@ -225,6 +245,7 @@ export function useTransactionRequestInfo({ logger.warn('useTransactionRequestInfo', 'useTransactionRequestInfo', UNKNOWN_SIM_ERROR, { ...getBaseTradeAnalyticsPropertiesFromSwapInfo({ derivedSwapInfo, transactionSettings, formatter, trace }), error: gasEstimateError, + simulationFailureReasons: isClassicQuote(swapQuote) ? swapQuote?.txFailureReasons : undefined, txRequest: data?.swap, }) @@ -233,10 +254,21 @@ export function useTransactionRequestInfo({ ...getBaseTradeAnalyticsPropertiesFromSwapInfo({ derivedSwapInfo, transactionSettings, formatter, trace }), error: gasEstimateError, txRequest: data?.swap, + simulationFailureReasons: isClassicQuote(swapQuote) ? swapQuote?.txFailureReasons : undefined, }) } } - }, [data?.swap, transactionSettings, derivedSwapInfo, formatter, gasEstimateError, swapRequestArgs, trade, trace]) + }, [ + data?.swap, + transactionSettings, + derivedSwapInfo, + formatter, + gasEstimateError, + swapRequestArgs, + trade, + trace, + swapQuote, + ]) const gasEstimate: SwapGasFeeEstimation = useMemo(() => { const activeGasEstimate = data?.gasEstimates?.find((e) => areEqualGasStrategies(e.strategy, activeGasStrategy)) @@ -260,5 +292,6 @@ export function useTransactionRequestInfo({ permitData, gasEstimate, swapRequestArgs, + simulationFailureReasons, } } diff --git a/packages/uniswap/src/features/transactions/swap/hooks/useUSDCPrice.ts b/packages/uniswap/src/features/transactions/swap/hooks/useUSDCPrice.ts index 63bb79cec1a..dc0a709326e 100644 --- a/packages/uniswap/src/features/transactions/swap/hooks/useUSDCPrice.ts +++ b/packages/uniswap/src/features/transactions/swap/hooks/useUSDCPrice.ts @@ -16,6 +16,7 @@ import { USDC_WORLD_CHAIN, USDC_ZKSYNC, USDC_ZORA, + USDT_MONAD_TESTNET, } from 'uniswap/src/constants/tokens' import { UniverseChainId } from 'uniswap/src/features/chains/types' import { useTrade } from 'uniswap/src/features/transactions/swap/hooks/useTrade' @@ -32,6 +33,7 @@ export const STABLECOIN_AMOUNT_OUT: { [chainId: number]: CurrencyAmount } [UniverseChainId.Blast]: CurrencyAmount.fromRawAmount(USDB_BLAST, 10_000e18), [UniverseChainId.Bnb]: CurrencyAmount.fromRawAmount(USDC_BNB, 10_000e18), [UniverseChainId.Celo]: CurrencyAmount.fromRawAmount(USDC_CELO, 10_000e18), + [UniverseChainId.MonadTestnet]: CurrencyAmount.fromRawAmount(USDT_MONAD_TESTNET, 10_000e6), [UniverseChainId.Optimism]: CurrencyAmount.fromRawAmount(USDC_OPTIMISM, 10_000e6), [UniverseChainId.Polygon]: CurrencyAmount.fromRawAmount(USDC_POLYGON, 10_000e6), [UniverseChainId.Sepolia]: CurrencyAmount.fromRawAmount(USDC_SEPOLIA, 100_000e6), diff --git a/packages/uniswap/src/features/transactions/swap/modals/RoutingInfo.tsx b/packages/uniswap/src/features/transactions/swap/modals/RoutingInfo.tsx index ab7af03ce35..a160945ea39 100644 --- a/packages/uniswap/src/features/transactions/swap/modals/RoutingInfo.tsx +++ b/packages/uniswap/src/features/transactions/swap/modals/RoutingInfo.tsx @@ -33,7 +33,7 @@ export function RoutingInfo({ const { trade } = useSwapTxContext() const { convertFiatAmountFormatted } = useLocalizationContext() - const { value: gasFeeUSD } = useUSDValueOfGasFee(chainId, gasFee.value ?? undefined) + const { value: gasFeeUSD } = useUSDValueOfGasFee(chainId, gasFee.displayValue ?? undefined) const gasFeeFormatted = gasFeeUSD !== undefined ? convertFiatAmountFormatted(gasFeeUSD, NumberType.FiatGasPrice) : undefined diff --git a/packages/uniswap/src/features/transactions/swap/review/SwapDetails.tsx b/packages/uniswap/src/features/transactions/swap/review/SwapDetails.tsx index ade46ccc879..50060130a86 100644 --- a/packages/uniswap/src/features/transactions/swap/review/SwapDetails.tsx +++ b/packages/uniswap/src/features/transactions/swap/review/SwapDetails.tsx @@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next' import { Flex, HeightAnimator, Text, TouchableArea } from 'ui/src' import { getAlertColor } from 'uniswap/src/components/modals/WarningModal/getAlertColor' import { Warning } from 'uniswap/src/components/modals/WarningModal/types' +import { TransactionFailureReason } from 'uniswap/src/data/tradingApi/__generated__' import { CurrencyInfo } from 'uniswap/src/features/dataApi/types' import { GasFeeResult } from 'uniswap/src/features/gas/types' import { FeatureFlags } from 'uniswap/src/features/gating/flags' @@ -30,6 +31,7 @@ import { CurrencyField } from 'uniswap/src/types/currency' import { getSymbolDisplayText } from 'uniswap/src/utils/currency' import { normalizePriceImpact } from 'utilities/src/format/normalizePriceImpact' import { NumberType } from 'utilities/src/format/types' +import { isMobileApp, isMobileWeb } from 'utilities/src/platform' interface SwapDetailsProps { acceptedDerivedSwapInfo: DerivedSwapInfo @@ -47,6 +49,7 @@ interface SwapDetailsProps { onAcceptTrade: () => void onShowWarning?: () => void setTokenWarningChecked?: (checked: boolean) => void + txSimulationErrors?: TransactionFailureReason[] } export function SwapDetails({ @@ -64,6 +67,7 @@ export function SwapDetails({ onAcceptTrade, onShowWarning, setTokenWarningChecked, + txSimulationErrors, }: SwapDetailsProps): JSX.Element { const v4Enabled = useFeatureFlag(FeatureFlags.V4Swap) const { t } = useTranslation() @@ -98,7 +102,7 @@ export function SwapDetails({ const priceImpactWarningColor = getAlertColor(priceImpactWarning?.severity).text return ( - + @@ -166,7 +171,7 @@ export function SwapDetails({ ) : null} - + ) } @@ -242,6 +247,15 @@ function AcceptNewQuoteRow({ ) } +// We don't need to animate the height on mobile because bottom sheet already handles the animation. +function HeightAnimatorWrapper({ children }: { children: React.ReactNode }): JSX.Element { + if (isMobileApp || isMobileWeb) { + return <>{children} + } else { + return {children} + } +} + function calculatePercentageDifference({ derivedSwapInfo, acceptedDerivedSwapInfo, diff --git a/packages/uniswap/src/features/transactions/swap/review/SwapReviewScreen.tsx b/packages/uniswap/src/features/transactions/swap/review/SwapReviewScreen.tsx index 931efd42ce3..2dd2108cc6e 100644 --- a/packages/uniswap/src/features/transactions/swap/review/SwapReviewScreen.tsx +++ b/packages/uniswap/src/features/transactions/swap/review/SwapReviewScreen.tsx @@ -38,7 +38,7 @@ import { TransactionStep } from 'uniswap/src/features/transactions/swap/types/st 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 { isUniswapX } from 'uniswap/src/features/transactions/swap/utils/routing' +import { isClassic, isUniswapX } from 'uniswap/src/features/transactions/swap/utils/routing' import { isWrapAction } from 'uniswap/src/features/transactions/swap/utils/wrap' import { CurrencyField } from 'uniswap/src/types/currency' import { createTransactionId } from 'uniswap/src/utils/createTransactionId' @@ -112,6 +112,13 @@ export function SwapReviewScreen(props: SwapReviewScreenProps): JSX.Element | nu const isWrap = isWrapAction(wrapType) const { blockingWarning, reviewScreenWarning } = useParsedSwapWarnings() + const txSimulationErrors = useMemo(() => { + if (!trade || !isClassic(trade)) { + return undefined + } + + return trade.quote?.quote.txFailureReasons + }, [trade]) const { onAcceptTrade, @@ -350,6 +357,7 @@ export function SwapReviewScreen(props: SwapReviewScreenProps): JSX.Element | nu chainId={chainId} gasFee={gasFee} warning={reviewScreenWarning?.warning} + txSimulationErrors={txSimulationErrors} onShowWarning={onShowWarning} /> ) : ( @@ -366,6 +374,7 @@ export function SwapReviewScreen(props: SwapReviewScreenProps): JSX.Element | nu newTradeRequiresAcceptance={newTradeRequiresAcceptance} uniswapXGasBreakdown={uniswapXGasBreakdown} warning={reviewScreenWarning?.warning} + txSimulationErrors={txSimulationErrors} onAcceptTrade={onAcceptTrade} onShowWarning={onShowWarning} /> diff --git a/packages/uniswap/src/features/transactions/swap/settings/SlippageControl.tsx b/packages/uniswap/src/features/transactions/swap/settings/SlippageControl.tsx new file mode 100644 index 00000000000..f7877025212 --- /dev/null +++ b/packages/uniswap/src/features/transactions/swap/settings/SlippageControl.tsx @@ -0,0 +1,115 @@ +import { useEffect, useMemo, useRef, useState } from 'react' +import { useTranslation } from 'react-i18next' +// eslint-disable-next-line no-restricted-imports -- type imports are safe +import type { LayoutChangeEvent } from 'react-native' +import { Flex, Input, Text } from 'ui/src' +import { useSlippageSettings } from 'uniswap/src/features/transactions/swap/settings/useSlippageSettings' +import { getSlippageWarningColor } from 'uniswap/src/features/transactions/swap/utils/styleHelpers' + +interface SlippageControlProps { + saveOnBlur: boolean +} + +const INPUT_MIN_WIDTH = 44 + +export function SlippageControl({ saveOnBlur }: SlippageControlProps): JSX.Element { + const { t } = useTranslation() + const inputRef = useRef(null) + const [inputWidth, setInputWidth] = useState(0) + const [isLayoutReady, setIsLayoutReady] = useState(false) + + const { + isEditingSlippage, + autoSlippageEnabled, + inputSlippageTolerance, + autoSlippageTolerance, + inputAnimatedStyle, + onPressAutoSlippage, + onChangeSlippageInput, + onFocusSlippageInput, + onBlurSlippageInput, + } = useSlippageSettings(saveOnBlur) + + useEffect(() => { + inputRef.current?.blur() + }, [isLayoutReady]) + + function onInputTextLayout(event: LayoutChangeEvent): void { + setInputWidth(event.nativeEvent.layout.width) + setIsLayoutReady(true) + } + + const backgroundColor = isEditingSlippage ? '$surface2' : '$surface1' + const inputValue = autoSlippageEnabled ? autoSlippageTolerance.toFixed(2).toString() : inputSlippageTolerance + const parsedInputValue = parseFloat(inputValue) + + const inputValueTextColor = useMemo( + () => + getSlippageWarningColor(parsedInputValue, autoSlippageTolerance, autoSlippageEnabled ? '$neutral2' : '$neutral1'), + [parsedInputValue, autoSlippageEnabled, autoSlippageTolerance], + ) + + return ( + + + + + {t('swap.settings.slippage.control.auto')} + + + + + + + {inputValue} + + + + % + + + + + ) +} diff --git a/packages/uniswap/src/features/transactions/swap/settings/SlippageWarningModal.tsx b/packages/uniswap/src/features/transactions/swap/settings/SlippageWarningModal.tsx new file mode 100644 index 00000000000..0f204decad6 --- /dev/null +++ b/packages/uniswap/src/features/transactions/swap/settings/SlippageWarningModal.tsx @@ -0,0 +1,61 @@ +import { Button, Flex, Text, TouchableArea } from 'ui/src' +import { AlertTriangleFilled } from 'ui/src/components/icons/AlertTriangleFilled' +import { X } from 'ui/src/components/icons/X' +import { iconSizes } from 'ui/src/theme' +import { Modal } from 'uniswap/src/components/modals/Modal' +import { ModalName } from 'uniswap/src/features/telemetry/constants' +import { Trans } from 'uniswap/src/i18n/Trans' +import { isMobileApp, isMobileWeb } from 'utilities/src/platform' + +interface SlippageWarningModalProps { + isOpen: boolean + onClose: () => void +} + +export default function SlippageWarningModal({ isOpen, onClose }: SlippageWarningModalProps): JSX.Element { + return ( + + {!isMobileApp && !isMobileWeb && ( + + + + )} + + + + + + + + + + + + + + + + + + ) +} diff --git a/packages/uniswap/src/features/transactions/swap/settings/SwapSettingsRow.tsx b/packages/uniswap/src/features/transactions/swap/settings/SwapSettingsRow.tsx index 345f75bf6a4..50d65539a65 100644 --- a/packages/uniswap/src/features/transactions/swap/settings/SwapSettingsRow.tsx +++ b/packages/uniswap/src/features/transactions/swap/settings/SwapSettingsRow.tsx @@ -1,23 +1,42 @@ -import { PropsWithChildren, useCallback, useState } from 'react' +import { PropsWithChildren, useCallback, useMemo, useState } from 'react' import { Flex, Text, TouchableArea } from 'ui/src' import { InfoCircleFilled } from 'ui/src/components/icons/InfoCircleFilled' import { RotatableChevron } from 'ui/src/components/icons/RotatableChevron' import { iconSizes } from 'ui/src/theme' +import { InfoTooltip } from 'uniswap/src/components/tooltip/InfoTooltip' +import { WarningMessage } from 'uniswap/src/components/WarningMessage/WarningMessage' +import { SLIPPAGE_CRITICAL_TOLERANCE } from 'uniswap/src/constants/transactions' import { FeatureFlags } from 'uniswap/src/features/gating/flags' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' import { SwapSettingConfig } from 'uniswap/src/features/transactions/swap/settings/configs/types' +import { useSlippageSettings } from 'uniswap/src/features/transactions/swap/settings/useSlippageSettings' import { useTranslation } from 'uniswap/src/i18n' +import { isMobileWeb, isWeb } from 'utilities/src/platform' interface SwapSettingRowProps { setting: SwapSettingConfig setSelectedSetting: (setting: SwapSettingConfig) => void + customSlippageTolerance?: number } -export function SwapSettingRow({ setting, setSelectedSetting }: SwapSettingRowProps): JSX.Element | null { - const { renderTitle, Control, Description, Screen, InfoModal, featureFlag } = setting +export function SwapSettingRow({ + setting, + setSelectedSetting, + customSlippageTolerance, +}: SwapSettingRowProps): JSX.Element | null { + const { renderTitle, renderTooltip, Control, Description, Screen, InfoModal, featureFlag } = setting + const { autoSlippageTolerance } = useSlippageSettings() const { t } = useTranslation() + const isCriticalSlippage = customSlippageTolerance && customSlippageTolerance >= SLIPPAGE_CRITICAL_TOLERANCE + const [showInfoModal, setShowInfoModal] = useState(false) + const showSlippageWarning = useMemo( + () => + !!customSlippageTolerance && customSlippageTolerance > autoSlippageTolerance && setting.settingId === 'slippage', + [autoSlippageTolerance, customSlippageTolerance, setting.settingId], + ) + const onPressControl = useCallback(() => { // If the setting has a screen, navigate to it, else inline control will handle the interaction. if (Screen) { @@ -27,21 +46,40 @@ export function SwapSettingRow({ setting, setSelectedSetting }: SwapSettingRowPr const row = ( <> - - + + setShowInfoModal(true)}> - + {renderTitle(t)} {InfoModal && } + {!!renderTooltip && ( + + + + } + text={renderTooltip(t)} + /> + )} {Description && ( )} + {showSlippageWarning && ( + + )} diff --git a/packages/uniswap/src/features/transactions/swap/settings/TransactionSettingsModal.tsx b/packages/uniswap/src/features/transactions/swap/settings/TransactionSettingsModal.tsx index 15e2f5793c0..f8e4c73a1cc 100644 --- a/packages/uniswap/src/features/transactions/swap/settings/TransactionSettingsModal.tsx +++ b/packages/uniswap/src/features/transactions/swap/settings/TransactionSettingsModal.tsx @@ -19,6 +19,7 @@ const POPOVER_WIDTH = 320 export type TransactionSettingsModalProps = { settings: SwapSettingConfig[] defaultTitle?: string + initialSelectedSetting?: SwapSettingConfig onClose?: () => void isOpen: boolean } @@ -26,41 +27,55 @@ export type TransactionSettingsModalProps = { const TransactionSettingsModalContent = ({ settings, defaultTitle, + initialSelectedSetting, onClose, }: Omit): JSX.Element => { const { t } = useTranslation() + const { customSlippageTolerance } = useTransactionSettingsContext() + const [SelectedSetting, setSelectedSetting] = useState() const title = SelectedSetting ? SelectedSetting.renderTitle(t) : defaultTitle ?? t('swap.settings.title') const screen = SelectedSetting?.Screen ? ( ) : ( - + {settings.map((setting, index) => ( - + ))} ) return ( - - - setSelectedSetting(undefined)}> - - - - {title} - - - + + {!SelectedSetting?.hideTitle && ( + + setSelectedSetting(undefined)}> + + + + {title} + + + + )} {screen} @@ -70,6 +85,7 @@ const TransactionSettingsModalContent = ({ function TransactionSettingsModalInterface({ settings, defaultTitle, + initialSelectedSetting, onClose, }: TransactionSettingsModalProps): JSX.Element { return ( @@ -93,12 +109,22 @@ function TransactionSettingsModalInterface({ shadowRadius={6} width={POPOVER_WIDTH} > - + ) } -function TransactionSettingsModalWallet({ settings, onClose, isOpen }: TransactionSettingsModalProps): JSX.Element { +function TransactionSettingsModalWallet({ + settings, + initialSelectedSetting, + onClose, + isOpen, +}: TransactionSettingsModalProps): JSX.Element { const swapFormContext = useSwapFormContext() const transactionSettingsContext = useTransactionSettingsContext() const colors = useSporeColors() @@ -115,7 +141,11 @@ function TransactionSettingsModalWallet({ settings, onClose, isOpen }: Transacti {/* Re-create the SwapFormContextProvider, since native Modal can cause its children to be in a separate component tree. */} - +
diff --git a/packages/uniswap/src/features/transactions/swap/settings/configs/ProtocolPreference.tsx b/packages/uniswap/src/features/transactions/swap/settings/configs/ProtocolPreference.tsx index 0aa277a1c73..fc56dd756b3 100644 --- a/packages/uniswap/src/features/transactions/swap/settings/configs/ProtocolPreference.tsx +++ b/packages/uniswap/src/features/transactions/swap/settings/configs/ProtocolPreference.tsx @@ -5,11 +5,13 @@ import { Flex, Switch, Text, UniswapXText } from 'ui/src' import { InfoCircleFilled } from 'ui/src/components/icons/InfoCircleFilled' import { UniswapX } from 'ui/src/components/icons/UniswapX' import { ProtocolItems } from 'uniswap/src/data/tradingApi/__generated__' +import { getChainInfo } from 'uniswap/src/features/chains/chainInfo' 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 { ElementName, ElementNameType } from 'uniswap/src/features/telemetry/constants' import { useTransactionSettingsContext } from 'uniswap/src/features/transactions/settings/contexts/TransactionSettingsContext' +import { useSwapFormContext } from 'uniswap/src/features/transactions/swap/contexts/SwapFormContext' import { UniswapXInfo } from 'uniswap/src/features/transactions/swap/modals/UniswapXInfo' import { SwapSettingConfig } from 'uniswap/src/features/transactions/swap/settings/configs/types' import { @@ -27,20 +29,38 @@ export const ProtocolPreference: SwapSettingConfig = { Control() { const { t } = useTranslation() const { selectedProtocols } = useTransactionSettingsContext() - const tradeProtocolPreferenceTitle = isDefaultOptions(selectedProtocols) ? t('common.default') : t('common.custom') + const { isOnlyV2Allowed } = useTransactionSettingsContext() + + const getTradeProtocolPreferenceTitle = (): string => { + if (isDefaultOptions(selectedProtocols)) { + return t('common.default') + } + + if (isOnlyV2Allowed) { + return t('swap.settings.routingPreference.option.v2.title') + } + + return t('common.custom') + } return ( - {tradeProtocolPreferenceTitle} + {getTradeProtocolPreferenceTitle()} ) }, Screen() { const { t } = useTranslation() - const { selectedProtocols, updateTransactionSettings } = useTransactionSettingsContext() + const { selectedProtocols, updateTransactionSettings, isOnlyV2Allowed } = useTransactionSettingsContext() const [isDefault, setIsDefault] = useState(isDefaultOptions(selectedProtocols)) const uniswapXEnabled = useFeatureFlag(FeatureFlags.UniswapX) + const { chainId } = useSwapFormContext().derivedSwapInfo + const chainName = getChainInfo(chainId).name + const v2RestrictionDescription = isOnlyV2Allowed + ? t('swap.settings.protection.subtitle.unavailable', { chainName }) + : null + // We prevent the user from deselecting all options const onlyOneProtocolSelected = selectedProtocols.length === 1 @@ -75,6 +95,7 @@ export const ProtocolPreference: SwapSettingConfig = { elementName={ElementName.SwapRoutingPreferenceDefault} title={t('common.default')} cantDisable={false} + disabled={isOnlyV2Allowed} onSelect={toggleDefault} /> {!isDefault && ( @@ -85,6 +106,8 @@ export const ProtocolPreference: SwapSettingConfig = { elementName={ElementName.SwapRoutingPreferenceUniswapX} title={getProtocolTitle(ProtocolItems.UNISWAPX_V2, t)} cantDisable={onlyOneProtocolSelected} + disabled={isOnlyV2Allowed} + description={v2RestrictionDescription} onSelect={() => toggleProtocol(ProtocolItems.UNISWAPX_V2)} /> )} @@ -94,6 +117,8 @@ export const ProtocolPreference: SwapSettingConfig = { elementName={ElementName.SwapRoutingPreferenceV4} title={getProtocolTitle(ProtocolItems.V4, t)} cantDisable={onlyOneProtocolSelected} + disabled={isOnlyV2Allowed} + description={v2RestrictionDescription} onSelect={() => toggleProtocol(ProtocolItems.V4)} /> )} @@ -102,13 +127,15 @@ export const ProtocolPreference: SwapSettingConfig = { elementName={ElementName.SwapRoutingPreferenceV3} title={getProtocolTitle(ProtocolItems.V3, t)} cantDisable={onlyOneClassicProtocolSelected} + disabled={isOnlyV2Allowed} + description={v2RestrictionDescription} onSelect={() => toggleProtocol(ProtocolItems.V3)} /> toggleProtocol(ProtocolItems.V2)} /> @@ -161,6 +188,7 @@ function OptionRow({ elementName, cantDisable, onSelect, + disabled, }: { title: JSX.Element | string active: boolean @@ -168,6 +196,7 @@ function OptionRow({ cantDisable: boolean onSelect: () => void description?: ReactNode + disabled?: boolean }): JSX.Element { return ( @@ -185,7 +214,12 @@ function OptionRow({ {/* Only log this event if toggle value is off, and then turned on */} - +
) diff --git a/packages/uniswap/src/features/transactions/swap/settings/configs/Slippage.native.tsx b/packages/uniswap/src/features/transactions/swap/settings/configs/Slippage.native.tsx index b9e320a1701..fc007de129b 100644 --- a/packages/uniswap/src/features/transactions/swap/settings/configs/Slippage.native.tsx +++ b/packages/uniswap/src/features/transactions/swap/settings/configs/Slippage.native.tsx @@ -8,7 +8,11 @@ import { AnimatedFlex } from 'ui/src/components/layout/AnimatedFlex' import { fonts, iconSizes, spacing } from 'ui/src/theme' import { BottomSheetTextInput } from 'uniswap/src/components/modals/Modal' import { LearnMoreLink } from 'uniswap/src/components/text/LearnMoreLink' -import { MAX_AUTO_SLIPPAGE_TOLERANCE, MAX_CUSTOM_SLIPPAGE_TOLERANCE } from 'uniswap/src/constants/transactions' +import { + MAX_AUTO_SLIPPAGE_TOLERANCE, + MAX_CUSTOM_SLIPPAGE_TOLERANCE, + SLIPPAGE_CRITICAL_TOLERANCE, +} from 'uniswap/src/constants/transactions' import { uniswapUrls } from 'uniswap/src/constants/urls' import { useLocalizationContext } from 'uniswap/src/features/language/LocalizationContext' import { useTransactionSettingsContext } from 'uniswap/src/features/transactions/settings/contexts/TransactionSettingsContext' @@ -17,6 +21,7 @@ import { SwapSettingConfig } from 'uniswap/src/features/transactions/swap/settin import { useSlippageSettings } from 'uniswap/src/features/transactions/swap/settings/useSlippageSettings' import { BridgeTrade, TradeWithSlippage } from 'uniswap/src/features/transactions/swap/types/trade' import { slippageToleranceToPercent } from 'uniswap/src/features/transactions/swap/utils/format' +import { getSlippageWarningColor } from 'uniswap/src/features/transactions/swap/utils/styleHelpers' import { getSymbolDisplayText } from 'uniswap/src/utils/currency' import { NumberType } from 'utilities/src/format/types' @@ -82,6 +87,11 @@ export const Slippage: SwapSettingConfig = { const isBridgeTrade = trade instanceof BridgeTrade + const inputValueTextColor = useMemo( + () => getSlippageWarningColor(currentSlippageTolerance, autoSlippageTolerance), + [currentSlippageTolerance, autoSlippageTolerance], + ) + const slippageMessage = useMemo(() => { if (isBridgeTrade) { return @@ -92,10 +102,11 @@ export const Slippage: SwapSettingConfig = { showSlippageWarning={showSlippageWarning} slippageTolerance={currentSlippageTolerance} trade={trade} + color={inputValueTextColor} /> ) } - }, [currentSlippageTolerance, inputWarning, isBridgeTrade, showSlippageWarning, t, trade]) + }, [currentSlippageTolerance, inputWarning, isBridgeTrade, showSlippageWarning, t, trade, inputValueTextColor]) return ( @@ -136,7 +147,10 @@ export const Slippage: SwapSettingConfig = { = SLIPPAGE_CRITICAL_TOLERANCE + ? colors.statusCritical.val + : colors.neutral1.val, fontSize: fonts.subheading1.fontSize, width: fonts.subheading1.fontSize * 4, padding: spacing.none, @@ -177,20 +191,21 @@ function SlippageMessage({ slippageTolerance, showSlippageWarning, showEmpty = true, + color = '$statusWarning', }: { inputWarning?: string trade: TradeWithSlippage | null slippageTolerance: number showSlippageWarning: boolean showEmpty?: boolean + color?: ColorTokens }): JSX.Element | null { - const colors = useSporeColors() const { t } = useTranslation() const { formatCurrencyAmount } = useLocalizationContext() const slippageTolerancePercent = slippageToleranceToPercent(slippageTolerance) if (inputWarning) { - return + return } return trade ? ( @@ -211,7 +226,7 @@ function SlippageMessage({ {showSlippageWarning ? ( - + {t('swap.settings.slippage.warning.message')} @@ -234,7 +249,7 @@ function WarningMessage({ }): JSX.Element { return ( - {showAlert ?? } + {showAlert && } {text} diff --git a/packages/uniswap/src/features/transactions/swap/settings/configs/Slippage.web.tsx b/packages/uniswap/src/features/transactions/swap/settings/configs/Slippage.web.tsx index fd3d2cd2415..4cd618b109e 100644 --- a/packages/uniswap/src/features/transactions/swap/settings/configs/Slippage.web.tsx +++ b/packages/uniswap/src/features/transactions/swap/settings/configs/Slippage.web.tsx @@ -1,130 +1,11 @@ -import { useEffect, useMemo, useRef, useState } from 'react' -import { useTranslation } from 'react-i18next' -// eslint-disable-next-line no-restricted-imports -- type imports are safe -import type { LayoutChangeEvent } from 'react-native' -import { Flex, Input, Text } from 'ui/src' +import { SlippageControl } from 'uniswap/src/features/transactions/swap/settings/SlippageControl' import { SwapSettingConfig } from 'uniswap/src/features/transactions/swap/settings/configs/types' -import { useSlippageSettings } from 'uniswap/src/features/transactions/swap/settings/useSlippageSettings' - -const INPUT_MIN_WIDTH = 44 export const Slippage: SwapSettingConfig = { renderTitle: (t) => t('swap.slippage.settings.title'), + renderTooltip: (t) => t('swap.settings.slippage.description'), + settingId: 'slippage', Control() { - const { t } = useTranslation() - const inputRef = useRef(null) - const [inputWidth, setInputWidth] = useState(0) - const [isLayoutReady, setIsLayoutReady] = useState(false) - - const { - isEditingSlippage, - autoSlippageEnabled, - inputSlippageTolerance, - autoSlippageTolerance, - inputAnimatedStyle, - onPressAutoSlippage, - onChangeSlippageInput, - onFocusSlippageInput, - onBlurSlippageInput, - } = useSlippageSettings() - - useEffect(() => { - // It seems like tamagui is automatically causing the Input to autofocus on first render, so we're force blurring it when the component mounts. - // Ideally, we could remove this if we can figure out how to prevent tamagui from triggering the autofocus. - inputRef.current?.blur() - }, [isLayoutReady]) - - function onInputTextLayout(event: LayoutChangeEvent): void { - setInputWidth(event.nativeEvent.layout.width) - setIsLayoutReady(true) - } - - const backgroundColor = isEditingSlippage ? '$surface2' : '$surface1' - const inputValue = autoSlippageEnabled ? autoSlippageTolerance.toFixed(2).toString() : inputSlippageTolerance - const parsedInputValue = parseFloat(inputValue) - - const inputValueTextColor = useMemo(() => { - if (parsedInputValue > 20) { - return '$statusCritical' - } - - if (parsedInputValue > 5.5) { - return '$statusWarning' - } - - return autoSlippageEnabled ? '$neutral2' : '$neutral1' - }, [parsedInputValue, autoSlippageEnabled]) - - const inputBorderColor = useMemo(() => { - if (parsedInputValue > 5.5) { - return inputValueTextColor - } - - return isEditingSlippage ? '$DEP_accentSoft' : '$surface3' - }, [parsedInputValue, inputValueTextColor, isEditingSlippage]) - - return ( - - - - - {t('swap.settings.slippage.control.auto')} - - - - - - - {inputValue} - - - - % - - - - - ) + return }, } diff --git a/packages/uniswap/src/features/transactions/swap/settings/configs/SlippageUpdate.native.tsx b/packages/uniswap/src/features/transactions/swap/settings/configs/SlippageUpdate.native.tsx new file mode 100644 index 00000000000..6189f33bb83 --- /dev/null +++ b/packages/uniswap/src/features/transactions/swap/settings/configs/SlippageUpdate.native.tsx @@ -0,0 +1,8 @@ +import { Slippage } from 'uniswap/src/features/transactions/swap/settings/configs/Slippage' +import { SwapSettingConfig } from 'uniswap/src/features/transactions/swap/settings/configs/types' + +// On native, the update slippage popup is the same as the usual tx settings update modal. +export const SlippageUpdate: SwapSettingConfig = { + ...Slippage, + renderCloseButtonText: (t): string => t('common.button.save'), +} diff --git a/packages/uniswap/src/features/transactions/swap/settings/configs/SlippageUpdate.tsx b/packages/uniswap/src/features/transactions/swap/settings/configs/SlippageUpdate.tsx new file mode 100644 index 00000000000..21801be2501 --- /dev/null +++ b/packages/uniswap/src/features/transactions/swap/settings/configs/SlippageUpdate.tsx @@ -0,0 +1,10 @@ +import { SwapSettingConfig } from 'uniswap/src/features/transactions/swap/settings/configs/types' +import { PlatformSplitStubError } from 'utilities/src/errors' + +export const SlippageUpdate: SwapSettingConfig = { + renderTitle: (t) => t('swap.slippage.settings.title'), + renderCloseButtonText: (t) => t('common.button.save'), + Control() { + throw new PlatformSplitStubError('Slippage') + }, +} diff --git a/packages/uniswap/src/features/transactions/swap/settings/configs/SlippageUpdate.web.tsx b/packages/uniswap/src/features/transactions/swap/settings/configs/SlippageUpdate.web.tsx new file mode 100644 index 00000000000..049bf4a4908 --- /dev/null +++ b/packages/uniswap/src/features/transactions/swap/settings/configs/SlippageUpdate.web.tsx @@ -0,0 +1,24 @@ +import { useTranslation } from 'react-i18next' +import { Flex, Text } from 'ui/src' +import { SlippageControl } from 'uniswap/src/features/transactions/swap/settings/SlippageControl' +import { SwapSettingConfig } from 'uniswap/src/features/transactions/swap/settings/configs/types' + +export const SlippageUpdate: SwapSettingConfig = { + renderTitle: (t) => t('swap.slippage.settings.title'), + renderCloseButtonText: (t) => t('common.button.save'), + hideTitle: true, + Control() { + return <> + }, + Screen() { + const { t } = useTranslation() + return ( + + + {t('swap.slippage.settings.title')} + + + + ) + }, +} diff --git a/packages/uniswap/src/features/transactions/swap/settings/configs/types.ts b/packages/uniswap/src/features/transactions/swap/settings/configs/types.ts index ab910fc60a3..8abda7782ba 100644 --- a/packages/uniswap/src/features/transactions/swap/settings/configs/types.ts +++ b/packages/uniswap/src/features/transactions/swap/settings/configs/types.ts @@ -1,8 +1,12 @@ import { AppTFunction } from 'ui/src/i18n/types' import { FeatureFlags } from 'uniswap/src/features/gating/flags' +type SwapSettingId = 'slippage' + export type SwapSettingConfig = { renderTitle: (t: AppTFunction) => string + renderCloseButtonText?: (t: AppTFunction) => string + hideTitle?: boolean Description?: React.FunctionComponent /** The UI that is displayed on the right side of a settings row, e.g. a Switch. If `Screen` is also defined, pressing `Control` will navigate to the screen. */ Control: React.FunctionComponent @@ -12,4 +16,6 @@ export type SwapSettingConfig = { InfoModal?: React.FunctionComponent<{ isOpen: boolean; onClose: () => void }> /** If defined and the `featureFlag` is disabled, this setting will not be displayed. */ featureFlag?: FeatureFlags + settingId?: SwapSettingId + renderTooltip?: (t: AppTFunction) => string } diff --git a/packages/uniswap/src/features/transactions/swap/settings/useSlippageSettings.ts b/packages/uniswap/src/features/transactions/swap/settings/useSlippageSettings.ts index 885b3c14253..5572b771642 100644 --- a/packages/uniswap/src/features/transactions/swap/settings/useSlippageSettings.ts +++ b/packages/uniswap/src/features/transactions/swap/settings/useSlippageSettings.ts @@ -5,12 +5,16 @@ import type { StyleProp, ViewStyle } from 'react-native' import { useAnimatedStyle, useSharedValue } from 'react-native-reanimated' import { errorShakeAnimation } from 'ui/src/animations/errorShakeAnimation' import { PlusMinusButtonType } from 'ui/src/components/button/PlusMinusButton' -import { MAX_AUTO_SLIPPAGE_TOLERANCE, MAX_CUSTOM_SLIPPAGE_TOLERANCE } from 'uniswap/src/constants/transactions' +import { + MAX_AUTO_SLIPPAGE_TOLERANCE, + MAX_CUSTOM_SLIPPAGE_TOLERANCE, + SLIPPAGE_CRITICAL_TOLERANCE, +} from 'uniswap/src/constants/transactions' import { useTransactionSettingsContext } from 'uniswap/src/features/transactions/settings/contexts/TransactionSettingsContext' const SLIPPAGE_INCREMENT = 0.1 -export function useSlippageSettings(): { +export function useSlippageSettings(saveOnBlur?: boolean): { isEditingSlippage: boolean autoSlippageEnabled: boolean showSlippageWarning: boolean @@ -69,6 +73,32 @@ export function useSlippageSettings(): { updateTransactionSettings({ customSlippageTolerance: undefined }) } + const updateInputWarning = useCallback( + (parsedValue: number) => { + const overMaxTolerance = parsedValue > MAX_CUSTOM_SLIPPAGE_TOLERANCE + const overWarningTolerance = parsedValue > autoSlippageTolerance + const overCriticalTolerance = parsedValue >= SLIPPAGE_CRITICAL_TOLERANCE + const isZero = parsedValue === 0 + + if (isZero) { + return setInputWarning(t('swap.settings.slippage.warning.min')) + } else if (overMaxTolerance) { + return setInputWarning( + t('swap.settings.slippage.warning.max', { + maxSlippageTolerance: MAX_CUSTOM_SLIPPAGE_TOLERANCE, + }), + ) + } else if (overCriticalTolerance) { + return setInputWarning(t('swap.settings.slippage.warning')) + } else if (overWarningTolerance) { + return setInputWarning(t('swap.settings.slippage.alert')) + } + + return setInputWarning(undefined) + }, + [autoSlippageTolerance, t], + ) + const onChangeSlippageInput = useCallback( async (value: string): Promise => { setAutoSlippageEnabled(false) @@ -93,19 +123,7 @@ export function useSlippageSettings(): { const moreThanTwoDecimals = decimalParts?.[1] && decimalParts?.[1].length > 2 const isZero = parsedValue === 0 - if (isZero) { - setInputSlippageTolerance('') - setInputWarning(t('swap.settings.slippage.warning.min')) - } - - if (overMaxTolerance) { - setInputWarning( - t('swap.settings.slippage.warning.max', { - maxSlippageTolerance: MAX_CUSTOM_SLIPPAGE_TOLERANCE, - }), - ) - setInputSlippageTolerance('') - } + updateInputWarning(parsedValue) /* Prevent invalid updates to input value with animation and haptic * isZero is intentionally left out here because the user should be able to type "0" @@ -117,9 +135,12 @@ export function useSlippageSettings(): { } setInputSlippageTolerance(value) - updateTransactionSettings({ customSlippageTolerance: parsedValue }) + + if (!saveOnBlur) { + updateTransactionSettings({ customSlippageTolerance: parsedValue }) + } }, - [inputShakeX, updateTransactionSettings, t], + [updateInputWarning, saveOnBlur, inputShakeX, updateTransactionSettings], ) const onFocusSlippageInput = useCallback((): void => { @@ -143,7 +164,10 @@ export function useSlippageSettings(): { } setInputSlippageTolerance(parsedInputSlippageTolerance.toFixed(2)) - }, [parsedInputSlippageTolerance, updateTransactionSettings]) + if (saveOnBlur) { + updateTransactionSettings({ customSlippageTolerance: parsedInputSlippageTolerance }) + } + }, [parsedInputSlippageTolerance, updateTransactionSettings, saveOnBlur]) const onPressPlusMinusButton = useCallback( (type: PlusMinusButtonType): void => { @@ -158,16 +182,12 @@ export function useSlippageSettings(): { ? Math.min(newSlippage, MAX_CUSTOM_SLIPPAGE_TOLERANCE) : Math.max(newSlippage, 0) - if (constrainedNewSlippage === 0) { - setInputWarning(t('swap.settings.slippage.warning.min')) - } else { - setInputWarning(undefined) - } + updateInputWarning(constrainedNewSlippage) setInputSlippageTolerance(constrainedNewSlippage.toFixed(2).toString()) updateTransactionSettings({ customSlippageTolerance: constrainedNewSlippage }) }, - [autoSlippageEnabled, currentSlippageToleranceNum, updateTransactionSettings, t], + [autoSlippageEnabled, currentSlippageToleranceNum, updateInputWarning, updateTransactionSettings], ) return { diff --git a/packages/uniswap/src/features/transactions/swap/types/swapTxAndGasInfo.ts b/packages/uniswap/src/features/transactions/swap/types/swapTxAndGasInfo.ts index d01efa81831..e51a21949c4 100644 --- a/packages/uniswap/src/features/transactions/swap/types/swapTxAndGasInfo.ts +++ b/packages/uniswap/src/features/transactions/swap/types/swapTxAndGasInfo.ts @@ -1,4 +1,4 @@ -import { Routing, CreateSwapRequest } from "uniswap/src/data/tradingApi/__generated__/index" +import { Routing, CreateSwapRequest, TransactionFailureReason } from "uniswap/src/data/tradingApi/__generated__/index" import { GasFeeResult, ValidatedGasFeeResult, validateGasFeeResult } from "uniswap/src/features/gas/types" import { BridgeTrade, ClassicTrade, IndicativeTrade, UniswapXTrade } from "uniswap/src/features/transactions/swap/types/trade" import { isBridge, isClassic, isUniswapX } from "uniswap/src/features/transactions/swap/utils/routing" @@ -42,7 +42,7 @@ export interface ClassicSwapTxAndGasInfo extends BaseSwapTxAndGasInfo { routing: Routing.CLASSIC trade?: ClassicTrade swapRequestArgs: CreateSwapRequest | undefined - + simulationErrors?: TransactionFailureReason[] /** * `unsigned` is true if `txRequest` is undefined due to a permit signature needing to be signed first. * This occurs on interface where the user must be prompted to sign a permit before txRequest can be fetched. @@ -77,7 +77,9 @@ interface BaseRequiredSwapTxContextFields { gasFee: ValidatedGasFeeResult } -export type ValidatedClassicSwapTxAndGasInfo = Required & BaseRequiredSwapTxContextFields & ({ +export type ValidatedClassicSwapTxAndGasInfo = Omit, 'simulationErrors'> & { + simulationErrors?: ClassicSwapTxAndGasInfo['simulationErrors'] +} & BaseRequiredSwapTxContextFields & ({ unsigned: true permit: ValidatedPermit txRequest: undefined @@ -123,7 +125,7 @@ function validateSwapTxContext(swapTxContext: SwapTxAndGasInfo | unknown): Valid } return { ...swapTxContext, trade, gasFee, unsigned, txRequest: undefined, permit } } else if (txRequest) { - return { ...swapTxContext, trade, gasFee, unsigned, txRequest, permit: undefined } + return { ...swapTxContext, trade, gasFee, unsigned, txRequest, permit: undefined, } } } else if (isBridge(swapTxContext) && swapTxContext.txRequest) { diff --git a/packages/uniswap/src/features/transactions/swap/utils/styleHelpers.ts b/packages/uniswap/src/features/transactions/swap/utils/styleHelpers.ts new file mode 100644 index 00000000000..66e317a8e93 --- /dev/null +++ b/packages/uniswap/src/features/transactions/swap/utils/styleHelpers.ts @@ -0,0 +1,18 @@ +import { ColorTokens } from 'ui/src' +import { SLIPPAGE_CRITICAL_TOLERANCE } from 'uniswap/src/constants/transactions' + +export const getSlippageWarningColor = ( + customSlippageValue: number, + autoSlippageTolerance: number, + fallbackColorValue?: ColorTokens, +): ColorTokens => { + if (customSlippageValue >= SLIPPAGE_CRITICAL_TOLERANCE) { + return '$statusCritical' + } + + if (customSlippageValue > autoSlippageTolerance) { + return '$statusWarning' + } + + return fallbackColorValue ?? '$neutral2' +} diff --git a/packages/uniswap/src/features/transactions/swap/utils/trade.ts b/packages/uniswap/src/features/transactions/swap/utils/trade.ts index 9286c01ffc7..e5d63c41027 100644 --- a/packages/uniswap/src/features/transactions/swap/utils/trade.ts +++ b/packages/uniswap/src/features/transactions/swap/utils/trade.ts @@ -56,6 +56,7 @@ export function tradeToTransactionInfo( gasUseEstimate, routeString, protocol: getProtocolVersionFromTrade(trade), + simulationFailureReasons: isClassic(trade) ? trade.quote?.quote.txFailureReasons : undefined, transactedUSDValue, gasEstimates, } diff --git a/packages/uniswap/src/features/transactions/types/transactionDetails.ts b/packages/uniswap/src/features/transactions/types/transactionDetails.ts index 30e5a289b58..2f69497a276 100644 --- a/packages/uniswap/src/features/transactions/types/transactionDetails.ts +++ b/packages/uniswap/src/features/transactions/types/transactionDetails.ts @@ -2,7 +2,7 @@ import { Protocol } from '@uniswap/router-sdk' import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core' import { providers } from 'ethers/lib/ethers' import { TransactionListQuery } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' -import { Routing } from 'uniswap/src/data/tradingApi/__generated__/index' +import { Routing, TransactionFailureReason } from 'uniswap/src/data/tradingApi/__generated__/index' import { GasEstimate } from 'uniswap/src/data/tradingApi/types' import { AssetType } from 'uniswap/src/entities/assets' import { UniverseChainId } from 'uniswap/src/features/chains/types' @@ -236,6 +236,7 @@ export interface BaseSwapTransactionInfo extends BaseTransactionInfo { routeString?: string gasUseEstimate?: string protocol?: Protocol + simulationFailureReasons?: TransactionFailureReason[] } export interface BridgeTransactionInfo extends BaseTransactionInfo { diff --git a/packages/uniswap/src/features/transactions/types/transactionState.ts b/packages/uniswap/src/features/transactions/types/transactionState.ts index ec5f091b382..a3449ae5c85 100644 --- a/packages/uniswap/src/features/transactions/types/transactionState.ts +++ b/packages/uniswap/src/features/transactions/types/transactionState.ts @@ -3,6 +3,7 @@ import { FrontendSupportedProtocol } from 'uniswap/src/features/transactions/swa import { UniverseChainId } from 'uniswap/src/features/chains/types' import { CurrencyField, CurrencyId } from 'uniswap/src/types/currency' import { currencyIdToAddress, currencyIdToChain } from 'uniswap/src/utils/currencyId' +import { FiatOffRampMetaData } from 'uniswap/src/features/fiatOnRamp/types' export interface TransactionState { txId?: string @@ -19,6 +20,7 @@ export interface TransactionState { customSlippageTolerance?: number customDeadline?: number selectedProtocols?: FrontendSupportedProtocol[] + fiatOffRampMetaData?: FiatOffRampMetaData } export const prepareSwapFormState = ({ diff --git a/packages/uniswap/src/i18n/locales/source/en-US.json b/packages/uniswap/src/i18n/locales/source/en-US.json index 3d29fb5819c..8c3db1c0dec 100644 --- a/packages/uniswap/src/i18n/locales/source/en-US.json +++ b/packages/uniswap/src/i18n/locales/source/en-US.json @@ -222,6 +222,7 @@ "common.button.disconnect": "Disconnect", "common.button.dismiss": "Dismiss", "common.button.done": "Done", + "common.button.edit": "Edit", "common.button.enable": "Enable", "common.button.finish": "Finish", "common.button.goBack": "Go back", @@ -313,7 +314,6 @@ "common.custom": "Custom", "common.customRange": "Custom range", "common.dataOutdated": "Data may be outdated", - "common.dataUnavailable": "Data unavailable", "common.default": "Default", "common.defaultTradeOptions": "Default trade options", "common.delegate.cancelled": "Delegate cancelled", @@ -434,6 +434,7 @@ "common.liquidity.removed": "Liquidity removed", "common.loading": "Loading", "common.loadingAllowance": "Loading allowance", + "common.loadMore": "Load more", "common.longText.button.less": "Read less", "common.longText.button.more": "Read more", "common.lowPrice": "Low price", @@ -461,6 +462,7 @@ "common.networkCost": "Network cost", "common.neverMind": "Never mind", "common.new": "New", + "common.new.exclamation": "New!", "common.nfts": "NFTs", "common.noActivity": "No activity yet", "common.noAmount.error": "Enter an amount", @@ -855,6 +857,7 @@ "fee.tier.new": "New tier", "fee.tier.percent.select": "{{percentage}} select", "fee.tier.recommended": "Recommended", + "fee.tier.recommended.description": "Recommended based on having the highest share of liquidity for the selected token pair.", "fee.tier.search": "Search or create other fee tiers", "fee.tier.search.short": "Search tiers", "fee.tier.select": "Select fee tier", @@ -904,11 +907,11 @@ "fiatOnRamp.region.placeholder": "Search by country or region", "fiatOnRamp.region.title": "Select your region", "fiatOnRamp.summary.total": "{{cryptoAmount}} for {{fiatAmount}}", - "forceUpgrade.action.confirm": "Update app", + "forceUpgrade.action.confirm": "Update now", "forceUpgrade.action.recoveryPhrase": "View recovery phrase", - "forceUpgrade.description": "The version of Uniswap Wallet you’re using is out of date and is missing critical upgrades. If you don’t update the app or you don’t have your recovery phrase written down, you won’t be able to access your assets.", + "forceUpgrade.description": "A new version of the app is available. To continue using the Uniswap Wallet, please update it to the latest version.", "forceUpgrade.label.recoveryPhrase": "Recovery phrase", - "forceUpgrade.title": "Update the app to continue", + "forceUpgrade.title": "Update to the latest version", "globalPreferences.title": "Global preferences", "hero.scroll": "Scroll to learn more", "hero.subtitle": "The largest onchain marketplace. Buy and sell crypto on Ethereum and 11+ other chains.", @@ -940,7 +943,6 @@ "home.feed.title": "Feed", "home.label.buy": "Buy", "home.label.receive": "Receive", - "home.label.scan": "Scan", "home.label.send": "Send", "home.label.swap": "Swap", "home.nfts.title": "NFTs", @@ -1064,7 +1066,6 @@ "mobileAppPromo.banner.getTheApp.link": "Get the Uniswap Wallet app", "mobileAppPromo.banner.title": "Uniswap: Crypto & NFT Wallet", "moonpay.poweredBy": "Fiat onramp powered by MoonPay USA LLC", - "moonpay.rampIframe": "MoonPay fiat on-ramp iframe", "moonpay.restricted.region": "Moonpay is not available in some regions. Click to learn more.", "nav.createAccount.button": "Create account", "nav.logIn.button": "Log in", @@ -1269,7 +1270,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "View recovery phrase", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 other wallet", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} other wallets", - "onboarding.import.onDeviceRecovery.warning.caption": "Please ensure you have backed up all of the other wallets. If you ever want to restore them, you’ll need their recovery phrases or corresponding iCloud backups.", + "onboarding.import.onDeviceRecovery.warning.caption": "Please ensure you have backed up all of the other wallets. If you ever want to restore them, you’ll need their recovery phrases or corresponding {{cloudProvider}} backups.", "onboarding.import.onDeviceRecovery.warning.title": "Are you sure?", "onboarding.import.title": "Choose how you want to add your wallet", "onboarding.importMnemonic.button.default": "My recovery phrase is 12 words", @@ -1370,7 +1371,10 @@ "pool.exporeAnalytics": "Explore Uniswap Analytics.", "pool.hideClosed": "Hide closed positions", "pool.import": "Import pool", - "pool.import.v2": "Import V2 pool", + "pool.import.link.description": "Some v2 positions aren’t displayed automatically.", + "pool.import.positions.v2": "Import V2 positions", + "pool.import.positions.v2.selectPair.description": "Some v2 positions aren’t displayed automatically. Select a token pair to import and view your positions.", + "pool.import.success": "Pool imported", "pool.increaseLiquidity": "Increase liquidity", "pool.info": "Pool info", "pool.initialShare": "Initial prices and pool share", @@ -1450,14 +1454,9 @@ "pool.volume.thirtyDay": "30 day volume", "pool.volume.thirtyDay.short": "30D vol", "pool.yourv2": "Your V2 liquidity", - "poolFinder.connect": "Connect to a wallet to find pools.", - "poolFinder.create": "Create pool", - "poolFinder.found": "Pool found!", - "poolFinder.managePool": "Manage this pool", - "poolFinder.noLiquidity": "You don’t have liquidity in this pool yet.", - "poolFinder.noPoolFound": "No pool found.", - "poolFinder.selectToken": "Select a token to find your v2 liquidity.", - "poolFinder.tip": "Tip: Use this tool to find v2 pools that don’t automatically appear in the interface.", + "poolFinder.availablePools": "Available pools", + "poolFinder.availablePools.found.description": "v2 pools matching your pair selection.", + "poolFinder.availablePools.notFound.description": "No matching v2 pools found. Double-check your token selection and ensure you’re connected to the correct wallet.", "pools.approving.amount": "Approving {{amount}}", "pools.explore": "Explore pools", "position.addHook": "Add a Hook", @@ -1500,6 +1499,7 @@ "position.step.price": "Set initial price", "position.step.range": "Set price range", "position.step.select": "Select token pair and fees", + "position.value": "Position value", "position.valueUnavailable": "Position value is unavailable due to low liquidity.", "position.your": "Your position", "positions.welcome": "Welcome to your positions", @@ -1854,12 +1854,16 @@ "swap.settings.routingPreference.option.v3.title": "v3 pools", "swap.settings.routingPreference.option.v4.title": "v4 pools", "swap.settings.routingPreference.title": "Trade options", + "swap.settings.slippage.alert": "High slippage", "swap.settings.slippage.control.auto": "Auto", "swap.settings.slippage.description": "Your transaction will revert if the price changes more than the slippage percentage.", "swap.settings.slippage.input.message": "If the price slips any further, your transaction will revert. Below is the minimum amount you are guaranteed to receive.", "swap.settings.slippage.input.receive.title": "Receive at least", "swap.settings.slippage.output.message": "If the price slips any further, your transaction will revert. Below is the maximum amount you would need to spend.", "swap.settings.slippage.output.spend.title": "Spend at most", + "swap.settings.slippage.warning": "Very high slippage", + "swap.settings.slippage.warning.description": "Slippage above 20% is likely to result in an unfavorable trade. To reduce the risk being front-run, lower your settings.", + "swap.settings.slippage.warning.hover": "This may result in an unfavorable trade. Try lowering your slippage setting.", "swap.settings.slippage.warning.max": "Enter a value less than {{maxSlippageTolerance}}", "swap.settings.slippage.warning.message": "Slippage may be higher than necessary", "swap.settings.slippage.warning.min": "Enter a value larger than 0", @@ -1883,7 +1887,8 @@ "swap.transaction.revertAfter": "Your transaction will revert if it is pending for more than this period of time.", "swap.unsupportedAssets.readMore": "Read more about unsupported assets", "swap.warning.enterLargerAmount.title": "Enter a larger amount", - "swap.warning.expectedFailure": "This transaction is expected to fail", + "swap.warning.expectedFailure.increaseSlippage": "Try increasing your slippage.", + "swap.warning.expectedFailure.titleMay": "This swap may fail", "swap.warning.insufficientBalance.title": "You don’t have enough {{currencySymbol}}", "swap.warning.insufficientGas.button": "Not enough {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Swap for {{ tokenSymbol }} on {{networkName}}", @@ -1936,6 +1941,10 @@ "tdp.noTestnetSupportDescription": "Some testnets do not support swapping, sending, or buying tokens.", "tdp.stats.unsupportedChainDescription": "Token stats and charts for {{chain}} are available on {{infoLink}}", "tdp.symbolNotFound": "Symbol not found", + "testnet.modal.swapDeepLink.description.toProdMode": "This action requires testnet mode to be disabled. Testnet mode can be reenabled at anytime within settings.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "This action requires testnet mode to be enabled. Tokens on testnets do not hold any real value. Testnet mode can be disabled at anytime within settings.", + "testnet.modal.swapDeepLink.title.toProdMode": "Disable testnet mode", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Enable testnet mode", "testnet.unsupported": "This functionality is not supported in testnet mode.", "themeToggle.theme": "Theme", "title.betterPricesMoreListings": "Better prices. More listings. Buy, sell, and trade NFTs across top marketplaces like OpenSea. Explore trending collections.", @@ -1979,10 +1988,14 @@ "token.priceExplorer.error.title": "Couldn’t load price chart", "token.priceExplorer.timeRangeLabel.all": "All time", "token.priceExplorer.timeRangeLabel.day": "1D", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 Day", "token.priceExplorer.timeRangeLabel.hour": "1H", "token.priceExplorer.timeRangeLabel.month": "1M", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 Month", "token.priceExplorer.timeRangeLabel.week": "1W", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 Week", "token.priceExplorer.timeRangeLabel.year": "1Y", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 Year", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} is not available", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} and {{tokenSymbol1}} are not available", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs does not receive any of these fees.", diff --git a/packages/uniswap/src/i18n/locales/translations/af-ZA.json b/packages/uniswap/src/i18n/locales/translations/af-ZA.json index 31ceed35c08..bfc622730ca 100644 --- a/packages/uniswap/src/i18n/locales/translations/af-ZA.json +++ b/packages/uniswap/src/i18n/locales/translations/af-ZA.json @@ -222,6 +222,7 @@ "common.button.disconnect": "Ontkoppel", "common.button.dismiss": "Verwerp", "common.button.done": "Klaar", + "common.button.edit": "Wysig", "common.button.enable": "Aktiveer", "common.button.finish": "Voltooi", "common.button.goBack": "Gaan terug", @@ -313,7 +314,6 @@ "common.custom": "Pasgemaak", "common.customRange": "Pasgemaakte reeks", "common.dataOutdated": "Data kan verouderd wees", - "common.dataUnavailable": "Data nie beskikbaar nie", "common.default": "Verstek", "common.defaultTradeOptions": "Standaard handel opsies", "common.delegate.cancelled": "Afgevaardigde gekanselleer", @@ -461,6 +461,7 @@ "common.networkCost": "Netwerk koste", "common.neverMind": "Toemaar", "common.new": "Nuut", + "common.new.exclamation": "Nuut!", "common.nfts": "NFT's", "common.noActivity": "Nog geen aktiwiteit nie", "common.noAmount.error": "Voer 'n bedrag in", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Soek volgens land of streek", "fiatOnRamp.region.title": "Kies jou streek", "fiatOnRamp.summary.total": "{{cryptoAmount}} vir {{fiatAmount}}", - "forceUpgrade.action.confirm": "Dateer app op", + "forceUpgrade.action.confirm": "Dateer nou op", "forceUpgrade.action.recoveryPhrase": "Bekyk herstelfrase", - "forceUpgrade.description": "Die weergawe van Uniswap Wallet wat jy gebruik, is verouderd en ontbreek kritieke opgraderings. As jy nie die program opdateer nie of jy het nie jou herstelfrase neergeskryf nie, sal jy nie toegang tot jou bates kan kry nie.", + "forceUpgrade.description": "'n Nuwe weergawe van die toepassing is beskikbaar. Om voort te gaan om die Uniswap Wallet te gebruik, dateer dit asseblief op na die nuutste weergawe.", "forceUpgrade.label.recoveryPhrase": "Herstel frase", - "forceUpgrade.title": "Dateer die toepassing op om voort te gaan", + "forceUpgrade.title": "Dateer op na die nuutste weergawe", "globalPreferences.title": "Globale voorkeure", "hero.scroll": "Blaai om meer te wete te kom", "hero.subtitle": "Die grootste onchain-mark. Koop en verkoop kripto op Ethereum en 11+ ander kettings.", @@ -940,7 +941,6 @@ "home.feed.title": "Voer", "home.label.buy": "Koop", "home.label.receive": "Ontvang", - "home.label.scan": "Skandeer", "home.label.send": "Stuur", "home.label.swap": "Ruil", "home.nfts.title": "NFT's", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Kry die Uniswap Wallet-toepassing", "mobileAppPromo.banner.title": "Uniswap: Crypto & NFT Wallet", "moonpay.poweredBy": "Fiat oprit aangedryf deur MoonPay USA LLC", - "moonpay.rampIframe": "MoonPay fiat-oprit-iframe", "moonpay.restricted.region": "Moonpay is nie in sommige streke beskikbaar nie. Klik om meer te wete te kom.", "nav.createAccount.button": "Skep rekening", "nav.logIn.button": "Meld aan", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Bekyk herstelfrase", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 ander beursie", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} ander beursies", - "onboarding.import.onDeviceRecovery.warning.caption": "Maak asseblief seker dat jy al die ander beursies gerugsteun het. As jy dit ooit wil herstel, sal jy hul herstelfrases of ooreenstemmende iCloud-rugsteun nodig hê.", + "onboarding.import.onDeviceRecovery.warning.caption": "Maak asseblief seker dat jy al die ander beursies gerugsteun het. As jy dit ooit wil herstel, sal jy hul herstelfrases of ooreenstemmende {{cloudProvider}} rugsteun nodig hê.", "onboarding.import.onDeviceRecovery.warning.title": "Is jy seker?", "onboarding.import.title": "Kies hoe jy jou beursie wil byvoeg", "onboarding.importMnemonic.button.default": "My herstelfrase is 12 woorde", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Verken Uniswap Analytics.", "pool.hideClosed": "Versteek geslote posisies", "pool.import": "Invoer swembad", - "pool.import.v2": "Voer V2 swembad in", + "pool.import.link.description": "Sommige v2-posisies word nie outomaties vertoon nie.", + "pool.import.positions.v2": "Voer V2-posisies in", + "pool.import.positions.v2.selectPair.description": "Sommige v2-posisies word nie outomaties vertoon nie. Kies 'n tekenpaar om jou posisies in te voer en te bekyk.", + "pool.import.success": "Swembad ingevoer", "pool.increaseLiquidity": "Verhoog likiditeit", "pool.info": "Swembad inligting", "pool.initialShare": "Aanvanklike pryse en poelaandeel", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "30 dae volume", "pool.volume.thirtyDay.short": "30D vol", "pool.yourv2": "Jou V2-likiditeit", - "poolFinder.connect": "Koppel aan 'n beursie om swembaddens te vind.", - "poolFinder.create": "Skep swembad", - "poolFinder.found": "Swembad gevind!", - "poolFinder.managePool": "Bestuur hierdie swembad", - "poolFinder.noLiquidity": "Jy het nog nie likiditeit in hierdie poel nie.", - "poolFinder.noPoolFound": "Geen swembad gevind nie.", - "poolFinder.selectToken": "Kies 'n teken om jou v2-likiditeit te vind.", - "poolFinder.tip": "Wenk: Gebruik hierdie hulpmiddel om v2-poele te vind wat nie outomaties in die koppelvlak verskyn nie.", + "poolFinder.availablePools": "Beskikbare swembaddens", + "poolFinder.availablePools.found.description": "v2 poele wat ooreenstem met jou paar seleksie.", + "poolFinder.availablePools.notFound.description": "Geen bypassende v2-poele gevind nie. Gaan jou tokenkeuse dubbel na en maak seker dat jy aan die regte beursie gekoppel is.", "pools.approving.amount": "Keur tans {{amount}}goed", "pools.explore": "Verken swembaddens", "position.addHook": "Voeg 'n haak by", @@ -1500,6 +1497,7 @@ "position.step.price": "Stel aanvanklike prys", "position.step.range": "Stel prysklas", "position.step.select": "Kies tokenpaar en fooie", + "position.value": "Posisiewaarde", "position.valueUnavailable": "Posisiewaarde is nie beskikbaar nie weens lae likiditeit.", "position.your": "Jou posisie", "positions.welcome": "Welkom by jou posisies", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "Jou transaksie sal terugdraai as dit vir langer as hierdie tydperk hangende is.", "swap.unsupportedAssets.readMore": "Lees meer oor nie-ondersteunde bates", "swap.warning.enterLargerAmount.title": "Voer 'n groter bedrag in", - "swap.warning.expectedFailure": "Hierdie transaksie sal na verwagting misluk", + "swap.warning.expectedFailure.increaseSlippage": "Probeer om jou glip te verhoog.", + "swap.warning.expectedFailure.titleMay": "Hierdie ruil kan misluk", "swap.warning.insufficientBalance.title": "Jy het nie genoeg {{currencySymbol}}nie", "swap.warning.insufficientGas.button": "Nie genoeg {{currencySymbol}}nie", "swap.warning.insufficientGas.button.bridge": "Ruil vir {{ tokenSymbol }} op {{networkName}}", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Sommige toetsnette ondersteun nie ruil, stuur of koop van tekens nie.", "tdp.stats.unsupportedChainDescription": "Tekenstatistieke en kaarte vir {{chain}} is beskikbaar op {{infoLink}}", "tdp.symbolNotFound": "Simbool nie gevind nie", + "testnet.modal.swapDeepLink.description.toProdMode": "Hierdie aksie vereis dat toetsnetmodus gedeaktiveer word. Testnet-modus kan te eniger tyd binne instellings heraktiveer word.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "Hierdie aksie vereis dat toetsnetmodus geaktiveer word. Tokens op toetsnette hou geen werklike waarde in nie. Testnet-modus kan enige tyd binne instellings gedeaktiveer word.", + "testnet.modal.swapDeepLink.title.toProdMode": "Deaktiveer toetsnetmodus", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Aktiveer toetsnetmodus", "testnet.unsupported": "Hierdie funksionaliteit word nie in die toetsnetmodus ondersteun nie.", "themeToggle.theme": "Tema", "title.betterPricesMoreListings": "Beter pryse. Meer inskrywings. Koop, verkoop en verhandel NFT's oor topmarkplekke soos OpenSea. Verken gewilde versamelings.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Kon nie pryskaart laai nie", "token.priceExplorer.timeRangeLabel.all": "Van alle tye", "token.priceExplorer.timeRangeLabel.day": "1D", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 Dag", "token.priceExplorer.timeRangeLabel.hour": "1H", "token.priceExplorer.timeRangeLabel.month": "1M", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 maand", "token.priceExplorer.timeRangeLabel.week": "1W", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 Week", "token.priceExplorer.timeRangeLabel.year": "1Y", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 Jaar", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} is nie beskikbaar nie", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} en {{tokenSymbol1}} is nie beskikbaar nie", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs ontvang nie enige van hierdie fooie nie.", diff --git a/packages/uniswap/src/i18n/locales/translations/ar-SA.json b/packages/uniswap/src/i18n/locales/translations/ar-SA.json index 196543bba7d..7d1853f636b 100644 --- a/packages/uniswap/src/i18n/locales/translations/ar-SA.json +++ b/packages/uniswap/src/i18n/locales/translations/ar-SA.json @@ -222,6 +222,7 @@ "common.button.disconnect": "قطع الاتصال", "common.button.dismiss": "رفض", "common.button.done": "منتهي", + "common.button.edit": "يحرر", "common.button.enable": "يُمكَِن", "common.button.finish": "ينهي", "common.button.goBack": "عُد", @@ -313,7 +314,6 @@ "common.custom": "مخصص", "common.customRange": "مجموعة مخصصة", "common.dataOutdated": "قد تكون البيانات قديمة", - "common.dataUnavailable": "البيانات غير متوفرة", "common.default": "تقصير", "common.defaultTradeOptions": "خيارات التجارة الافتراضية", "common.delegate.cancelled": "تم إلغاء المندوب", @@ -461,6 +461,7 @@ "common.networkCost": "تكلفة الشبكة", "common.neverMind": "لا تهتم", "common.new": "جديد", + "common.new.exclamation": "جديد!", "common.nfts": "الرموز غير القابلة للاستبدال", "common.noActivity": "لا يوجد نشاط بعد", "common.noAmount.error": "أدخل المبلغ", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "البحث حسب البلد أو المنطقة", "fiatOnRamp.region.title": "اختر منطقتك", "fiatOnRamp.summary.total": "{{cryptoAmount}} لـ {{fiatAmount}}", - "forceUpgrade.action.confirm": "تحديث التطبيق", + "forceUpgrade.action.confirm": "تحديث الآن", "forceUpgrade.action.recoveryPhrase": "عرض عبارة الاسترداد", - "forceUpgrade.description": "إصدار Uniswap Wallet الذي تستخدمه قديم ويفتقد إلى ترقيات مهمة. إذا لم تقم بتحديث التطبيق أو لم تكن عبارة الاسترداد مكتوبة، فلن تتمكن من الوصول إلى الأصول الخاصة بك.", + "forceUpgrade.description": "يتوفر إصدار جديد من التطبيق. لمواصلة استخدام محفظة Uniswap، يرجى تحديثها إلى أحدث إصدار.", "forceUpgrade.label.recoveryPhrase": "عبارة الاسترداد", - "forceUpgrade.title": "قم بتحديث التطبيق للمتابعة", + "forceUpgrade.title": "التحديث إلى الإصدار الأحدث", "globalPreferences.title": "التفضيلات العالمية", "hero.scroll": "قم بالتمرير لمعرفة المزيد", "hero.subtitle": "أكبر سوق onchain. قم بشراء وبيع العملات المشفرة على Ethereum وأكثر من 11 سلاسل أخرى.", @@ -940,7 +941,6 @@ "home.feed.title": "يٌطعم", "home.label.buy": "يشتري", "home.label.receive": "يستلم", - "home.label.scan": "مسح", "home.label.send": "يرسل", "home.label.swap": "تبديل", "home.nfts.title": "الرموز غير القابلة للاستبدال", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "احصل على تطبيق Uniswap Wallet", "mobileAppPromo.banner.title": "Uniswap: محفظة العملات المشفرة وNFT", "moonpay.poweredBy": "فيات onramp مدعوم من MoonPay USA LLC", - "moonpay.rampIframe": "MoonPay أمر iframe على المنحدر", "moonpay.restricted.region": "Moonpay غير متوفر في بعض المناطق. اضغط لتتعلم المزيد.", "nav.createAccount.button": "إنشاء حساب", "nav.logIn.button": "تسجيل الدخول", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "عرض عبارة الاسترداد", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 محفظة أخرى", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} محافظ أخرى", - "onboarding.import.onDeviceRecovery.warning.caption": "يرجى التأكد من عمل نسخة احتياطية لجميع المحافظ الأخرى. إذا كنت ترغب في استعادتها في أي وقت، فستحتاج إلى عبارات الاسترداد الخاصة بها أو النسخ الاحتياطية المقابلة على iCloud.", + "onboarding.import.onDeviceRecovery.warning.caption": "يرجى التأكد من عمل نسخة احتياطية لجميع المحافظ الأخرى. إذا كنت ترغب في استعادتها في أي وقت، فستحتاج إلى عبارات الاسترداد الخاصة بها أو النسخ الاحتياطية المقابلة لها {{cloudProvider}} .", "onboarding.import.onDeviceRecovery.warning.title": "هل أنت متأكد؟", "onboarding.import.title": "اختر الطريقة التي تريد بها إضافة محفظتك", "onboarding.importMnemonic.button.default": "عبارة الاسترداد الخاصة بي هي 12 كلمة", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "اكتشف تحليلات Uniswap.", "pool.hideClosed": "إخفاء المواقف المغلقة", "pool.import": "تجمع الاستيراد", - "pool.import.v2": "استيراد تجمع V2", + "pool.import.link.description": "لا يتم عرض بعض مواضع v2 تلقائيًا.", + "pool.import.positions.v2": "استيراد مواضع V2", + "pool.import.positions.v2.selectPair.description": "لا يتم عرض بعض مواضع الإصدار 2 تلقائيًا. حدد زوجًا من الرموز لاستيرادها وعرض مواضعك.", + "pool.import.success": "تم استيراد المسبح", "pool.increaseLiquidity": "زيادة السيولة", "pool.info": "معلومات عن المسبح", "pool.initialShare": "الأسعار الأولية وحصة المجمع", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "حجم 30 يوم", "pool.volume.thirtyDay.short": "حجم 30D", "pool.yourv2": "السيولة V2 الخاصة بك", - "poolFinder.connect": "اتصل بالمحفظة للعثور على حمامات السباحة.", - "poolFinder.create": "إنشاء تجمع", - "poolFinder.found": "تم العثور على حمام السباحة!", - "poolFinder.managePool": "إدارة هذا المجمع", - "poolFinder.noLiquidity": "ليس لديك سيولة في هذا المجمع حتى الآن.", - "poolFinder.noPoolFound": "لم يتم العثور على تجمع.", - "poolFinder.selectToken": "حدد رمزًا للعثور على سيولة الإصدار الثاني الخاصة بك.", - "poolFinder.tip": "نصيحة: استخدم هذه الأداة للعثور على تجمعات v2 التي لا تظهر تلقائيًا في الواجهة.", + "poolFinder.availablePools": "المسابح المتاحة", + "poolFinder.availablePools.found.description": "تجمعات v2 التي تتوافق مع اختيار الزوج الخاص بك.", + "poolFinder.availablePools.notFound.description": "لم يتم العثور على مجموعات v2 متطابقة. تحقق مرة أخرى من اختيار الرمز الخاص بك وتأكد من اتصالك بالمحفظة الصحيحة.", "pools.approving.amount": "الموافقة {{amount}}", "pools.explore": "استكشاف حمامات السباحة", "position.addHook": "أضف خطافًا", @@ -1500,6 +1497,7 @@ "position.step.price": "تحديد السعر الأولي", "position.step.range": "تحديد النطاق السعري", "position.step.select": "حدد زوج الرمز والرسوم", + "position.value": "قيمة الموضع", "position.valueUnavailable": "قيمة الموقف غير متوفرة بسبب انخفاض السيولة.", "position.your": "موقعك", "positions.welcome": "مرحبا بكم في مناصبكم", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "سيتم إرجاع معاملتك إذا كانت معلقة لأكثر من هذه الفترة الزمنية.", "swap.unsupportedAssets.readMore": "اقرأ المزيد عن الأصول غير المدعومة", "swap.warning.enterLargerAmount.title": "أدخل مبلغًا أكبر", - "swap.warning.expectedFailure": "من المتوقع أن تفشل هذه المعاملة", + "swap.warning.expectedFailure.increaseSlippage": "حاول زيادة الانزلاق الخاص بك.", + "swap.warning.expectedFailure.titleMay": "قد تفشل هذه المبادلة", "swap.warning.insufficientBalance.title": "ليس لديك ما يكفي {{currencySymbol}}", "swap.warning.insufficientGas.button": "لا يكفي {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "قم بالتبديل إلى {{ tokenSymbol }} على {{networkName}}", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "بعض شبكات الاختبار لا تدعم تبادل الرموز أو إرسالها أو شرائها.", "tdp.stats.unsupportedChainDescription": "إحصائيات ومخططات الرمز المميز لـ {{chain}} متاحة على {{infoLink}}", "tdp.symbolNotFound": "لم يتم العثور على الرمز", + "testnet.modal.swapDeepLink.description.toProdMode": "يتطلب هذا الإجراء تعطيل وضع الشبكة التجريبية. يمكن إعادة تمكين وضع الشبكة التجريبية في أي وقت ضمن الإعدادات.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "يتطلب هذا الإجراء تمكين وضع الشبكة التجريبية. لا تحمل الرموز الموجودة على الشبكات التجريبية أي قيمة حقيقية. يمكن تعطيل وضع الشبكة التجريبية في أي وقت ضمن الإعدادات.", + "testnet.modal.swapDeepLink.title.toProdMode": "تعطيل وضع الشبكة التجريبية", + "testnet.modal.swapDeepLink.title.toTestnetMode": "تمكين وضع الشبكة التجريبية", "testnet.unsupported": "لا يتم دعم هذه الوظيفة في وضع الشبكة التجريبية.", "themeToggle.theme": "سمة", "title.betterPricesMoreListings": "افضل اسعار. المزيد من القوائم. قم بشراء وبيع وتداول NFTs عبر أفضل الأسواق مثل OpenSea. استكشاف مجموعات تتجه.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "تعذر تحميل مخطط الأسعار", "token.priceExplorer.timeRangeLabel.all": "كل الوقت", "token.priceExplorer.timeRangeLabel.day": "1د", + "token.priceExplorer.timeRangeLabel.day.verbose": "يوم واحد", "token.priceExplorer.timeRangeLabel.hour": "1 ح", "token.priceExplorer.timeRangeLabel.month": "1 م", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 شهر", "token.priceExplorer.timeRangeLabel.week": "1 واط", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 اسبوع", "token.priceExplorer.timeRangeLabel.year": "1 سنة", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 سنة", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} غير متاح", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} و {{tokenSymbol1}} غير متاحين", "token.safety.fees.uniswapLabsDoesNotReceive": "لا تتلقى Uniswap Labs أيًا من هذه الرسوم.", diff --git a/packages/uniswap/src/i18n/locales/translations/ca-ES.json b/packages/uniswap/src/i18n/locales/translations/ca-ES.json index 6c77682c999..800e2c4fa37 100644 --- a/packages/uniswap/src/i18n/locales/translations/ca-ES.json +++ b/packages/uniswap/src/i18n/locales/translations/ca-ES.json @@ -222,6 +222,7 @@ "common.button.disconnect": "Desconnecta", "common.button.dismiss": "Descartar", "common.button.done": "Fet", + "common.button.edit": "Edita", "common.button.enable": "Activa", "common.button.finish": "Acabar", "common.button.goBack": "Torna", @@ -313,7 +314,6 @@ "common.custom": "Personalitzat", "common.customRange": "Gamma personalitzada", "common.dataOutdated": "Les dades poden estar obsoletes", - "common.dataUnavailable": "Dades no disponibles", "common.default": "Per defecte", "common.defaultTradeOptions": "Opcions comercials per defecte", "common.delegate.cancelled": "Delegat cancel·lat", @@ -461,6 +461,7 @@ "common.networkCost": "Cost de la xarxa", "common.neverMind": "No importa", "common.new": "Nou", + "common.new.exclamation": "Nou!", "common.nfts": "NFT", "common.noActivity": "Encara no hi ha activitat", "common.noAmount.error": "Introduïu una quantitat", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Cerca per país o regió", "fiatOnRamp.region.title": "Seleccioneu la vostra regió", "fiatOnRamp.summary.total": "{{cryptoAmount}} per a {{fiatAmount}}", - "forceUpgrade.action.confirm": "Actualitza l'aplicació", + "forceUpgrade.action.confirm": "Actualitza ara", "forceUpgrade.action.recoveryPhrase": "Visualitza la frase de recuperació", - "forceUpgrade.description": "La versió d'Uniswap Wallet que utilitzeu està obsoleta i li falten actualitzacions crítiques. Si no actualitzeu l'aplicació o no teniu la frase de recuperació anotada, no podreu accedir als vostres actius.", + "forceUpgrade.description": "Hi ha disponible una nova versió de l'aplicació. Per continuar utilitzant Uniswap Wallet, actualitzeu-lo a la darrera versió.", "forceUpgrade.label.recoveryPhrase": "Frase de recuperació", - "forceUpgrade.title": "Actualitza l'aplicació per continuar", + "forceUpgrade.title": "Actualitza a la darrera versió", "globalPreferences.title": "Preferències globals", "hero.scroll": "Desplaceu-vos per obtenir més informació", "hero.subtitle": "El mercat onchain més gran. Compra i ven criptografia a Ethereum i més de 11 cadenes més.", @@ -940,7 +941,6 @@ "home.feed.title": "Alimentació", "home.label.buy": "Compra", "home.label.receive": "Rebre", - "home.label.scan": "Escaneja", "home.label.send": "Enviar", "home.label.swap": "Canviar", "home.nfts.title": "NFT", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Obteniu l'aplicació Uniswap Wallet", "mobileAppPromo.banner.title": "Uniswap: cartera Crypto i NFT", "moonpay.poweredBy": "Fiat onramp impulsat per MoonPay USA LLC", - "moonpay.rampIframe": "MoonPay fiat on-ramp iframe", "moonpay.restricted.region": "Moonpay no està disponible en algunes regions. Feu clic per obtenir més informació.", "nav.createAccount.button": "Crea un compte", "nav.logIn.button": "Inicieu sessió", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Visualitza la frase de recuperació", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 cartera més", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} altres carteres", - "onboarding.import.onDeviceRecovery.warning.caption": "Assegureu-vos d'haver fet una còpia de seguretat de totes les altres carteres. Si mai voleu restaurar-los, necessitareu les seves frases de recuperació o les còpies de seguretat d'iCloud corresponents.", + "onboarding.import.onDeviceRecovery.warning.caption": "Assegureu-vos d'haver fet una còpia de seguretat de totes les altres carteres. Si mai voleu restaurar-los, necessitareu les seves frases de recuperació o les còpies de seguretat {{cloudProvider}} corresponents.", "onboarding.import.onDeviceRecovery.warning.title": "Estàs segur?", "onboarding.import.title": "Trieu com voleu afegir la vostra cartera", "onboarding.importMnemonic.button.default": "La meva frase de recuperació té 12 paraules", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Exploreu Uniswap Analytics.", "pool.hideClosed": "Amaga les posicions tancades", "pool.import": "Grup d'importació", - "pool.import.v2": "Importa el grup V2", + "pool.import.link.description": "Algunes posicions v2 no es mostren automàticament.", + "pool.import.positions.v2": "Importa posicions V2", + "pool.import.positions.v2.selectPair.description": "Algunes posicions v2 no es mostren automàticament. Seleccioneu un parell de fitxes per importar i veure les vostres posicions.", + "pool.import.success": "S'ha importat la piscina", "pool.increaseLiquidity": "Augmentar la liquiditat", "pool.info": "Informació de la piscina", "pool.initialShare": "Preus inicials i quota de piscina", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "volum de 30 dies", "pool.volume.thirtyDay.short": "30D vol", "pool.yourv2": "La teva liquiditat V2", - "poolFinder.connect": "Connecteu-vos a una cartera per trobar piscines.", - "poolFinder.create": "Crear piscina", - "poolFinder.found": "Piscina trobada!", - "poolFinder.managePool": "Gestiona aquesta piscina", - "poolFinder.noLiquidity": "Encara no teniu liquiditat en aquest grup.", - "poolFinder.noPoolFound": "No s'ha trobat cap piscina.", - "poolFinder.selectToken": "Seleccioneu un testimoni per trobar la vostra liquiditat v2.", - "poolFinder.tip": "Consell: utilitzeu aquesta eina per trobar grups v2 que no apareixen automàticament a la interfície.", + "poolFinder.availablePools": "Piscines disponibles", + "poolFinder.availablePools.found.description": "grups v2 que coincideixen amb la vostra selecció de parella.", + "poolFinder.availablePools.notFound.description": "No s'han trobat grups v2 coincidents. Comproveu la vostra selecció de testimoni i assegureu-vos que esteu connectat a la cartera correcta.", "pools.approving.amount": "S'està aprovant {{amount}}", "pools.explore": "Explora les piscines", "position.addHook": "Afegiu un ganxo", @@ -1500,6 +1497,7 @@ "position.step.price": "Estableix el preu inicial", "position.step.range": "Estableix el rang de preus", "position.step.select": "Seleccioneu parell de fitxes i tarifes", + "position.value": "Valor de posició", "position.valueUnavailable": "El valor de la posició no està disponible a causa de la poca liquiditat.", "position.your": "La teva posició", "positions.welcome": "Benvinguts a les vostres posicions", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "La transacció es revertirà si està pendent durant més d'aquest període de temps.", "swap.unsupportedAssets.readMore": "Obteniu més informació sobre els recursos no compatibles", "swap.warning.enterLargerAmount.title": "Introduïu una quantitat més gran", - "swap.warning.expectedFailure": "S'espera que aquesta transacció fracassi", + "swap.warning.expectedFailure.increaseSlippage": "Intenta augmentar el teu lliscament.", + "swap.warning.expectedFailure.titleMay": "Aquest intercanvi pot fallar", "swap.warning.insufficientBalance.title": "No en tens prou {{currencySymbol}}", "swap.warning.insufficientGas.button": "No n'hi ha prou {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Canvia per {{ tokenSymbol }} a {{networkName}}", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Algunes xarxes de prova no admeten l'intercanvi, l'enviament o la compra de fitxes.", "tdp.stats.unsupportedChainDescription": "Les estadístiques i els gràfics de testimonis per a {{chain}} estan disponibles a {{infoLink}}", "tdp.symbolNotFound": "No s'ha trobat el símbol", + "testnet.modal.swapDeepLink.description.toProdMode": "Aquesta acció requereix que el mode testnet estigui desactivat. El mode Testnet es pot tornar a activar en qualsevol moment dins de la configuració.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "Aquesta acció requereix que el mode testnet estigui habilitat. Els testimonis de les xarxes de prova no tenen cap valor real. El mode Testnet es pot desactivar en qualsevol moment dins de la configuració.", + "testnet.modal.swapDeepLink.title.toProdMode": "Desactiva el mode testnet", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Activa el mode testnet", "testnet.unsupported": "Aquesta funcionalitat no és compatible amb el mode Testnet.", "themeToggle.theme": "Tema", "title.betterPricesMoreListings": "Millors preus. Més llistats. Compreu, veneu i comercialitzeu NFT als principals mercats com OpenSea. Exploreu les col·leccions de tendències.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "No s'ha pogut carregar el gràfic de preus", "token.priceExplorer.timeRangeLabel.all": "Tot el temps", "token.priceExplorer.timeRangeLabel.day": "1D", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 dia", "token.priceExplorer.timeRangeLabel.hour": "1H", "token.priceExplorer.timeRangeLabel.month": "1M", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 mes", "token.priceExplorer.timeRangeLabel.week": "1W", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 setmana", "token.priceExplorer.timeRangeLabel.year": "1 any", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 any", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} no està disponible", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} i {{tokenSymbol1}} no estan disponibles", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs no rep cap d'aquestes tarifes.", diff --git a/packages/uniswap/src/i18n/locales/translations/cs-CZ.json b/packages/uniswap/src/i18n/locales/translations/cs-CZ.json index 631b192cdc6..6e6d009c92a 100644 --- a/packages/uniswap/src/i18n/locales/translations/cs-CZ.json +++ b/packages/uniswap/src/i18n/locales/translations/cs-CZ.json @@ -222,6 +222,7 @@ "common.button.disconnect": "Odpojit", "common.button.dismiss": "Zavrhnout", "common.button.done": "Hotovo", + "common.button.edit": "Upravit", "common.button.enable": "Umožnit", "common.button.finish": "Dokončit", "common.button.goBack": "Vraťte se", @@ -313,7 +314,6 @@ "common.custom": "Zvyk", "common.customRange": "Vlastní rozsah", "common.dataOutdated": "Data mohou být zastaralá", - "common.dataUnavailable": "Data nedostupná", "common.default": "Výchozí", "common.defaultTradeOptions": "Výchozí obchodní možnosti", "common.delegate.cancelled": "Delegace zrušena", @@ -461,6 +461,7 @@ "common.networkCost": "Náklady na síť", "common.neverMind": "Nevadí", "common.new": "Nový", + "common.new.exclamation": "Nový!", "common.nfts": "NFT", "common.noActivity": "Zatím žádná aktivita", "common.noAmount.error": "Zadejte částku", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Vyhledávání podle země nebo regionu", "fiatOnRamp.region.title": "Vyberte svůj region", "fiatOnRamp.summary.total": "{{cryptoAmount}} pro {{fiatAmount}}", - "forceUpgrade.action.confirm": "Aktualizovat aplikaci", + "forceUpgrade.action.confirm": "Aktualizujte nyní", "forceUpgrade.action.recoveryPhrase": "Zobrazit frázi pro obnovení", - "forceUpgrade.description": "Verze peněženky Uniswap, kterou používáte, je zastaralá a chybí jí důležité aktualizace. Pokud aplikaci neaktualizujete nebo nemáte zapsanou frázi pro obnovení, nebudete mít přístup ke svým prostředkům.", + "forceUpgrade.description": "K dispozici je nová verze aplikace. Chcete-li nadále používat peněženku Uniswap, aktualizujte ji na nejnovější verzi.", "forceUpgrade.label.recoveryPhrase": "Fráze obnovy", - "forceUpgrade.title": "Chcete-li pokračovat, aktualizujte aplikaci", + "forceUpgrade.title": "Aktualizujte na nejnovější verzi", "globalPreferences.title": "Globální preference", "hero.scroll": "Posuňte se a dozvíte se více", "hero.subtitle": "Největší onchain tržiště. Nakupujte a prodávejte kryptoměny na Ethereu a dalších 11+ řetězcích.", @@ -940,7 +941,6 @@ "home.feed.title": "Krmit", "home.label.buy": "Koupit", "home.label.receive": "Dostávat", - "home.label.scan": "Skenovat", "home.label.send": "Poslat", "home.label.swap": "Vyměňte", "home.nfts.title": "NFT", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Získejte aplikaci Uniswap Wallet", "mobileAppPromo.banner.title": "Uniswap: Crypto & NFT Wallet", "moonpay.poweredBy": "Fiat onramp poháněný společností MoonPay USA LLC", - "moonpay.rampIframe": "MoonPay fiat na rampě iframe", "moonpay.restricted.region": "Moonpay není v některých regionech k dispozici. Kliknutím se dozvíte více.", "nav.createAccount.button": "Vytvořit účet", "nav.logIn.button": "Přihlaste se", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Zobrazit frázi pro obnovení", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 další peněženka", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} další peněženky", - "onboarding.import.onDeviceRecovery.warning.caption": "Ujistěte se, že jste si zazálohovali všechny ostatní peněženky. Pokud je někdy budete chtít obnovit, budete potřebovat jejich obnovovací fráze nebo odpovídající zálohy na iCloudu.", + "onboarding.import.onDeviceRecovery.warning.caption": "Ujistěte se, že jste si zazálohovali všechny ostatní peněženky. Pokud je někdy budete chtít obnovit, budete potřebovat jejich obnovovací fráze nebo odpovídající {{cloudProvider}} zálohy.", "onboarding.import.onDeviceRecovery.warning.title": "Jsi si jistá?", "onboarding.import.title": "Vyberte, jak chcete přidat svou peněženku", "onboarding.importMnemonic.button.default": "Moje obnovovací fráze je 12 slov", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Prozkoumejte Uniswap Analytics.", "pool.hideClosed": "Skryjte uzavřené pozice", "pool.import": "Import bazénu", - "pool.import.v2": "Import bazénu V2", + "pool.import.link.description": "Některé pozice v2 se nezobrazují automaticky.", + "pool.import.positions.v2": "Import pozic V2", + "pool.import.positions.v2.selectPair.description": "Některé pozice v2 se nezobrazují automaticky. Vyberte pár tokenů, který chcete importovat a zobrazit své pozice.", + "pool.import.success": "Bazén importován", "pool.increaseLiquidity": "Zvyšte likviditu", "pool.info": "Informace o bazénu", "pool.initialShare": "Počáteční ceny a podíl v bazénu", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "30denní objem", "pool.volume.thirtyDay.short": "30D sv", "pool.yourv2": "Vaše likvidita V2", - "poolFinder.connect": "Připojte se k peněžence a vyhledejte bazény.", - "poolFinder.create": "Vytvořte bazén", - "poolFinder.found": "Bazén nalezen!", - "poolFinder.managePool": "Spravujte tento bazén", - "poolFinder.noLiquidity": "V tomto fondu ještě nemáte likviditu.", - "poolFinder.noPoolFound": "Nebyl nalezen žádný bazén.", - "poolFinder.selectToken": "Vyberte token a zjistěte svou likviditu v2.", - "poolFinder.tip": "Tip: Pomocí tohoto nástroje můžete najít fondy verze 2, které se automaticky nezobrazují v rozhraní.", + "poolFinder.availablePools": "K dispozici bazény", + "poolFinder.availablePools.found.description": "v2 bazény odpovídající vašemu výběru páru.", + "poolFinder.availablePools.notFound.description": "Nebyly nalezeny žádné odpovídající fondy v2. Znovu zkontrolujte výběr tokenu a ujistěte se, že jste připojeni ke správné peněžence.", "pools.approving.amount": "Schvalování {{amount}}", "pools.explore": "Prozkoumejte bazény", "position.addHook": "Přidejte háček", @@ -1500,6 +1497,7 @@ "position.step.price": "Nastavte počáteční cenu", "position.step.range": "Nastavit cenové rozpětí", "position.step.select": "Vyberte pár tokenů a poplatky", + "position.value": "Hodnota pozice", "position.valueUnavailable": "Hodnota pozice není k dispozici z důvodu nízké likvidity.", "position.your": "Tvoje pozice", "positions.welcome": "Vítejte na svých pozicích", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "Vaše transakce se vrátí zpět, pokud čeká na vyřízení déle než toto časové období.", "swap.unsupportedAssets.readMore": "Přečtěte si další informace o nepodporovaných aktivech", "swap.warning.enterLargerAmount.title": "Zadejte větší částku", - "swap.warning.expectedFailure": "Očekává se, že tato transakce selže", + "swap.warning.expectedFailure.increaseSlippage": "Zkuste zvýšit svůj skluz.", + "swap.warning.expectedFailure.titleMay": "Tato výměna může selhat", "swap.warning.insufficientBalance.title": "Nemáte dost {{currencySymbol}}", "swap.warning.insufficientGas.button": "Nestačí {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Vyměňte za {{ tokenSymbol }} na {{networkName}}", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Některé testovací sítě nepodporují výměnu, odesílání nebo nákup tokenů.", "tdp.stats.unsupportedChainDescription": "Statistiky tokenů a grafy pro {{chain}} jsou k dispozici na {{infoLink}}", "tdp.symbolNotFound": "Symbol nenalezen", + "testnet.modal.swapDeepLink.description.toProdMode": "Tato akce vyžaduje deaktivaci režimu testovací sítě. Režim Testnet lze kdykoli znovu povolit v rámci nastavení.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "Tato akce vyžaduje, aby byl povolen režim testovací sítě. Tokeny na testovacích sítích nemají žádnou skutečnou hodnotu. Režim Testnet lze kdykoli vypnout v rámci nastavení.", + "testnet.modal.swapDeepLink.title.toProdMode": "Zakázat režim testnet", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Povolit režim testovací sítě", "testnet.unsupported": "Tato funkce není podporována v režimu testovací sítě.", "themeToggle.theme": "Téma", "title.betterPricesMoreListings": "Lepší ceny. Další výpisy. Nakupujte, prodávejte a obchodujte s NFT na špičkových tržištích, jako je OpenSea. Prozkoumejte trendy kolekce.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Cenový graf se nepodařilo načíst", "token.priceExplorer.timeRangeLabel.all": "Pořád", "token.priceExplorer.timeRangeLabel.day": "1D", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 den", "token.priceExplorer.timeRangeLabel.hour": "1H", "token.priceExplorer.timeRangeLabel.month": "1 mil", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 měsíc", "token.priceExplorer.timeRangeLabel.week": "1W", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 týden", "token.priceExplorer.timeRangeLabel.year": "1Y", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 rok", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} není k dispozici", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} a {{tokenSymbol1}} nejsou k dispozici", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs neobdrží žádný z těchto poplatků.", diff --git a/packages/uniswap/src/i18n/locales/translations/da-DK.json b/packages/uniswap/src/i18n/locales/translations/da-DK.json index cfaf21072db..94606dbd330 100644 --- a/packages/uniswap/src/i18n/locales/translations/da-DK.json +++ b/packages/uniswap/src/i18n/locales/translations/da-DK.json @@ -222,6 +222,7 @@ "common.button.disconnect": "Koble fra", "common.button.dismiss": "Afskedige", "common.button.done": "Færdig", + "common.button.edit": "Redigere", "common.button.enable": "Aktiver", "common.button.finish": "Slutte", "common.button.goBack": "Gå tilbage", @@ -313,7 +314,6 @@ "common.custom": "Brugerdefinerede", "common.customRange": "Brugerdefineret rækkevidde", "common.dataOutdated": "Data kan være forældede", - "common.dataUnavailable": "Data er ikke tilgængelige", "common.default": "Standard", "common.defaultTradeOptions": "Standard handelsoptioner", "common.delegate.cancelled": "Delegeret aflyst", @@ -461,6 +461,7 @@ "common.networkCost": "Netværksomkostninger", "common.neverMind": "Glem det", "common.new": "Ny", + "common.new.exclamation": "Ny!", "common.nfts": "NFT'er", "common.noActivity": "Ingen aktivitet endnu", "common.noAmount.error": "Indtast et beløb", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Søg efter land eller region", "fiatOnRamp.region.title": "Vælg din region", "fiatOnRamp.summary.total": "{{cryptoAmount}} for {{fiatAmount}}", - "forceUpgrade.action.confirm": "Opdater app", + "forceUpgrade.action.confirm": "Opdater nu", "forceUpgrade.action.recoveryPhrase": "Se gendannelsessætning", - "forceUpgrade.description": "Den version af Uniswap Wallet, du bruger, er forældet og mangler vigtige opgraderinger. Hvis du ikke opdaterer appen, eller du ikke har din gendannelsessætning skrevet ned, vil du ikke kunne få adgang til dine aktiver.", + "forceUpgrade.description": "En ny version af appen er tilgængelig. For at fortsætte med at bruge Uniswap Wallet skal du opdatere den til den nyeste version.", "forceUpgrade.label.recoveryPhrase": "Gendannelsessætning", - "forceUpgrade.title": "Opdater appen for at fortsætte", + "forceUpgrade.title": "Opdater til den nyeste version", "globalPreferences.title": "Globale præferencer", "hero.scroll": "Rul for at lære mere", "hero.subtitle": "Den største onchain-markedsplads. Køb og sælg krypto på Ethereum og 11+ andre kæder.", @@ -940,7 +941,6 @@ "home.feed.title": "Foder", "home.label.buy": "Købe", "home.label.receive": "Modtage", - "home.label.scan": "Scan", "home.label.send": "Sende", "home.label.swap": "Bytte rundt", "home.nfts.title": "NFT'er", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Hent Uniswap Wallet-appen", "mobileAppPromo.banner.title": "Uniswap: Crypto & NFT Wallet", "moonpay.poweredBy": "Fiat onramp drevet af MoonPay USA LLC", - "moonpay.rampIframe": "MoonPay fiat on-ramp iframe", "moonpay.restricted.region": "Moonpay er ikke tilgængelig i nogle regioner. Klik for at lære mere.", "nav.createAccount.button": "Opret konto", "nav.logIn.button": "Log ind", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Se gendannelsessætning", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 anden tegnebog", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} andre tegnebøger", - "onboarding.import.onDeviceRecovery.warning.caption": "Sørg for, at du har sikkerhedskopieret alle de andre tegnebøger. Hvis du nogensinde vil gendanne dem, skal du bruge deres gendannelsessætninger eller tilsvarende iCloud-sikkerhedskopier.", + "onboarding.import.onDeviceRecovery.warning.caption": "Sørg for, at du har sikkerhedskopieret alle de andre tegnebøger. Hvis du nogensinde vil gendanne dem, skal du bruge deres gendannelsessætninger eller tilsvarende {{cloudProvider}} sikkerhedskopier.", "onboarding.import.onDeviceRecovery.warning.title": "Er du sikker?", "onboarding.import.title": "Vælg, hvordan du vil tilføje din tegnebog", "onboarding.importMnemonic.button.default": "Min gendannelsessætning er på 12 ord", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Udforsk Uniswap Analytics.", "pool.hideClosed": "Skjul lukkede positioner", "pool.import": "Import pool", - "pool.import.v2": "Importer V2 pool", + "pool.import.link.description": "Nogle v2-positioner vises ikke automatisk.", + "pool.import.positions.v2": "Importer V2-positioner", + "pool.import.positions.v2.selectPair.description": "Nogle v2-positioner vises ikke automatisk. Vælg et token-par for at importere og se dine positioner.", + "pool.import.success": "Pool importeret", "pool.increaseLiquidity": "Øge likviditeten", "pool.info": "Pool info", "pool.initialShare": "Startpriser og puljeandel", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "30 dages volumen", "pool.volume.thirtyDay.short": "30D vol", "pool.yourv2": "Din V2-likviditet", - "poolFinder.connect": "Opret forbindelse til en pung for at finde pools.", - "poolFinder.create": "Opret pool", - "poolFinder.found": "Pool fundet!", - "poolFinder.managePool": "Administrer denne pool", - "poolFinder.noLiquidity": "Du har ikke likviditet i denne pulje endnu.", - "poolFinder.noPoolFound": "Ingen pool fundet.", - "poolFinder.selectToken": "Vælg et token for at finde din v2-likviditet.", - "poolFinder.tip": "Tip: Brug dette værktøj til at finde v2-puljer, der ikke automatisk vises i grænsefladen.", + "poolFinder.availablePools": "Tilgængelige pools", + "poolFinder.availablePools.found.description": "v2-puljer, der matcher dit parvalg.", + "poolFinder.availablePools.notFound.description": "Ingen matchende v2-puljer fundet. Dobbelttjek dit tokenvalg, og sørg for, at du er tilsluttet den korrekte tegnebog.", "pools.approving.amount": "Godkender {{amount}}", "pools.explore": "Udforsk pools", "position.addHook": "Tilføj en krog", @@ -1500,6 +1497,7 @@ "position.step.price": "Indstil startpris", "position.step.range": "Sæt prisinterval", "position.step.select": "Vælg tokenpar og gebyrer", + "position.value": "Positionsværdi", "position.valueUnavailable": "Positionsværdien er ikke tilgængelig på grund af lav likviditet.", "position.your": "Din position", "positions.welcome": "Velkommen til dine stillinger", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "Din transaktion vil vende tilbage, hvis den er afventende i mere end denne periode.", "swap.unsupportedAssets.readMore": "Læs mere om ikke-understøttede aktiver", "swap.warning.enterLargerAmount.title": "Indtast et større beløb", - "swap.warning.expectedFailure": "Denne transaktion forventes at mislykkes", + "swap.warning.expectedFailure.increaseSlippage": "Prøv at øge din glidning.", + "swap.warning.expectedFailure.titleMay": "Dette bytte kan mislykkes", "swap.warning.insufficientBalance.title": "Du har ikke nok {{currencySymbol}}", "swap.warning.insufficientGas.button": "Ikke nok {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Byt til {{ tokenSymbol }} på {{networkName}}", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Nogle testnet understøtter ikke bytte, afsendelse eller køb af tokens.", "tdp.stats.unsupportedChainDescription": "Tokenstatistik og diagrammer for {{chain}} er tilgængelige på {{infoLink}}", "tdp.symbolNotFound": "Symbol ikke fundet", + "testnet.modal.swapDeepLink.description.toProdMode": "Denne handling kræver, at testnet-tilstand er deaktiveret. Testnet-tilstand kan genaktiveres når som helst i indstillingerne.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "Denne handling kræver, at testnet-tilstand er aktiveret. Tokens på testnet har ikke nogen reel værdi. Testnet-tilstand kan til enhver tid deaktiveres i indstillingerne.", + "testnet.modal.swapDeepLink.title.toProdMode": "Deaktiver testnet-tilstand", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Aktiver testnet-tilstand", "testnet.unsupported": "Denne funktionalitet understøttes ikke i testnet-tilstand.", "themeToggle.theme": "Tema", "title.betterPricesMoreListings": "Bedre priser. Flere opslag. Køb, sælg og byt NFT'er på tværs af topmarkedspladser som OpenSea. Udforsk populære samlinger.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Prisdiagrammet kunne ikke indlæses", "token.priceExplorer.timeRangeLabel.all": "Hele tiden", "token.priceExplorer.timeRangeLabel.day": "1D", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 dag", "token.priceExplorer.timeRangeLabel.hour": "1H", "token.priceExplorer.timeRangeLabel.month": "1M", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 måned", "token.priceExplorer.timeRangeLabel.week": "1W", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 uge", "token.priceExplorer.timeRangeLabel.year": "1Y", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 år", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} er ikke tilgængelig", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} og {{tokenSymbol1}} er ikke tilgængelige", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs modtager ikke nogen af disse gebyrer.", diff --git a/packages/uniswap/src/i18n/locales/translations/de-DE.json b/packages/uniswap/src/i18n/locales/translations/de-DE.json index 0a9b745a0c2..5016acaaeb5 100644 --- a/packages/uniswap/src/i18n/locales/translations/de-DE.json +++ b/packages/uniswap/src/i18n/locales/translations/de-DE.json @@ -222,6 +222,7 @@ "common.button.disconnect": "Trennen", "common.button.dismiss": "Zurückweisen", "common.button.done": "Erledigt", + "common.button.edit": "Bearbeiten", "common.button.enable": "Aktivieren", "common.button.finish": "Beenden", "common.button.goBack": "Geh zurück", @@ -313,7 +314,6 @@ "common.custom": "Brauch", "common.customRange": "Benutzerdefiniertes Sortiment", "common.dataOutdated": "Daten können veraltet sein", - "common.dataUnavailable": "Daten nicht verfügbar", "common.default": "Standard", "common.defaultTradeOptions": "Standard-Handelsoptionen", "common.delegate.cancelled": "Delegierter abgesagt", @@ -461,6 +461,7 @@ "common.networkCost": "Netzwerkkosten", "common.neverMind": "Egal", "common.new": "Neu", + "common.new.exclamation": "Neu!", "common.nfts": "NFTs", "common.noActivity": "Noch keine Aktivität", "common.noAmount.error": "Geben Sie einen Betrag ein", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Suche nach Land oder Region", "fiatOnRamp.region.title": "Wählen Sie Ihre Region", "fiatOnRamp.summary.total": "{{cryptoAmount}} für {{fiatAmount}}", - "forceUpgrade.action.confirm": "App aktualisieren", + "forceUpgrade.action.confirm": "Jetzt aktualisieren", "forceUpgrade.action.recoveryPhrase": "Wiederherstellungsphrase anzeigen", - "forceUpgrade.description": "Die von Ihnen verwendete Version von Uniswap Wallet ist veraltet und es fehlen wichtige Upgrades. Wenn Sie die App nicht aktualisieren oder Ihre Wiederherstellungsphrase nicht aufgeschrieben haben, können Sie nicht auf Ihre Assets zugreifen.", + "forceUpgrade.description": "Eine neue Version der App ist verfügbar. Um das Uniswap Wallet weiterhin nutzen zu können, aktualisieren Sie es bitte auf die neueste Version.", "forceUpgrade.label.recoveryPhrase": "Wiederherstellungsphrase", - "forceUpgrade.title": "Aktualisieren Sie die App, um fortzufahren", + "forceUpgrade.title": "Update auf die neueste Version", "globalPreferences.title": "Globale Einstellungen", "hero.scroll": "Scrollen Sie, um mehr zu erfahren", "hero.subtitle": "Der größte Onchain-Marktplatz. Kaufen und verkaufen Sie Kryptowährungen auf Ethereum und über 11 anderen Chains.", @@ -940,7 +941,6 @@ "home.feed.title": "Füttern", "home.label.buy": "Kaufen", "home.label.receive": "Erhalten", - "home.label.scan": "Scan", "home.label.send": "Schicken", "home.label.swap": "Tauschen", "home.nfts.title": "NFTs", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Holen Sie sich die Uniswap Wallet-App", "mobileAppPromo.banner.title": "Uniswap: Krypto- und NFT-Wallet", "moonpay.poweredBy": "Fiat-Onramp betrieben durch MoonPay USA LLC", - "moonpay.rampIframe": "MoonPay Fiat-On-Ramp-Iframe", "moonpay.restricted.region": "Moonpay ist in einigen Regionen nicht verfügbar. Klicken Sie hier, um mehr zu erfahren.", "nav.createAccount.button": "Benutzerkonto erstellen", "nav.logIn.button": "Einloggen", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Wiederherstellungsphrase anzeigen", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 andere Geldbörse", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} andere Geldbörsen", - "onboarding.import.onDeviceRecovery.warning.caption": "Bitte stellen Sie sicher, dass Sie alle anderen Wallets gesichert haben. Wenn Sie sie jemals wiederherstellen möchten, benötigen Sie ihre Wiederherstellungsphrasen oder entsprechenden iCloud-Backups.", + "onboarding.import.onDeviceRecovery.warning.caption": "Bitte stellen Sie sicher, dass Sie alle anderen Wallets gesichert haben. Wenn Sie sie jemals wiederherstellen möchten, benötigen Sie ihre Wiederherstellungsphrasen oder entsprechende {{cloudProvider}} -Backups.", "onboarding.import.onDeviceRecovery.warning.title": "Bist du sicher?", "onboarding.import.title": "Wählen Sie, wie Sie Ihr Wallet hinzufügen möchten", "onboarding.importMnemonic.button.default": "Meine Wiederherstellungsphrase besteht aus 12 Wörtern", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Entdecken Sie Uniswap Analytics.", "pool.hideClosed": "Geschlossene Positionen ausblenden", "pool.import": "Pool importieren", - "pool.import.v2": "V2-Pool importieren", + "pool.import.link.description": "Einige v2-Positionen werden nicht automatisch angezeigt.", + "pool.import.positions.v2": "V2-Positionen importieren", + "pool.import.positions.v2.selectPair.description": "Einige v2-Positionen werden nicht automatisch angezeigt. Wählen Sie ein Token-Paar zum Importieren und Anzeigen Ihrer Positionen aus.", + "pool.import.success": "Pool importiert", "pool.increaseLiquidity": "Liquidität erhöhen", "pool.info": "Informationen zum Pool", "pool.initialShare": "Anfangspreise und Poolanteil", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "30 Tage Volumen", "pool.volume.thirtyDay.short": "30D Volumen", "pool.yourv2": "Ihre V2-Liquidität", - "poolFinder.connect": "Stellen Sie eine Verbindung zu einem Wallet her, um Pools zu finden.", - "poolFinder.create": "Pool erstellen", - "poolFinder.found": "Pool gefunden!", - "poolFinder.managePool": "Diesen Pool verwalten", - "poolFinder.noLiquidity": "Sie haben noch keine Liquidität in diesem Pool.", - "poolFinder.noPoolFound": "Kein Pool gefunden.", - "poolFinder.selectToken": "Wählen Sie ein Token aus, um Ihre v2-Liquidität zu finden.", - "poolFinder.tip": "Tipp: Verwenden Sie dieses Tool, um v2-Pools zu finden, die nicht automatisch in der Benutzeroberfläche angezeigt werden.", + "poolFinder.availablePools": "Verfügbare Pools", + "poolFinder.availablePools.found.description": "v2-Pools, die zu Ihrer Paarauswahl passen.", + "poolFinder.availablePools.notFound.description": "Keine passenden v2-Pools gefunden. Überprüfen Sie Ihre Token-Auswahl noch einmal und stellen Sie sicher, dass Sie mit der richtigen Wallet verbunden sind.", "pools.approving.amount": "Genehmigen {{amount}}", "pools.explore": "Pools erkunden", "position.addHook": "Einen Haken hinzufügen", @@ -1500,6 +1497,7 @@ "position.step.price": "Anfangspreis festlegen", "position.step.range": "Preisspanne festlegen", "position.step.select": "Token-Paar und Gebühren auswählen", + "position.value": "Positionswert", "position.valueUnavailable": "Aufgrund geringer Liquidität ist der Positionswert nicht verfügbar.", "position.your": "Dein Standpunkt", "positions.welcome": "Willkommen in Ihren Positionen", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "Ihre Transaktion wird rückgängig gemacht, wenn sie länger als diesen Zeitraum aussteht.", "swap.unsupportedAssets.readMore": "Mehr zu nicht unterstützten Assets", "swap.warning.enterLargerAmount.title": "Geben Sie einen größeren Betrag ein", - "swap.warning.expectedFailure": "Diese Transaktion wird voraussichtlich fehlschlagen", + "swap.warning.expectedFailure.increaseSlippage": "Versuchen Sie, Ihren Schlupf zu erhöhen.", + "swap.warning.expectedFailure.titleMay": "Dieser Austausch kann fehlschlagen", "swap.warning.insufficientBalance.title": "Du hast nicht genug {{currencySymbol}}", "swap.warning.insufficientGas.button": "Nicht genug {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Tausche {{ tokenSymbol }} gegen {{networkName}}aus", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Einige Testnetze unterstützen das Tauschen, Senden oder Kaufen von Token nicht.", "tdp.stats.unsupportedChainDescription": "Token-Statistiken und Diagramme für {{chain}} sind verfügbar auf {{infoLink}}", "tdp.symbolNotFound": "Symbol nicht gefunden", + "testnet.modal.swapDeepLink.description.toProdMode": "Für diese Aktion muss der Testnet-Modus deaktiviert sein. Der Testnet-Modus kann jederzeit in den Einstellungen wieder aktiviert werden.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "Für diese Aktion muss der Testnet-Modus aktiviert sein. Token in Testnetzen haben keinen realen Wert. Der Testnet-Modus kann jederzeit in den Einstellungen deaktiviert werden.", + "testnet.modal.swapDeepLink.title.toProdMode": "Testnet-Modus deaktivieren", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Testnet-Modus aktivieren", "testnet.unsupported": "Diese Funktionalität wird im Testnet-Modus nicht unterstützt.", "themeToggle.theme": "Thema", "title.betterPricesMoreListings": "Bessere Preise. Mehr Angebote. Kaufen, verkaufen und handeln Sie NFTs auf Top-Marktplätzen wie OpenSea. Entdecken Sie trendige Sammlungen.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Preisdiagramm konnte nicht geladen werden", "token.priceExplorer.timeRangeLabel.all": "Alle Zeit", "token.priceExplorer.timeRangeLabel.day": "1D", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 Tag", "token.priceExplorer.timeRangeLabel.hour": "1 Stunde", "token.priceExplorer.timeRangeLabel.month": "1 Mio.", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 Monat", "token.priceExplorer.timeRangeLabel.week": "1W", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 Woche", "token.priceExplorer.timeRangeLabel.year": "1 Jahr", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 Jahr", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} ist nicht verfügbar", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} und {{tokenSymbol1}} sind nicht verfügbar", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs erhält keine dieser Gebühren.", diff --git a/packages/uniswap/src/i18n/locales/translations/el-GR.json b/packages/uniswap/src/i18n/locales/translations/el-GR.json index dbc634eda20..159e382d8ac 100644 --- a/packages/uniswap/src/i18n/locales/translations/el-GR.json +++ b/packages/uniswap/src/i18n/locales/translations/el-GR.json @@ -222,6 +222,7 @@ "common.button.disconnect": "Αποσυνδέω", "common.button.dismiss": "Απολύω", "common.button.done": "Εγινε", + "common.button.edit": "Επεξεργασία", "common.button.enable": "επιτρέπω", "common.button.finish": "Φινίρισμα", "common.button.goBack": "Πήγαινε πίσω", @@ -313,7 +314,6 @@ "common.custom": "Εθιμο", "common.customRange": "Προσαρμοσμένο εύρος", "common.dataOutdated": "Τα δεδομένα μπορεί να είναι παλιά", - "common.dataUnavailable": "Τα δεδομένα δεν είναι διαθέσιμα", "common.default": "Προκαθορισμένο", "common.defaultTradeOptions": "Προεπιλεγμένες επιλογές συναλλαγών", "common.delegate.cancelled": "Ο εκπρόσωπος ακυρώθηκε", @@ -461,6 +461,7 @@ "common.networkCost": "Κόστος δικτύου", "common.neverMind": "Δεν πειράζει", "common.new": "Νέος", + "common.new.exclamation": "Νέος!", "common.nfts": "NFTs", "common.noActivity": "Καμία δραστηριότητα ακόμα", "common.noAmount.error": "Εισαγάγετε ένα ποσό", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Αναζήτηση ανά χώρα ή περιοχή", "fiatOnRamp.region.title": "Επιλέξτε την περιοχή σας", "fiatOnRamp.summary.total": "{{cryptoAmount}} για {{fiatAmount}}", - "forceUpgrade.action.confirm": "Ενημέρωση εφαρμογής", + "forceUpgrade.action.confirm": "Ενημέρωση τώρα", "forceUpgrade.action.recoveryPhrase": "Προβολή φράσης ανάκτησης", - "forceUpgrade.description": "Η έκδοση του Πορτοφολιού Uniswap που χρησιμοποιείτε δεν είναι ενημερωμένη και δεν έχει σημαντικές αναβαθμίσεις. Εάν δεν ενημερώσετε την εφαρμογή ή δεν έχετε γραμμένη τη φράση ανάκτησης, δεν θα έχετε πρόσβαση στα στοιχεία σας.", + "forceUpgrade.description": "Μια νέα έκδοση της εφαρμογής είναι διαθέσιμη. Για να συνεχίσετε να χρησιμοποιείτε το Πορτοφόλι Uniswap, ενημερώστε το στην πιο πρόσφατη έκδοση.", "forceUpgrade.label.recoveryPhrase": "Φράση ανάκτησης", - "forceUpgrade.title": "Ενημερώστε την εφαρμογή για να συνεχίσετε", + "forceUpgrade.title": "Ενημέρωση στην πιο πρόσφατη έκδοση", "globalPreferences.title": "Παγκόσμιες προτιμήσεις", "hero.scroll": "Κάντε κύλιση για να μάθετε περισσότερα", "hero.subtitle": "Η μεγαλύτερη αγορά onchain. Αγορά και πώληση κρυπτογράφησης στο Ethereum και σε 11+ άλλες αλυσίδες.", @@ -940,7 +941,6 @@ "home.feed.title": "Ταίζω", "home.label.buy": "Αγορά", "home.label.receive": "Λαμβάνω", - "home.label.scan": "Σάρωση", "home.label.send": "Στείλετε", "home.label.swap": "Ανταλαγή", "home.nfts.title": "NFTs", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Αποκτήστε την εφαρμογή Uniswap Wallet", "mobileAppPromo.banner.title": "Unswap: Πορτοφόλι Crypto & NFT", "moonpay.poweredBy": "Fiat onramp powered by MoonPay USA LLC", - "moonpay.rampIframe": "MoonPay fiat on-ramp iframe", "moonpay.restricted.region": "Το Moonpay δεν είναι διαθέσιμο σε ορισμένες περιοχές. Κάντε κλικ για να μάθετε περισσότερα.", "nav.createAccount.button": "Δημιουργία λογαριασμού", "nav.logIn.button": "Συνδεθείτε", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Προβολή φράσης ανάκτησης", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 άλλο πορτοφόλι", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} άλλα πορτοφόλια", - "onboarding.import.onDeviceRecovery.warning.caption": "Βεβαιωθείτε ότι έχετε δημιουργήσει αντίγραφα ασφαλείας όλων των άλλων πορτοφολιών. Εάν θέλετε ποτέ να τα επαναφέρετε, θα χρειαστείτε τις φράσεις ανάκτησης ή τα αντίστοιχα αντίγραφα ασφαλείας iCloud.", + "onboarding.import.onDeviceRecovery.warning.caption": "Βεβαιωθείτε ότι έχετε δημιουργήσει αντίγραφα ασφαλείας όλων των άλλων πορτοφολιών. Εάν θέλετε να τα επαναφέρετε ποτέ, θα χρειαστείτε τις φράσεις ανάκτησης ή τα αντίστοιχα {{cloudProvider}} αντίγραφα ασφαλείας.", "onboarding.import.onDeviceRecovery.warning.title": "Είσαι σίγουρος;", "onboarding.import.title": "Επιλέξτε πώς θέλετε να προσθέσετε το πορτοφόλι σας", "onboarding.importMnemonic.button.default": "Η φράση αποθεραπείας μου είναι 12 λέξεις", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Εξερευνήστε το Uniswap Analytics.", "pool.hideClosed": "Απόκρυψη κλειστών θέσεων", "pool.import": "Πισίνα εισαγωγής", - "pool.import.v2": "Εισαγωγή πισίνας V2", + "pool.import.link.description": "Ορισμένες θέσεις v2 δεν εμφανίζονται αυτόματα.", + "pool.import.positions.v2": "Εισαγωγή θέσεων V2", + "pool.import.positions.v2.selectPair.description": "Ορισμένες θέσεις v2 δεν εμφανίζονται αυτόματα. Επιλέξτε ένα ζεύγος διακριτικών για εισαγωγή και προβολή των θέσεων σας.", + "pool.import.success": "Εισαγωγή πισίνας", "pool.increaseLiquidity": "Αύξηση ρευστότητας", "pool.info": "Πληροφορίες για την πισίνα", "pool.initialShare": "Αρχικές τιμές και μερίδιο της ομάδας", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "Τόμος 30 ημερών", "pool.volume.thirtyDay.short": "30D τόμ", "pool.yourv2": "Η ρευστότητά σας V2", - "poolFinder.connect": "Συνδεθείτε σε ένα πορτοφόλι για να βρείτε πισίνες.", - "poolFinder.create": "Δημιουργία πισίνας", - "poolFinder.found": "Βρέθηκε πισίνα!", - "poolFinder.managePool": "Διαχειριστείτε αυτήν την πισίνα", - "poolFinder.noLiquidity": "Δεν έχετε ρευστότητα σε αυτό το pool ακόμα.", - "poolFinder.noPoolFound": "Δεν βρέθηκε πισίνα.", - "poolFinder.selectToken": "Επιλέξτε ένα διακριτικό για να βρείτε τη ρευστότητά σας v2.", - "poolFinder.tip": "Συμβουλή: Χρησιμοποιήστε αυτό το εργαλείο για να βρείτε ομάδες v2 που δεν εμφανίζονται αυτόματα στη διεπαφή.", + "poolFinder.availablePools": "Διαθέσιμες πισίνες", + "poolFinder.availablePools.found.description": "v2 πισίνες που ταιριάζουν με την επιλογή του ζευγαριού σας.", + "poolFinder.availablePools.notFound.description": "Δεν βρέθηκαν αντίστοιχες ομάδες v2. Ελέγξτε ξανά την επιλογή του διακριτικού σας και βεβαιωθείτε ότι είστε συνδεδεμένοι στο σωστό πορτοφόλι.", "pools.approving.amount": "Έγκριση {{amount}}", "pools.explore": "Εξερευνήστε πισίνες", "position.addHook": "Προσθέστε ένα άγκιστρο", @@ -1500,6 +1497,7 @@ "position.step.price": "Ορισμός αρχικής τιμής", "position.step.range": "Ορίστε το εύρος τιμών", "position.step.select": "Επιλέξτε ζεύγος διακριτικών και χρεώσεις", + "position.value": "Τιμή θέσης", "position.valueUnavailable": "Η αξία θέσης δεν είναι διαθέσιμη λόγω χαμηλής ρευστότητας.", "position.your": "Η θέση σου", "positions.welcome": "Καλώς ήρθατε στις θέσεις σας", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "Η συναλλαγή σας θα επανέλθει εάν είναι σε εκκρεμότητα για περισσότερο από αυτό το χρονικό διάστημα.", "swap.unsupportedAssets.readMore": "Διαβάστε περισσότερα σχετικά με τα μη υποστηριζόμενα στοιχεία", "swap.warning.enterLargerAmount.title": "Εισαγάγετε μεγαλύτερο ποσό", - "swap.warning.expectedFailure": "Αυτή η συναλλαγή αναμένεται να αποτύχει", + "swap.warning.expectedFailure.increaseSlippage": "Προσπαθήστε να αυξήσετε την ολίσθησή σας.", + "swap.warning.expectedFailure.titleMay": "Αυτή η ανταλλαγή μπορεί να αποτύχει", "swap.warning.insufficientBalance.title": "Δεν σου φτάνουν {{currencySymbol}}", "swap.warning.insufficientGas.button": "Δεν αρκεί {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Ανταλλάξτε για {{ tokenSymbol }} στο {{networkName}}", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Ορισμένα δοκιμαστικά δίκτυα δεν υποστηρίζουν την ανταλλαγή, την αποστολή ή την αγορά κουπονιών.", "tdp.stats.unsupportedChainDescription": "Τα στατιστικά στοιχεία και τα γραφήματα για {{chain}} είναι διαθέσιμα στο {{infoLink}}", "tdp.symbolNotFound": "Το σύμβολο δεν βρέθηκε", + "testnet.modal.swapDeepLink.description.toProdMode": "Αυτή η ενέργεια απαιτεί την απενεργοποίηση της λειτουργίας δοκιμαστικού δικτύου. Η λειτουργία Testnet μπορεί να ενεργοποιηθεί ξανά ανά πάσα στιγμή εντός των ρυθμίσεων.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "Αυτή η ενέργεια απαιτεί την ενεργοποίηση της λειτουργίας δοκιμαστικού δικτύου. Τα διακριτικά στα δοκιμαστικά δίκτυα δεν έχουν καμία πραγματική αξία. Η λειτουργία Testnet μπορεί να απενεργοποιηθεί ανά πάσα στιγμή εντός των ρυθμίσεων.", + "testnet.modal.swapDeepLink.title.toProdMode": "Απενεργοποιήστε τη λειτουργία δοκιμαστικού δικτύου", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Ενεργοποίηση λειτουργίας δοκιμαστικού δικτύου", "testnet.unsupported": "Αυτή η λειτουργία δεν υποστηρίζεται σε λειτουργία δοκιμαστικού δικτύου.", "themeToggle.theme": "Θέμα", "title.betterPricesMoreListings": "Καλύτερες τιμές. Περισσότερες καταχωρίσεις. Αγοράστε, πουλήστε και ανταλλάξτε NFT σε κορυφαίες αγορές όπως το OpenSea. Εξερευνήστε τις τάσεις συλλογές.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Δεν ήταν δυνατή η φόρτωση του γραφήματος τιμών", "token.priceExplorer.timeRangeLabel.all": "Συνεχώς", "token.priceExplorer.timeRangeLabel.day": "1Δ", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 Ημέρα", "token.priceExplorer.timeRangeLabel.hour": "1Η", "token.priceExplorer.timeRangeLabel.month": "1 Μ", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 Μήνας", "token.priceExplorer.timeRangeLabel.week": "1W", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 Εβδομάδα", "token.priceExplorer.timeRangeLabel.year": "1Y", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 Έτος", "token.safety.blocked.title.tokenNotAvailable": "Το {{tokenSymbol}} δεν είναι διαθέσιμο", "token.safety.blocked.title.tokensNotAvailable": "Τα {{tokenSymbol0}} και {{tokenSymbol1}} δεν είναι διαθέσιμα", "token.safety.fees.uniswapLabsDoesNotReceive": "Η Uniswap Labs δεν λαμβάνει καμία από αυτές τις χρεώσεις.", diff --git a/packages/uniswap/src/i18n/locales/translations/es-ES.json b/packages/uniswap/src/i18n/locales/translations/es-ES.json index 32da2511bf6..2f6ecef011c 100644 --- a/packages/uniswap/src/i18n/locales/translations/es-ES.json +++ b/packages/uniswap/src/i18n/locales/translations/es-ES.json @@ -132,15 +132,15 @@ "addressInput.recipient": "Destinatario", "analytics.allow": "Permitir análisis", "analytics.allow.message": "Utilizamos datos anonimizados para mejorar tu experiencia con los productos de Uniswap Labs.", - "appRating.button.notReally": "Not really", - "appRating.description": "Let us know if you’re having a good experience with this app", - "appRating.extension.review.description": "Pick a star rating and leave a review on the Chrome Web Store.", - "appRating.extension.review.title": "Review Uniswap Extension?", - "appRating.extension.title": "Enjoying Uniswap Extension?", - "appRating.feedback.button.send": "Send feedback", - "appRating.feedback.description": "Let us know how we can improve your experience", - "appRating.feedback.title": "We’re sorry to hear that.", - "appRating.mobile.title": "Enjoying Uniswap Wallet?", + "appRating.button.notReally": "No realmente", + "appRating.description": "Cuentanos si tienes una buena experiencia con esta app", + "appRating.extension.review.description": "Elige una calificación por estrellas y deja una reseña en la Chrome Web Store.", + "appRating.extension.review.title": "¿Quieres dejar una reseña sobre la extensión de Uniswap?", + "appRating.extension.title": "¿Estás disfrutando de la extensión de Uniswap?", + "appRating.feedback.button.send": "Enviar comentarios", + "appRating.feedback.description": "Cuentanos cómo podemos mejorar tu experiencia", + "appRating.feedback.title": "Lo sentimos mucho.", + "appRating.mobile.title": "¿Estás disfrutando de Uniswap Wallet?", "bridging.estimatedTime.minutesAndSeconds": "~{{minutes}} min {{seconds}} s", "bridging.estimatedTime.minutesOnly": "~{{minutes}} min", "bridging.estimatedTime.secondsOnly": "~{{seconds}} s", @@ -222,6 +222,7 @@ "common.button.disconnect": "Desconectar", "common.button.dismiss": "Rechazar", "common.button.done": "Listo", + "common.button.edit": "Editar", "common.button.enable": "Activar", "common.button.finish": "Finalizar", "common.button.goBack": "Volver", @@ -313,7 +314,6 @@ "common.custom": "Personalizar", "common.customRange": "Rango personalizado", "common.dataOutdated": "Es posible que los datos estén desactualizados", - "common.dataUnavailable": "Datos no disponibles", "common.default": "Predeterminado", "common.defaultTradeOptions": "Opciones predeterminadas de intercambio", "common.delegate.cancelled": "Se canceló la delegación", @@ -461,6 +461,7 @@ "common.networkCost": "Costo de la red", "common.neverMind": "Olvídalo", "common.new": "Nuevo", + "common.new.exclamation": "New!", "common.nfts": "NFT", "common.noActivity": "Aún no hay actividad", "common.noAmount.error": "Ingresa un monto", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Buscar por país o región", "fiatOnRamp.region.title": "Selecciona tu región", "fiatOnRamp.summary.total": "{{cryptoAmount}} por {{fiatAmount}}", - "forceUpgrade.action.confirm": "Actualizar app", + "forceUpgrade.action.confirm": "Update now", "forceUpgrade.action.recoveryPhrase": "Ver frase de recuperación", - "forceUpgrade.description": "La versión de Uniswap Wallet que estás utilizando está obsoleta y le faltan actualizaciones fundamentales. Si no actualizas la app o no tienes escrita la frase de recuperación, no podrás acceder a los activos.", + "forceUpgrade.description": "A new version of the app is available. To continue using the Uniswap Wallet, please update it to the latest version.", "forceUpgrade.label.recoveryPhrase": "Frase de recuperación", - "forceUpgrade.title": "Actualiza la app para continuar", + "forceUpgrade.title": "Update to the latest version", "globalPreferences.title": "Preferencias globales", "hero.scroll": "Desplázate para obtener más información", "hero.subtitle": "El marketplace más grande en la cadena. Compra y vende criptomonedas en Ethereum y más de 11 otras cadenas.", @@ -940,7 +941,6 @@ "home.feed.title": "Fuente", "home.label.buy": "Comprar", "home.label.receive": "Recibir", - "home.label.scan": "Escanear", "home.label.send": "Enviar", "home.label.swap": "Intercambiar", "home.nfts.title": "NFT", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Obtén la app de Uniswap Wallet", "mobileAppPromo.banner.title": "Uniswap: billetera de criptomonedas y NFT", "moonpay.poweredBy": "Rampa de acceso fiduciaria desarrollada por MoonPay USA, LLC", - "moonpay.rampIframe": "iframe de rampa de acceso fiduciaria de MoonPay", "moonpay.restricted.region": "MoonPay no está disponible en algunas regiones. Haz clic para obtener más información.", "nav.createAccount.button": "Crear cuenta", "nav.logIn.button": "Iniciar sesión", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Ver frase de recuperación", "onboarding.import.onDeviceRecovery.wallet.count_one": "1 billetera más", "onboarding.import.onDeviceRecovery.wallet.count_other": "Más de {{count}} otras billeteras", - "onboarding.import.onDeviceRecovery.warning.caption": "Asegúrate de haber realizado la copia de seguridad de todas las otras billeteras. Si alguna vez quieres restaurarlas, necesitarás las frases de recuperación o las copias de seguridad de iCloud correspondientes.", + "onboarding.import.onDeviceRecovery.warning.caption": "Asegúrate de haber realizado la copia de seguridad de todas las otras billeteras. Si alguna vez quieres restaurarlas, necesitarás las frases de recuperación o las copias de seguridad de {{cloudProvider}} correspondientes.", "onboarding.import.onDeviceRecovery.warning.title": "¿Estás seguro?", "onboarding.import.title": "Elige cómo deseas agregar la billetera", "onboarding.importMnemonic.button.default": "Mi frase de recuperación tiene 12 palabras", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Explorar los análisis en Uniswap.", "pool.hideClosed": "Ocultar posiciones cerradas", "pool.import": "Importar fondo", - "pool.import.v2": "Importar fondo V2", + "pool.import.link.description": "Some v2 positions aren’t displayed automatically.", + "pool.import.positions.v2": "Import V2 positions", + "pool.import.positions.v2.selectPair.description": "Some v2 positions aren’t displayed automatically. Select a token pair to import and view your positions.", + "pool.import.success": "Pool imported", "pool.increaseLiquidity": "Aumentar liquidez", "pool.info": "Información del fondo", "pool.initialShare": "Precios iniciales y participación del fondo", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "Volumen de 30 días", "pool.volume.thirtyDay.short": "Vol. de 30 d", "pool.yourv2": "Tu liquidez V2", - "poolFinder.connect": "Conéctate a una billetera para encontrar fondos.", - "poolFinder.create": "Crear fondo", - "poolFinder.found": "¡Se encontró un fondo!", - "poolFinder.managePool": "Administrar fondo", - "poolFinder.noLiquidity": "Aún no tienes liquidez en este fondo.", - "poolFinder.noPoolFound": "No se encontró ningún fondo.", - "poolFinder.selectToken": "Selecciona un token para encontrar tu liquidez v2.", - "poolFinder.tip": "Sugerencia: Usa esta herramienta para buscar fondos v2 que no aparezcan automáticamente en la interfaz.", + "poolFinder.availablePools": "Available pools", + "poolFinder.availablePools.found.description": "v2 pools matching your pair selection.", + "poolFinder.availablePools.notFound.description": "No matching v2 pools found. Double-check your token selection and ensure you’re connected to the correct wallet.", "pools.approving.amount": "Aprobando {{amount}}", "pools.explore": "Explorar los fondos", "position.addHook": "Agregar un hook", @@ -1500,6 +1497,7 @@ "position.step.price": "Establece el precio inicial", "position.step.range": "Establecer rango de precios", "position.step.select": "Selecciona un par de tokens y las comisiones", + "position.value": "Position value", "position.valueUnavailable": "El valor de posición no está disponible por una liquidez baja.", "position.your": "Tu posición", "positions.welcome": "Te damos la bienvenida a tus posiciones", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "La transacción se revertirá si está pendiente por más tiempo que el indicado.", "swap.unsupportedAssets.readMore": "Leer más sobre los activos no compatibles", "swap.warning.enterLargerAmount.title": "Ingresa una cantidad mayor", - "swap.warning.expectedFailure": "Se prevé que esta transacción fallará", + "swap.warning.expectedFailure.increaseSlippage": "Intenta aumentar tu deslizamiento.", + "swap.warning.expectedFailure.titleMay": "This swap may fail", "swap.warning.insufficientBalance.title": "No tienes suficientes {{currencySymbol}}", "swap.warning.insufficientGas.button": "No hay suficientes {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Intercambiar por {{ tokenSymbol }} en {{networkName}}", @@ -1917,7 +1916,7 @@ "swap.warning.rateLimit.title": "Se excedió el límite de tasas", "swap.warning.router.message": "Es posible que hayas perdido la conexión o que la red esté caída. Si el problema persiste, inténtalo de nuevo más tarde.", "swap.warning.router.title": "Esta operación no se puede completar en este momento", - "swap.warning.tokenBlocked.button": "{{tokenSymbol}} is blocked", + "swap.warning.tokenBlocked.button": "{{tokenSymbol}} está bloqueado", "swap.warning.uniswapFee.message.default": "Se aplican comisiones para garantizar la mejor experiencia con Uniswap. No hay ninguna comisión asociada a este intercambio.", "swap.warning.uniswapFee.message.included": "Se aplican comisiones, que ya están incluidas en esta cotización, para garantizar la mejor experiencia con Uniswap.", "swap.warning.uniswapFee.title": "Comisión de intercambio", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Algunas redes de prueba no son compatibles con el intercambio, el envío o la compra de tokens.", "tdp.stats.unsupportedChainDescription": "Las estadísticas y los gráficos del token para {{chain}} están disponibles en {{infoLink}}", "tdp.symbolNotFound": "No se encontró el símbolo", + "testnet.modal.swapDeepLink.description.toProdMode": "Esta acción requiere que se deshabilite el modo de red de prueba. Este modo se puede volver a habilitar en cualquier momento desde la configuración.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "Esta acción requiere que se habilite el modo de red de prueba. Los tokens en las redes de prueba no tienen ningún valor real. Este modo de red de prueba se puede deshabilitar en cualquier momento desde la configuración.", + "testnet.modal.swapDeepLink.title.toProdMode": "Deshabilitar el modo de red de prueba", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Habilitar el modo de red de prueba", "testnet.unsupported": "Esta funcionalidad no es compatible con el modo de red de prueba.", "themeToggle.theme": "Tema", "title.betterPricesMoreListings": "Mejores precios. Más listados. Compra, vende e intercambia NFT en los principales marketplaces, como OpenSea. Explora colecciones populares.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "No se pudo cargar el gráfico de precios", "token.priceExplorer.timeRangeLabel.all": "Histórico", "token.priceExplorer.timeRangeLabel.day": "1 día", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 Day", "token.priceExplorer.timeRangeLabel.hour": "1 h", "token.priceExplorer.timeRangeLabel.month": "1 mes", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 Month", "token.priceExplorer.timeRangeLabel.week": "1 sem.", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 Week", "token.priceExplorer.timeRangeLabel.year": "1 año", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 Year", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} no está disponible", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} y {{tokenSymbol1}} no están disponibles", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs no recibe ninguna parte de estas comisiones.", diff --git a/packages/uniswap/src/i18n/locales/translations/fi-FI.json b/packages/uniswap/src/i18n/locales/translations/fi-FI.json index a65f98e54f4..e45a2f20b11 100644 --- a/packages/uniswap/src/i18n/locales/translations/fi-FI.json +++ b/packages/uniswap/src/i18n/locales/translations/fi-FI.json @@ -222,6 +222,7 @@ "common.button.disconnect": "Katkaista", "common.button.dismiss": "Hylkää", "common.button.done": "Tehty", + "common.button.edit": "Muokata", "common.button.enable": "ota käyttöön", "common.button.finish": "Valmis", "common.button.goBack": "Mene takaisin", @@ -313,7 +314,6 @@ "common.custom": "Mukautettu", "common.customRange": "Mukautettu valikoima", "common.dataOutdated": "Tiedot voivat olla vanhentuneita", - "common.dataUnavailable": "Tietoja ei ole saatavilla", "common.default": "Oletus", "common.defaultTradeOptions": "Kaupan oletusvaihtoehdot", "common.delegate.cancelled": "Edustaja peruutettu", @@ -461,6 +461,7 @@ "common.networkCost": "Verkon hinta", "common.neverMind": "Unohda koko juttu", "common.new": "Uusi", + "common.new.exclamation": "Uusi!", "common.nfts": "NFT:t", "common.noActivity": "Ei toimintaa vielä", "common.noAmount.error": "Syötä summa", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Hae maan tai alueen mukaan", "fiatOnRamp.region.title": "Valitse alueesi", "fiatOnRamp.summary.total": "{{cryptoAmount}} {{fiatAmount}}:lle", - "forceUpgrade.action.confirm": "Päivitä sovellus", + "forceUpgrade.action.confirm": "Päivitä nyt", "forceUpgrade.action.recoveryPhrase": "Näytä palautuslauseke", - "forceUpgrade.description": "Käyttämäsi Uniswap Wallet -versio on vanhentunut ja siitä puuttuu tärkeitä päivityksiä. Jos et päivitä sovellusta tai et ole kirjoittanut palautuslausekettasi muistiin, et voi käyttää omaisuuttasi.", + "forceUpgrade.description": "Sovelluksesta on saatavilla uusi versio. Jos haluat jatkaa Uniswap Walletin käyttöä, päivitä se uusimpaan versioon.", "forceUpgrade.label.recoveryPhrase": "Palautuslause", - "forceUpgrade.title": "Päivitä sovellus jatkaaksesi", + "forceUpgrade.title": "Päivitä uusimpaan versioon", "globalPreferences.title": "Globaalit mieltymykset", "hero.scroll": "Vieritä saadaksesi lisätietoja", "hero.subtitle": "Suurin onchain-markkinapaikka. Osta ja myy kryptotuotteita Ethereumissa ja yli 11 muussa ketjussa.", @@ -940,7 +941,6 @@ "home.feed.title": "Syötä", "home.label.buy": "Ostaa", "home.label.receive": "Vastaanottaa", - "home.label.scan": "Skannata", "home.label.send": "Lähettää", "home.label.swap": "Vaihtaa", "home.nfts.title": "NFT:t", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Hanki Uniswap Wallet -sovellus", "mobileAppPromo.banner.title": "Uniswap: Crypto & NFT Wallet", "moonpay.poweredBy": "MoonPay USA LLC:n tuottama Fiat onramp", - "moonpay.rampIframe": "MoonPay fiat on-ramp iframe", "moonpay.restricted.region": "Moonpay ei ole saatavilla joillakin alueilla. Napsauta saadaksesi lisätietoja.", "nav.createAccount.button": "Luo tili", "nav.logIn.button": "Kirjaudu sisään", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Näytä palautuslauseke", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 muu lompakko", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} muut lompakot", - "onboarding.import.onDeviceRecovery.warning.caption": "Varmista, että olet varmuuskopioinut kaikki muut lompakot. Jos haluat joskus palauttaa ne, tarvitset niiden palautuslausekkeet tai vastaavat iCloud-varmuuskopiot.", + "onboarding.import.onDeviceRecovery.warning.caption": "Varmista, että olet varmuuskopioinut kaikki muut lompakot. Jos haluat joskus palauttaa ne, tarvitset niiden palautuslausekkeet tai vastaavat {{cloudProvider}} -varmuuskopiot.", "onboarding.import.onDeviceRecovery.warning.title": "Oletko varma?", "onboarding.import.title": "Valitse, kuinka haluat lisätä lompakkosi", "onboarding.importMnemonic.button.default": "Palautuslauseeni on 12 sanaa", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Tutustu Uniswap Analyticsiin.", "pool.hideClosed": "Piilota suljetut asennot", "pool.import": "Tuo allas", - "pool.import.v2": "Tuo V2-allas", + "pool.import.link.description": "Joitakin v2-paikkoja ei näytetä automaattisesti.", + "pool.import.positions.v2": "Tuo V2-paikat", + "pool.import.positions.v2.selectPair.description": "Joitakin v2-paikkoja ei näytetä automaattisesti. Valitse merkkipari tuodaksesi ja tarkastellaksesi sijaintiasi.", + "pool.import.success": "Allas tuotu", "pool.increaseLiquidity": "Lisää likviditeettiä", "pool.info": "Allas tiedot", "pool.initialShare": "Alkuhinnat ja poolin osuus", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "30 päivän volyymi", "pool.volume.thirtyDay.short": "30D vol", "pool.yourv2": "V2-likviditeettisi", - "poolFinder.connect": "Yhdistä lompakkoon löytääksesi uima-altaita.", - "poolFinder.create": "Luo allas", - "poolFinder.found": "Allas löytynyt!", - "poolFinder.managePool": "Hallinnoi tätä allasta", - "poolFinder.noLiquidity": "Sinulla ei ole vielä likviditeettiä tässä poolissa.", - "poolFinder.noPoolFound": "Allasta ei löytynyt.", - "poolFinder.selectToken": "Valitse token löytääksesi v2-likviditeettisi.", - "poolFinder.tip": "Vihje: Käytä tätä työkalua löytääksesi v2-varastot, jotka eivät näy automaattisesti käyttöliittymässä.", + "poolFinder.availablePools": "Käytettävissä olevat uima-altaat", + "poolFinder.availablePools.found.description": "v2 poolit, jotka vastaavat parivalintaasi.", + "poolFinder.availablePools.notFound.description": "Vastaavia v2-poolia ei löytynyt. Tarkista token-valintasi ja varmista, että olet yhteydessä oikeaan lompakkoon.", "pools.approving.amount": "Hyväksytään {{amount}}", "pools.explore": "Tutustu uima-altaisiin", "position.addHook": "Lisää koukku", @@ -1500,6 +1497,7 @@ "position.step.price": "Aseta alkuhinta", "position.step.range": "Aseta hintaluokka", "position.step.select": "Valitse tunnuspari ja maksut", + "position.value": "Aseman arvo", "position.valueUnavailable": "Positioarvo ei ole saatavilla alhaisen likviditeetin vuoksi.", "position.your": "Sinun asemasi", "positions.welcome": "Tervetuloa tehtäviisi", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "Tapahtumasi palautetaan, jos se on vireillä yli tämän ajanjakson.", "swap.unsupportedAssets.readMore": "Lue lisää tukemattomista sisällöistä", "swap.warning.enterLargerAmount.title": "Syötä suurempi summa", - "swap.warning.expectedFailure": "Tämän kaupan odotetaan epäonnistuvan", + "swap.warning.expectedFailure.increaseSlippage": "Yritä lisätä liukumistasi.", + "swap.warning.expectedFailure.titleMay": "Tämä vaihto saattaa epäonnistua", "swap.warning.insufficientBalance.title": "Sinulla ei ole tarpeeksi {{currencySymbol}}", "swap.warning.insufficientGas.button": "Ei tarpeeksi {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Vaihda arvoon {{ tokenSymbol }} , {{networkName}}", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Jotkut testiverkot eivät tue tunnuksien vaihtamista, lähettämistä tai ostamista.", "tdp.stats.unsupportedChainDescription": "Token-tilastot ja kaaviot kohteelle {{chain}} ovat saatavilla osoitteessa {{infoLink}}", "tdp.symbolNotFound": "Symbolia ei löydy", + "testnet.modal.swapDeepLink.description.toProdMode": "Tämä toiminto edellyttää testnet-tilan poistamista käytöstä. Testnet-tila voidaan ottaa uudelleen käyttöön milloin tahansa asetuksista.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "Tämä toiminto edellyttää, että testiverkkotila on käytössä. Testiverkkojen tokeneilla ei ole todellista arvoa. Testnet-tila voidaan poistaa käytöstä milloin tahansa asetuksista.", + "testnet.modal.swapDeepLink.title.toProdMode": "Poista testnet-tila käytöstä", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Ota testiverkkotila käyttöön", "testnet.unsupported": "Tätä toimintoa ei tueta testnet-tilassa.", "themeToggle.theme": "Teema", "title.betterPricesMoreListings": "Paremmat hinnat. Lisää listauksia. Osta, myy ja vaihda NFT-tuotteita parhailla markkinapaikoilla, kuten OpenSea. Tutustu trendikkäisiin kokoelmiin.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Hintakaaviota ei voitu ladata", "token.priceExplorer.timeRangeLabel.all": "Koko ajan", "token.priceExplorer.timeRangeLabel.day": "1D", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 päivä", "token.priceExplorer.timeRangeLabel.hour": "1H", "token.priceExplorer.timeRangeLabel.month": "1 milj", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 kuukausi", "token.priceExplorer.timeRangeLabel.week": "1W", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 viikko", "token.priceExplorer.timeRangeLabel.year": "1V", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 vuosi", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} ei ole saatavilla", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} ja {{tokenSymbol1}} eivät ole saatavilla", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs ei saa mitään näistä maksuista.", diff --git a/packages/uniswap/src/i18n/locales/translations/fil-PH.json b/packages/uniswap/src/i18n/locales/translations/fil-PH.json index 697267219bb..e458f2c4013 100644 --- a/packages/uniswap/src/i18n/locales/translations/fil-PH.json +++ b/packages/uniswap/src/i18n/locales/translations/fil-PH.json @@ -132,15 +132,15 @@ "addressInput.recipient": "Recipient", "analytics.allow": "Payagan ang analytics", "analytics.allow.message": "Gumagamit kami ng na-anonymize na data para mapaganda ang karanasan mo sa mga produkto ng Uniswap Labs.", - "appRating.button.notReally": "Not really", - "appRating.description": "Let us know if you’re having a good experience with this app", - "appRating.extension.review.description": "Pick a star rating and leave a review on the Chrome Web Store.", - "appRating.extension.review.title": "Review Uniswap Extension?", - "appRating.extension.title": "Enjoying Uniswap Extension?", - "appRating.feedback.button.send": "Send feedback", - "appRating.feedback.description": "Let us know how we can improve your experience", - "appRating.feedback.title": "We’re sorry to hear that.", - "appRating.mobile.title": "Enjoying Uniswap Wallet?", + "appRating.button.notReally": "Hindi naman", + "appRating.description": "Sabihin sa amin kung maganda ang nararanasan mo sa app na ito", + "appRating.extension.review.description": "Pumili ng star rating at mag-iwan ng review sa Chrome Web Store.", + "appRating.extension.review.title": "Gawan ng review ang Uniswap Extension?", + "appRating.extension.title": "Nae-enjoy ang Uniswap Extension?", + "appRating.feedback.button.send": "Magpadala ng feedback", + "appRating.feedback.description": "Sabihin sa amin kung paano pa namin mapapaganda ang karanasan mo", + "appRating.feedback.title": "Ikinalulungkot naming malaman iyon.", + "appRating.mobile.title": "Nae-enjoy ang Uniswap Wallet?", "bridging.estimatedTime.minutesAndSeconds": "~{{minutes}}min {{seconds}}s", "bridging.estimatedTime.minutesOnly": "~{{minutes}}min", "bridging.estimatedTime.secondsOnly": "~{{seconds}}s", @@ -222,6 +222,7 @@ "common.button.disconnect": "Idiskonekta", "common.button.dismiss": "I-dismiss", "common.button.done": "Tapos na", + "common.button.edit": "I-edit", "common.button.enable": "I-enable", "common.button.finish": "Tapusin", "common.button.goBack": "Bumalik", @@ -313,7 +314,6 @@ "common.custom": "Custom", "common.customRange": "Custom na range", "common.dataOutdated": "Posibleng luma na ang data", - "common.dataUnavailable": "Hindi available ang data", "common.default": "Default", "common.defaultTradeOptions": "Mga default na opsyon sa pag-trade", "common.delegate.cancelled": "Nakansela ang pag-delegate", @@ -461,6 +461,7 @@ "common.networkCost": "Bayad sa network", "common.neverMind": "Huwag na lang", "common.new": "Bago", + "common.new.exclamation": "New!", "common.nfts": "Mga NFT", "common.noActivity": "Wala pang aktibidad", "common.noAmount.error": "Maglagay ng halaga", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Maghanap ayon sa bansa o rehiyon", "fiatOnRamp.region.title": "Piliin ang iyong rehiyon", "fiatOnRamp.summary.total": "{{cryptoAmount}} para sa {{fiatAmount}}", - "forceUpgrade.action.confirm": "I-update ang app", + "forceUpgrade.action.confirm": "Update now", "forceUpgrade.action.recoveryPhrase": "Tingnan ang recovery phrase", - "forceUpgrade.description": "Luma na at may mga kulang na kritikal na pag-upgrade ang bersyon ng Uniswap Wallet na ginagamit mo. Kung hindi mo ia-update ang app o hindi mo naisulat ang recovery phrase, hindi mo maa-access ang iyong mga asset.", + "forceUpgrade.description": "A new version of the app is available. To continue using the Uniswap Wallet, please update it to the latest version.", "forceUpgrade.label.recoveryPhrase": "Recovery phrase", - "forceUpgrade.title": "I-update ang app para magpatuloy", + "forceUpgrade.title": "Update to the latest version", "globalPreferences.title": "Mga pangkalahatang preference", "hero.scroll": "Mag-scroll para matuto pa", "hero.subtitle": "Ang pinakamalaking onchain marketplace. Bumili at magbenta ng crypto sa Ethereum at 11+ pang chain.", @@ -940,7 +941,6 @@ "home.feed.title": "Feed", "home.label.buy": "Bumili", "home.label.receive": "Tumanggap", - "home.label.scan": "I-scan", "home.label.send": "Ipadala", "home.label.swap": "Mag-swap", "home.nfts.title": "Mga NFT", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Kunin ang Uniswap Wallet app", "mobileAppPromo.banner.title": "Uniswap: Crypto at NFT Wallet", "moonpay.poweredBy": "Fiat onramp na pinapagana ng MoonPay USA LLC", - "moonpay.rampIframe": "MoonPay fiat on-ramp iframe", "moonpay.restricted.region": "Hindi available ang Moonpay sa ilang rehiyon. Mag-click para matuto pa.", "nav.createAccount.button": "Gumawa ng account", "nav.logIn.button": "Mag-log in", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Tingnan ang recovery phrase", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 pang wallet", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} pang wallet", - "onboarding.import.onDeviceRecovery.warning.caption": "Pakitiyak na na-back up mo ang lahat ng iba pang wallet. Kung sakaling gusto mong i-restore ang mga ito, kakailanganin mo ang mga recovery phrase ng mga ito o ang mga kaukulang backup nito sa iCloud.", + "onboarding.import.onDeviceRecovery.warning.caption": "Pakitiyak na na-back up mo ang lahat ng iba pang wallet. Kung sakaling gusto mong i-restore ang mga ito, kakailanganin mo ang mga recovery phrase ng mga ito o ang mga kaukulang backup ng mga ito sa {{cloudProvider}}.", "onboarding.import.onDeviceRecovery.warning.title": "Sigurado ka ba?", "onboarding.import.title": "Piliin kung paano mo gustong idagdag ang iyong wallet", "onboarding.importMnemonic.button.default": "12 salita ang aking recovery phrase", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "I-explore ang Uniswap Analytics.", "pool.hideClosed": "Itago ang mga saradong posisyon", "pool.import": "Mag-import ng pool", - "pool.import.v2": "Mag-import ng V2 pool", + "pool.import.link.description": "Some v2 positions aren’t displayed automatically.", + "pool.import.positions.v2": "Import V2 positions", + "pool.import.positions.v2.selectPair.description": "Some v2 positions aren’t displayed automatically. Select a token pair to import and view your positions.", + "pool.import.success": "Pool imported", "pool.increaseLiquidity": "Taasan ang liquidity", "pool.info": "Impormasyon ng pool", "pool.initialShare": "Mga inisyal na presyo at share sa pool", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "30 araw na volume", "pool.volume.thirtyDay.short": "30D vol", "pool.yourv2": "Ang iyong V2 liquidity", - "poolFinder.connect": "Kumonekta sa isang wallet para maghanap ng mga pool.", - "poolFinder.create": "Gumawa ng pool", - "poolFinder.found": "May nakitang pool!", - "poolFinder.managePool": "Pamahalaan ang pool na ito", - "poolFinder.noLiquidity": "Wala ka pang liquidity sa pool na ito.", - "poolFinder.noPoolFound": "Walang nakitang pool.", - "poolFinder.selectToken": "Pumili ng token para mahanap ang iyong v2 liquidity.", - "poolFinder.tip": "Tip: Gamitin ang tool na ito para maghanap ng mga v2 pool na hindi awtomatikong lumalabas sa interface.", + "poolFinder.availablePools": "Available pools", + "poolFinder.availablePools.found.description": "v2 pools matching your pair selection.", + "poolFinder.availablePools.notFound.description": "No matching v2 pools found. Double-check your token selection and ensure you’re connected to the correct wallet.", "pools.approving.amount": "Inaaprubahan ang {{amount}}", "pools.explore": "I-explore ang mga pool", "position.addHook": "Magdagdag ng Hook", @@ -1500,6 +1497,7 @@ "position.step.price": "Magtakda ng inisyal na presyo", "position.step.range": "Itakda ang range ng presyo", "position.step.select": "Pumili ng pares ng token at mga fee", + "position.value": "Position value", "position.valueUnavailable": "Hindi available ang value ng posisyon dahil sa mababang liquidity.", "position.your": "Ang posisyon mo", "positions.welcome": "Welcome sa iyong mga posisyon", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "Mare-revert ang iyong transaksyon kung nakabinbin ito nang mas mahaba sa panahong ito.", "swap.unsupportedAssets.readMore": "Magbasa pa tungkol sa mga hindi sinusuportahang asset", "swap.warning.enterLargerAmount.title": "Maglagay ng mas malaking halaga", - "swap.warning.expectedFailure": "Inaasahang hindi maisagawa ang transaksyong ito", + "swap.warning.expectedFailure.increaseSlippage": "Subukang taasan ang iyong slippage.", + "swap.warning.expectedFailure.titleMay": "This swap may fail", "swap.warning.insufficientBalance.title": "Wala kang sapat na {{currencySymbol}}", "swap.warning.insufficientGas.button": "Hindi sapat ang {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Mag-swap para sa {{ tokenSymbol }} sa {{networkName}}", @@ -1917,7 +1916,7 @@ "swap.warning.rateLimit.title": "Lumampas sa limit sa rate", "swap.warning.router.message": "Posibleng nawalan ka ng koneksyon o hindi gumagana ang network. Kung magpapatuloy ang problema, pakisubukang muli sa ibang pagkakataon.", "swap.warning.router.title": "Hindi makukumpleto ang pag-trade na ito sa ngayon", - "swap.warning.tokenBlocked.button": "{{tokenSymbol}} is blocked", + "swap.warning.tokenBlocked.button": "Naka-block ang {{tokenSymbol}}", "swap.warning.uniswapFee.message.default": "Naglalapat ng mga fee para matiyak ang pinakamagandang karanasan sa Uniswap. Walang fee na nauugnay sa pag-swap na ito.", "swap.warning.uniswapFee.message.included": "Naglalapat ng mga fee para matiyak ang pinakamagandang karanasan sa Uniswap, at na-factor na ang mga ito sa quote na ito.", "swap.warning.uniswapFee.title": "Fee sa pag-swap", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Hindi sinusuportahan ng ilang testnet ang pag-swap, pagpapadala, o pagbili ng mga token.", "tdp.stats.unsupportedChainDescription": "Available ang mga istatistika at chart ng token para sa {{chain}} sa {{infoLink}}", "tdp.symbolNotFound": "Hindi nahanap ang simbolo", + "testnet.modal.swapDeepLink.description.toProdMode": "Kinakailangang naka-disable ang testnet mode sa pagkilos na ito. Puwedeng i-enable ulit ang testnet mode sa anumang oras sa mga setting.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "Kinakailangang naka-enable ang testnet mode sa pagkilos na ito. Walang tunay na value ang mga token sa mga testnet. Puwedeng i-disable ang testnet mode sa anumang oras sa mga setting.", + "testnet.modal.swapDeepLink.title.toProdMode": "I-disable ang testnet mode", + "testnet.modal.swapDeepLink.title.toTestnetMode": "I-enable ang testnet mode", "testnet.unsupported": "Hindi sinusuportahan ang functionality na ito sa testnet mode.", "themeToggle.theme": "Tema", "title.betterPricesMoreListings": "Mas magagandang presyo. Higit pang listing. Bumili, magbenta, at mag-trade ng mga NFT sa mga nangungunang marketplace tulad ng OpenSea. I-explore ang mga trending na koleksyon.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Hindi ma-load ang chart ng presyo", "token.priceExplorer.timeRangeLabel.all": "Lahat ng oras", "token.priceExplorer.timeRangeLabel.day": "1D", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 Day", "token.priceExplorer.timeRangeLabel.hour": "1H", "token.priceExplorer.timeRangeLabel.month": "1M", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 Month", "token.priceExplorer.timeRangeLabel.week": "1W", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 Week", "token.priceExplorer.timeRangeLabel.year": "1Y", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 Year", "token.safety.blocked.title.tokenNotAvailable": "Hindi available ang {{tokenSymbol}}", "token.safety.blocked.title.tokensNotAvailable": "Hindi available ang {{tokenSymbol0}} at {{tokenSymbol1}}", "token.safety.fees.uniswapLabsDoesNotReceive": "Hindi nakakatanggap ang Uniswap Labs ng alinman sa mga fee na ito.", diff --git a/packages/uniswap/src/i18n/locales/translations/fr-FR.json b/packages/uniswap/src/i18n/locales/translations/fr-FR.json index b556e8d1ee1..c6f43920afb 100644 --- a/packages/uniswap/src/i18n/locales/translations/fr-FR.json +++ b/packages/uniswap/src/i18n/locales/translations/fr-FR.json @@ -222,6 +222,7 @@ "common.button.disconnect": "Déconnecter", "common.button.dismiss": "Rejeter", "common.button.done": "Terminé", + "common.button.edit": "Edit", "common.button.enable": "Activer", "common.button.finish": "Terminer", "common.button.goBack": "Revenir", @@ -313,7 +314,6 @@ "common.custom": "Personnalisé", "common.customRange": "Plage personnalisée", "common.dataOutdated": "Les données sont peut-être obsolètes.", - "common.dataUnavailable": "Data unavailable", "common.default": "Par défaut", "common.defaultTradeOptions": "Options de négociation par défaut", "common.delegate.cancelled": "Délégation annulée", @@ -461,6 +461,7 @@ "common.networkCost": "Frais de réseau", "common.neverMind": "Peu importe", "common.new": "Nouveau", + "common.new.exclamation": "New!", "common.nfts": "NFT", "common.noActivity": "Pas encore d'activité", "common.noAmount.error": "Saisir un montant", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Rechercher par pays ou région", "fiatOnRamp.region.title": "Sélectionner votre région", "fiatOnRamp.summary.total": "{{cryptoAmount}} pour {{fiatAmount}}", - "forceUpgrade.action.confirm": "Mettre à jour l'app", + "forceUpgrade.action.confirm": "Update now", "forceUpgrade.action.recoveryPhrase": "Voir la phrase de récupération", - "forceUpgrade.description": "La version d'Uniswap Wallet que vous utilisez est obsolète et ne dispose pas des mises à niveau essentielles. Si vous ne mettez pas à jour l'app ou si vous n'écrivez pas votre phrase de récupération, vous ne pourrez pas accéder à vos actifs.", + "forceUpgrade.description": "A new version of the app is available. To continue using the Uniswap Wallet, please update it to the latest version.", "forceUpgrade.label.recoveryPhrase": "Phrase de récupération", - "forceUpgrade.title": "Mettre à jour l'app pour continuer", + "forceUpgrade.title": "Update to the latest version", "globalPreferences.title": "Préférences générales", "hero.scroll": "Faire défiler pour en savoir plus", "hero.subtitle": "Le plus grand marché en chaîne. Achetez et vendez des cryptos sur Ethereum et plus de 11 autres chaînes.", @@ -940,7 +941,6 @@ "home.feed.title": "Fil d'actualités", "home.label.buy": "Acheter", "home.label.receive": "Recevoir", - "home.label.scan": "Analyser", "home.label.send": "Envoyer", "home.label.swap": "Échanger", "home.nfts.title": "NFT", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Obtenir l'app Uniswap Wallet", "mobileAppPromo.banner.title": "Uniswap : wallet crypto et NFT", "moonpay.poweredBy": "Passerelle Fiat optimisée par MoonPay USA LLC", - "moonpay.rampIframe": "Iframe de passerelle fiat MoonPay", "moonpay.restricted.region": "Moonpay n'est pas disponible dans certaines régions. Cliquez pour en savoir plus.", "nav.createAccount.button": "Créer un compte", "nav.logIn.button": "Se connecter", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Voir la phrase de récupération", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 autre wallet", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} autres wallets", - "onboarding.import.onDeviceRecovery.warning.caption": "Vérifiez que vous avez sauvegardé tous les autres wallets. Si jamais vous souhaitez les restaurer, vous aurez besoin de leurs phrases de récupération ou des sauvegardes sur iCloud correspondantes.", + "onboarding.import.onDeviceRecovery.warning.caption": "Please ensure you have backed up all of the other wallets. If you ever want to restore them, you’ll need their recovery phrases or corresponding {{cloudProvider}} backups.", "onboarding.import.onDeviceRecovery.warning.title": "Voulez-vous vraiment effectuer cette action ?", "onboarding.import.title": "Choisir la méthode d'ajout de votre wallet", "onboarding.importMnemonic.button.default": "Ma phrase de récupération est de 12 mots", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Découvrez les analyses d'Uniswap.", "pool.hideClosed": "Masquer les positions fermées", "pool.import": "Importer un pool", - "pool.import.v2": "Importer un pool V2", + "pool.import.link.description": "Some v2 positions aren’t displayed automatically.", + "pool.import.positions.v2": "Import V2 positions", + "pool.import.positions.v2.selectPair.description": "Some v2 positions aren’t displayed automatically. Select a token pair to import and view your positions.", + "pool.import.success": "Pool imported", "pool.increaseLiquidity": "Augmenter la liquidité", "pool.info": "Infos du pool", "pool.initialShare": "Prix initiaux et part du pool", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "30 day volume", "pool.volume.thirtyDay.short": "30D vol", "pool.yourv2": "Votre liquidité V2", - "poolFinder.connect": "Connectez-vous à un wallet pour trouver des pools.", - "poolFinder.create": "Créer un pool", - "poolFinder.found": "Pool trouvé.", - "poolFinder.managePool": "Gérer ce pool", - "poolFinder.noLiquidity": "Vous n'avez pas encore de liquidité dans ce pool.", - "poolFinder.noPoolFound": "Aucun pool trouvé.", - "poolFinder.selectToken": "Sélectionnez un token pour trouver votre liquidité v2.", - "poolFinder.tip": "Astuce : utilisez cet outil pour rechercher les pools v2 qui n'apparaissent pas automatiquement sur l'interface.", + "poolFinder.availablePools": "Available pools", + "poolFinder.availablePools.found.description": "v2 pools matching your pair selection.", + "poolFinder.availablePools.notFound.description": "No matching v2 pools found. Double-check your token selection and ensure you’re connected to the correct wallet.", "pools.approving.amount": "Approbation de {{amount}} en cours", "pools.explore": "Découvrir les pools", "position.addHook": "Ajouter un hook", @@ -1500,6 +1497,7 @@ "position.step.price": "Définir le prix initial", "position.step.range": "Définir la plage de prix", "position.step.select": "Sélectionner la paire de tokens et les frais", + "position.value": "Position value", "position.valueUnavailable": "La valeur de la position n'est pas disponible en raison d'une faible liquidité.", "position.your": "Votre position", "positions.welcome": "Bienvenue dans vos positions", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "Votre transaction sera annulée si elle reste en attente plus longtemps que cette période.", "swap.unsupportedAssets.readMore": "En savoir plus sur les actifs non pris en charge", "swap.warning.enterLargerAmount.title": "Saisir un montant plus élevé", - "swap.warning.expectedFailure": "Cette transaction échouera sans doute", + "swap.warning.expectedFailure.increaseSlippage": "Try increasing your slippage.", + "swap.warning.expectedFailure.titleMay": "This swap may fail", "swap.warning.insufficientBalance.title": "Vous ne possédez pas suffisamment de {{currencySymbol}}", "swap.warning.insufficientGas.button": "{{currencySymbol}} insuffisants", "swap.warning.insufficientGas.button.bridge": "Échanger contre des {{ tokenSymbol }} sur {{networkName}}", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Certains réseaux de test ne prennent pas en charge l'échange, l'envoi ou l'achat de tokens.", "tdp.stats.unsupportedChainDescription": "Les statistiques et graphiques des tokens pour {{chain}} sont disponibles sur {{infoLink}}", "tdp.symbolNotFound": "Symbole introuvable", + "testnet.modal.swapDeepLink.description.toProdMode": "This action requires testnet mode to be disabled. Testnet mode can be reenabled at anytime within settings.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "This action requires testnet mode to be enabled. Tokens on testnets do not hold any real value. Testnet mode can be disabled at anytime within settings.", + "testnet.modal.swapDeepLink.title.toProdMode": "Disable testnet mode", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Enable testnet mode", "testnet.unsupported": "Cette fonctionnalité n'est pas prise en charge en mode réseau de test.", "themeToggle.theme": "Thème", "title.betterPricesMoreListings": "De meilleurs prix, et plus de listings. Achetez, vendez et négociez des NFT sur les plus grands marchés tels qu'OpenSea. Découvrez les collections populaires.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Impossible de charger le graphique des prix", "token.priceExplorer.timeRangeLabel.all": "All time", "token.priceExplorer.timeRangeLabel.day": "1 j", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 Day", "token.priceExplorer.timeRangeLabel.hour": "1 h", "token.priceExplorer.timeRangeLabel.month": "1 m", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 Month", "token.priceExplorer.timeRangeLabel.week": "1 sem.", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 Week", "token.priceExplorer.timeRangeLabel.year": "1 an", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 Year", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} indisponible", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} et {{tokenSymbol1}} indisponibles", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs ne reçoit aucune part de ces frais.", diff --git a/packages/uniswap/src/i18n/locales/translations/he-IL.json b/packages/uniswap/src/i18n/locales/translations/he-IL.json index bbc779174a6..110f3e0272a 100644 --- a/packages/uniswap/src/i18n/locales/translations/he-IL.json +++ b/packages/uniswap/src/i18n/locales/translations/he-IL.json @@ -222,6 +222,7 @@ "common.button.disconnect": "לְנַתֵק", "common.button.dismiss": "לשחרר", "common.button.done": "בוצע", + "common.button.edit": "לַעֲרוֹך", "common.button.enable": "לְאַפשֵׁר", "common.button.finish": "סִיוּם", "common.button.goBack": "תחזור", @@ -313,7 +314,6 @@ "common.custom": "המותאם אישית", "common.customRange": "טווח מותאם אישית", "common.dataOutdated": "הנתונים עשויים להיות מיושנים", - "common.dataUnavailable": "הנתונים אינם זמינים", "common.default": "בְּרִירַת מֶחדָל", "common.defaultTradeOptions": "ברירת מחדל לאפשרויות סחר", "common.delegate.cancelled": "הנציג בוטל", @@ -461,6 +461,7 @@ "common.networkCost": "עלות רשת", "common.neverMind": "לא משנה", "common.new": "חָדָשׁ", + "common.new.exclamation": "חָדָשׁ!", "common.nfts": "NFTs", "common.noActivity": "עדיין אין פעילות", "common.noAmount.error": "הזן סכום", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "חפש לפי מדינה או אזור", "fiatOnRamp.region.title": "בחר את האיזור שלך", "fiatOnRamp.summary.total": "{{cryptoAmount}} עבור {{fiatAmount}}", - "forceUpgrade.action.confirm": "עדכן את האפליקציה", + "forceUpgrade.action.confirm": "עדכן עכשיו", "forceUpgrade.action.recoveryPhrase": "הצג את ביטוי השחזור", - "forceUpgrade.description": "הגרסה של ארנק Uniswap שבה אתה משתמש אינה מעודכנת וחסרים בה שדרוגים קריטיים. אם לא תעדכן את האפליקציה או שביטוי השחזור שלך לא רשום לך, לא תוכל לגשת לנכסים שלך.", + "forceUpgrade.description": "גרסה חדשה של האפליקציה זמינה. כדי להמשיך להשתמש בארנק Uniswap, אנא עדכן אותו לגרסה העדכנית ביותר.", "forceUpgrade.label.recoveryPhrase": "ביטוי התאוששות", - "forceUpgrade.title": "עדכן את האפליקציה כדי להמשיך", + "forceUpgrade.title": "עדכן לגרסה האחרונה", "globalPreferences.title": "העדפות גלובליות", "hero.scroll": "גלול למידע נוסף", "hero.subtitle": "שוק ה-onchain הגדול ביותר. קנה ומכור קריפטו ב-Ethereum וב-11+ רשתות אחרות.", @@ -940,7 +941,6 @@ "home.feed.title": "הזנה", "home.label.buy": "לִקְנוֹת", "home.label.receive": "לְקַבֵּל", - "home.label.scan": "לִסְרוֹק", "home.label.send": "לִשְׁלוֹחַ", "home.label.swap": "לְהַחלִיף", "home.nfts.title": "NFTs", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "קבל את אפליקציית ארנק Uniswap", "mobileAppPromo.banner.title": "יחידת החלפה: ארנק קריפטו ו-NFT", "moonpay.poweredBy": "פיאט onramp מופעל על ידי MoonPay USA LLC", - "moonpay.rampIframe": "MoonPay fiat on-ramp iframe", "moonpay.restricted.region": "Moonpay אינו זמין באזורים מסוימים. לחץ כדי ללמוד עוד.", "nav.createAccount.button": "צור חשבון", "nav.logIn.button": "התחבר", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "הצג את ביטוי השחזור", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 ארנק נוסף", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} ארנקים אחרים", - "onboarding.import.onDeviceRecovery.warning.caption": "אנא ודא שגיבית את כל הארנקים האחרים. אם אי פעם תרצה לשחזר אותם, תזדקק לביטויי השחזור שלהם או לגיבויים מתאימים של iCloud.", + "onboarding.import.onDeviceRecovery.warning.caption": "אנא ודא שגיבית את כל הארנקים האחרים. אם אי פעם תרצה לשחזר אותם, תזדקק לביטויי השחזור שלהם או לגיבויים תואמים של {{cloudProvider}} .", "onboarding.import.onDeviceRecovery.warning.title": "האם אתה בטוח?", "onboarding.import.title": "בחר כיצד ברצונך להוסיף את הארנק שלך", "onboarding.importMnemonic.button.default": "משפט ההחלמה שלי הוא 12 מילים", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "חקור את Uniswap Analytics.", "pool.hideClosed": "הסתר עמדות סגורות", "pool.import": "בריכת ייבוא", - "pool.import.v2": "ייבוא בריכת V2", + "pool.import.link.description": "מיקומי v2 מסוימים אינם מוצגים באופן אוטומטי.", + "pool.import.positions.v2": "ייבוא עמדות V2", + "pool.import.positions.v2.selectPair.description": "מיקומי v2 מסוימים אינם מוצגים באופן אוטומטי. בחר זוג אסימונים כדי לייבא ולהציג את המיקומים שלך.", + "pool.import.success": "בריכה מיובאת", "pool.increaseLiquidity": "הגדל את הנזילות", "pool.info": "מידע על הבריכה", "pool.initialShare": "מחירים ראשוניים ונתח מאגר", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "נפח 30 יום", "pool.volume.thirtyDay.short": "כרך 30D", "pool.yourv2": "הנזילות שלך ב-V2", - "poolFinder.connect": "התחבר לארנק כדי למצוא בריכות.", - "poolFinder.create": "צור בריכה", - "poolFinder.found": "נמצאה בריכה!", - "poolFinder.managePool": "נהל את הבריכה הזו", - "poolFinder.noLiquidity": "עדיין אין לך נזילות במאגר הזה.", - "poolFinder.noPoolFound": "לא נמצאה בריכה.", - "poolFinder.selectToken": "בחר אסימון כדי למצוא את הנזילות שלך ב-v2.", - "poolFinder.tip": "טיפ: השתמש בכלי זה כדי למצוא בריכות v2 שאינן מופיעות אוטומטית בממשק.", + "poolFinder.availablePools": "בריכות זמינות", + "poolFinder.availablePools.found.description": "בריכות v2 התואמות את בחירת הזוגות שלך.", + "poolFinder.availablePools.notFound.description": "לא נמצאו בריכות תואמות של v2. בדוק שוב את בחירת האסימון שלך וודא שאתה מחובר לארנק הנכון.", "pools.approving.amount": "מאשר {{amount}}", "pools.explore": "חקור בריכות", "position.addHook": "הוסף הוק", @@ -1500,6 +1497,7 @@ "position.step.price": "קבע מחיר התחלתי", "position.step.range": "קבע טווח מחירים", "position.step.select": "בחר זוג אסימונים ועמלות", + "position.value": "ערך מיקום", "position.valueUnavailable": "ערך המיקום אינו זמין עקב נזילות נמוכה.", "position.your": "העמדה שלך", "positions.welcome": "ברוכים הבאים לתפקידיכם", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "העסקה שלך תחזור אם היא בהמתנה במשך יותר מתקופת זמן זו.", "swap.unsupportedAssets.readMore": "קרא עוד על נכסים לא נתמכים", "swap.warning.enterLargerAmount.title": "הזן כמות גדולה יותר", - "swap.warning.expectedFailure": "עסקה זו צפויה להיכשל", + "swap.warning.expectedFailure.increaseSlippage": "נסה להגדיל את ההחלקה שלך.", + "swap.warning.expectedFailure.titleMay": "ההחלפה הזו עלולה להיכשל", "swap.warning.insufficientBalance.title": "אין לך מספיק {{currencySymbol}}", "swap.warning.insufficientGas.button": "לא מספיק {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "החלף עבור {{ tokenSymbol }} ב- {{networkName}}", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "רשתות בדיקה מסוימות אינן תומכות בהחלפה, שליחה או קנייה של אסימונים.", "tdp.stats.unsupportedChainDescription": "סטטיסטיקות אסימונים ותרשימים עבור {{chain}} זמינים ב- {{infoLink}}", "tdp.symbolNotFound": "הסמל לא נמצא", + "testnet.modal.swapDeepLink.description.toProdMode": "פעולה זו מחייבת את השבתת מצב testnet. ניתן להפעיל מחדש את מצב Testnet בכל עת בהגדרות.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "פעולה זו דורשת הפעלה של מצב testnet. לאסימונים ברשתות בדיקות אין ערך אמיתי. ניתן להשבית את מצב Testnet בכל עת בהגדרות.", + "testnet.modal.swapDeepLink.title.toProdMode": "השבת את מצב testnet", + "testnet.modal.swapDeepLink.title.toTestnetMode": "הפעל מצב testnet", "testnet.unsupported": "פונקציונליות זו אינה נתמכת במצב testnet.", "themeToggle.theme": "נושא", "title.betterPricesMoreListings": "מחירים טובים יותר. רישומים נוספים. קנה, מכור וסחר ב-NFT במקומות שווקים מובילים כמו OpenSea. חקור אוספים פופולריים.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "לא ניתן היה לטעון את תרשים המחירים", "token.priceExplorer.timeRangeLabel.all": "כל הזמן", "token.priceExplorer.timeRangeLabel.day": "1D", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 יום", "token.priceExplorer.timeRangeLabel.hour": "1H", "token.priceExplorer.timeRangeLabel.month": "1M", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 חודש", "token.priceExplorer.timeRangeLabel.week": "1W", + "token.priceExplorer.timeRangeLabel.week.verbose": "שבוע אחד", "token.priceExplorer.timeRangeLabel.year": "1Y", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 שנה", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} אינו זמין", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} ו {{tokenSymbol1}} אינם זמינים", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs אינה מקבלת אף אחת מהעמלות הללו.", diff --git a/packages/uniswap/src/i18n/locales/translations/hi-IN.json b/packages/uniswap/src/i18n/locales/translations/hi-IN.json index a036c5ecac1..98683b12ca3 100644 --- a/packages/uniswap/src/i18n/locales/translations/hi-IN.json +++ b/packages/uniswap/src/i18n/locales/translations/hi-IN.json @@ -222,6 +222,7 @@ "common.button.disconnect": "डिस्कनेक्ट", "common.button.dismiss": "नकार देना", "common.button.done": "हो गया", + "common.button.edit": "संपादन करना", "common.button.enable": "सक्षम", "common.button.finish": "खत्म करना", "common.button.goBack": "वापस जाओ", @@ -313,7 +314,6 @@ "common.custom": "रिवाज़", "common.customRange": "कस्टम रेंज", "common.dataOutdated": "डेटा पुराना हो सकता है", - "common.dataUnavailable": "डेटा उपलब्ध नहीं", "common.default": "गलती करना", "common.defaultTradeOptions": "डिफ़ॉल्ट व्यापार विकल्प", "common.delegate.cancelled": "प्रतिनिधि रद्द", @@ -461,6 +461,7 @@ "common.networkCost": "नेटवर्क लागत", "common.neverMind": "कोई बात नहीं", "common.new": "नया", + "common.new.exclamation": "नया!", "common.nfts": "एनएफटी", "common.noActivity": "अभी तक कोई गतिविधि नहीं", "common.noAmount.error": "राशि दर्ज करें", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "देश या क्षेत्र के अनुसार खोजें", "fiatOnRamp.region.title": "अपना क्षेत्र चुनें", "fiatOnRamp.summary.total": "{{fiatAmount}}के बदले {{cryptoAmount}}", - "forceUpgrade.action.confirm": "ऐप अपडेट करें", + "forceUpgrade.action.confirm": "अभी अद्यतन करें", "forceUpgrade.action.recoveryPhrase": "पुनर्प्राप्ति वाक्यांश देखें", - "forceUpgrade.description": "Uniswap वॉलेट का जो संस्करण आप उपयोग कर रहे हैं वह पुराना हो चुका है और उसमें महत्वपूर्ण अपग्रेड नहीं हैं। यदि आप ऐप को अपडेट नहीं करते हैं या आपने अपना पुनर्प्राप्ति वाक्यांश नहीं लिखा है, तो आप अपनी संपत्तियों तक नहीं पहुंच पाएंगे।", + "forceUpgrade.description": "ऐप का नया संस्करण उपलब्ध है। Uniswap वॉलेट का उपयोग जारी रखने के लिए, कृपया इसे नवीनतम संस्करण में अपडेट करें।", "forceUpgrade.label.recoveryPhrase": "पुनर्प्राप्ति वाक्यांश", - "forceUpgrade.title": "जारी रखने के लिए ऐप को अपडेट करें", + "forceUpgrade.title": "नवीनतम संस्करण में अपडेट करें", "globalPreferences.title": "वैश्विक प्राथमिकताएं", "hero.scroll": "अधिक जानने के लिए स्क्रॉल करें", "hero.subtitle": "सबसे बड़ा ऑनचेन मार्केटप्लेस। एथेरियम और 11+ अन्य चेन पर क्रिप्टो खरीदें और बेचें।", @@ -940,7 +941,6 @@ "home.feed.title": "खिलाना", "home.label.buy": "खरीदना", "home.label.receive": "प्राप्त करें", - "home.label.scan": "स्कैन", "home.label.send": "भेजना", "home.label.swap": "बदलना", "home.nfts.title": "एनएफटी", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Uniswap वॉलेट ऐप प्राप्त करें", "mobileAppPromo.banner.title": "यूनिस्वैप: क्रिप्टो और एनएफटी वॉलेट", "moonpay.poweredBy": "मूनपे यूएसए एलएलसी द्वारा संचालित फिएट ऑनरैम्प", - "moonpay.rampIframe": "मूनपे फिएट ऑन-रैंप iframe", "moonpay.restricted.region": "मूनपे कुछ क्षेत्रों में उपलब्ध नहीं है। अधिक जानने के लिए क्लिक करें।", "nav.createAccount.button": "खाता बनाएं", "nav.logIn.button": "लॉग इन करें", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "पुनर्प्राप्ति वाक्यांश देखें", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 अन्य वॉलेट", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} अन्य वॉलेट", - "onboarding.import.onDeviceRecovery.warning.caption": "कृपया सुनिश्चित करें कि आपने अन्य सभी वॉलेट का बैकअप ले लिया है। यदि आप कभी उन्हें पुनर्स्थापित करना चाहते हैं, तो आपको उनके पुनर्प्राप्ति वाक्यांशों या संबंधित iCloud बैकअप की आवश्यकता होगी।", + "onboarding.import.onDeviceRecovery.warning.caption": "कृपया सुनिश्चित करें कि आपने अन्य सभी वॉलेट का बैकअप ले लिया है। यदि आप कभी उन्हें पुनर्स्थापित करना चाहते हैं, तो आपको उनके पुनर्प्राप्ति वाक्यांशों या संबंधित {{cloudProvider}} बैकअप की आवश्यकता होगी।", "onboarding.import.onDeviceRecovery.warning.title": "क्या आपको यकीन है?", "onboarding.import.title": "चुनें कि आप अपना बटुआ कैसे जोड़ना चाहते हैं", "onboarding.importMnemonic.button.default": "मेरा पुनर्प्राप्ति वाक्यांश 12 शब्दों का है", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "यूनिस्वैप एनालिटिक्स का अन्वेषण करें.", "pool.hideClosed": "बंद स्थिति छिपाएँ", "pool.import": "आयात पूल", - "pool.import.v2": "V2 पूल आयात करें", + "pool.import.link.description": "कुछ v2 स्थितियाँ स्वचालित रूप से प्रदर्शित नहीं होतीं.", + "pool.import.positions.v2": "V2 स्थिति आयात करें", + "pool.import.positions.v2.selectPair.description": "कुछ v2 स्थितियाँ स्वचालित रूप से प्रदर्शित नहीं होती हैं। अपनी स्थितियाँ आयात करने और देखने के लिए टोकन जोड़ी चुनें।", + "pool.import.success": "पूल आयातित", "pool.increaseLiquidity": "तरलता बढ़ाएँ", "pool.info": "पूल जानकारी", "pool.initialShare": "प्रारंभिक मूल्य और पूल शेयर", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "30 दिन का वॉल्यूम", "pool.volume.thirtyDay.short": "30डी वॉल्यूम", "pool.yourv2": "आपकी V2 तरलता", - "poolFinder.connect": "पूल खोजने के लिए वॉलेट से कनेक्ट करें।", - "poolFinder.create": "पूल बनाएं", - "poolFinder.found": "पूल मिल गया!", - "poolFinder.managePool": "इस पूल का प्रबंधन करें", - "poolFinder.noLiquidity": "आपके पास अभी इस पूल में तरलता नहीं है।", - "poolFinder.noPoolFound": "कोई पूल नहीं मिला.", - "poolFinder.selectToken": "अपनी v2 लिक्विडिटी जानने के लिए एक टोकन चुनें।", - "poolFinder.tip": "सुझाव: इस टूल का उपयोग उन v2 पूल को खोजने के लिए करें जो इंटरफ़ेस में स्वचालित रूप से दिखाई नहीं देते हैं।", + "poolFinder.availablePools": "उपलब्ध पूल", + "poolFinder.availablePools.found.description": "v2 पूल आपके जोड़ी चयन से मेल खाते हैं।", + "poolFinder.availablePools.notFound.description": "कोई मेल खाता v2 पूल नहीं मिला। अपने टोकन चयन की दोबारा जाँच करें और सुनिश्चित करें कि आप सही वॉलेट से जुड़े हैं।", "pools.approving.amount": "अनुमोदन {{amount}}", "pools.explore": "पूल का अन्वेषण करें", "position.addHook": "एक हुक जोड़ें", @@ -1500,6 +1497,7 @@ "position.step.price": "प्रारंभिक मूल्य निर्धारित करें", "position.step.range": "मूल्य सीमा निर्धारित करें", "position.step.select": "टोकन जोड़ी और शुल्क का चयन करें", + "position.value": "स्थिति मान", "position.valueUnavailable": "कम तरलता के कारण स्थिति मूल्य उपलब्ध नहीं है।", "position.your": "आपका मत", "positions.welcome": "आपके पदों पर आपका स्वागत है", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "यदि आपका लेन-देन इस अवधि से अधिक समय तक लंबित रहता है तो उसे वापस कर दिया जाएगा।", "swap.unsupportedAssets.readMore": "असमर्थित परिसंपत्तियों के बारे में अधिक पढ़ें", "swap.warning.enterLargerAmount.title": "अधिक राशि दर्ज करें", - "swap.warning.expectedFailure": "इस लेन-देन के विफल होने की आशंका है", + "swap.warning.expectedFailure.increaseSlippage": "अपनी फिसलन को बढ़ाने का प्रयास करें।", + "swap.warning.expectedFailure.titleMay": "यह स्वैप विफल हो सकता है", "swap.warning.insufficientBalance.title": "आपके पास पर्याप्त {{currencySymbol}}नहीं है", "swap.warning.insufficientGas.button": "पर्याप्त नहीं {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "{{ tokenSymbol }} को {{networkName}}पर बदलें", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "कुछ टेस्टनेट टोकन की अदला-बदली, भेजने या खरीदने का समर्थन नहीं करते हैं।", "tdp.stats.unsupportedChainDescription": "{{chain}} के लिए टोकन आँकड़े और चार्ट {{infoLink}}पर उपलब्ध हैं", "tdp.symbolNotFound": "प्रतीक नहीं मिला", + "testnet.modal.swapDeepLink.description.toProdMode": "इस क्रिया के लिए टेस्टनेट मोड को अक्षम करना आवश्यक है। टेस्टनेट मोड को सेटिंग्स के भीतर किसी भी समय पुनः सक्षम किया जा सकता है।", + "testnet.modal.swapDeepLink.description.toTestnetMode": "इस क्रिया के लिए टेस्टनेट मोड को सक्षम करना आवश्यक है। टेस्टनेट पर टोकन का कोई वास्तविक मूल्य नहीं होता है। सेटिंग के भीतर टेस्टनेट मोड को कभी भी अक्षम किया जा सकता है।", + "testnet.modal.swapDeepLink.title.toProdMode": "टेस्टनेट मोड अक्षम करें", + "testnet.modal.swapDeepLink.title.toTestnetMode": "टेस्टनेट मोड सक्षम करें", "testnet.unsupported": "यह कार्यक्षमता टेस्टनेट मोड में समर्थित नहीं है।", "themeToggle.theme": "विषय", "title.betterPricesMoreListings": "बेहतर कीमतें। ज़्यादा लिस्टिंग। OpenSea जैसे शीर्ष मार्केटप्लेस पर NFT खरीदें, बेचें और ट्रेड करें। ट्रेंडिंग कलेक्शन एक्सप्लोर करें।", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "मूल्य चार्ट लोड नहीं किया जा सका", "token.priceExplorer.timeRangeLabel.all": "पूरे समय", "token.priceExplorer.timeRangeLabel.day": "-1 डी", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 दिन", "token.priceExplorer.timeRangeLabel.hour": "1 घंटे", "token.priceExplorer.timeRangeLabel.month": "1एम", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 महीना", "token.priceExplorer.timeRangeLabel.week": "1 माह", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 सप्ताह", "token.priceExplorer.timeRangeLabel.year": "1 वर्ष", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 वर्ष", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} उपलब्ध नहीं है", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} और {{tokenSymbol1}} उपलब्ध नहीं हैं", "token.safety.fees.uniswapLabsDoesNotReceive": "यूनिस्वैप लैब्स को इनमें से कोई भी शुल्क नहीं मिलता है।", diff --git a/packages/uniswap/src/i18n/locales/translations/hu-HU.json b/packages/uniswap/src/i18n/locales/translations/hu-HU.json index 5b30120345d..4b21563daaa 100644 --- a/packages/uniswap/src/i18n/locales/translations/hu-HU.json +++ b/packages/uniswap/src/i18n/locales/translations/hu-HU.json @@ -222,6 +222,7 @@ "common.button.disconnect": "Leválasztás", "common.button.dismiss": "Elvetés", "common.button.done": "Kész", + "common.button.edit": "Szerkesztés", "common.button.enable": "Engedélyezze", "common.button.finish": "Befejezés", "common.button.goBack": "Menjen vissza", @@ -313,7 +314,6 @@ "common.custom": "Egyedi", "common.customRange": "Egyedi tartomány", "common.dataOutdated": "Az adatok elavultak lehetnek", - "common.dataUnavailable": "Az adatok nem állnak rendelkezésre", "common.default": "Alapértelmezett", "common.defaultTradeOptions": "Alapértelmezett kereskedési opciók", "common.delegate.cancelled": "A delegált törölve", @@ -461,6 +461,7 @@ "common.networkCost": "Hálózati költség", "common.neverMind": "Nem fontos", "common.new": "Új", + "common.new.exclamation": "Új!", "common.nfts": "NFT-k", "common.noActivity": "Még nincs tevékenység", "common.noAmount.error": "Adjon meg egy összeget", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Keresés ország vagy régió szerint", "fiatOnRamp.region.title": "Válassza ki régióját", "fiatOnRamp.summary.total": "{{cryptoAmount}} {{fiatAmount}}esetén", - "forceUpgrade.action.confirm": "Frissítse az alkalmazást", + "forceUpgrade.action.confirm": "Frissítse most", "forceUpgrade.action.recoveryPhrase": "A helyreállítási kifejezés megtekintése", - "forceUpgrade.description": "Az Ön által használt Uniswap Wallet verzió elavult, és hiányoznak a kritikus frissítések. Ha nem frissíti az alkalmazást, vagy nincs leírva a helyreállítási kifejezés, akkor nem fog tudni hozzáférni az eszközökhöz.", + "forceUpgrade.description": "Elérhető az alkalmazás új verziója. Az Uniswap Wallet használatának folytatásához frissítse a legújabb verzióra.", "forceUpgrade.label.recoveryPhrase": "Helyreállítási kifejezés", - "forceUpgrade.title": "A folytatáshoz frissítse az alkalmazást", + "forceUpgrade.title": "Frissítés a legújabb verzióra", "globalPreferences.title": "Globális preferenciák", "hero.scroll": "További információért görgessen", "hero.subtitle": "A legnagyobb onchain piactér. Vásároljon és adjon el kriptot az Ethereumon és 11+ másik láncon.", @@ -940,7 +941,6 @@ "home.feed.title": "Takarmány", "home.label.buy": "megvesz", "home.label.receive": "Kap", - "home.label.scan": "Letapogatás", "home.label.send": "Küld", "home.label.swap": "Csere", "home.nfts.title": "NFT-k", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Töltse le az Uniswap Wallet alkalmazást", "mobileAppPromo.banner.title": "Unswap: Crypto & NFT Wallet", "moonpay.poweredBy": "A Fiat rámpát a MoonPay USA LLC működteti", - "moonpay.rampIframe": "MoonPay fiat on-ramp iframe", "moonpay.restricted.region": "A Moonpay egyes régiókban nem érhető el. Kattintson a további információért.", "nav.createAccount.button": "Hozzon létre fiókot", "nav.logIn.button": "Jelentkezzen be", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "A helyreállítási kifejezés megtekintése", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 másik pénztárca", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} egyéb pénztárcák", - "onboarding.import.onDeviceRecovery.warning.caption": "Kérjük, győződjön meg róla, hogy az összes többi pénztárcáról készített biztonsági másolatot. Ha valaha is vissza szeretné állítani őket, szüksége lesz a helyreállítási kifejezéseikre vagy a megfelelő iCloud biztonsági másolatokra.", + "onboarding.import.onDeviceRecovery.warning.caption": "Kérjük, győződjön meg róla, hogy az összes többi pénztárcáról biztonsági másolatot készített. Ha valaha is vissza szeretné állítani őket, szüksége lesz a helyreállítási kifejezéseikre vagy a megfelelő {{cloudProvider}} biztonsági másolatokra.", "onboarding.import.onDeviceRecovery.warning.title": "biztos vagy ebben?", "onboarding.import.title": "Válassza ki, hogyan szeretné hozzáadni pénztárcáját", "onboarding.importMnemonic.button.default": "A helyreállítási kifejezésem 12 szó", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Fedezze fel az Uniswap Analytics szolgáltatást.", "pool.hideClosed": "Zárt pozíciók elrejtése", "pool.import": "Medence importálása", - "pool.import.v2": "Import V2 pool", + "pool.import.link.description": "Egyes v2-pozíciók nem jelennek meg automatikusan.", + "pool.import.positions.v2": "V2 pozíciók importálása", + "pool.import.positions.v2.selectPair.description": "Egyes v2-pozíciók nem jelennek meg automatikusan. Válasszon ki egy tokenpárt az importáláshoz és a pozíciók megtekintéséhez.", + "pool.import.success": "Medence importálva", "pool.increaseLiquidity": "Növelje a likviditást", "pool.info": "Medence információk", "pool.initialShare": "Kezdeti árak és a medence részesedése", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "30 napos mennyiség", "pool.volume.thirtyDay.short": "30D köt", "pool.yourv2": "Az Ön V2 likviditása", - "poolFinder.connect": "Csatlakozzon egy pénztárcához, hogy medencéket keressen.", - "poolFinder.create": "Pool létrehozása", - "poolFinder.found": "Medence található!", - "poolFinder.managePool": "Kezelje ezt a medencét", - "poolFinder.noLiquidity": "Még nincs likviditása ebben a poolban.", - "poolFinder.noPoolFound": "Nem található medence.", - "poolFinder.selectToken": "Válasszon ki egy tokent a v2 likviditásának megtalálásához.", - "poolFinder.tip": "Tipp: Ezzel az eszközzel olyan v2-készleteket kereshet, amelyek nem jelennek meg automatikusan a felületen.", + "poolFinder.availablePools": "Rendelkezésre álló medencék", + "poolFinder.availablePools.found.description": "v2 poolok, amelyek megfelelnek a párválasztásnak.", + "poolFinder.availablePools.notFound.description": "Nem található megfelelő v2-készlet. Ellenőrizze még egyszer a token kiválasztását, és győződjön meg arról, hogy a megfelelő pénztárcához csatlakozik.", "pools.approving.amount": "{{amount}}jóváhagyása", "pools.explore": "Fedezze fel a medencéket", "position.addHook": "Adj hozzá egy horgot", @@ -1500,6 +1497,7 @@ "position.step.price": "Állítsa be a kezdeti árat", "position.step.range": "Állítsa be az árkategóriát", "position.step.select": "Válassza ki a tokenpárt és a díjakat", + "position.value": "Pozíció értéke", "position.valueUnavailable": "A pozíció értéke az alacsony likviditás miatt nem érhető el.", "position.your": "A te helyzeted", "positions.welcome": "Üdvözöljük pozícióin", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "A tranzakció visszaáll, ha az ennél hosszabb ideig függőben van.", "swap.unsupportedAssets.readMore": "További információ a nem támogatott eszközökről", "swap.warning.enterLargerAmount.title": "Adjon meg nagyobb összeget", - "swap.warning.expectedFailure": "Ez a tranzakció várhatóan meghiúsul", + "swap.warning.expectedFailure.increaseSlippage": "Próbálja meg növelni a csúszását.", + "swap.warning.expectedFailure.titleMay": "Ez a csere sikertelen lehet", "swap.warning.insufficientBalance.title": "Nincs elég {{currencySymbol}}", "swap.warning.insufficientGas.button": "Nem elég {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Csere {{ tokenSymbol }} értékre {{networkName}}-n", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Egyes teszthálózatok nem támogatják a tokenek cseréjét, küldését vagy vásárlását.", "tdp.stats.unsupportedChainDescription": "A {{chain}} tokenstatisztikái és diagramjai a {{infoLink}}oldalon érhetők el", "tdp.symbolNotFound": "A szimbólum nem található", + "testnet.modal.swapDeepLink.description.toProdMode": "Ehhez a művelethez le kell tiltani a teszthálózati módot. A Testnet mód a beállításokon belül bármikor újra engedélyezhető.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "Ehhez a művelethez engedélyezni kell a teszthálózati módot. A teszthálókon található tokenek nem rendelkeznek valós értékkel. A Testnet mód bármikor letiltható a beállításokon belül.", + "testnet.modal.swapDeepLink.title.toProdMode": "A tesztnet mód letiltása", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Engedélyezze a teszthálózati módot", "testnet.unsupported": "Ez a funkció nem támogatott tesztnet módban.", "themeToggle.theme": "Téma", "title.betterPricesMoreListings": "Jobb árak. További listák. Vásároljon, adjon el és keressen NFT-ket olyan vezető piacokon, mint az OpenSea. Fedezze fel a felkapott kollekciókat.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Nem sikerült betölteni az árdiagramot", "token.priceExplorer.timeRangeLabel.all": "Mindig", "token.priceExplorer.timeRangeLabel.day": "1D", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 nap", "token.priceExplorer.timeRangeLabel.hour": "1H", "token.priceExplorer.timeRangeLabel.month": "1M", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 hónap", "token.priceExplorer.timeRangeLabel.week": "1W", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 hét", "token.priceExplorer.timeRangeLabel.year": "1Y", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 év", "token.safety.blocked.title.tokenNotAvailable": "A {{tokenSymbol}} nem érhető el", "token.safety.blocked.title.tokensNotAvailable": "A {{tokenSymbol0}} és {{tokenSymbol1}} nem elérhető", "token.safety.fees.uniswapLabsDoesNotReceive": "Az Uniswap Labs nem kapja meg ezeket a díjakat.", diff --git a/packages/uniswap/src/i18n/locales/translations/id-ID.json b/packages/uniswap/src/i18n/locales/translations/id-ID.json index 7c198ea10fc..f8c9fae225f 100644 --- a/packages/uniswap/src/i18n/locales/translations/id-ID.json +++ b/packages/uniswap/src/i18n/locales/translations/id-ID.json @@ -222,6 +222,7 @@ "common.button.disconnect": "Putuskan", "common.button.dismiss": "Tutup", "common.button.done": "Selesai", + "common.button.edit": "Edit", "common.button.enable": "Aktifkan", "common.button.finish": "Selesai", "common.button.goBack": "Kembali", @@ -313,7 +314,6 @@ "common.custom": "Khusus", "common.customRange": "Rentang khusus", "common.dataOutdated": "Data mungkin sudah usang", - "common.dataUnavailable": "Data tidak tersedia", "common.default": "Bawaan", "common.defaultTradeOptions": "Opsi perdagangan bawaan", "common.delegate.cancelled": "Delegasi dibatalkan", @@ -461,6 +461,7 @@ "common.networkCost": "Biaya jaringan", "common.neverMind": "Abaikan", "common.new": "Baru", + "common.new.exclamation": "New!", "common.nfts": "NFT", "common.noActivity": "Belum ada aktivitas", "common.noAmount.error": "Masukkan jumlah", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Cari berdasarkan negara atau wilayah", "fiatOnRamp.region.title": "Pilih wilayah Anda", "fiatOnRamp.summary.total": "{{cryptoAmount}} untuk {{fiatAmount}}", - "forceUpgrade.action.confirm": "Perbarui aplikasi", + "forceUpgrade.action.confirm": "Update now", "forceUpgrade.action.recoveryPhrase": "Lihat frasa pemulihan", - "forceUpgrade.description": "Versi Dompet Uniswap yang Anda gunakan sudah kedaluwarsa dan belum mendapatkan peningkatan penting. Jika Anda tidak memperbarui aplikasi atau belum mencatat frasa pemulihan, Anda tidak akan dapat mengakses aset Anda.", + "forceUpgrade.description": "A new version of the app is available. To continue using the Uniswap Wallet, please update it to the latest version.", "forceUpgrade.label.recoveryPhrase": "Frasa pemulihan", - "forceUpgrade.title": "Perbarui aplikasi untuk melanjutkan", + "forceUpgrade.title": "Update to the latest version", "globalPreferences.title": "Preferensi global", "hero.scroll": "Gulir untuk mempelajari lebih lanjut", "hero.subtitle": "Marketplace onchain terbesar. Beli dan jual kripto di Ethereum dan 11+ chain lainnya.", @@ -940,7 +941,6 @@ "home.feed.title": "Umpan", "home.label.buy": "Beli", "home.label.receive": "Terima", - "home.label.scan": "Pindai", "home.label.send": "Kirim", "home.label.swap": "Tukar", "home.nfts.title": "NFT", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Unduh aplikasi Dompet Uniswap", "mobileAppPromo.banner.title": "Uniswap: Dompet Kripto & NFT", "moonpay.poweredBy": "Fiat onramp didukung oleh MoonPay USA LLC", - "moonpay.rampIframe": "iframe fiat on-ramp MoonPay", "moonpay.restricted.region": "Moonpay tidak tersedia di beberapa wilayah. Klik untuk mempelajari lebih lanjut.", "nav.createAccount.button": "Buat akun", "nav.logIn.button": "Masuk", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Lihat frasa pemulihan", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 dompet lainnya", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} dompet lainnya", - "onboarding.import.onDeviceRecovery.warning.caption": "Harap pastikan Anda telah mencadangkan semua dompet lainnya. Jika Anda ingin memulihkannya, Anda memerlukan frasa pemulihan atau cadangan iCloud yang sesuai.", + "onboarding.import.onDeviceRecovery.warning.caption": "Please ensure you have backed up all of the other wallets. If you ever want to restore them, you’ll need their recovery phrases or corresponding {{cloudProvider}} backups.", "onboarding.import.onDeviceRecovery.warning.title": "Anda yakin?", "onboarding.import.title": "Pilih cara untuk menambahkan dompet Anda", "onboarding.importMnemonic.button.default": "Frasa pemulihan saya adalah 12 kata", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Jelajahi Analisis Uniswap.", "pool.hideClosed": "Sembunyikan posisi tertutup", "pool.import": "Impor cadangan aset", - "pool.import.v2": "Impor cadangan aset V2", + "pool.import.link.description": "Some v2 positions aren’t displayed automatically.", + "pool.import.positions.v2": "Import V2 positions", + "pool.import.positions.v2.selectPair.description": "Some v2 positions aren’t displayed automatically. Select a token pair to import and view your positions.", + "pool.import.success": "Pool imported", "pool.increaseLiquidity": "Tambah likuiditas", "pool.info": "Info pool", "pool.initialShare": "Harga awal dan kontribusi pelaku mining", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "Volume 30 hari", "pool.volume.thirtyDay.short": "Vol 30hari", "pool.yourv2": "Likuiditas V2 Anda", - "poolFinder.connect": "Hubungkan ke dompet untuk menemukan cadangan aset.", - "poolFinder.create": "Buat cadangan aset", - "poolFinder.found": "Cadangan aset ditemukan!", - "poolFinder.managePool": "Kelola cadangan aset ini", - "poolFinder.noLiquidity": "Anda belum memiliki likuiditas di cadangan aset ini.", - "poolFinder.noPoolFound": "Cadangan aset tidak ditemukan.", - "poolFinder.selectToken": "Pilih token untuk menemukan likuiditas v2 Anda.", - "poolFinder.tip": "Tip: Gunakan alat ini untuk menemukan cadangan aset v2 yang tidak muncul secara otomatis di antarmuka.", + "poolFinder.availablePools": "Available pools", + "poolFinder.availablePools.found.description": "v2 pools matching your pair selection.", + "poolFinder.availablePools.notFound.description": "No matching v2 pools found. Double-check your token selection and ensure you’re connected to the correct wallet.", "pools.approving.amount": "Menyetujui {{amount}}", "pools.explore": "Jelajahi cadangan aset", "position.addHook": "Tambahkan Hook", @@ -1500,6 +1497,7 @@ "position.step.price": "Tetapkan harga awal", "position.step.range": "Tetapkan rentang harga", "position.step.select": "Pilih pasangan token dan biaya", + "position.value": "Position value", "position.valueUnavailable": "Nilai posisi tidak tersedia karena likuiditas yang rendah.", "position.your": "Posisi Anda", "positions.welcome": "Selamat datang di posisi Anda", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "Transaksi Anda akan dibatalkan jika tertunda lebih dari jangka waktu ini.", "swap.unsupportedAssets.readMore": "Baca selengkapnya tentang aset yang tidak didukung", "swap.warning.enterLargerAmount.title": "Masukkan jumlah yang lebih besar", - "swap.warning.expectedFailure": "Transaksi ini diperkirakan gagal", + "swap.warning.expectedFailure.increaseSlippage": "Coba tingkatkan slippage.", + "swap.warning.expectedFailure.titleMay": "This swap may fail", "swap.warning.insufficientBalance.title": "Anda tidak punya cukup {{currencySymbol}}", "swap.warning.insufficientGas.button": "Tidak cukup {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Tukar dengan {{ tokenSymbol }} di {{networkName}}", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Beberapa testnet tidak mendukung pertukaran, pengiriman, atau pembelian token.", "tdp.stats.unsupportedChainDescription": "Statistik dan grafik token untuk {{chain}} tersedia di {{infoLink}}", "tdp.symbolNotFound": "Simbol tidak ditemukan", + "testnet.modal.swapDeepLink.description.toProdMode": "This action requires testnet mode to be disabled. Testnet mode can be reenabled at anytime within settings.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "This action requires testnet mode to be enabled. Tokens on testnets do not hold any real value. Testnet mode can be disabled at anytime within settings.", + "testnet.modal.swapDeepLink.title.toProdMode": "Disable testnet mode", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Enable testnet mode", "testnet.unsupported": "Fungsionalitas ini tidak didukung dalam mode testnet.", "themeToggle.theme": "Tema", "title.betterPricesMoreListings": "Harga yang lebih baik. Listingan lebih banyak. Beli, jual, dan trading NFT di marketplace terkemuka, seperti OpenSea. Jelajahi koleksi yang sedang tren.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Tidak dapat memuat grafik harga", "token.priceExplorer.timeRangeLabel.all": "Sepanjang periode", "token.priceExplorer.timeRangeLabel.day": "1 Hari", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 Day", "token.priceExplorer.timeRangeLabel.hour": "1 Jam", "token.priceExplorer.timeRangeLabel.month": "1 Bulan", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 Month", "token.priceExplorer.timeRangeLabel.week": "1 Minggu", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 Week", "token.priceExplorer.timeRangeLabel.year": "1 Tahun", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 Year", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} tidak tersedia", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} dan {{tokenSymbol1}} tidak tersedia", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs tidak mendapatkan apa pun dari biaya ini.", diff --git a/packages/uniswap/src/i18n/locales/translations/it-IT.json b/packages/uniswap/src/i18n/locales/translations/it-IT.json index a758b0a914c..9c90713f9f9 100644 --- a/packages/uniswap/src/i18n/locales/translations/it-IT.json +++ b/packages/uniswap/src/i18n/locales/translations/it-IT.json @@ -222,6 +222,7 @@ "common.button.disconnect": "Disconnetti", "common.button.dismiss": "Congedare", "common.button.done": "Fatto", + "common.button.edit": "Modificare", "common.button.enable": "Abilitare", "common.button.finish": "Fine", "common.button.goBack": "Torna indietro", @@ -313,7 +314,6 @@ "common.custom": "Costume", "common.customRange": "Gamma personalizzata", "common.dataOutdated": "I dati potrebbero essere obsoleti", - "common.dataUnavailable": "Dati non disponibili", "common.default": "Predefinito", "common.defaultTradeOptions": "Opzioni commerciali predefinite", "common.delegate.cancelled": "Il delegato è stato annullato", @@ -461,6 +461,7 @@ "common.networkCost": "Costo di rete", "common.neverMind": "Non importa", "common.new": "Nuovo", + "common.new.exclamation": "Nuovo!", "common.nfts": "NFT", "common.noActivity": "Nessuna attività ancora", "common.noAmount.error": "Inserisci un importo", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Cerca per paese o regione", "fiatOnRamp.region.title": "Seleziona la tua regione", "fiatOnRamp.summary.total": "{{cryptoAmount}} per {{fiatAmount}}", - "forceUpgrade.action.confirm": "Aggiorna l'app", + "forceUpgrade.action.confirm": "Aggiorna ora", "forceUpgrade.action.recoveryPhrase": "Visualizza la frase di recupero", - "forceUpgrade.description": "La versione di Uniswap Wallet che stai utilizzando non è aggiornata e mancano aggiornamenti critici. Se non aggiorni l'app o non hai annotato la frase di recupero, non potrai accedere alle tue risorse.", + "forceUpgrade.description": "È disponibile una nuova versione dell'app. Per continuare a usare Uniswap Wallet, aggiornalo all'ultima versione.", "forceUpgrade.label.recoveryPhrase": "Frase di recupero", - "forceUpgrade.title": "Aggiorna l'app per continuare", + "forceUpgrade.title": "Aggiorna all'ultima versione", "globalPreferences.title": "Preferenze globali", "hero.scroll": "Scorri per saperne di più", "hero.subtitle": "Il più grande mercato onchain. Acquista e vendi criptovalute su Ethereum e oltre 11 altre catene.", @@ -940,7 +941,6 @@ "home.feed.title": "Foraggio", "home.label.buy": "Acquistare", "home.label.receive": "Ricevere", - "home.label.scan": "Scansione", "home.label.send": "Inviare", "home.label.swap": "Scambio", "home.nfts.title": "NFT", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Ottieni l'app Uniswap Wallet", "mobileAppPromo.banner.title": "Uniswap: portafoglio criptovaluta e NFT", "moonpay.poweredBy": "Fiat onramp gestito da MoonPay USA LLC", - "moonpay.rampIframe": "MoonPay iframe fiat on-ramp", "moonpay.restricted.region": "Moonpay non è disponibile in alcune regioni. Clicca per saperne di più.", "nav.createAccount.button": "Creare un account", "nav.logIn.button": "Login", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Visualizza la frase di recupero", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 altro portafoglio", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} altri portafogli", - "onboarding.import.onDeviceRecovery.warning.caption": "Assicurati di aver eseguito il backup di tutti gli altri portafogli. Se mai desideri ripristinarli, avrai bisogno delle loro frasi di recupero o dei corrispondenti backup iCloud.", + "onboarding.import.onDeviceRecovery.warning.caption": "Assicurati di aver eseguito il backup di tutti gli altri wallet. Se mai volessi ripristinarli, ti serviranno le loro frasi di recupero o i corrispondenti backup {{cloudProvider}} .", "onboarding.import.onDeviceRecovery.warning.title": "Sei sicuro?", "onboarding.import.title": "Scegli come vuoi aggiungere il tuo portafoglio", "onboarding.importMnemonic.button.default": "La mia frase di recupero è di 12 parole", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Esplora Uniswap Analytics.", "pool.hideClosed": "Nascondi le posizioni chiuse", "pool.import": "Importa pool", - "pool.import.v2": "Importa pool V2", + "pool.import.link.description": "Alcune posizioni v2 non vengono visualizzate automaticamente.", + "pool.import.positions.v2": "Importa posizioni V2", + "pool.import.positions.v2.selectPair.description": "Alcune posizioni v2 non vengono visualizzate automaticamente. Seleziona una coppia di token da importare e visualizza le tue posizioni.", + "pool.import.success": "Pool importato", "pool.increaseLiquidity": "Aumentare la liquidità", "pool.info": "Informazioni sulla piscina", "pool.initialShare": "Prezzi iniziali e quota del pool", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "Volume 30 giorni", "pool.volume.thirtyDay.short": "30D vol", "pool.yourv2": "La tua liquidità V2", - "poolFinder.connect": "Connettiti a un portafoglio per trovare pool.", - "poolFinder.create": "Crea piscina", - "poolFinder.found": "Piscina trovata!", - "poolFinder.managePool": "Gestisci questo pool", - "poolFinder.noLiquidity": "Non hai ancora liquidità in questo pool.", - "poolFinder.noPoolFound": "Nessuna piscina trovata.", - "poolFinder.selectToken": "Seleziona un token per trovare la tua liquidità v2.", - "poolFinder.tip": "Suggerimento: utilizzare questo strumento per trovare pool v2 che non vengono visualizzati automaticamente nell'interfaccia.", + "poolFinder.availablePools": "Piscine disponibili", + "poolFinder.availablePools.found.description": "Pool v2 corrispondenti alla tua selezione di coppie.", + "poolFinder.availablePools.notFound.description": "Non sono stati trovati pool v2 corrispondenti. Controlla attentamente la selezione del token e assicurati di essere connesso al portafoglio corretto.", "pools.approving.amount": "Approvazione {{amount}}", "pools.explore": "Esplora le piscine", "position.addHook": "Aggiungi un gancio", @@ -1500,6 +1497,7 @@ "position.step.price": "Imposta il prezzo iniziale", "position.step.range": "Imposta la fascia di prezzo", "position.step.select": "Seleziona la coppia di token e le commissioni", + "position.value": "Valore della posizione", "position.valueUnavailable": "Il valore della posizione non è disponibile a causa della scarsa liquidità.", "position.your": "La tua posizione", "positions.welcome": "Benvenuti alle vostre posizioni", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "La tua transazione verrà annullata se rimane in sospeso per più di questo periodo di tempo.", "swap.unsupportedAssets.readMore": "Ulteriori informazioni sulle risorse non supportate", "swap.warning.enterLargerAmount.title": "Inserisci un importo maggiore", - "swap.warning.expectedFailure": "Si prevede che questa transazione fallirà", + "swap.warning.expectedFailure.increaseSlippage": "Prova ad aumentare lo slittamento.", + "swap.warning.expectedFailure.titleMay": "Questo scambio potrebbe fallire", "swap.warning.insufficientBalance.title": "Non ne hai abbastanza {{currencySymbol}}", "swap.warning.insufficientGas.button": "Non abbastanza {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Sostituisci {{ tokenSymbol }} con {{networkName}}", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Alcune testnet non supportano lo scambio, l'invio o l'acquisto di token.", "tdp.stats.unsupportedChainDescription": "Le statistiche e i grafici dei token per {{chain}} sono disponibili su {{infoLink}}", "tdp.symbolNotFound": "Simbolo non trovato", + "testnet.modal.swapDeepLink.description.toProdMode": "Questa azione richiede che la modalità testnet sia disabilitata. La modalità testnet può essere riabilitata in qualsiasi momento nelle impostazioni.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "Questa azione richiede che la modalità testnet sia abilitata. I token sulle testnet non hanno alcun valore reale. La modalità testnet può essere disabilitata in qualsiasi momento nelle impostazioni.", + "testnet.modal.swapDeepLink.title.toProdMode": "Disabilita la modalità testnet", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Abilita la modalità testnet", "testnet.unsupported": "Questa funzionalità non è supportata in modalità testnet.", "themeToggle.theme": "Tema", "title.betterPricesMoreListings": "Prezzi migliori. Più elenchi. Acquista, vendi e scambia NFT sui principali mercati come OpenSea. Esplora le collezioni di tendenza.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Impossibile caricare il grafico dei prezzi", "token.priceExplorer.timeRangeLabel.all": "Sempre", "token.priceExplorer.timeRangeLabel.day": "1D", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 giorno", "token.priceExplorer.timeRangeLabel.hour": "1 ora", "token.priceExplorer.timeRangeLabel.month": "1 milione", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 mese", "token.priceExplorer.timeRangeLabel.week": "1 W", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 settimana", "token.priceExplorer.timeRangeLabel.year": "1 anno", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 anno", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} non è disponibile", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} e {{tokenSymbol1}} non sono disponibili", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs non riceve nessuna di queste commissioni.", diff --git a/packages/uniswap/src/i18n/locales/translations/ja-JP.json b/packages/uniswap/src/i18n/locales/translations/ja-JP.json index 557ddcda29f..3b777b18720 100644 --- a/packages/uniswap/src/i18n/locales/translations/ja-JP.json +++ b/packages/uniswap/src/i18n/locales/translations/ja-JP.json @@ -222,6 +222,7 @@ "common.button.disconnect": "切断", "common.button.dismiss": "閉じる", "common.button.done": "完了しました", + "common.button.edit": "Edit", "common.button.enable": "有効にする", "common.button.finish": "完了", "common.button.goBack": "戻る", @@ -313,7 +314,6 @@ "common.custom": "カスタム", "common.customRange": "カスタム範囲", "common.dataOutdated": "データが古い可能性があります", - "common.dataUnavailable": "データを利用できません", "common.default": "デフォルト", "common.defaultTradeOptions": "デフォルトの取引オプション", "common.delegate.cancelled": "委任がキャンセルされました", @@ -461,6 +461,7 @@ "common.networkCost": "ネットワークコスト", "common.neverMind": "気にしないでください", "common.new": "新しい", + "common.new.exclamation": "New!", "common.nfts": "NFT", "common.noActivity": "まだアクティビティがありません", "common.noAmount.error": "金額を入力してください", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "国または地域で検索", "fiatOnRamp.region.title": "お住まいの地域を選択してください", "fiatOnRamp.summary.total": "{{cryptoAmount}} - 次に相当:{{fiatAmount}}", - "forceUpgrade.action.confirm": "アプリを更新", + "forceUpgrade.action.confirm": "Update now", "forceUpgrade.action.recoveryPhrase": "回復フレーズを表示する", - "forceUpgrade.description": "お使いの Uniswap ウォレットは古いバージョンで、重要なアップグレードがなされていません。アプリを更新しない場合、または回復フレーズを書き留めていない場合は、アセットにアクセスできなくなります。", + "forceUpgrade.description": "A new version of the app is available. To continue using the Uniswap Wallet, please update it to the latest version.", "forceUpgrade.label.recoveryPhrase": "回復フレーズ", - "forceUpgrade.title": "続行するにはアプリを更新してください", + "forceUpgrade.title": "Update to the latest version", "globalPreferences.title": "グローバル設定", "hero.scroll": "スクロールして詳細をご覧ください", "hero.subtitle": "最大のオンチェーンマーケットプレイスです。イーサリアムやその他 11 以上のチェーンで暗号通貨を売買できます。", @@ -940,7 +941,6 @@ "home.feed.title": "フィード", "home.label.buy": "購入", "home.label.receive": "受け取る", - "home.label.scan": "スキャン", "home.label.send": "送信", "home.label.swap": "スワップ", "home.nfts.title": "NFT", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Uniswap ウォレットアプリを入手", "mobileAppPromo.banner.title": "Uniswap:暗号通貨と NFT ウォレット", "moonpay.poweredBy": "MoonPay USA LLC による Fiat onramp", - "moonpay.rampIframe": "MoonPay Fiat on-ramp iframe", "moonpay.restricted.region": "一部の地域では Moonpay はご利用いただけません。クリックして詳細をご覧ください。", "nav.createAccount.button": "アカウントを作成", "nav.logIn.button": "ログイン", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "回復フレーズを表示する", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 個の他のウォレット", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} 個の他のウォレット", - "onboarding.import.onDeviceRecovery.warning.caption": "他のウォレットもすべてバックアップ済みであることを確認してください。復元する場合は、それぞれの回復フレーズまたは対応する iCloud バックアップが必要になります。", + "onboarding.import.onDeviceRecovery.warning.caption": "Please ensure you have backed up all of the other wallets. If you ever want to restore them, you’ll need their recovery phrases or corresponding {{cloudProvider}} backups.", "onboarding.import.onDeviceRecovery.warning.title": "よろしいですか?", "onboarding.import.title": "ウォレットの追加方法を選択してください", "onboarding.importMnemonic.button.default": "回復フレーズの単語数は 12 個です", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Uniswap Analytics をご覧ください。", "pool.hideClosed": "クローズしたポジションを非表示にする", "pool.import": "プールをインポート", - "pool.import.v2": "V2 プールをインポート", + "pool.import.link.description": "Some v2 positions aren’t displayed automatically.", + "pool.import.positions.v2": "Import V2 positions", + "pool.import.positions.v2.selectPair.description": "Some v2 positions aren’t displayed automatically. Select a token pair to import and view your positions.", + "pool.import.success": "Pool imported", "pool.increaseLiquidity": "流動性を高める", "pool.info": "プール情報", "pool.initialShare": "初期価格とプールシェア", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "30 日間のボリューム", "pool.volume.thirtyDay.short": "30 日間のボリューム", "pool.yourv2": "お客様の V2 流動性", - "poolFinder.connect": "ウォレットに接続してプールを見つけます。", - "poolFinder.create": "プールを作成", - "poolFinder.found": "プールが見つかりました。", - "poolFinder.managePool": "このプールを管理", - "poolFinder.noLiquidity": "このプールにはまだ流動性がありません。", - "poolFinder.noPoolFound": "プールが見つかりません。", - "poolFinder.selectToken": "トークンを選択して、v2 流動性を確認します。", - "poolFinder.tip": "ヒント:このツールを使用して、インターフェイスに自動的に表示されない v2 プールを見つけます。", + "poolFinder.availablePools": "Available pools", + "poolFinder.availablePools.found.description": "v2 pools matching your pair selection.", + "poolFinder.availablePools.notFound.description": "No matching v2 pools found. Double-check your token selection and ensure you’re connected to the correct wallet.", "pools.approving.amount": "{{amount}} を承認中です", "pools.explore": "プールを探索", "position.addHook": "フックを追加", @@ -1500,6 +1497,7 @@ "position.step.price": "初期価格を設定", "position.step.range": "価格範囲を設定", "position.step.select": "トークンペアと手数料を選択", + "position.value": "Position value", "position.valueUnavailable": "流動性が低いため、ポジションの値を利用できません。", "position.your": "お客様のポジション", "positions.welcome": "お客様のポジションへようこそ", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "実施中になっている経過時間がこの時間を超えた場合、トランザクションは取り消されます。", "swap.unsupportedAssets.readMore": "サポートされていないアセットの詳細を読む", "swap.warning.enterLargerAmount.title": "より大きな金額を入力してください", - "swap.warning.expectedFailure": "このトランザクションは失敗することが予想されます", + "swap.warning.expectedFailure.increaseSlippage": "Try increasing your slippage.", + "swap.warning.expectedFailure.titleMay": "This swap may fail", "swap.warning.insufficientBalance.title": "{{currencySymbol}} が足りません", "swap.warning.insufficientGas.button": "{{currencySymbol}} が十分ではありません", "swap.warning.insufficientGas.button.bridge": "{{networkName}} の {{ tokenSymbol }} にスワップ", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "一部のテストネットでは、トークンのスワップ、送信、購入がサポートされていません。", "tdp.stats.unsupportedChainDescription": "{{chain}} のトークンの統計とチャートは {{infoLink}} で入手できます", "tdp.symbolNotFound": "シンボルが見つかりません", + "testnet.modal.swapDeepLink.description.toProdMode": "This action requires testnet mode to be disabled. Testnet mode can be reenabled at anytime within settings.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "This action requires testnet mode to be enabled. Tokens on testnets do not hold any real value. Testnet mode can be disabled at anytime within settings.", + "testnet.modal.swapDeepLink.title.toProdMode": "Disable testnet mode", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Enable testnet mode", "testnet.unsupported": "この機能はテストネットモードではサポートされていません。", "themeToggle.theme": "テーマ", "title.betterPricesMoreListings": "より良い価格。さらに多くのリスティング。OpenSea のようなトップマーケットプレイスで NFT を購入、販売、取引。トレンドのコレクションをご覧ください。", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "価格チャートを読み込めませんでした", "token.priceExplorer.timeRangeLabel.all": "全期間", "token.priceExplorer.timeRangeLabel.day": "1 日", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 Day", "token.priceExplorer.timeRangeLabel.hour": "1 時間", "token.priceExplorer.timeRangeLabel.month": "1 か月", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 Month", "token.priceExplorer.timeRangeLabel.week": "1 週間", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 Week", "token.priceExplorer.timeRangeLabel.year": "1 年", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 Year", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} は利用できません", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} および {{tokenSymbol1}} は利用できません", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs はこれらの手数料を一切受け取りません。", diff --git a/packages/uniswap/src/i18n/locales/translations/ko-KR.json b/packages/uniswap/src/i18n/locales/translations/ko-KR.json index ba074de6327..a87f72e622b 100644 --- a/packages/uniswap/src/i18n/locales/translations/ko-KR.json +++ b/packages/uniswap/src/i18n/locales/translations/ko-KR.json @@ -132,15 +132,15 @@ "addressInput.recipient": "받는 사람", "analytics.allow": "분석 허용", "analytics.allow.message": "당사는 Uniswap Labs 제품에 대한 당신의 경험을 향상시키기 위해 익명화된 데이터를 사용합니다.", - "appRating.button.notReally": "Not really", - "appRating.description": "Let us know if you’re having a good experience with this app", - "appRating.extension.review.description": "Pick a star rating and leave a review on the Chrome Web Store.", - "appRating.extension.review.title": "Review Uniswap Extension?", - "appRating.extension.title": "Enjoying Uniswap Extension?", - "appRating.feedback.button.send": "Send feedback", - "appRating.feedback.description": "Let us know how we can improve your experience", - "appRating.feedback.title": "We’re sorry to hear that.", - "appRating.mobile.title": "Enjoying Uniswap Wallet?", + "appRating.button.notReally": "별로예요", + "appRating.description": "이 앱을 사용하면서 좋은 경험을 했다면 알려주세요", + "appRating.extension.review.description": "별점을 선택하고 Chrome Web Store에 후기를 남겨 주세요.", + "appRating.extension.review.title": "Uniswap Extension을 평가하시겠습니까?", + "appRating.extension.title": "Uniswap Extension을 잘 이용하고 계신가요?", + "appRating.feedback.button.send": "피드백 보내기", + "appRating.feedback.description": "사용자 경험을 어떻게 개선하면 좋을지 알려주세요", + "appRating.feedback.title": "그 말씀을 들으니 안타깝습니다.", + "appRating.mobile.title": "Uniswap 지갑을 잘 이용하고 계신가요?", "bridging.estimatedTime.minutesAndSeconds": "~{{minutes}}분 {{seconds}}초", "bridging.estimatedTime.minutesOnly": "~{{minutes}}분", "bridging.estimatedTime.secondsOnly": "~{{seconds}}초", @@ -222,6 +222,7 @@ "common.button.disconnect": "연결 끊기", "common.button.dismiss": "닫기", "common.button.done": "완료", + "common.button.edit": "편집", "common.button.enable": "활성화", "common.button.finish": "완료", "common.button.goBack": "뒤로가기", @@ -313,7 +314,6 @@ "common.custom": "사용자 정의", "common.customRange": "맞춤 설정 범위", "common.dataOutdated": "데이터가 오래되었을 수 있습니다.", - "common.dataUnavailable": "데이터 없음", "common.default": "기본", "common.defaultTradeOptions": "기본 거래 옵션", "common.delegate.cancelled": "위임 취소됨", @@ -461,6 +461,7 @@ "common.networkCost": "네트워크 비용", "common.neverMind": "괜찮아요", "common.new": "신규", + "common.new.exclamation": "New!", "common.nfts": "NFT", "common.noActivity": "아직 액티비티가 없습니다", "common.noAmount.error": "금액을 입력하세요", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "국가 또는 지역으로 검색", "fiatOnRamp.region.title": "지역을 선택하세요", "fiatOnRamp.summary.total": "{{fiatAmount}} 의 {{cryptoAmount}}", - "forceUpgrade.action.confirm": "앱 업데이트", + "forceUpgrade.action.confirm": "Update now", "forceUpgrade.action.recoveryPhrase": "복구 문구 보기", - "forceUpgrade.description": "사용 중인 Uniswap 지갑 버전이 오래되어 중요한 업그레이드가 누락되었습니다. 앱을 업데이트하지 않거나 복구 문구를 적어두지 않으면 자산에 접근할 수 없습니다.", + "forceUpgrade.description": "A new version of the app is available. To continue using the Uniswap Wallet, please update it to the latest version.", "forceUpgrade.label.recoveryPhrase": "복구 문구", - "forceUpgrade.title": "계속하려면 앱을 업데이트하세요.", + "forceUpgrade.title": "Update to the latest version", "globalPreferences.title": "글로벌 선호도", "hero.scroll": "자세히 알아보려면 스크롤하세요.", "hero.subtitle": "가장 큰 온체인 마켓플레이스. Ethereum 및 11개 이상의 기타 체인에서 암호화폐를 사고 팔 수 있습니다.", @@ -940,7 +941,6 @@ "home.feed.title": "피드", "home.label.buy": "구매", "home.label.receive": "받기", - "home.label.scan": "스캔", "home.label.send": "보내기", "home.label.swap": "스왑", "home.nfts.title": "NFT", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Uniswap 지갑 앱 다운로드", "mobileAppPromo.banner.title": "Uniswap: 암호화폐 및 NFT 지갑", "moonpay.poweredBy": "MoonPay USA LLC에서 제공하는 법정화폐 온램프", - "moonpay.rampIframe": "MoonPay 법정화폐 온램프 iframe", "moonpay.restricted.region": "일부 지역에서는 Moonpay를 사용할 수 없습니다. 자세히 알아보려면 클릭하세요.", "nav.createAccount.button": "계정 생성", "nav.logIn.button": "로그인", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "복구 문구 보기", "onboarding.import.onDeviceRecovery.wallet.count_one": "다른 지갑 +1개", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} 다른 지갑", - "onboarding.import.onDeviceRecovery.warning.caption": "다른 지갑을 모두 백업했는지 확인하세요. 복원하려면 복구 문구나 해당 iCloud 백업이 필요합니다.", + "onboarding.import.onDeviceRecovery.warning.caption": "다른 지갑을 모두 백업했는지 확인하세요. 지갑을 복원하려면 복구 문구나 해당 {{cloudProvider}} 백업이 필요합니다.", "onboarding.import.onDeviceRecovery.warning.title": "확실합니까?", "onboarding.import.title": "지갑 추가 방법을 선택하세요.", "onboarding.importMnemonic.button.default": "내 복구 문구는 12단어입니다", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Uniswap Analytics을 살펴보세요.", "pool.hideClosed": "마감된 포지션 숨기기", "pool.import": "풀 가져오기", - "pool.import.v2": "V2 풀 가져오기", + "pool.import.link.description": "Some v2 positions aren’t displayed automatically.", + "pool.import.positions.v2": "Import V2 positions", + "pool.import.positions.v2.selectPair.description": "Some v2 positions aren’t displayed automatically. Select a token pair to import and view your positions.", + "pool.import.success": "Pool imported", "pool.increaseLiquidity": "유동성 증대", "pool.info": "풀 정보", "pool.initialShare": "초기 가격 및 풀 비율", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "30일 거래량", "pool.volume.thirtyDay.short": "30일 거래량", "pool.yourv2": "당신의 V2 유동성", - "poolFinder.connect": "풀을 찾으려면 지갑에 연결하세요.", - "poolFinder.create": "풀 생성", - "poolFinder.found": "풀 발견!", - "poolFinder.managePool": "이 풀 관리", - "poolFinder.noLiquidity": "이 풀에는 아직 유동성이 없습니다.", - "poolFinder.noPoolFound": "풀을 찾을 수 없습니다.", - "poolFinder.selectToken": "v2 유동성을 찾으려면 토큰을 선택하세요.", - "poolFinder.tip": "팁: 인터페이스에 자동으로 표시되지 않는 v2 풀을 찾으려면 이 도구를 사용하세요.", + "poolFinder.availablePools": "Available pools", + "poolFinder.availablePools.found.description": "v2 pools matching your pair selection.", + "poolFinder.availablePools.notFound.description": "No matching v2 pools found. Double-check your token selection and ensure you’re connected to the correct wallet.", "pools.approving.amount": "{{amount}} 승인 중", "pools.explore": "풀 탐색", "position.addHook": "후크 추가", @@ -1500,6 +1497,7 @@ "position.step.price": "초기 가격 설정", "position.step.range": "가격대 설정", "position.step.select": "토큰 쌍 및 수수료 선택", + "position.value": "Position value", "position.valueUnavailable": "유동성이 낮아서 포지션 값을 사용할 수 없습니다.", "position.your": "당신의 포지션", "positions.welcome": "당신의 포지션에 오신 것을 환영합니다", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "이 기간 이상 보류 중인 경우 트랜잭션이 취소됩니다.", "swap.unsupportedAssets.readMore": "지원되지 않는 자산에 대해 자세히 알아보세요.", "swap.warning.enterLargerAmount.title": "더 큰 금액을 입력하세요", - "swap.warning.expectedFailure": "이 트랜잭션은 실패할 것으로 예상됩니다.", + "swap.warning.expectedFailure.increaseSlippage": "슬리피지를 증가시켜 보세요.", + "swap.warning.expectedFailure.titleMay": "This swap may fail", "swap.warning.insufficientBalance.title": "{{currencySymbol}}이(가) 충분하지 않습니다", "swap.warning.insufficientGas.button": "{{currencySymbol}} 부족", "swap.warning.insufficientGas.button.bridge": "{{networkName}}에서 {{ tokenSymbol }}(으)로 스왑", @@ -1917,7 +1916,7 @@ "swap.warning.rateLimit.title": "요청 제한 초과됨", "swap.warning.router.message": "연결이 끊어졌거나 네트워크가 다운되었을 수 있습니다. 문제가 지속되면 나중에 다시 시도해 보세요.", "swap.warning.router.title": "지금은 이 거래를 완료할 수 없습니다.", - "swap.warning.tokenBlocked.button": "{{tokenSymbol}} is blocked", + "swap.warning.tokenBlocked.button": "{{tokenSymbol}} 차단됨", "swap.warning.uniswapFee.message.default": "Uniswap에서 최상의 경험을 보장하기 위해 수수료가 부과됩니다. 이 스왑에는 수수료가 없습니다.", "swap.warning.uniswapFee.message.included": "Uniswap에 대한 최고의 경험을 보장하기 위해 수수료가 적용되며 이미 이 견적에 포함되어 있습니다.", "swap.warning.uniswapFee.title": "스왑 수수료", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "일부 테스트넷은 토큰 교환, 전송, 구매를 지원하지 않습니다.", "tdp.stats.unsupportedChainDescription": "{{chain}} 에 대한 토큰 통계 및 차트는 {{infoLink}}에서 확인할 수 있습니다.", "tdp.symbolNotFound": "기호를 찾을 수 없습니다", + "testnet.modal.swapDeepLink.description.toProdMode": "이 작업은 테스트넷 모드를 비활성화해야 합니다. 테스트넷 모드는 언제든지 설정에서 다시 활성화할 수 있습니다.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "이 작업은 테스트넷 모드를 활성화해야 합니다. 테스트넷의 토큰은 실제 가치를 보유하지 않습니다. 테스트넷 모드는 언제든지 설정에서 비활성화할 수 있습니다.", + "testnet.modal.swapDeepLink.title.toProdMode": "테스트넷 모드 비활성화", + "testnet.modal.swapDeepLink.title.toTestnetMode": "테스트넷 모드 활성화", "testnet.unsupported": "이 기능은 테스트넷 모드에서는 지원되지 않습니다.", "themeToggle.theme": "테마", "title.betterPricesMoreListings": "더 좋은 가격. 더 많은 목록. OpenSea 같은 상위 마켓플레이스에서 NFT를 사고팔고 거래하세요. 트렌딩 컬렉션을 탐색하세요.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "가격 차트를 로드할 수 없습니다.", "token.priceExplorer.timeRangeLabel.all": "누적", "token.priceExplorer.timeRangeLabel.day": "1D", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 Day", "token.priceExplorer.timeRangeLabel.hour": "상반기", "token.priceExplorer.timeRangeLabel.month": "100만", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 Month", "token.priceExplorer.timeRangeLabel.week": "1주", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 Week", "token.priceExplorer.timeRangeLabel.year": "1년", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 Year", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}}을(를) 사용할 수 없습니다", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} 및 {{tokenSymbol1}}은(는) 사용할 수 없습니다.", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs는 이러한 수수료를 받지 않습니다.", @@ -2016,7 +2023,7 @@ "token.safety.warning.sellFee100.title": "100% 판매 수수료 감지됨", "token.safety.warning.spam.message": "{{tokenSymbol}}이(가) Blockaid에서 스팸으로 표시되었습니다.", "token.safety.warning.spam.title": "스팸 토큰이 감지되었습니다", - "token.safety.warning.spamsUsers": "스팸 사용자", + "token.safety.warning.spamsUsers": "사용자에게 스팸 전송", "token.safety.warning.strong.heading.default_one": "이 토큰은 미국의 주요 중앙 거래소에서 거래되지 않으며 Uniswap에서 자주 스왑되지 않습니다.", "token.safety.warning.strong.heading.default_other": "이러한 토큰은 미국의 주요 중앙 거래소에서 거래되지 않으며 Uniswap에서 자주 스왑되지 않습니다.", "token.safety.warning.strong.heading.named": "{{tokenSymbol}} 은 미국의 주요 중앙 거래소에서 거래되지 않거나 Uniswap에서 자주 스왑되지 않습니다.", diff --git a/packages/uniswap/src/i18n/locales/translations/ms-MY.json b/packages/uniswap/src/i18n/locales/translations/ms-MY.json index a8e87f580e1..99dd8607f26 100644 --- a/packages/uniswap/src/i18n/locales/translations/ms-MY.json +++ b/packages/uniswap/src/i18n/locales/translations/ms-MY.json @@ -222,6 +222,7 @@ "common.button.disconnect": "Putuskan sambungan", "common.button.dismiss": "Tolak", "common.button.done": "Selesai", + "common.button.edit": "Sunting", "common.button.enable": "Dayakan", "common.button.finish": "Selesai", "common.button.goBack": "Pergi balik", @@ -313,7 +314,6 @@ "common.custom": "Adat", "common.customRange": "Julat tersuai", "common.dataOutdated": "Data mungkin sudah lapuk", - "common.dataUnavailable": "Data tidak tersedia", "common.default": "Lalai", "common.defaultTradeOptions": "Pilihan perdagangan lalai", "common.delegate.cancelled": "Perwakilan dibatalkan", @@ -461,6 +461,7 @@ "common.networkCost": "Kos rangkaian", "common.neverMind": "Tidak mengapa", "common.new": "baru", + "common.new.exclamation": "Baru!", "common.nfts": "NFT", "common.noActivity": "Tiada aktiviti lagi", "common.noAmount.error": "Masukkan jumlah", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Cari mengikut negara atau wilayah", "fiatOnRamp.region.title": "Pilih wilayah anda", "fiatOnRamp.summary.total": "{{cryptoAmount}} untuk {{fiatAmount}}", - "forceUpgrade.action.confirm": "Kemas kini apl", + "forceUpgrade.action.confirm": "Kemas kini sekarang", "forceUpgrade.action.recoveryPhrase": "Lihat frasa pemulihan", - "forceUpgrade.description": "Versi Uniswap Wallet yang anda gunakan sudah lapuk dan tiada peningkatan kritikal. Jika anda tidak mengemas kini apl atau anda tidak menulis frasa pemulihan anda, anda tidak akan dapat mengakses aset anda.", + "forceUpgrade.description": "Versi baharu apl tersedia. Untuk terus menggunakan Uniswap Wallet, sila kemas kini kepada versi terkini.", "forceUpgrade.label.recoveryPhrase": "Frasa pemulihan", - "forceUpgrade.title": "Kemas kini apl untuk meneruskan", + "forceUpgrade.title": "Kemas kini kepada versi terkini", "globalPreferences.title": "Pilihan global", "hero.scroll": "Tatal untuk mengetahui lebih lanjut", "hero.subtitle": "Pasaran onchain terbesar. Beli dan jual kripto di Ethereum dan 11+ rantaian lain.", @@ -940,7 +941,6 @@ "home.feed.title": "suapan", "home.label.buy": "Beli", "home.label.receive": "terima", - "home.label.scan": "Imbas", "home.label.send": "Hantar", "home.label.swap": "Tukar", "home.nfts.title": "NFT", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Dapatkan apl Uniswap Wallet", "mobileAppPromo.banner.title": "Uniswap: Dompet Kripto & NFT", "moonpay.poweredBy": "Fiat onramp dikuasakan oleh MoonPay USA LLC", - "moonpay.rampIframe": "MoonPay fiat on-ramp iframe", "moonpay.restricted.region": "Moonpay tidak tersedia di sesetengah wilayah. Klik untuk mengetahui lebih lanjut.", "nav.createAccount.button": "Buat akaun", "nav.logIn.button": "Log masuk", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Lihat frasa pemulihan", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 dompet lain", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} dompet lain", - "onboarding.import.onDeviceRecovery.warning.caption": "Sila pastikan anda telah menyandarkan semua dompet lain. Jika anda mahu memulihkannya, anda memerlukan frasa pemulihan atau sandaran iCloud yang sepadan.", + "onboarding.import.onDeviceRecovery.warning.caption": "Sila pastikan anda telah menyandarkan semua dompet lain. Jika anda mahu memulihkannya, anda memerlukan frasa pemulihan atau sandaran {{cloudProvider}} yang sepadan.", "onboarding.import.onDeviceRecovery.warning.title": "Adakah anda pasti?", "onboarding.import.title": "Pilih cara anda mahu menambah dompet anda", "onboarding.importMnemonic.button.default": "Frasa pemulihan saya ialah 12 patah perkataan", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Terokai Analitis Uniswap.", "pool.hideClosed": "Sembunyikan kedudukan tertutup", "pool.import": "Kolam import", - "pool.import.v2": "Import kolam V2", + "pool.import.link.description": "Sesetengah kedudukan v2 tidak dipaparkan secara automatik.", + "pool.import.positions.v2": "Import kedudukan V2", + "pool.import.positions.v2.selectPair.description": "Sesetengah kedudukan v2 tidak dipaparkan secara automatik. Pilih pasangan token untuk diimport dan melihat kedudukan anda.", + "pool.import.success": "Kolam diimport", "pool.increaseLiquidity": "Meningkatkan kecairan", "pool.info": "Maklumat kolam", "pool.initialShare": "Harga permulaan dan bahagian kolam", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "volum 30 hari", "pool.volume.thirtyDay.short": "30D jld", "pool.yourv2": "Kecairan V2 anda", - "poolFinder.connect": "Sambung ke dompet untuk mencari kolam.", - "poolFinder.create": "Buat kolam", - "poolFinder.found": "Kolam ditemui!", - "poolFinder.managePool": "Uruskan kolam ini", - "poolFinder.noLiquidity": "Anda belum mempunyai kecairan dalam kumpulan ini.", - "poolFinder.noPoolFound": "Tiada kolam ditemui.", - "poolFinder.selectToken": "Pilih token untuk mencari kecairan v2 anda.", - "poolFinder.tip": "Petua: Gunakan alat ini untuk mencari kumpulan v2 yang tidak muncul secara automatik dalam antara muka.", + "poolFinder.availablePools": "Kolam yang tersedia", + "poolFinder.availablePools.found.description": "kolam v2 sepadan dengan pilihan pasangan anda.", + "poolFinder.availablePools.notFound.description": "Tiada kumpulan v2 yang sepadan ditemui. Semak semula pemilihan token anda dan pastikan anda disambungkan ke dompet yang betul.", "pools.approving.amount": "Meluluskan {{amount}}", "pools.explore": "Terokai kolam", "position.addHook": "Tambah Cangkuk", @@ -1500,6 +1497,7 @@ "position.step.price": "Tetapkan harga awal", "position.step.range": "Tetapkan julat harga", "position.step.select": "Pilih pasangan token dan yuran", + "position.value": "Nilai kedudukan", "position.valueUnavailable": "Nilai kedudukan tidak tersedia kerana kecairan yang rendah.", "position.your": "kedudukan awak", "positions.welcome": "Selamat datang ke jawatan anda", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "Urus niaga anda akan kembali jika ia belum selesai lebih daripada tempoh masa ini.", "swap.unsupportedAssets.readMore": "Baca lebih lanjut tentang aset yang tidak disokong", "swap.warning.enterLargerAmount.title": "Masukkan jumlah yang lebih besar", - "swap.warning.expectedFailure": "Urus niaga ini dijangka gagal", + "swap.warning.expectedFailure.increaseSlippage": "Cuba tingkatkan gelinciran anda.", + "swap.warning.expectedFailure.titleMay": "Pertukaran ini mungkin gagal", "swap.warning.insufficientBalance.title": "Anda tidak mempunyai {{currencySymbol}}", "swap.warning.insufficientGas.button": "Tidak cukup {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Tukar kepada {{ tokenSymbol }} pada {{networkName}}", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Sesetengah testnet tidak menyokong pertukaran, penghantaran atau pembelian token.", "tdp.stats.unsupportedChainDescription": "Statistik dan carta token untuk {{chain}} tersedia di {{infoLink}}", "tdp.symbolNotFound": "Simbol tidak ditemui", + "testnet.modal.swapDeepLink.description.toProdMode": "Tindakan ini memerlukan mod testnet untuk dilumpuhkan. Mod Testnet boleh didayakan semula pada bila-bila masa dalam tetapan.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "Tindakan ini memerlukan mod testnet didayakan. Token pada testnets tidak mempunyai sebarang nilai sebenar. Mod Testnet boleh dilumpuhkan pada bila-bila masa dalam tetapan.", + "testnet.modal.swapDeepLink.title.toProdMode": "Lumpuhkan mod testnet", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Dayakan mod testnet", "testnet.unsupported": "Fungsi ini tidak disokong dalam mod testnet.", "themeToggle.theme": "Tema", "title.betterPricesMoreListings": "Harga yang lebih baik. Lebih banyak penyenaraian. Beli, jual dan dagangan NFT merentas pasaran teratas seperti OpenSea. Terokai koleksi sohor kini.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Tidak dapat memuatkan carta harga", "token.priceExplorer.timeRangeLabel.all": "Setiap masa", "token.priceExplorer.timeRangeLabel.day": "1D", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 Hari", "token.priceExplorer.timeRangeLabel.hour": "1H", "token.priceExplorer.timeRangeLabel.month": "1M", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 Bulan", "token.priceExplorer.timeRangeLabel.week": "1W", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 Minggu", "token.priceExplorer.timeRangeLabel.year": "1Y", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 Tahun", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} tidak tersedia", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} dan {{tokenSymbol1}} tidak tersedia", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs tidak menerima sebarang yuran ini.", diff --git a/packages/uniswap/src/i18n/locales/translations/nl-NL.json b/packages/uniswap/src/i18n/locales/translations/nl-NL.json index 6599e497712..9cf4b073a21 100644 --- a/packages/uniswap/src/i18n/locales/translations/nl-NL.json +++ b/packages/uniswap/src/i18n/locales/translations/nl-NL.json @@ -132,15 +132,15 @@ "addressInput.recipient": "Ontvanger", "analytics.allow": "Analytics toestaan", "analytics.allow.message": "We maken gebruik van geanonimiseerde data om je ervaring met Uniswap Labs-producten te verbeteren.", - "appRating.button.notReally": "Not really", - "appRating.description": "Let us know if you’re having a good experience with this app", - "appRating.extension.review.description": "Pick a star rating and leave a review on the Chrome Web Store.", - "appRating.extension.review.title": "Review Uniswap Extension?", - "appRating.extension.title": "Enjoying Uniswap Extension?", - "appRating.feedback.button.send": "Send feedback", - "appRating.feedback.description": "Let us know how we can improve your experience", - "appRating.feedback.title": "We’re sorry to hear that.", - "appRating.mobile.title": "Enjoying Uniswap Wallet?", + "appRating.button.notReally": "Niet echte", + "appRating.description": "Laat ons weten of je goede ervaringen met deze app hebt", + "appRating.extension.review.description": "Kies het aantal sterren en laat een beoordeling achter in de Chrome Web Store.", + "appRating.extension.review.title": "Uniswap Extension beoordelen?", + "appRating.extension.title": "Bevalt Uniswap Extension je?", + "appRating.feedback.button.send": "Feedback verzenden", + "appRating.feedback.description": "Laat ons weten hoe we je ervaring kunnen verbeteren", + "appRating.feedback.title": "Vervelend om te horen.", + "appRating.mobile.title": "Bevalt Uniswap Wallet je?", "bridging.estimatedTime.minutesAndSeconds": "~{{minutes}}min {{seconds}}s", "bridging.estimatedTime.minutesOnly": "~{{minutes}}min", "bridging.estimatedTime.secondsOnly": "~{{seconds}}s", @@ -186,7 +186,7 @@ "common.approvePending": "Goedkeuring in behandeling...", "common.approveSpend": "Uitgaven in {{symbol}} goedkeuren", "common.approving": "Bezig met goedkeuren", - "common.areYouSure": "Are you sure?", + "common.areYouSure": "Weet je het zeker?", "common.automatic": "Automatisch", "common.availableIn": "Uniswap is beschikbaar in: ", "common.availableOnIOSAndroid": "Beschikbaar op iOS en Android", @@ -222,6 +222,7 @@ "common.button.disconnect": "Ontkoppelen", "common.button.dismiss": "Sluiten", "common.button.done": "Gereed", + "common.button.edit": "Bewerken", "common.button.enable": "Inschakelen", "common.button.finish": "Voltooien", "common.button.goBack": "Ga terug", @@ -278,7 +279,7 @@ "common.claimed": "Geclaimd", "common.claiming": "Claimen", "common.claimUnis": "Claim je UNI-tokens", - "common.clear": "Clear", + "common.clear": "Wissen", "common.close": "Sluiten", "common.closed": "Gesloten", "common.collect.button": "Innen", @@ -301,7 +302,7 @@ "common.contactUs.button": "Neem contact met ons op", "common.contractInteraction": "Contractinteractie", "common.copied": "Gekopieerd", - "common.copy.address": "Copy address", + "common.copy.address": "Adres kopiëren", "common.copyLink.button": "Link kopiëren", "common.create.pool.cancelled": "Aanmaken van de pool geannuleerd", "common.create.pool.failed": "Aanmaken van de pool mislukt", @@ -313,7 +314,6 @@ "common.custom": "Aangepast", "common.customRange": "Aangepast bereik", "common.dataOutdated": "De data zijn mogelijk verouderd", - "common.dataUnavailable": "Data unavailable", "common.default": "Standaard", "common.defaultTradeOptions": "Standaard handelsopties", "common.delegate.cancelled": "Delegeren geannuleerd", @@ -342,7 +342,7 @@ "common.downloadPlayStore": "In de Play Store downloaden", "common.downloadUniswap": "Uniswap downloaden", "common.downloadUniswapApp": "De Uniswap-app downloaden", - "common.dynamic": "Dynamic", + "common.dynamic": "Dynamisch", "common.edit.button": "Bewerken", "common.error.general": "Er is iets fout gegaan", "common.error.label": "Fout", @@ -372,7 +372,7 @@ "common.feesEarned.label": "In {{symbol}} verdiende vergoedingen:", "common.feesEarnedPerBase": "{{symbolA}} per {{symbolB}}", "common.fetchingRoute": "Bezig route op te halen", - "common.flag": "Flag", + "common.flag": "Markering", "common.floor": "Bodem", "common.floorPrice": "Bodemprijs", "common.for": "Voor", @@ -444,7 +444,7 @@ "common.migrate.liquidity.cancelled": "Migreren van de liquiditeit is geannuleerd", "common.migrate.liquidity.failed": "Migreren van de liquiditeit is mislukt", "common.migrate.position": "Positie migreren", - "common.migrate.v3": "Migrate to V3", + "common.migrate.v3": "Migreren naar v3", "common.migrated.liquidity": "Gemigreerde liquiditeit", "common.migrating.liquidity": "Liquiditeit migreren", "common.min": "Minimum", @@ -461,6 +461,7 @@ "common.networkCost": "Netwerkkosten", "common.neverMind": "Laat maar zitten", "common.new": "Nieuw", + "common.new.exclamation": "Nieuw", "common.nfts": "NFT's", "common.noActivity": "Nog geen activiteit", "common.noAmount.error": "Een bedrag invoeren", @@ -499,11 +500,11 @@ "common.price": "Prijs", "common.priceImpact": "Waarschuwing voor prijsimpact", "common.priceUpdated": "Prijs bijgewerkt", - "common.privacyChoices": "Your Privacy Choices", - "common.privacyChoices.checkbox.description": "When checked, we will not share your data with third-party partners for personalized advertising. You can enable sharing anytime by unchecking this box.", - "common.privacyChoices.checkbox.label": "Do not share my information", - "common.privacyChoices.description": "We may share device identifiers with our advertising partners to promote our services on other websites and platforms. Where this qualifies as selling, sharing or targeted advertising under applicable laws, you can opt out by checking the \"do not share my information\" box. For more information about our privacy practices please review our Privacy Policy.", - "common.privacyChoices.disclaimer": "Please note that your selection will apply only to this browser on this device. You can also opt out by enabling the Global Privacy Control setting within the browser that you use to access our services. To see more options, go to your settings.", + "common.privacyChoices": "Jouw privacyvoorkeuren", + "common.privacyChoices.checkbox.description": "Als je dit aanvinkt, delen we je gegevens niet met externe partners voor gepersonaliseerde advertenties. Je kunt delen op elk moment toestaan door dit vakje uit te vinken.", + "common.privacyChoices.checkbox.label": "Mijn gegevens niet delen", + "common.privacyChoices.description": "Wij kunnen apparaat-ID's met onze advertentiepartners delen om onze diensten op andere websites en platformen te promoten. In gevallen waar dit volgens de toepasselijke wetgeving wordt beschouwd als het verkopen, delen of gericht adverteren, kun je je hiervoor afmelden door het vakje Mijn gegevens niet delen aan te vinken. Raadpleeg ons privacybeleid voor meer informatie over onze privacypraktijken.", + "common.privacyChoices.disclaimer": "Houd er rekening mee dat je selectie alleen in deze browser op dit apparaat van toepassing is. Je kunt je ook afmelden voor het delen van je gegevens door de instelling Global Privacy Control in te schakelen voor de browser die je gebruikt om toegang te krijgen tot onze diensten. Ga naar je instellingen om meer opties te bekijken.", "common.privacyPolicy": "Privacybeleid", "common.proceed": "Ga verder", "common.proceedInWallet": "Verdergaan in je wallet", @@ -659,7 +660,7 @@ "common.unwrap.failed": "Unwrappen mislukt", "common.unwrapped": "Uitgepakt", "common.unwrapping": "Bezig met unwrappen", - "common.view.profile": "View profile", + "common.view.profile": "Houd er rekening mee dat je selectie alleen op deze browser op dit apparaat van toepassing is. Je kunt je ook afmelden voor het delen van je gegevens door de instelling Global Privacy Control in te schakelen voor de browser die je gebruikt om toegang te krijgen tot onze diensten. Ga naar je instellingen om meer opties te bekijken.", "common.viewOnBlockExplorer": "In Block Explorer bekijken", "common.viewOnExplorer": "In verkenner bekijken", "common.volume": "Volume", @@ -763,7 +764,7 @@ "errors.crash.message": "Er is iets gecrasht.", "errors.crash.restart": "Start de app opnieuw", "errors.crash.title": "Oh, oh!", - "explore.more.pools": "Explore more pools", + "explore.more.pools": "Meer pools verkennen", "explore.search.action.clear": "Duidelijk", "explore.search.action.viewEtherscan": "In {{blockExplorerName}} bekijken", "explore.search.empty.full": "Geen resultaten voor \"{{searchQuery}}\" gevonden", @@ -838,33 +839,33 @@ "fee.bestForMost": "Het beste voor de meeste paren.", "fee.bestForStablePairs": "Het beste voor stabiele paren.", "fee.bestForVeryStable": "Het beste voor zeer stabiele paren.", - "fee.dynamic": "Dynamic fee", + "fee.dynamic": "Dynamische transactiekosten", "fee.percentEarned": "Het percentage dat je aan vergoedingen verdient.", "fee.selectPercent": "{{pct}}% selecteren", "fee.tier": "Vergoedingsniveau", "fee.tier.create": "Vergoedingsniveau aanmaken", "fee.tier.create.button": "Nieuw vergoedingsniveau aanmaken", "fee.tier.create.description": "Als je een nieuw niveau aanmaakt, wordt deze in een nieuwe pool geïnitialiseerd. Dit leidt tot hogere netwerkkosten dan normaal.", - "fee.tier.description": "The amount earned providing liquidity. Choose an amount that suits your risk tolerance and strategy.", - "fee.tier.description.v2": "The amount earned providing liquidity. All v2 pools have fixed 0.3% fees. For more options, provide liquidity on v4.", - "fee.tier.dynamic": "Dynamic fee tier", - "fee.tier.dynamic.create": "Creating dynamic fee tier", - "fee.tier.dynamic.create.info": "You are about to create a pool with a dynamic fee tier. Before proceeding, please ensure that the selected hook supports dynamic fees.", + "fee.tier.description": "Het bedrag dat je verdient door liquiditeit te verstrekken. Kies een bedrag dat past bij je risicotolerantie en -strategie.", + "fee.tier.description.v2": "Het bedrag dat je verdient door liquiditeit te verstrekken. Alle v2-pools hebben vaste kosten van 0,3%. Voor meer opties kun je liquiditeit verstrekken op v4.", + "fee.tier.dynamic": "Dynamisch kostenniveau", + "fee.tier.dynamic.create": "Dynamisch kostenniveau aanmaken", + "fee.tier.dynamic.create.info": "Je staat op het punt een pool aan te maken met een dynamisch kostenniveau. Controleer voordat je doorgaat of de gekozen hook dynamische kosten ondersteunt.", "fee.tier.label": "Het percentage dat je aan vergoedingen zult verdienen", "fee.tier.missing.description": "Kun je het niveau dat je zoekt niet vinden?", "fee.tier.new": "Nieuw niveau", - "fee.tier.percent.select": "{{percentage}} select", + "fee.tier.percent.select": "{{percentage}} selecteren", "fee.tier.recommended": "Aanbevolen", - "fee.tier.search": "Search or create other fee tiers", + "fee.tier.search": "Andere kostenniveaus zoeken of aanmaken", "fee.tier.search.short": "Niveaus zoeken", "fee.tier.select": "Vergoedingsniveau selecteren", "fee.tier.select.existing.button": "Een bestaand vergoedingsniveau selecteren", "fee.tierExact": "{{fee}} vergoedingsniveau", - "fee.unavailable": "Earned fees are not visible for v2 positions until liquidity is removed.", - "fee.uncollected": "Includes uncollected fees:", + "fee.unavailable": "Verdiende vergoedingen zijn voor v2-posities pas zichtbaar nadat de liquiditeit is verwijderd.", + "fee.uncollected": "Inclusief ongeïnde transactiekosten:", "fiatOffRamp.checkout.title": "Verkopen met", "fiatOffRamp.connection.quote": "{{amount}} ter waarde van {{currencySymbol}} verkopen", - "fiatOffRamp.error.balance": "Exceeds balance", + "fiatOffRamp.error.balance": "Overschrijdt saldo", "fiatOffRamp.unsupportedToken.back": "Ga terug", "fiatOffRamp.unsupportedToken.divider": "Niet-ondersteunde tokens", "fiatOffRamp.unsupportedToken.message": "Deze token wordt niet ondersteund om te verkopen. Swap deze asset naar een van de ondersteunde tokens.", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Zoeken op land of regio", "fiatOnRamp.region.title": "Selecteer je regio", "fiatOnRamp.summary.total": "{{cryptoAmount}} voor {{fiatAmount}}", - "forceUpgrade.action.confirm": "App bijwerken", + "forceUpgrade.action.confirm": "Nu bijwerken", "forceUpgrade.action.recoveryPhrase": "Herstelzin bekijken", - "forceUpgrade.description": "De versie van de Uniswap Wallet die je gebruikt is verouderd en mist belangrijke upgrades. Als je de app niet bijwerkt of je herstelzin niet hebt opgeschreven, kun je geen toegang krijgen tot je assets.", + "forceUpgrade.description": "Er is een nieuwe versie van de app beschikbaar. Update de app naar de nieuwste versie om de Uniswap Wallet te kunnen blijven gebruiken.", "forceUpgrade.label.recoveryPhrase": "Herstelzin", - "forceUpgrade.title": "App bijwerken om door te gaan", + "forceUpgrade.title": "Bijwerken naar de nieuwste versie", "globalPreferences.title": "Globale voorkeuren", "hero.scroll": "Scrol voor meer informatie", "hero.subtitle": "De grootste on-chain marketplace. Koop en verkoop crypto op Ethereum en 11+ andere chains.", @@ -940,15 +941,14 @@ "home.feed.title": "Feed", "home.label.buy": "Kopen", "home.label.receive": "Ontvangen", - "home.label.scan": "Scannen", "home.label.send": "Versturen", "home.label.swap": "Swappen", "home.nfts.title": "NFT's", - "home.tokens.empty.action.buy.description": "Purchase with a debit card or bank account.", - "home.tokens.empty.action.buy.title": "Buy Crypto", + "home.tokens.empty.action.buy.description": "Koop met een betaalpas of via een bankrekening.", + "home.tokens.empty.action.buy.title": "Crypto kopen", "home.tokens.empty.action.import.description": "Voer de herstelzin van deze wallet in om te beginnen met swappen en versturen.", "home.tokens.empty.action.import.title": "Wallet importeren", - "home.tokens.empty.action.receive.description": "Transfer from another wallet or account.", + "home.tokens.empty.action.receive.description": "Overboeking vanuit een andere wallet of ander account.", "home.tokens.empty.action.receive.title": "Crypto ontvangen", "home.tokens.empty.description": "Wanneer deze wallet tokens koopt of ontvangt, worden deze hier weergegeven.", "home.tokens.empty.title": "Nog geen tokens", @@ -1029,7 +1029,7 @@ "liquidity.provideOnProtocols": "Liquiditeit aan verschillende protocollen bieden", "liquidityPool.chart.tooltip.amount": "Liquiditeit van {{token}}: {{amount}}", "liquidityPool.page.title": "Voeg liquiditeit aan pools{{version}} toe op Uniswap", - "liquidityPool.positions.closed.title": "Closed positions", + "liquidityPool.positions.closed.title": "Gesloten posities", "liquidityPool.positions.page.title": "Beheer {{quoteSymbol}}/{{baseSymbol}} poolliquiditeit op Uniswap", "liquidityPool.positions.page.version.description": "Bekijk je actieve liquiditeitsposities van {{version}}. Voeg nieuwe posities toe.", "liquidityPool.positions.page.version.title": "Beheer de liquiditeit van de pool in {{version}} op Uniswap", @@ -1064,14 +1064,13 @@ "mobileAppPromo.banner.getTheApp.link": "Download de Uniswap Wallet-app", "mobileAppPromo.banner.title": "Uniswap: Crypto- en NFT-wallet", "moonpay.poweredBy": "Fiat-onramp wordt mogelijk gemaakt door MoonPay USA LLC", - "moonpay.rampIframe": "MoonPay fiat-onramp iframe", "moonpay.restricted.region": "Moonpay is in sommige regio's niet beschikbaar. Klik voor meer informatie.", "nav.createAccount.button": "Account aanmaken", "nav.logIn.button": "Inloggen", "nav.signIn.button": "Aanmelden", "nav.signUp.button": "Registreren", "nav.tabs.createPosition": "Positie aanmaken", - "nav.tabs.viewPositions": "View positions", + "nav.tabs.viewPositions": "Posities bekijken", "network.lostConnection": "Mogelijk is je netwerkverbinding verbroken.", "network.mightBeDown": "Het kan zijn dat {{network}} momenteel niet beschikbaar is of dat je netwerkverbinding is verbroken.", "network.warning": "Netwerkwaarschuwing", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Herstelzin bekijken", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 andere wallet", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} andere wallets", - "onboarding.import.onDeviceRecovery.warning.caption": "Zorg ervoor dat je een back-up hebt gemaakt van alle andere wallets. Als je deze ooit wilt herstellen, heb je de herstelzinnen of bijbehorende iCloud-reservekopieën nodig.", + "onboarding.import.onDeviceRecovery.warning.caption": "Zorg ervoor dat je een back-up van alle andere wallets hebt gemaakt. Als je deze ooit wilt herstellen, heb je de herstelzinnen of bijbehorende back-ups vanuit {{cloudProvider}} nodig.", "onboarding.import.onDeviceRecovery.warning.title": "Weet je het zeker?", "onboarding.import.title": "Kies hoe je je wallet wilt toevoegen", "onboarding.importMnemonic.button.default": "Mijn herstelzin heeft 12 woorden", @@ -1347,7 +1346,7 @@ "pool.areFirst": "Je bent de eerste liquiditeitsverschaffer.", "pool.back": "Terug naar de pool", "pool.balances": "Poolsaldi", - "pool.closedCTA.description": "Je kunt deze zien door de filter aan de bovenzijde van de pagina te gebruiken.", + "pool.closedCTA.description": "Je kunt deze zien door het filter bovenaan de pagina te gebruiken.", "pool.closedCTA.title": "Zoek je gesloten posities?", "pool.collectAs": "Innen als {{nativeWrappedSymbol}}", "pool.collected": "Geïnd", @@ -1360,9 +1359,9 @@ "pool.create.info": "Je selecties creëren een nieuwe liquiditeitspool die kan resulteren in een lagere initiële liquiditeit en een hogere volatiliteit. Overweeg om een bestaande pool uit te breiden om deze risico's te minimaliseren.", "pool.create.pair": "Een paar aanmaken", "pool.createAndSupply": "Pool en aanbod aanmaken", - "pool.createdPosition": "Created position", - "pool.createdPosition.cancelled": "Create position cancelled", - "pool.createdPosition.failed": "Create position failed", + "pool.createdPosition": "Positie aangemaakt", + "pool.createdPosition.cancelled": "Positie aanmaken geannuleerd", + "pool.createdPosition.failed": "Positie aanmaken mislukt", "pool.depositAmounts": "Stortingsbedragen", "pool.earnFees": "Door liquiditeit toe te voegen, verdien je 0,3% van alle transacties op dit paar, proportioneel aan jouw aandeel in de pool. Vergoedingen worden toegevoegd aan de pool, ontstaan in realtime en kunnen worden geclaimd door je liquiditeit op te nemen.", "pool.estimatePercentToRevert": "De output wordt geschat. Als de prijs met meer dan {{allowed}}% verandert, wordt je transactie teruggedraaid.", @@ -1370,9 +1369,12 @@ "pool.exporeAnalytics": "Ontdek Uniswap Analytics.", "pool.hideClosed": "Verberg gesloten posities", "pool.import": "Pool importeren", - "pool.import.v2": "V2-pool importeren", + "pool.import.link.description": "Some v2 positions aren’t displayed automatically.", + "pool.import.positions.v2": "Import V2 positions", + "pool.import.positions.v2.selectPair.description": "Some v2 positions aren’t displayed automatically. Select a token pair to import and view your positions.", + "pool.import.success": "Pool imported", "pool.increaseLiquidity": "Verhoog de liquiditeit", - "pool.info": "Pool info", + "pool.info": "Poolinformatie", "pool.initialShare": "Initiële prijzen en poolaandeel", "pool.learn": "Meer informatie", "pool.learnAbout": "Lees meer over het verstrekken van liquiditeit", @@ -1380,10 +1382,10 @@ "pool.learnv3LP": "Bekijk onze v3 LP-stappenplan en migratiehandleidingen.", "pool.limitFluctuation.warning": "Houd er rekening mee dat de uitvoering van limieten kan variëren op basis van realtime marktfluctuaties en congestie op het Ethereum-netwerk. Limieten worden mogelijk niet exact uitgevoerd wanneer tokens de opgegeven prijs bereiken.", "pool.liquidity.connectToAdd": "Maak verbinding met een wallet om je liquiditeit te bekijken.", - "pool.liquidity.data.error.message": "There was an error fetching data required for your transaction.", + "pool.liquidity.data.error.message": "Er is een fout opgetreden bij het ophalen van de gegevens die nodig zijn voor je transactie.", "pool.liquidity.earn.fee": "Liquiditeitsverschaffers verdienen een vergoeding van 0,3% op alle transacties, proportioneel aan hun aandeel in de pool. Vergoedingen worden toegevoegd aan de pool, ontstaan in realtime en kunnen worden opgeëist door je liquiditeit op te nemen.", - "pool.liquidity.outOfSync": "Pool prices out of sync", - "pool.liquidity.outOfSync.message": "Prices in this pool are out of sync with the current market. Adding liquidity may result in a loss of funds.", + "pool.liquidity.outOfSync": "Poolprijzen niet synchroon", + "pool.liquidity.outOfSync.message": "De prijzen in deze pool zijn niet gesynchroniseerd met de huidige markt. Als je liquiditeit toevoegt, kan dat resulteren in geldverlies.", "pool.liquidity.ownershipWarning.message": "Je bent niet de eigenaar van deze LP-positie. Je kunt de liquiditeit uit deze positie niet opnemen tenzij je eigenaar bent van het volgende adres: {{ownerAddress}}", "pool.liquidity.rewards": "Beloningen voor liquiditeitsverschaffers", "pool.liquidity.taxWarning": "Tokenbelastingen", @@ -1393,7 +1395,7 @@ "pool.max.label": "Maximum:", "pool.maxPrice": "Maximale prijs", "pool.migrateLiquidity": "Liquiditeit migreren", - "pool.migrateToV4": "Migrate to v4", + "pool.migrateToV4": "Migreren naar v4", "pool.min.label": "Minimum:", "pool.minPrice": "Minimale prijs", "pool.mustBeInitialized": "Deze pool moet worden geïnitialiseerd voordat je liquiditeit kunt toevoegen. Om te initialiseren, selecteer je een startprijs voor de pool. Voer vervolgens je liquiditeitsprijsbereik en stortingsbedrag in. De gasvergoedingen zullen hoger zijn dan normaal vanwege de initialisatietransactie.", @@ -1415,7 +1417,7 @@ "pool.position.willBe100": "Tegen deze prijs bestaat je positie voor 100% uit {{sym}}", "pool.positions": "Posities", "pool.positions.title": "Je posities", - "pool.positions.transaction.settings": "Transaction settings", + "pool.positions.transaction.settings": "Transactie-instellingen", "pool.priceRange": "Prijsbereik", "pool.rangeBadge.tooltip.outsideRange": "De prijs van deze pool ligt buiten het door jou geselecteerde bereik. Voor je positie worden momenteel geen vergoedingen gegenereerd.", "pool.rangeBadge.tooltip.text": "Je positie heeft geen liquiditeit en genereert geen vergoedingen.", @@ -1436,7 +1438,7 @@ "pool.supplyingMaths": "Aanbieden van {{amtA}} {{symA}} en {{amtB}} {{symB}}", "pool.tokenPair": "Tokenpaar", "pool.top": "Toppools", - "pool.top.tvl": "Top pools by TVL", + "pool.top.tvl": "Beste pools op basis van TVL", "pool.totalTokens": "Je totale pooltokens:", "pool.uncollectedFees": "Niet-geïnde vergoedingen", "pool.v2": "v2-pools", @@ -1445,40 +1447,35 @@ "pool.v2liquidity": "V2-liquiditeit", "pool.v3": "v3-pools", "pool.v4": "v4-pools", - "pool.viewUncollectedFees": "View uncollected fees and analytics", + "pool.viewUncollectedFees": "Ongeïnde transactiekosten en analyses bekijken", "pool.volOverTvl": "1D vol/Totale waarde vergrendeld (TVL)", - "pool.volume.thirtyDay": "30 day volume", - "pool.volume.thirtyDay.short": "30D vol", + "pool.volume.thirtyDay": "30-daags volume", + "pool.volume.thirtyDay.short": "30-d vol", "pool.yourv2": "Je V2-liquiditeit", - "poolFinder.connect": "Maak verbinding met een wallet om pools te vinden.", - "poolFinder.create": "Een pool aanmaken", - "poolFinder.found": "Pool gevonden!", - "poolFinder.managePool": "Beheer deze pool", - "poolFinder.noLiquidity": "Je hebt nog geen liquiditeit in deze pool.", - "poolFinder.noPoolFound": "Geen pool gevonden.", - "poolFinder.selectToken": "Selecteer een token om je v2-liquiditeit te vinden.", - "poolFinder.tip": "Tip: Gebruik deze tool om v2-pools te vinden die niet automatisch in de interface verschijnen.", + "poolFinder.availablePools": "Available pools", + "poolFinder.availablePools.found.description": "v2 pools matching your pair selection.", + "poolFinder.availablePools.notFound.description": "No matching v2 pools found. Double-check your token selection and ensure you’re connected to the correct wallet.", "pools.approving.amount": " {{amount}} goedkeuren", "pools.explore": "Pools verkennen", "position.addHook": "Een hook toevoegen", "position.addHook.tooltip": "Hooks zijn een geavanceerde functie die het mogelijk maken voor pools om te interageren met smartcontracten, waardoor verschillende mogelijkheden beschikbaar worden. Wees voorzichtig bij het toevoegen van hooks, aangezien sommige kwaadaardig kunnen zijn of onbedoelde gevolgen kunnen hebben.", - "position.addingHook": "Een hook toevoegen", - "position.addingHook.disclaimer": "Het toevoegen van hooks kan tot onbedoelde gevolgen leiden. Doe onderzoek en vervolg op eigen risico.", - "position.addingHook.invalidAddress": "Enter a valid hook address", + "position.addingHook": "Hook toevoegen", + "position.addingHook.disclaimer": "Het toevoegen van hooks kan onvoorziene gevolgen hebben. Doe je onderzoek en ga verder op eigen risico.", + "position.addingHook.invalidAddress": "Voer een geldig hook-adres in", "position.addingHook.viewProperties": "Eigenschappen bekijken", "position.appearHere": "Je positie wordt hier weergegeven.", - "position.create.invalidPrice": "Invalid price", - "position.create.invalidRange": "Invalid range", + "position.create.invalidPrice": "Ongeldige prijs", + "position.create.invalidRange": "Ongeldig bereik", "position.create.modal.header": "Positie aanmaken", "position.currentValue": "Huidige positiewaarden", "position.deposit.description": "Geef de tokenbedragen voor je liquiditeitsbijdrage op.", "position.depositedCurrency": "{{currencySymbol}} gestort", "position.hook.disclaimer": "Ik begrijp de risico´s.", - "position.hook.liquidityWarning": "Deze vlag kan ertoe leiden dat de pool de toevoeging van nieuw liquiditeit blokkeert. Je transactie kan worden teruggedraaid.", - "position.hook.removeWarning": "Deze vlag kan ertoe lieden dat je vermogen wordt vergrendeld of geblokkeerd waardoor je geen vergoedingen kunt innen.", - "position.hook.swapWarning": "Met deze vlag kunnen geavanceerde gebruikers gemakkelijker Just-In-Time liquiditeit benutten, wat resulteert in lagere verdiende vergoedingen.", - "position.hook.warningHeader": "Er is een hook met hoog risico gedetecteerd", - "position.hook.warningInfo": "We hebben potentiële risico's met deze hook geïdentificeerd. Beoordeel de vlaggen en controleer dat dit de hook is die je wilt gebruiken voordat je verder gaat.", + "position.hook.liquidityWarning": "Deze melding kan ervoor zorgen dat de pool het toevoegen van nieuwe liquiditeit blokkeert. Je transactie kan worden teruggedraaid.", + "position.hook.removeWarning": "Deze melding kan ervoor zorgen dat je geld wordt vergrendeld of dat je geen vergoedingen kunt innen.", + "position.hook.swapWarning": "Met deze melding kunnen geavanceerde gebruikers gemakkelijker just-in-time-liquiditeit benutten, wat resulteert in lagere vergoedingen.", + "position.hook.warningHeader": "Hoogrisico-hook gedetecteerd", + "position.hook.warningInfo": "We hebben mogelijke risico's met deze hook geïdentificeerd. Controleer de meldingen en verifieer dat dit de hook is die je wilt gebruiken voordat je verdergaat.", "position.initialPrice": "Initiële prijs", "position.initialPrice.info": "Stel de startwisselkoers in tussen de 2 tokens die je aanbiedt.", "position.migrate.liquidity": "Bij het migreren van posities kun je je tokenpaar niet wijzigen, maar je kunt wel een hook toevoegen om de functionaliteit te verbeteren.", @@ -1486,20 +1483,21 @@ "position.new.protocol": "Nieuwe {{protocol}}-positie", "position.noLiquidity": "Liquiditeitsdata zijn niet beschikbaar.", "position.noLiquidityData": "Er zijn geen liquiditeitsdata.", - "position.notFound": "Kon de positie niet vinden", + "position.notFound": "Positie niet gevonden", "position.notFound.description": "Details over deze positie zijn niet beschikbaar. Controleer of je met de juiste wallet bent verbonden.", "position.protocol": "{{protocol}} positie", "position.provide.liquidity": "Kies de tokens waarvoor je liquiditeit wilt bieden. Je kunt tokens op alle ondersteunde netwerken selecteren.", "position.provide.liquidityDescription": "Het verstrekken van liquiditeit over het volledige bereik zorgt voor continue marktdeelname over alle mogelijke prijzen. Dit biedt eenvoud, maar brengt ook de mogelijkheid van hogere tijdelijke verliezen met zich mee.", - "position.provide.liquidityDescription.custom": "Custom range allows you to concentrate your liquidity within specific price bounds, enhancing capital efficiency and fee earnings but requiring more active management.", - "position.removeHook": "De hook verwijderen", - "position.resetDescription": "Your tokens, price, and range selections will be reset.", + "position.provide.liquidityDescription.custom": "Met een aangepast bereik kun je je liquiditeit concentreren binnen specifieke prijsgrenzen, wat leidt tot een betere kapitaalefficiëntie en hogere inkomsten van transactiekosten. Dit vereist wel actiever beheer.", + "position.removeHook": "Hook verwijderen", + "position.resetDescription": "Je selectie voor tokens, prijzen en bereik wordt gereset.", "position.setRange": "Prijsbereik instellen", - "position.setRange.inputsBelow": "Use the inputs below to set your range.", + "position.setRange.inputsBelow": "Gebruik de onderstaande invoeren om je bereik in te stellen.", "position.step.deposit": "Stortingsbedragen invoeren", "position.step.price": "Initiële prijs instellen", "position.step.range": "Prijsbereik instellen", "position.step.select": "Selecteer tokenpaar en vergoedingen", + "position.value": "Position value", "position.valueUnavailable": "De positiewaarde is niet beschikbaar vanwege lage liquiditeit.", "position.your": "Jouw positie", "positions.welcome": "Welkom bij je posities", @@ -1530,18 +1528,18 @@ "qrScanner.title": "Scan een QR-code", "qrScanner.wallet.networks": "Ondersteunde netwerken", "qrScanner.wallet.title": "Je kunt op al onze {{numOfNetworks}} ondersteunde netwerken tokens en NFT's versturen en ontvangen.", - "range.outOfView": "Range out of view", + "range.outOfView": "Bereik niet zichtbaar", "removeLiquidity.collectFees": "Je int ook de vergoedingen die je uit deze functie verdient.", "removeLiquidity.outputEstimated": "De output wordt geschat. Als de prijs met meer dan {{allowed}}% verandert, wordt je transactie teruggedraaid.", "removeLiquidity.pendingText": "{{amtA}} {{symA}} en {{amtB}} {{symB}} verwijderen", "removeLiquidity.pooled": "Gepoold {{symbol}}:", "removeLiquidity.removing": "{{amt1}} {{symbol1}} en {{amt2}} {{symbol2}} verwijderen", - "removeLiquidity.removingTokensTip": "Tip: Removing pool tokens converts your position back into underlying tokens at the current rate, proportional to your share of the pool. Uncollected fees are included in the amounts you receive.", + "removeLiquidity.removingTokensTip": "Tip: Als je pooltokens verwijdert, wordt je positie tegen de huidige koers terugggezet naar de onderliggende tokens, evenredig aan je aandeel in de pool. Ongeïnde transacties zijn inbegrepen in je ontvangen bedragen.", "removeLiquidity.uniBurned": "UNI {{a}}/{{b}} verbrand", "revoke.failed.message": "Hiermee krijgt het Uniswap Protocol toegang tot je token om te traden.", "routing.aggregateLiquidity": "Indien beschikbaar worden liquiditeitsbronnen samengevoegd voor betere prijzen en gasvrij swappen.", "routing.cheapest": "De Uniswap-cliënt kiest de goedkoopste handelsoptie, rekening houdend met prijs en netwerkkosten.", - "routing.cheapest.v4": "The Uniswap client selects the optimal trade option factoring in price and network costs.", + "routing.cheapest.v4": "De Uniswap Client selecteert de optimale tradingoptie, waarbij rekening wordt gehouden met de prijs en netwerkkosten.", "scantastic.code.expired": "Verlopen", "scantastic.code.subtitle": "Voer deze code in de Uniswap Extension in. Je herstelzin wordt veilig gecodeerd en overgedragen.", "scantastic.code.timeRemaining.shorthand.hours": "Nieuwe code over {{hours}}u {{minutes}}m {{seconds}}s", @@ -1762,7 +1760,7 @@ "swap.approveInWallet": "In je wallet goedkeuren", "swap.balance.amount": "Saldo: {{amount}}", "swap.bestRoute.cost": "De beste prijsroute kost ongeveer {{gasPrice}} aan gas.", - "swap.bestRoute.cost.v4": "Optimal route costs ~{{gasPrice}} in gas. ", + "swap.bestRoute.cost.v4": "De optimale route kost ongeveer {{gasPrice}} aan benzine. ", "swap.bridging.estimatedTime": "Geschatte tijd", "swap.bridging.title": "Swappen tussen netwerken", "swap.bridging.warning.description": "Je swapt van {{fromNetwork}} naar {{toNetwork}}. Dit staat ook bekend als bridgen, waarbij je tokens van het ene netwerk naar het andere worden verplaatst.", @@ -1848,8 +1846,8 @@ "swap.settings.protection.subtitle.supported": "{{chainName}}-netwerk", "swap.settings.protection.subtitle.unavailable": "Niet beschikbaar op {{chainName}}", "swap.settings.protection.title": "Swapbescherming", - "swap.settings.routingPreference.option.default.description": "The Uniswap client selects the cheapest trade option factoring in price and network costs.", - "swap.settings.routingPreference.option.default.description.v4": "The Uniswap client selects the optimal trade option factoring in price and network costs.", + "swap.settings.routingPreference.option.default.description": "De Uniswap Client selecteert de goedkoopste tradingoptie, waarbij rekening wordt gehouden met de prijs en netwerkkosten.", + "swap.settings.routingPreference.option.default.description.v4": "De Uniswap Client selecteert de optimale tradingoptie, waarbij rekening wordt gehouden met de prijs en netwerkkosten.", "swap.settings.routingPreference.option.v2.title": "v2-pools", "swap.settings.routingPreference.option.v3.title": "v3-pools", "swap.settings.routingPreference.option.v4.title": "v4-pools", @@ -1878,12 +1876,13 @@ "swap.taxTooltip.tokenSelected": "{{tokenSymbol}}-kosten staan geen nauwkeurige, exacte outputs toe. Gebruik in plaats daarvan het veld Verkopen.", "swap.tokenOwnFees": "Sommige tokens brengen kosten in rekening bij aankoop of verkoop, ingesteld door de tokenuitgever. Uniswap ontvangt geen van deze kosten.", "swap.total": "Totaal", - "swap.tradeRoutes": "Trade routes", + "swap.tradeRoutes": "Handelsroutes", "swap.transaction.deadline": "Transactiedeadline", "swap.transaction.revertAfter": "Je transactie wordt teruggedraaid als deze langer in behandeling blijft dan deze tijdsperiode.", "swap.unsupportedAssets.readMore": "Lees meer over niet-ondersteunde assets", "swap.warning.enterLargerAmount.title": "Voer een groter bedrag in", - "swap.warning.expectedFailure": "Deze transactie zal naar verwachting mislukken", + "swap.warning.expectedFailure.increaseSlippage": "Probeer je slippage te verhogen.", + "swap.warning.expectedFailure.titleMay": "This swap may fail", "swap.warning.insufficientBalance.title": "Je hebt niet genoeg {{currencySymbol}}", "swap.warning.insufficientGas.button": "Je hebt niet genoeg {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Swappen voor {{ tokenSymbol }} op {{networkName}}", @@ -1897,8 +1896,8 @@ "swap.warning.networkFee.message": "Dit zijn de kosten om je transactie op de blockchain te verwerken. Uniswap ontvangt geen van deze kosten.", "swap.warning.networkFee.message.uniswapX": "Dit zijn de kosten om je transactie op de blockchain te verwerken. Uniswap ontvangt geen van deze kosten. UniswapX verzamelt liquiditeitsbronnen voor betere prijzen en gasvrije swaps.", "swap.warning.networkFee.wrap": "ETH wrappen", - "swap.warning.noRoutesFound.message": "There are currently no routes available for your selected tokens. Please try a different pair or check again later.", - "swap.warning.noRoutesFound.title": "No routes available", + "swap.warning.noRoutesFound.message": "Er zijn momenteel geen routes beschikbaar voor de geselecteerde tokens. Probeer een ander paar of kom later terug.", + "swap.warning.noRoutesFound.title": "Geen routes beschikbaar", "swap.warning.offline.message": "Mogelijk is je internetverbinding verbroken of is het netwerk uitgevallen. Controleer je internetverbinding en probeer het opnieuw.", "swap.warning.offline.title": "Je bent offline", "swap.warning.priceImpact": "Deze transactie zal resulteren in een prijsimpact van op de marktprijs van deze pool. Wil je doorgaan?", @@ -1917,7 +1916,7 @@ "swap.warning.rateLimit.title": "Tarieflimiet overschreden", "swap.warning.router.message": "Mogelijk is de verbinding verbroken of is het netwerk uitgevallen. Als het probleem zich blijft voordoen, probeer het dan later opnieuw.", "swap.warning.router.title": "Deze transactie kan momenteel niet worden voltooid", - "swap.warning.tokenBlocked.button": "{{tokenSymbol}} is blocked", + "swap.warning.tokenBlocked.button": "{{tokenSymbol}} is geblokkeerd", "swap.warning.uniswapFee.message.default": "Er worden kosten in rekening gebracht om de beste ervaring met Uniswap te garanderen. Aan deze swap zijn geen kosten verbonden.", "swap.warning.uniswapFee.message.included": "Er worden kosten in rekening gebracht om de beste ervaring met Uniswap te garanderen, en deze zijn al in deze koers verwerkt.", "swap.warning.uniswapFee.title": "Swapkosten", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Sommige testnetten ondersteunen het swappen, versturen of kopen van tokens niet.", "tdp.stats.unsupportedChainDescription": "Tokenstatistieken en grafieken voor {{chain}} zijn beschikbaar op {{infoLink}}", "tdp.symbolNotFound": "Symbool niet gevonden", + "testnet.modal.swapDeepLink.description.toProdMode": "Voor deze actie moet de testnetmodus zijn uitgeschakeld. Je kunt de testnetmodus op elk moment via de instellingen weer inschakelen.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "Voor deze actie moet de testnetmodus zijn ingeschakeld. Tokens op testnets hebben geen echte waarde. Je kunt de testnetmodus op elk moment via de instellingen weer uitschakelen.", + "testnet.modal.swapDeepLink.title.toProdMode": "Testnetmodus uitschakelen", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Testnetmodus inschakelen", "testnet.unsupported": "Deze functionaliteit wordt niet ondersteund in de testnetmodus.", "themeToggle.theme": "Thema", "title.betterPricesMoreListings": "Betere prijzen. Meer noteringen. Koop, verkoop en verhandel NFT's op de beste marketplaces zoals OpenSea. Ontdek trending collecties.", @@ -1977,12 +1980,16 @@ "token.links.website": "Website", "token.priceExplorer.error.description": "Er is iets fout gegaan.", "token.priceExplorer.error.title": "Kon de prijsgrafiek niet laden", - "token.priceExplorer.timeRangeLabel.all": "All time", + "token.priceExplorer.timeRangeLabel.all": "Altijd", "token.priceExplorer.timeRangeLabel.day": "1d", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 Day", "token.priceExplorer.timeRangeLabel.hour": "1u", "token.priceExplorer.timeRangeLabel.month": "1ma", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 Month", "token.priceExplorer.timeRangeLabel.week": "1w", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 Week", "token.priceExplorer.timeRangeLabel.year": "1j", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 Year", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} is niet beschikbaar", "token.safety.blocked.title.tokensNotAvailable": "Het {{tokenSymbol0}} en {{tokenSymbol1}} zijn niet beschikbaar", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs ontvangt geen van deze kosten.", @@ -1992,37 +1999,37 @@ "token.safety.warning.blocked.description.named": "Je kunt {{tokenSymbol}} niet met de Uniswap-app traden.", "token.safety.warning.dontShowWarningAgain": "Laat deze waarschuwing niet meer zien", "token.safety.warning.doYourOwnResearch": "Doe altijd je eigen onderzoek voordat je verdergaat.", - "token.safety.warning.feeDescription": "Charges a when {{action}}", - "token.safety.warning.flaggedAsMalicious": "Flagged as malicious", - "token.safety.warning.fotHigh.title": "High fee detected", - "token.safety.warning.fotLow.title": "Fee detected", - "token.safety.warning.fotVeryHigh.title": "Very high fee detected", + "token.safety.warning.feeDescription": "Brengt in rekening bij {{action}}", + "token.safety.warning.flaggedAsMalicious": "Gemarkeerd als schadelijk", + "token.safety.warning.fotHigh.title": "Hoge transactiekosten gedetecteerd", + "token.safety.warning.fotLow.title": "Transactiekosten gedetecteerd", + "token.safety.warning.fotVeryHigh.title": "Zeer hoge transactiekosten gedetecteerd", "token.safety.warning.honeypot.message": "{{tokenSymbol}} is gemarkeerd als onverkoopbaar. Het swappen van deze token kan resulteren in verlies van je geld.", - "token.safety.warning.honeypot.title": "100% sell fee detected", - "token.safety.warning.impersonator": "Impersonates another token", - "token.safety.warning.impersonator.title": "Impersonator token detected", - "token.safety.warning.malicious.general.message": "{{tokenSymbol}} has been flagged as malicious by Blockaid.", - "token.safety.warning.malicious.impersonator.message": "{{tokenSymbol}} has been flagged by Blockaid for attempting to copy a different token. It may not be the token you are looking to swap.", - "token.safety.warning.malicious.impersonator.message.short": "{{tokenSymbol}} may not be the token you are looking to swap.", + "token.safety.warning.honeypot.title": "100% verkoopkosten gedetecteerd", + "token.safety.warning.impersonator": "Doet zich voor als een ander token", + "token.safety.warning.impersonator.title": "Imitatietoken gedetecteerd", + "token.safety.warning.malicious.general.message": "Blockaid heeft {{tokenSymbol}} als schadelijk gemarkeerd.", + "token.safety.warning.malicious.impersonator.message": "Blockaid heeft {{tokenSymbol}} gemarkeerd als een poging tot imitatie van een ander token. Dit is mogelijk niet het token dat je wilt swappen.", + "token.safety.warning.malicious.impersonator.message.short": "{{tokenSymbol}} is mogelijk niet het token dat je wilt swappen.", "token.safety.warning.malicious.title": "Schadelijke token gedetecteerd", - "token.safety.warning.mayResultInLoss": "Swapping it may result in a loss of funds.", + "token.safety.warning.mayResultInLoss": "Als je deze token swapt, kan dit leiden tot geldverlies.", "token.safety.warning.medium.heading.default_one": "Deze token wordt niet op toonaangevende gecentraliseerde Amerikaanse beurzen verhandeld.", "token.safety.warning.medium.heading.default_other": "Deze tokens worden niet op toonaangevende gecentraliseerde Amerikaanse beurzen verhandeld.", "token.safety.warning.medium.heading.default_one_also": "Deze token wordt ook niet op toonaangevende gecentraliseerde Amerikaanse beurzen verhandeld.", "token.safety.warning.medium.heading.default_other_also": "Deze tokens worden ook niet op toonaangevende gecentraliseerde Amerikaanse beurzen verhandeld.", "token.safety.warning.medium.heading.named": "{{tokenSymbol}} wordt niet op toonaangevende gecentraliseerde Amerikaanse beurzen verhandeld.", - "token.safety.warning.notListedOnExchanges": "Not listed on leading U.S. exchanges", - "token.safety.warning.sellFee100.message": "{{ tokenSymbol }} has been flagged as unsellable.", - "token.safety.warning.sellFee100.title": "100% sell fee detected", - "token.safety.warning.spam.message": "{{tokenSymbol}} has been flagged as spam by Blockaid.", + "token.safety.warning.notListedOnExchanges": "Niet genoteerd bij toonaangevende Amerikaanse beurzen", + "token.safety.warning.sellFee100.message": "{{ tokenSymbol }} is gemarkeerd als onverkoopbaar.", + "token.safety.warning.sellFee100.title": "100% verkoopkosten gedetecteerd", + "token.safety.warning.spam.message": "Blockaid heeft {{tokenSymbol}} als spam gemarkeerd.", "token.safety.warning.spam.title": "Spam-token gedetecteerd", - "token.safety.warning.spamsUsers": "Spams users", + "token.safety.warning.spamsUsers": "Spamt gebruikers", "token.safety.warning.strong.heading.default_one": "Deze token wordt niet verhandeld op toonaangevende gecentraliseerde Amerikaanse beurzen en ook niet vaak geswapt op Uniswap.", "token.safety.warning.strong.heading.default_other": "Deze tokens worden niet verhandeld op toonaangevende Amerikaanse gecentraliseerde beurzen en worden ook niet vaak geswapt op Uniswap.", "token.safety.warning.strong.heading.named": "{{tokenSymbol}} wordt niet verhandeld op toonaangevende Amerikaanse gecentraliseerde beurzen en worden ook niet vaak geswapt op Uniswap.", - "token.safety.warning.tokenChargesFee.both.message": "{{tokenSymbol}} charges a {{buyFeePercent}} fee when bought and {{sellFeePercent}} when sold.", - "token.safety.warning.tokenChargesFee.buy.message": "{{tokenSymbol}} charges a {{feePercent}} fee when bought.", - "token.safety.warning.tokenChargesFee.sell.message": "{{tokenSymbol}} charges a {{feePercent}} fee when sold.", + "token.safety.warning.tokenChargesFee.both.message": "{{tokenSymbol}} rekent transactiekosten van {{buyFeePercent}} bij aankoop en {{sellFeePercent}} bij verkoop.", + "token.safety.warning.tokenChargesFee.buy.message": "{{tokenSymbol}} rekent transactiekosten van {{feePercent}} bij de aankoop.", + "token.safety.warning.tokenChargesFee.sell.message": "{{tokenSymbol}} rekent transactiekosten van {{feePercent}} bij de verkoop.", "token.safetyLevel.blocked.header": "Niet beschikbaar", "token.safetyLevel.blocked.message": "Je kunt deze token niet verhandelen via de Uniswap Wallet.", "token.safetyLevel.medium.header": "Let op", diff --git a/packages/uniswap/src/i18n/locales/translations/no-NO.json b/packages/uniswap/src/i18n/locales/translations/no-NO.json index 40c6def7687..2e19ef8609c 100644 --- a/packages/uniswap/src/i18n/locales/translations/no-NO.json +++ b/packages/uniswap/src/i18n/locales/translations/no-NO.json @@ -222,6 +222,7 @@ "common.button.disconnect": "Koble fra", "common.button.dismiss": "Avskjedige", "common.button.done": "Ferdig", + "common.button.edit": "Redigere", "common.button.enable": "Muliggjøre", "common.button.finish": "Fullfør", "common.button.goBack": "Gå tilbake", @@ -313,7 +314,6 @@ "common.custom": "Tilpasset", "common.customRange": "Egendefinert rekkevidde", "common.dataOutdated": "Data kan være utdaterte", - "common.dataUnavailable": "Data utilgjengelig", "common.default": "Misligholde", "common.defaultTradeOptions": "Standard handelsopsjoner", "common.delegate.cancelled": "Delegat kansellert", @@ -461,6 +461,7 @@ "common.networkCost": "Nettverkskostnad", "common.neverMind": "Glem det", "common.new": "Ny", + "common.new.exclamation": "Ny!", "common.nfts": "NFT-er", "common.noActivity": "Ingen aktivitet ennå", "common.noAmount.error": "Angi et beløp", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Søk etter land eller region", "fiatOnRamp.region.title": "Velg din region", "fiatOnRamp.summary.total": "{{cryptoAmount}} for {{fiatAmount}}", - "forceUpgrade.action.confirm": "Oppdater appen", + "forceUpgrade.action.confirm": "Oppdater nå", "forceUpgrade.action.recoveryPhrase": "Se gjenopprettingsfrase", - "forceUpgrade.description": "Versjonen av Uniswap Wallet du bruker er utdatert og mangler kritiske oppgraderinger. Hvis du ikke oppdaterer appen eller du ikke har skrevet ned gjenopprettingsfrasen, vil du ikke få tilgang til ressursene dine.", + "forceUpgrade.description": "En ny versjon av appen er tilgjengelig. For å fortsette å bruke Uniswap Wallet, vennligst oppdater den til den nyeste versjonen.", "forceUpgrade.label.recoveryPhrase": "Gjenopprettingsfrase", - "forceUpgrade.title": "Oppdater appen for å fortsette", + "forceUpgrade.title": "Oppdater til siste versjon", "globalPreferences.title": "Globale preferanser", "hero.scroll": "Rull for å lære mer", "hero.subtitle": "Den største onchain-markedsplassen. Kjøp og selg krypto på Ethereum og 11+ andre kjeder.", @@ -940,7 +941,6 @@ "home.feed.title": "Mate", "home.label.buy": "Kjøpe", "home.label.receive": "Motta", - "home.label.scan": "Skann", "home.label.send": "Sende", "home.label.swap": "Bytte", "home.nfts.title": "NFT-er", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Skaff deg Uniswap Wallet-appen", "mobileAppPromo.banner.title": "Uniswap: Krypto- og NFT-lommebok", "moonpay.poweredBy": "Fiat onramp drevet av MoonPay USA LLC", - "moonpay.rampIframe": "MoonPay fiat på-rampe iframe", "moonpay.restricted.region": "Moonpay er ikke tilgjengelig i enkelte regioner. Klikk for å lære mer.", "nav.createAccount.button": "Opprett konto", "nav.logIn.button": "Logg inn", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Se gjenopprettingsfrase", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 annen lommebok", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} andre lommebøker", - "onboarding.import.onDeviceRecovery.warning.caption": "Sørg for at du har sikkerhetskopiert alle de andre lommebokene. Hvis du noen gang vil gjenopprette dem, trenger du gjenopprettingsfrasene deres eller tilsvarende iCloud-sikkerhetskopier.", + "onboarding.import.onDeviceRecovery.warning.caption": "Sørg for at du har sikkerhetskopiert alle de andre lommebokene. Hvis du noen gang vil gjenopprette dem, trenger du gjenopprettingsfrasene deres eller tilsvarende {{cloudProvider}} sikkerhetskopier.", "onboarding.import.onDeviceRecovery.warning.title": "Er du sikker?", "onboarding.import.title": "Velg hvordan du vil legge til lommeboken", "onboarding.importMnemonic.button.default": "Min gjenopprettingsfrase er på 12 ord", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Utforsk Uniswap Analytics.", "pool.hideClosed": "Skjul lukkede posisjoner", "pool.import": "Import basseng", - "pool.import.v2": "Importer V2 basseng", + "pool.import.link.description": "Noen v2-posisjoner vises ikke automatisk.", + "pool.import.positions.v2": "Importer V2-posisjoner", + "pool.import.positions.v2.selectPair.description": "Noen v2-posisjoner vises ikke automatisk. Velg et token-par for å importere og se posisjonene dine.", + "pool.import.success": "Pool importert", "pool.increaseLiquidity": "Øk likviditeten", "pool.info": "Bassenginformasjon", "pool.initialShare": "Startpriser og poolandel", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "30 dagers volum", "pool.volume.thirtyDay.short": "30D vol", "pool.yourv2": "Din V2-likviditet", - "poolFinder.connect": "Koble til en lommebok for å finne bassenger.", - "poolFinder.create": "Lag basseng", - "poolFinder.found": "Basseng funnet!", - "poolFinder.managePool": "Administrer dette bassenget", - "poolFinder.noLiquidity": "Du har ikke likviditet i denne poolen ennå.", - "poolFinder.noPoolFound": "Ingen basseng funnet.", - "poolFinder.selectToken": "Velg et token for å finne v2-likviditeten din.", - "poolFinder.tip": "Tips: Bruk dette verktøyet til å finne v2-pooler som ikke automatisk vises i grensesnittet.", + "poolFinder.availablePools": "Tilgjengelige bassenger", + "poolFinder.availablePools.found.description": "v2-puljer som matcher parvalget ditt.", + "poolFinder.availablePools.notFound.description": "Ingen samsvarende v2-pooler funnet. Dobbeltsjekk tokenvalget ditt og sørg for at du er koblet til riktig lommebok.", "pools.approving.amount": "Godkjenner {{amount}}", "pools.explore": "Utforsk bassenger", "position.addHook": "Legg til en krok", @@ -1500,6 +1497,7 @@ "position.step.price": "Angi startpris", "position.step.range": "Angi prisklasse", "position.step.select": "Velg token-par og avgifter", + "position.value": "Posisjonsverdi", "position.valueUnavailable": "Posisjonsverdi er utilgjengelig på grunn av lav likviditet.", "position.your": "Din posisjon", "positions.welcome": "Velkommen til dine stillinger", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "Transaksjonen din vil gå tilbake hvis den venter i mer enn denne perioden.", "swap.unsupportedAssets.readMore": "Les mer om ikke-støttede eiendeler", "swap.warning.enterLargerAmount.title": "Angi et større beløp", - "swap.warning.expectedFailure": "Denne transaksjonen forventes å mislykkes", + "swap.warning.expectedFailure.increaseSlippage": "Prøv å øke glidningen.", + "swap.warning.expectedFailure.titleMay": "Dette byttet kan mislykkes", "swap.warning.insufficientBalance.title": "Du har ikke nok {{currencySymbol}}", "swap.warning.insufficientGas.button": "Ikke nok {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Bytt til {{ tokenSymbol }} på {{networkName}}", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Noen testnett støtter ikke bytte, sending eller kjøp av tokens.", "tdp.stats.unsupportedChainDescription": "Tokenstatistikk og diagrammer for {{chain}} er tilgjengelig på {{infoLink}}", "tdp.symbolNotFound": "Symbol ikke funnet", + "testnet.modal.swapDeepLink.description.toProdMode": "Denne handlingen krever at testnettmodus er deaktivert. Testnett-modus kan aktiveres igjen når som helst innenfor innstillingene.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "Denne handlingen krever at testnettmodus er aktivert. Tokens på testnett har ingen reell verdi. Testnet-modus kan deaktiveres når som helst i innstillingene.", + "testnet.modal.swapDeepLink.title.toProdMode": "Deaktiver testnettmodus", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Aktiver testnettmodus", "testnet.unsupported": "Denne funksjonaliteten støttes ikke i testnettmodus.", "themeToggle.theme": "Tema", "title.betterPricesMoreListings": "Bedre priser. Flere oppføringer. Kjøp, selg og bytt NFT-er på tvers av toppmarkedsplasser som OpenSea. Utforsk populære samlinger.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Kunne ikke laste inn prisdiagrammet", "token.priceExplorer.timeRangeLabel.all": "Hele tiden", "token.priceExplorer.timeRangeLabel.day": "1D", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 dag", "token.priceExplorer.timeRangeLabel.hour": "1H", "token.priceExplorer.timeRangeLabel.month": "1M", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 måned", "token.priceExplorer.timeRangeLabel.week": "1W", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 uke", "token.priceExplorer.timeRangeLabel.year": "1Y", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 år", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} er ikke tilgjengelig", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} og {{tokenSymbol1}} er ikke tilgjengelige", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs mottar ingen av disse avgiftene.", diff --git a/packages/uniswap/src/i18n/locales/translations/pl-PL.json b/packages/uniswap/src/i18n/locales/translations/pl-PL.json index 26e99b69cca..aebaebc7b54 100644 --- a/packages/uniswap/src/i18n/locales/translations/pl-PL.json +++ b/packages/uniswap/src/i18n/locales/translations/pl-PL.json @@ -222,6 +222,7 @@ "common.button.disconnect": "Rozłączyć się", "common.button.dismiss": "Odrzucać", "common.button.done": "Zrobione", + "common.button.edit": "Edytować", "common.button.enable": "Włączać", "common.button.finish": "Skończyć", "common.button.goBack": "Wróć", @@ -313,7 +314,6 @@ "common.custom": "Zwyczaj", "common.customRange": "Zakres niestandardowy", "common.dataOutdated": "Dane mogą być nieaktualne", - "common.dataUnavailable": "Dane niedostępne", "common.default": "Domyślny", "common.defaultTradeOptions": "Domyślne opcje handlu", "common.delegate.cancelled": "Delegat odwołany", @@ -461,6 +461,7 @@ "common.networkCost": "Koszt sieci", "common.neverMind": "Nieważne", "common.new": "Nowy", + "common.new.exclamation": "Nowy!", "common.nfts": "NFT", "common.noActivity": "Brak aktywności", "common.noAmount.error": "Wpisz kwotę", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Szukaj według kraju lub regionu", "fiatOnRamp.region.title": "Wybierz swój region", "fiatOnRamp.summary.total": "{{cryptoAmount}} dla {{fiatAmount}}", - "forceUpgrade.action.confirm": "Zaktualizuj aplikację", + "forceUpgrade.action.confirm": "Aktualizuj teraz", "forceUpgrade.action.recoveryPhrase": "Zobacz frazę odzyskiwania", - "forceUpgrade.description": "Wersja portfela Uniswap, z której korzystasz, jest nieaktualna i brakuje w niej krytycznych aktualizacji. Jeśli nie zaktualizujesz aplikacji lub nie masz zapisanej frazy odzyskiwania, nie będziesz mieć dostępu do swoich zasobów.", + "forceUpgrade.description": "Dostępna jest nowa wersja aplikacji. Aby kontynuować korzystanie z Uniswap Wallet, zaktualizuj ją do najnowszej wersji.", "forceUpgrade.label.recoveryPhrase": "Fraza odzyskiwania", - "forceUpgrade.title": "Zaktualizuj aplikację, aby kontynuować", + "forceUpgrade.title": "Zaktualizuj do najnowszej wersji", "globalPreferences.title": "Globalne preferencje", "hero.scroll": "Przewiń, aby dowiedzieć się więcej", "hero.subtitle": "Największy rynek onchain. Kupuj i sprzedawaj kryptowaluty w Ethereum i ponad 11 innych sieciach.", @@ -940,7 +941,6 @@ "home.feed.title": "Karmić", "home.label.buy": "Kupić", "home.label.receive": "Odbierać", - "home.label.scan": "Skanowanie", "home.label.send": "Wysłać", "home.label.swap": "Zamieniać", "home.nfts.title": "NFT", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Pobierz aplikację Portfel Uniswap", "mobileAppPromo.banner.title": "Uniswap: Portfel kryptowalut i NFT", "moonpay.poweredBy": "Fiat onramp obsługiwany przez MoonPay USA LLC", - "moonpay.rampIframe": "MoonPay fiat iframe na rampie", "moonpay.restricted.region": "Usługa Moonpay nie jest dostępna w niektórych regionach. Kliknij by dowiedzieć się więcej.", "nav.createAccount.button": "Utwórz konto", "nav.logIn.button": "Zaloguj się", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Zobacz frazę odzyskiwania", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 inny portfel", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} inne portfele", - "onboarding.import.onDeviceRecovery.warning.caption": "Upewnij się, że wykonałeś kopię zapasową wszystkich pozostałych portfeli. Jeśli kiedykolwiek będziesz chciał je przywrócić, będziesz potrzebować fraz odzyskiwania lub odpowiednich kopii zapasowych iCloud.", + "onboarding.import.onDeviceRecovery.warning.caption": "Upewnij się, że wykonałeś kopię zapasową wszystkich innych portfeli. Jeśli kiedykolwiek będziesz chciał je przywrócić, będziesz potrzebować ich fraz odzyskiwania lub odpowiadających im kopii zapasowych {{cloudProvider}} .", "onboarding.import.onDeviceRecovery.warning.title": "Jesteś pewny?", "onboarding.import.title": "Wybierz sposób dodania portfela", "onboarding.importMnemonic.button.default": "Moje zdanie naprawcze składa się z 12 słów", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Poznaj analizę Uniswap.", "pool.hideClosed": "Ukryj zamknięte pozycje", "pool.import": "Importuj pulę", - "pool.import.v2": "Importuj pulę V2", + "pool.import.link.description": "Niektóre pozycje v2 nie są wyświetlane automatycznie.", + "pool.import.positions.v2": "Importuj pozycje V2", + "pool.import.positions.v2.selectPair.description": "Niektóre pozycje v2 nie są wyświetlane automatycznie. Wybierz parę tokenów, aby zaimportować i wyświetlić swoje pozycje.", + "pool.import.success": "Pula zaimportowana", "pool.increaseLiquidity": "Zwiększ płynność", "pool.info": "Informacje o basenie", "pool.initialShare": "Ceny początkowe i udział w puli", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "30-dniowy wolumen", "pool.volume.thirtyDay.short": "30D tom", "pool.yourv2": "Twoja płynność V2", - "poolFinder.connect": "Połącz się z portfelem, aby znaleźć pule.", - "poolFinder.create": "Utwórz pulę", - "poolFinder.found": "Znaleziono basen!", - "poolFinder.managePool": "Zarządzaj tą pulą", - "poolFinder.noLiquidity": "Nie masz jeszcze płynności w tej puli.", - "poolFinder.noPoolFound": "Nie znaleziono basenu.", - "poolFinder.selectToken": "Wybierz token, aby znaleźć płynność v2.", - "poolFinder.tip": "Wskazówka: Użyj tego narzędzia, aby znaleźć pule w wersji 2, które nie pojawiają się automatycznie w interfejsie.", + "poolFinder.availablePools": "Dostępne baseny", + "poolFinder.availablePools.found.description": "Pule v2 odpowiadające wybranemu przez Ciebie wyborowi par.", + "poolFinder.availablePools.notFound.description": "Nie znaleziono pasujących puli v2. Sprawdź ponownie swój wybór tokenów i upewnij się, że jesteś połączony z właściwym portfelem.", "pools.approving.amount": "Zatwierdzanie {{amount}}", "pools.explore": "Odkryj baseny", "position.addHook": "Dodaj hak", @@ -1500,6 +1497,7 @@ "position.step.price": "Ustaw cenę początkową", "position.step.range": "Ustal przedział cenowy", "position.step.select": "Wybierz parę tokenów i opłaty", + "position.value": "Wartość pozycji", "position.valueUnavailable": "Wartość pozycji jest niedostępna ze względu na niską płynność.", "position.your": "Twoje stanowisko", "positions.welcome": "Witamy na stanowiskach", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "Twoja transakcja zostanie cofnięta, jeśli będzie oczekująca dłużej niż ten okres.", "swap.unsupportedAssets.readMore": "Przeczytaj więcej o nieobsługiwanych zasobach", "swap.warning.enterLargerAmount.title": "Wprowadź większą kwotę", - "swap.warning.expectedFailure": "Oczekuje się, że ta transakcja zakończy się niepowodzeniem", + "swap.warning.expectedFailure.increaseSlippage": "Spróbuj zwiększyć poślizg.", + "swap.warning.expectedFailure.titleMay": "Ta zamiana może się nie powieść", "swap.warning.insufficientBalance.title": "Nie masz dość {{currencySymbol}}", "swap.warning.insufficientGas.button": "Za mało {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Zamień na {{ tokenSymbol }} na {{networkName}}", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Niektóre sieci testowe nie obsługują wymiany, wysyłania ani kupowania tokenów.", "tdp.stats.unsupportedChainDescription": "Statystyki i wykresy tokenów dla {{chain}} są dostępne na {{infoLink}}", "tdp.symbolNotFound": "Nie znaleziono symbolu", + "testnet.modal.swapDeepLink.description.toProdMode": "Ta akcja wymaga wyłączenia trybu testnet. Tryb testnet można ponownie włączyć w dowolnym momencie w ustawieniach.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "Ta akcja wymaga włączenia trybu testnet. Tokeny w sieciach testnet nie mają żadnej rzeczywistej wartości. Tryb testnet można wyłączyć w dowolnym momencie w ustawieniach.", + "testnet.modal.swapDeepLink.title.toProdMode": "Wyłącz tryb testowy", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Włącz tryb testowy", "testnet.unsupported": "Ta funkcjonalność nie jest obsługiwana w trybie testnetowym.", "themeToggle.theme": "Temat", "title.betterPricesMoreListings": "Lepsze ceny. Więcej ofert. Kupuj, sprzedawaj i handluj NFT na najlepszych platformach handlowych, takich jak OpenSea. Przeglądaj popularne kolekcje.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Nie udało się załadować wykresu cen", "token.priceExplorer.timeRangeLabel.all": "Cały czas", "token.priceExplorer.timeRangeLabel.day": "1D", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 dzień", "token.priceExplorer.timeRangeLabel.hour": "1 godz.", "token.priceExplorer.timeRangeLabel.month": "1 mln", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 miesiąc", "token.priceExplorer.timeRangeLabel.week": "1 W", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 tydzień", "token.priceExplorer.timeRangeLabel.year": "1 rok", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 rok", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} nie jest dostępny", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} i {{tokenSymbol1}} nie są dostępne", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs nie pobiera żadnych z tych opłat.", diff --git a/packages/uniswap/src/i18n/locales/translations/pt-PT.json b/packages/uniswap/src/i18n/locales/translations/pt-PT.json index b2fdb9733dc..c9358dae4db 100644 --- a/packages/uniswap/src/i18n/locales/translations/pt-PT.json +++ b/packages/uniswap/src/i18n/locales/translations/pt-PT.json @@ -132,15 +132,15 @@ "addressInput.recipient": "Destinatário", "analytics.allow": "Permitir análise", "analytics.allow.message": "Usamos dados anonimizados para aprimorar sua experiência com os produtos da Uniswap Labs.", - "appRating.button.notReally": "Not really", - "appRating.description": "Let us know if you’re having a good experience with this app", - "appRating.extension.review.description": "Pick a star rating and leave a review on the Chrome Web Store.", - "appRating.extension.review.title": "Review Uniswap Extension?", - "appRating.extension.title": "Enjoying Uniswap Extension?", - "appRating.feedback.button.send": "Send feedback", - "appRating.feedback.description": "Let us know how we can improve your experience", - "appRating.feedback.title": "We’re sorry to hear that.", - "appRating.mobile.title": "Enjoying Uniswap Wallet?", + "appRating.button.notReally": "Não", + "appRating.description": "Compartilhe conosco a sua experiência no aplicativo", + "appRating.extension.review.description": "Dê uma nota e deixe a sua avaliação na Chrome Web Store.", + "appRating.extension.review.title": "Deixar uma avaliação para Uniswap Extension?", + "appRating.extension.title": "Está gostando da Uniswap Extension?", + "appRating.feedback.button.send": "Enviar feedback", + "appRating.feedback.description": "Compartilhe conosco como podemos melhorar a sua experiência", + "appRating.feedback.title": "Lamentamos ouvir isso.", + "appRating.mobile.title": "Está gostando da Carteira Uniswap?", "bridging.estimatedTime.minutesAndSeconds": "~{{minutes}} min {{seconds}} s", "bridging.estimatedTime.minutesOnly": "~{{minutes}} min", "bridging.estimatedTime.secondsOnly": "~{{seconds}} s", @@ -186,12 +186,12 @@ "common.approvePending": "Aprovação pendente...", "common.approveSpend": "Aprovar gastos em {{symbol}}", "common.approving": "Aprovando", - "common.areYouSure": "Are you sure?", + "common.areYouSure": "Tem certeza?", "common.automatic": "Automático", "common.availableIn": "Uniswap disponível em: ", "common.availableOnIOSAndroid": "Disponível para iOS e Android", "common.availableOnIOSAndroidChrome": "Disponível para iOS, Android e Chrome", - "common.backToPositions": "Voltar para posições", + "common.backToPositions": "Voltar às posições", "common.blocked.ifError": "Se você acredita que essa decisão é um erro, envie um e-mail informando seu endereço para ", "common.blocked.reason": "Este endereço está bloqueado na interface do Uniswap Labs porque está associado a uma ou mais atividades bloqueadas.", "common.blockedAddress": "Endereço bloqueado", @@ -222,6 +222,7 @@ "common.button.disconnect": "Desconectar", "common.button.dismiss": "Descartar", "common.button.done": "Concluído", + "common.button.edit": "Editar", "common.button.enable": "Ativar", "common.button.finish": "Concluir", "common.button.goBack": "Voltar", @@ -278,7 +279,7 @@ "common.claimed": "Resgatado", "common.claiming": "Resgatando", "common.claimUnis": "Resgatar tokens UNI", - "common.clear": "Clear", + "common.clear": "Apagar", "common.close": "Fechar", "common.closed": "Fechado", "common.collect.button": "Recolher", @@ -301,7 +302,7 @@ "common.contactUs.button": "Fale conosco", "common.contractInteraction": "Interação contratual", "common.copied": "Copiado", - "common.copy.address": "Copy address", + "common.copy.address": "Copiar endereço", "common.copyLink.button": "Copiar link", "common.create.pool.cancelled": "Criação de pool cancelada", "common.create.pool.failed": "Falha ao criar pool", @@ -313,7 +314,6 @@ "common.custom": "Personalizado", "common.customRange": "Intervalo personalizado", "common.dataOutdated": "Os dados podem estar desatualizados", - "common.dataUnavailable": "Data unavailable", "common.default": "Padrão", "common.defaultTradeOptions": "Opções de negociação padrão", "common.delegate.cancelled": "Delegação cancelada", @@ -342,7 +342,7 @@ "common.downloadPlayStore": "Baixar na Play Store", "common.downloadUniswap": "Baixar Uniswap", "common.downloadUniswapApp": "Baixar o aplicativo Uniswap", - "common.dynamic": "Dynamic", + "common.dynamic": "Dinâmico", "common.edit.button": "Editar", "common.error.general": "Algo deu errado", "common.error.label": "Erro", @@ -372,7 +372,7 @@ "common.feesEarned.label": "{{symbol}} tarifas ganhas:", "common.feesEarnedPerBase": "{{symbolA}} por {{symbolB}}", "common.fetchingRoute": "Buscando rota", - "common.flag": "Flag", + "common.flag": "Sinalizar", "common.floor": "Mínimo", "common.floorPrice": "Preço mínimo", "common.for": "Para", @@ -444,7 +444,7 @@ "common.migrate.liquidity.cancelled": "Migração de liquidez cancelada", "common.migrate.liquidity.failed": "Falha na migração de liquidez", "common.migrate.position": "Migrar posição", - "common.migrate.v3": "Migrate to V3", + "common.migrate.v3": "Migrar para v3", "common.migrated.liquidity": "Liquidez migrada", "common.migrating.liquidity": "Migrando liquidez", "common.min": "Mín.", @@ -461,6 +461,7 @@ "common.networkCost": "Taxa de rede", "common.neverMind": "Esquecer", "common.new": "Novo", + "common.new.exclamation": "New!", "common.nfts": "NFTs", "common.noActivity": "Nenhuma atividade ainda", "common.noAmount.error": "Insira um valor", @@ -499,11 +500,11 @@ "common.price": "Preço", "common.priceImpact": "Aviso de impacto de preço", "common.priceUpdated": "Preço atualizado", - "common.privacyChoices": "Your Privacy Choices", - "common.privacyChoices.checkbox.description": "When checked, we will not share your data with third-party partners for personalized advertising. You can enable sharing anytime by unchecking this box.", - "common.privacyChoices.checkbox.label": "Do not share my information", - "common.privacyChoices.description": "We may share device identifiers with our advertising partners to promote our services on other websites and platforms. Where this qualifies as selling, sharing or targeted advertising under applicable laws, you can opt out by checking the \"do not share my information\" box. For more information about our privacy practices please review our Privacy Policy.", - "common.privacyChoices.disclaimer": "Please note that your selection will apply only to this browser on this device. You can also opt out by enabling the Global Privacy Control setting within the browser that you use to access our services. To see more options, go to your settings.", + "common.privacyChoices": "Opções de privacidade", + "common.privacyChoices.checkbox.description": "Se marcada, não compartilharemos seus dados com parceiros externos para fins de publicidade personalizada. Você pode permitir o compartilhamento quando quiser desmarcando esta caixa.", + "common.privacyChoices.checkbox.label": "Não compartilhar meus dados", + "common.privacyChoices.description": "Podemos compartilhar identificadores de dispositivo com parceiros de publicidade para promover nossos serviços em outros sites e plataformas. Para os casos considerados venda, compartilhamento ou publicidade direcionada ao abrigo das leis aplicáveis, você pode solicitar sua exclusão marcando a caixa \"Não compartilhar meus dados\". Para saber mais sobre nossas práticas de privacidade, leia a Política de privacidade.", + "common.privacyChoices.disclaimer": "Observe que sua seleção será aplicada somente a este navegador neste dispositivo. Você também pode solicitar sua exclusão ativando a configuração \"Controle de privacidade global\" no navegador usado para acessar nossos serviços. Para ver mais opções, acesse as configurações.", "common.privacyPolicy": "Política de privacidade", "common.proceed": "Continuar", "common.proceedInWallet": "Continuar na sua carteira", @@ -659,7 +660,7 @@ "common.unwrap.failed": "Falha no unwrap", "common.unwrapped": "Unwrap realizado", "common.unwrapping": "Fazendo unwrap", - "common.view.profile": "View profile", + "common.view.profile": "Ver perfil", "common.viewOnBlockExplorer": "Ver no Block Explorer", "common.viewOnExplorer": "Ver no Explorer", "common.volume": "Volume", @@ -763,7 +764,7 @@ "errors.crash.message": "Algo deu errado.", "errors.crash.restart": "Reinicie o aplicativo", "errors.crash.title": "Ah, não!", - "explore.more.pools": "Explore more pools", + "explore.more.pools": "Explorar mais pools", "explore.search.action.clear": "Apagar", "explore.search.action.viewEtherscan": "Ver em {{blockExplorerName}}", "explore.search.empty.full": "Nenhum resultado encontrado para \"{{searchQuery}}\"", @@ -838,7 +839,7 @@ "fee.bestForMost": "Ideal para a maioria dos pares.", "fee.bestForStablePairs": "Ideal para pares estáveis.", "fee.bestForVeryStable": "Ideal para pares muito estáveis.", - "fee.dynamic": "Dynamic fee", + "fee.dynamic": "Tarifa dinâmica", "fee.percentEarned": "A porcentagem que você ganhará em tarifas.", "fee.selectPercent": "{{pct}}% selecionam", "fee.tier": "Nível de tarifas", @@ -847,24 +848,24 @@ "fee.tier.create.description": "A criação de um novo nível iniciará em um novo pool e gerará taxas de rede mais altas do que o normal.", "fee.tier.description": "O valor ganho por oferecer liquidez. Escolha um valor compatível com sua tolerância a risco e estratégia.", "fee.tier.description.v2": "O valor ganho por ofertar liquidez. Todos os pools v2 têm tarifa fixa de 0,3%. Para mais opções, oferte liquidez no v4.", - "fee.tier.dynamic": "Dynamic fee tier", - "fee.tier.dynamic.create": "Creating dynamic fee tier", - "fee.tier.dynamic.create.info": "You are about to create a pool with a dynamic fee tier. Before proceeding, please ensure that the selected hook supports dynamic fees.", + "fee.tier.dynamic": "Nível de tarifas dinâmico", + "fee.tier.dynamic.create": "Criando nível de tarifas dinâmico", + "fee.tier.dynamic.create.info": "Você está criando um pool com tarifas dinâmicas. Antes de continuar, confirme que o hook selecionado é compatível com esse tipo de tarifa.", "fee.tier.label": "A porcentagem que você ganhará em tarifas", "fee.tier.missing.description": "Não consegue encontrar o nível que está procurando?", "fee.tier.new": "Novo nível", - "fee.tier.percent.select": "{{percentage}} select", + "fee.tier.percent.select": "Seleção de {{percentage}}", "fee.tier.recommended": "Recomendado", - "fee.tier.search": "Search or create other fee tiers", + "fee.tier.search": "Buscar ou criar outros níveis de tarifas", "fee.tier.search.short": "Procurar níveis", "fee.tier.select": "Selecionar nível de tarifas", "fee.tier.select.existing.button": "Selecionar nível de tarifas existente", "fee.tierExact": "Nível de tarifas {{fee}}", - "fee.unavailable": "Earned fees are not visible for v2 positions until liquidity is removed.", - "fee.uncollected": "Includes uncollected fees:", + "fee.unavailable": "Tarifas recebidas só ficam visíveis em posições de v2 após a remoção da liquidez.", + "fee.uncollected": "Inclui tarifas não recolhidas:", "fiatOffRamp.checkout.title": "Vender com", "fiatOffRamp.connection.quote": "Vendendo {{amount}} em {{currencySymbol}}", - "fiatOffRamp.error.balance": "Exceeds balance", + "fiatOffRamp.error.balance": "Excede o saldo", "fiatOffRamp.unsupportedToken.back": "Voltar", "fiatOffRamp.unsupportedToken.divider": "Tokens sem suporte", "fiatOffRamp.unsupportedToken.message": "Não há suporte para a venda deste token. Troque este ativo por um dos tokens com suporte.", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Pesquisar por país ou região", "fiatOnRamp.region.title": "Selecione a sua região", "fiatOnRamp.summary.total": "{{cryptoAmount}} para {{fiatAmount}}", - "forceUpgrade.action.confirm": "Atualizar aplicativo", + "forceUpgrade.action.confirm": "Update now", "forceUpgrade.action.recoveryPhrase": "Ver frase de recuperação", - "forceUpgrade.description": "A versão da Carteira Uniswap que você está usando está desatualizada e não tem atualizações críticas. Se você não atualizar o aplicativo ou não tiver sua frase de recuperação anotada, não será possível acessar seus ativos.", + "forceUpgrade.description": "A new version of the app is available. To continue using the Uniswap Wallet, please update it to the latest version.", "forceUpgrade.label.recoveryPhrase": "Frase de recuperação", - "forceUpgrade.title": "Atualize o aplicativo para continuar", + "forceUpgrade.title": "Update to the latest version", "globalPreferences.title": "Preferências globais", "hero.scroll": "Role para saber mais", "hero.subtitle": "O maior mercado de on-chain. Compre e venda criptos na Ethereum e em mais de 11 outros chains.", @@ -940,15 +941,14 @@ "home.feed.title": "Feed", "home.label.buy": "Comprar", "home.label.receive": "Receber", - "home.label.scan": "Ler", "home.label.send": "Enviar", "home.label.swap": "Trocar", "home.nfts.title": "NFTs", - "home.tokens.empty.action.buy.description": "Purchase with a debit card or bank account.", - "home.tokens.empty.action.buy.title": "Buy Crypto", + "home.tokens.empty.action.buy.description": "Compre com cartão de débito ou conta bancária.", + "home.tokens.empty.action.buy.title": "Comprar criptoativos", "home.tokens.empty.action.import.description": "Digite a frase de recuperação desta carteira para começar a trocar e enviar.", "home.tokens.empty.action.import.title": "Importar carteira", - "home.tokens.empty.action.receive.description": "Transfer from another wallet or account.", + "home.tokens.empty.action.receive.description": "Transfira de outra carteira ou conta.", "home.tokens.empty.action.receive.title": "Receber criptomoedas", "home.tokens.empty.description": "Quando esta carteira comprar ou receber tokens, eles aparecerão aqui.", "home.tokens.empty.title": "Nenhum token ainda", @@ -1029,7 +1029,7 @@ "liquidity.provideOnProtocols": "Fornecer liquidez em protocolos diferentes", "liquidityPool.chart.tooltip.amount": "Liquidez de {{token}}: {{amount}}", "liquidityPool.page.title": "Adicionar liquidez a pools {{version}} na Uniswap", - "liquidityPool.positions.closed.title": "Closed positions", + "liquidityPool.positions.closed.title": "Posições fechadas", "liquidityPool.positions.page.title": "Gerenciar liquidez do pool {{quoteSymbol}}/{{baseSymbol}} na Uniswap", "liquidityPool.positions.page.version.description": "Visualize suas posições de liquidez {{version}} ativas. Adicione novas posições.", "liquidityPool.positions.page.version.title": "Gerenciar liquidez do pool {{version}} na Uniswap", @@ -1064,14 +1064,13 @@ "mobileAppPromo.banner.getTheApp.link": "Obtenha o aplicativo de Carteira Uniswap", "mobileAppPromo.banner.title": "Uniswap: carteira de criptos e NFTs", "moonpay.poweredBy": "Fiat Onramp desenvolvido pela MoonPay USA LLC", - "moonpay.rampIframe": "iframe de conversão em moeda fiduciária do MoonPay", "moonpay.restricted.region": "O Moonpay não está disponível em algumas regiões. Clique para saber mais.", "nav.createAccount.button": "Criar conta", "nav.logIn.button": "Acessar", "nav.signIn.button": "Entrar", "nav.signUp.button": "Criar conta", "nav.tabs.createPosition": "Criar posição", - "nav.tabs.viewPositions": "View positions", + "nav.tabs.viewPositions": "Ver posições", "network.lostConnection": "Você pode ter perdido sua conexão de rede.", "network.mightBeDown": "A rede {{network}} pode estar indisponível, ou talvez você tenha perdido sua conexão de rede.", "network.warning": "Aviso de rede", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Ver frase de recuperação", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 outra carteira", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} outras carteiras", - "onboarding.import.onDeviceRecovery.warning.caption": "É importante fazer backup de todas as outras carteiras. Se quiser restaurá-las, você precisará das frases de recuperação ou dos backups correspondentes do iCloud.", + "onboarding.import.onDeviceRecovery.warning.caption": "É importante fazer backup de todas as outras carteiras. Se quiser restaurá-las, será necessário usar suas frases de recuperação ou fazer uso dos backups correspondentes do {{cloudProvider}}.", "onboarding.import.onDeviceRecovery.warning.title": "Tem certeza disso?", "onboarding.import.title": "Escolha como deseja adicionar sua carteira", "onboarding.importMnemonic.button.default": "Minha frase de recuperação tem 12 palavras", @@ -1347,8 +1346,8 @@ "pool.areFirst": "Você é o primeiro provedor de liquidez.", "pool.back": "Voltar para o pool", "pool.balances": "Saldos do pool", - "pool.closedCTA.description": "You can see them by using the filter at the top of the page.", - "pool.closedCTA.title": "Looking for your closed positions?", + "pool.closedCTA.description": "Para vê-las, use o filtro na parte superior da página.", + "pool.closedCTA.title": "Quer ver suas posições fechadas?", "pool.collectAs": "Recolher como {{nativeWrappedSymbol}}", "pool.collected": " Recolhido", "pool.collectFees": "Recolher tarifas", @@ -1360,9 +1359,9 @@ "pool.create.info": "Suas seleções criarão um pool de liquidez que pode resultar em menor liquidez inicial e maior volatilidade. Considere a adição a um pool existente para minimizar esses riscos.", "pool.create.pair": "Criar um par", "pool.createAndSupply": "Criar pool e suprimento", - "pool.createdPosition": "Created position", - "pool.createdPosition.cancelled": "Create position cancelled", - "pool.createdPosition.failed": "Create position failed", + "pool.createdPosition": "Posição criada", + "pool.createdPosition.cancelled": "Criação de posição cancelada", + "pool.createdPosition.failed": "Falha na criação de posição", "pool.depositAmounts": "Valores de depósito", "pool.earnFees": "Ao adicionar liquidez, você ganhará 0,3% de todas as negociações neste par, proporcionalmente à sua participação no pool. As tarifas são adicionadas ao pool, acumuladas em tempo real e podem ser resgatadas ao sacar sua liquidez.", "pool.estimatePercentToRevert": "A saída é estimada. Se o preço mudar em mais de {{allowed}}%, sua transação será revertida.", @@ -1370,9 +1369,12 @@ "pool.exporeAnalytics": "Explorar as análises da Uniswap.", "pool.hideClosed": "Ocultar posições fechadas", "pool.import": "Importar pool", - "pool.import.v2": "Importar pool V2", + "pool.import.link.description": "Some v2 positions aren’t displayed automatically.", + "pool.import.positions.v2": "Import V2 positions", + "pool.import.positions.v2.selectPair.description": "Some v2 positions aren’t displayed automatically. Select a token pair to import and view your positions.", + "pool.import.success": "Pool imported", "pool.increaseLiquidity": "Aumentar liquidez", - "pool.info": "Pool info", + "pool.info": "Informações do pool", "pool.initialShare": "Preços iniciais e quota do pool", "pool.learn": "Saiba mais", "pool.learnAbout": "Leia mais sobre como fornecer liquidez", @@ -1380,10 +1382,10 @@ "pool.learnv3LP": "Confira nosso passo a passo do LP v3 e os guias de migração.", "pool.limitFluctuation.warning": "É importante saber que a execução das ordens-limite pode variar com as oscilações do mercado em tempo real e com o congestionamento da rede Ethereum. É possível que as ordens não sejam executadas assim que os tokens atingirem o preço especificado.", "pool.liquidity.connectToAdd": "Conecte-se a uma carteira para visualizar sua liquidez.", - "pool.liquidity.data.error.message": "There was an error fetching data required for your transaction.", + "pool.liquidity.data.error.message": "Houve um erro ao obter dados necessários para sua transação.", "pool.liquidity.earn.fee": "Os provedores de liquidez ganham uma tarifa de 0,3% em todas as negociações, proporcionalmente à sua quota no pool. As tarifas são adicionadas ao pool, acumuladas em tempo real e podem ser resgatadas ao sacar sua liquidez.", - "pool.liquidity.outOfSync": "Pool prices out of sync", - "pool.liquidity.outOfSync.message": "Prices in this pool are out of sync with the current market. Adding liquidity may result in a loss of funds.", + "pool.liquidity.outOfSync": "Preços do pool dessincronizados", + "pool.liquidity.outOfSync.message": "Os preços deste pool não estão sincronizados com o mercado atual. Adicionar liquidez pode gerar perda de fundos.", "pool.liquidity.ownershipWarning.message": "Esta posição de PL não é sua. Portanto, você não poderá sacar a liquidez dela, a menos que o seguinte endereço seja seu: {{ownerAddress}}", "pool.liquidity.rewards": "Recompensas do provedor de liquidez", "pool.liquidity.taxWarning": "Impostos do token", @@ -1393,12 +1395,12 @@ "pool.max.label": "Máx.:", "pool.maxPrice": "Preço máximo", "pool.migrateLiquidity": "Migrar liquidez", - "pool.migrateToV4": "Migrate to v4", + "pool.migrateToV4": "Migrar para v4", "pool.min.label": "Mín.:", "pool.minPrice": "Preço mínimo", "pool.mustBeInitialized": "Antes de adicionar liquidez, este pool deve ser inicializado. Para inicializar, selecione um preço inicial para o pool. Em seguida, insira o intervalo de preço de liquidez e o valor de depósito. As taxas de gas serão mais altas do que o normal devido à transação de inicialização.", "pool.newPosition.plus": "+ Nova posição", - "pool.newPosition.title": "New position", + "pool.newPosition.title": "Nova posição", "pool.newSpecificPosition": "Nova posição de {{symbol}}", "pool.noLiquidity": "Nenhuma liquidez encontrada.", "pool.onceHappyReview": "Quando você concordar com a taxa, clique em Suprimento para revisar.", @@ -1415,7 +1417,7 @@ "pool.position.willBe100": "Sua posição será 100% composta por {{sym}} a este preço", "pool.positions": "Posições", "pool.positions.title": "Suas posições", - "pool.positions.transaction.settings": "Transaction settings", + "pool.positions.transaction.settings": "Configurações da transação", "pool.priceRange": "Intervalo de preços", "pool.rangeBadge.tooltip.outsideRange": "O preço deste pool está fora do intervalo selecionado. No momento, sua posição não está ganhando tarifas.", "pool.rangeBadge.tooltip.text": "Sua posição tem liquidez 0 e não está ganhando tarifas.", @@ -1436,7 +1438,7 @@ "pool.supplyingMaths": "Fornecendo {{symA}} {{amtA}} e {{symB}} {{amtB}}", "pool.tokenPair": "Par de tokens", "pool.top": "Principais pools", - "pool.top.tvl": "Top pools by TVL", + "pool.top.tvl": "Maiores pools por TVL", "pool.totalTokens": "Seu total de tokens no pool:", "pool.uncollectedFees": "Tarifas não recolhidas", "pool.v2": "Pools v2", @@ -1445,40 +1447,35 @@ "pool.v2liquidity": "Liquidez V2", "pool.v3": "Pools v3", "pool.v4": "Pools v4", - "pool.viewUncollectedFees": "View uncollected fees and analytics", + "pool.viewUncollectedFees": "Ver tarifas não recolhidas e análise", "pool.volOverTvl": "Vol. de 1 dia/TVL", - "pool.volume.thirtyDay": "30 day volume", - "pool.volume.thirtyDay.short": "30D vol", + "pool.volume.thirtyDay": "Volume de 30 dias", + "pool.volume.thirtyDay.short": "Vol. 30 d", "pool.yourv2": "Sua liquidez V2", - "poolFinder.connect": "Conecte-se a uma carteira para encontrar pools.", - "poolFinder.create": "Criar pool", - "poolFinder.found": "Pool encontrado!", - "poolFinder.managePool": "Gerenciar este pool", - "poolFinder.noLiquidity": "Você ainda não tem liquidez neste pool.", - "poolFinder.noPoolFound": "Nenhum pool encontrado.", - "poolFinder.selectToken": "Selecione um token para encontrar sua liquidez v2.", - "poolFinder.tip": "Dica: use esta ferramenta para encontrar pools v2 que não aparecem automaticamente na interface.", + "poolFinder.availablePools": "Available pools", + "poolFinder.availablePools.found.description": "v2 pools matching your pair selection.", + "poolFinder.availablePools.notFound.description": "No matching v2 pools found. Double-check your token selection and ensure you’re connected to the correct wallet.", "pools.approving.amount": "Aprovando {{amount}}", "pools.explore": "Explorar pools", "position.addHook": "Adicionar um hook", "position.addHook.tooltip": "Hooks são um recurso avançado que permite que pools interajam com contratos inteligentes, possibilitando o acesso a vários recursos. Tenha cuidado ao adicionar hooks, pois alguns podem ser maliciosos ou causar consequências não intencionais.", - "position.addingHook": "Adding hook", - "position.addingHook.disclaimer": "Adding hooks may have unintended consequences. Do your research and proceed at your own risk.", - "position.addingHook.invalidAddress": "Enter a valid hook address", - "position.addingHook.viewProperties": "View properties", + "position.addingHook": "Adicionar hook", + "position.addingHook.disclaimer": "A adição de hooks pode ter consequências e riscos inesperados para você. Pesquise antes de continuar.", + "position.addingHook.invalidAddress": "Insira um endereço de hook válido", + "position.addingHook.viewProperties": "Ver propriedades", "position.appearHere": "Sua posição aparecerá aqui.", - "position.create.invalidPrice": "Invalid price", - "position.create.invalidRange": "Invalid range", + "position.create.invalidPrice": "Preço inválido", + "position.create.invalidRange": "Intervalo inválido", "position.create.modal.header": "Criando posição", "position.currentValue": "Valor da posição atual", "position.deposit.description": "Especifique os valores de token para sua contribuição de liquidez.", "position.depositedCurrency": "Depósito de {{currencySymbol}}", - "position.hook.disclaimer": "I understand the risks.", - "position.hook.liquidityWarning": "This flag can cause the pool to block the addition of new liquidity. Your transaction may revert.", - "position.hook.removeWarning": "This flag can cause your funds to be locked or block you from collecting fees.", - "position.hook.swapWarning": "This flag can allow sophisticated users to more easily leverage Just-In-Time liquidity resulting in lower fees earned.", - "position.hook.warningHeader": "High risk hook detected", - "position.hook.warningInfo": "We’ve identified potential risks with this hook. Please review the flags and verify that this is the hook you want to use before proceeding.", + "position.hook.disclaimer": "Entendo os riscos.", + "position.hook.liquidityWarning": "Esta sinalização pode fazer o pool bloquear a adição de liquidez. Sua transação pode ser retornada.", + "position.hook.removeWarning": "Esta sinalização pode bloquear seus fundos ou impedir o recolhimento de tarifas.", + "position.hook.swapWarning": "Esta sinalização pode dar a usuários sofisticados a chance de usar liquidez pontual, o que pode reduzir o ganho com tarifas.", + "position.hook.warningHeader": "Hook de alto risco detectado", + "position.hook.warningInfo": "Identificamos possíveis riscos com este hook. Veja as sinalizações e verifique se quer realmente usar este hook antes de continuar.", "position.initialPrice": "Preço inicial", "position.initialPrice.info": "Defina a taxa de câmbio inicial entre os dois tokens que você está fornecendo.", "position.migrate.liquidity": "Ao migrar posições, você não pode alterar seu par de tokens, mas pode adicionar um hook para melhorar a funcionalidade.", @@ -1487,19 +1484,20 @@ "position.noLiquidity": "Dados de liquidez não disponíveis.", "position.noLiquidityData": "Não há dados de liquidez.", "position.notFound": "Posição não encontrada", - "position.notFound.description": "Detalhes sobre esta posição não estão disponíveis. Por favor, verifique se você está conectado com a carteira correta.", + "position.notFound.description": "Os detalhes desta posição não estão disponíveis. Confirme que você se conectou com a carteira correta.", "position.protocol": "Posição de {{protocol}}", "position.provide.liquidity": "Escolha os tokens para os quais você deseja fornecer liquidez. É possível selecionar tokens em todas as redes com suporte.", "position.provide.liquidityDescription": "Fornecer liquidez no intervalo completo garante participação contínua no mercado em todos os preços possíveis, oferecendo simplicidade, mas com potencial de perdas inconstantes maiores.", - "position.provide.liquidityDescription.custom": "Custom range allows you to concentrate your liquidity within specific price bounds, enhancing capital efficiency and fee earnings but requiring more active management.", - "position.removeHook": "Remove hook", - "position.resetDescription": "Your tokens, price, and range selections will be reset.", + "position.provide.liquidityDescription.custom": "Com um intervalo personalizado, você pode concentrar sua liquidez em faixas de preço específicas, o que aumenta a eficiência de capital e os ganhos com tarifas, mas exige uma gestão mais ativa.", + "position.removeHook": "Remover hook", + "position.resetDescription": "Os tokens, preços e intervalos selecionados serão redefinidos.", "position.setRange": "Definir intervalo de preços", - "position.setRange.inputsBelow": "Use the inputs below to set your range.", + "position.setRange.inputsBelow": "Use os dados abaixo para definir o intervalo.", "position.step.deposit": "Inserir valores de depósito", "position.step.price": "Definir preço inicial", "position.step.range": "Definir intervalo de preços", "position.step.select": "Selecionar par de tokens e tarifas", + "position.value": "Position value", "position.valueUnavailable": "O valor da posição está indisponível devido à baixa liquidez.", "position.your": "Sua posição", "positions.welcome": "Estas são as suas posições", @@ -1530,18 +1528,18 @@ "qrScanner.title": "Ler um código QR", "qrScanner.wallet.networks": "Redes com suporte", "qrScanner.wallet.title": "Você pode enviar e receber tokens e NFTs em todas as nossas {{numOfNetworks}} redes com suporte.", - "range.outOfView": "Range out of view", + "range.outOfView": "Intervalo fora da vista", "removeLiquidity.collectFees": "Você também recolherá as tarifas obtidas nesta posição.", "removeLiquidity.outputEstimated": "A saída é estimada. Se o preço mudar em mais de {{allowed}}%, sua transação será revertida.", "removeLiquidity.pendingText": "Removendo {{symA}} {{amtA}} e {{symB}} {{amtB}}", "removeLiquidity.pooled": "{{symbol}} em pool:", "removeLiquidity.removing": "Removendo {{symbol1}} {{amt1}} e {{symbol2}} {{amt2}}", - "removeLiquidity.removingTokensTip": "Tip: Removing pool tokens converts your position back into underlying tokens at the current rate, proportional to your share of the pool. Uncollected fees are included in the amounts you receive.", + "removeLiquidity.removingTokensTip": "Dica: remover tokens de um pool retorna sua posição para os tokens em questão ao valor de mercado, proporcionalmente à sua participação no pool. Tarifas não recolhidas serão incluídas no que você receberá.", "removeLiquidity.uniBurned": "Queima de UNI {{a}}/{{b}}", "revoke.failed.message": "Isso fornece ao Uniswap Protocol acesso ao seu token para trading.", "routing.aggregateLiquidity": "Quando disponível, agrega fontes de liquidez para melhores preços e trocas sem custos de gas.", "routing.cheapest": "O cliente Uniswap seleciona a opção de negociação mais barata, considerando o preço e as taxas de rede.", - "routing.cheapest.v4": "The Uniswap client selects the optimal trade option factoring in price and network costs.", + "routing.cheapest.v4": "O cliente Uniswap seleciona a opção de negociação ideal, considerando cotação e custos da rede.", "scantastic.code.expired": "Expirado", "scantastic.code.subtitle": "Digite este código no Uniswap Extension. Sua frase de recuperação será criptografada e transferida com segurança.", "scantastic.code.timeRemaining.shorthand.hours": "Novo código em {{hours}} h {{minutes}} min {{seconds}} s", @@ -1762,7 +1760,7 @@ "swap.approveInWallet": "Aprovar na sua carteira", "swap.balance.amount": "Saldo: {{amount}}", "swap.bestRoute.cost": "A rota de melhor preço custa ~{{gasPrice}} em gas. ", - "swap.bestRoute.cost.v4": "Optimal route costs ~{{gasPrice}} in gas. ", + "swap.bestRoute.cost.v4": "Custos de rota ideal: aprox. {{gasPrice}} em gas.", "swap.bridging.estimatedTime": "Tempo estimado", "swap.bridging.title": "Troca entre redes", "swap.bridging.warning.description": "Você está trocando de {{fromNetwork}} para {{toNetwork}}. Isso também é conhecido como \"transferência\", que move seus tokens de uma rede para outra.", @@ -1848,8 +1846,8 @@ "swap.settings.protection.subtitle.supported": "Rede {{chainName}}", "swap.settings.protection.subtitle.unavailable": "Não disponível em {{chainName}}", "swap.settings.protection.title": "Proteção contra troca", - "swap.settings.routingPreference.option.default.description": "The Uniswap client selects the cheapest trade option factoring in price and network costs.", - "swap.settings.routingPreference.option.default.description.v4": "The Uniswap client selects the optimal trade option factoring in price and network costs.", + "swap.settings.routingPreference.option.default.description": "O cliente Uniswap seleciona a opção de negociação mais barata, considerando cotação e custos da rede.", + "swap.settings.routingPreference.option.default.description.v4": "O cliente Uniswap seleciona a opção de negociação ideal, considerando cotação e custos da rede.", "swap.settings.routingPreference.option.v2.title": "Pools v2", "swap.settings.routingPreference.option.v3.title": "Pools v3", "swap.settings.routingPreference.option.v4.title": "Pools v4", @@ -1878,12 +1876,13 @@ "swap.taxTooltip.tokenSelected": "As tarifas em {{tokenSymbol}} não possibilitam saídas exatas e precisas. Use o campo \"Vender\".", "swap.tokenOwnFees": "Alguns tokens cobram tarifas quando são comprados ou vendidos. Essas tarifas são definidas pelo emissor do token, e a Uniswap não recebe nenhuma delas.", "swap.total": "Total", - "swap.tradeRoutes": "Trade routes", + "swap.tradeRoutes": "Rotas de negociação", "swap.transaction.deadline": "Prazo da transação", "swap.transaction.revertAfter": "Sua transação será revertida se ficar pendente por mais tempo que este período.", "swap.unsupportedAssets.readMore": "Leia mais sobre ativos sem suporte", "swap.warning.enterLargerAmount.title": "Digite um valor maior", - "swap.warning.expectedFailure": "É provável que ocorra falha nesta transação", + "swap.warning.expectedFailure.increaseSlippage": "Tente aumentar a sua derrapagem.", + "swap.warning.expectedFailure.titleMay": "This swap may fail", "swap.warning.insufficientBalance.title": "Você não tem {{currencySymbol}} o suficiente", "swap.warning.insufficientGas.button": "{{currencySymbol}} insuficiente", "swap.warning.insufficientGas.button.bridge": "Trocar por {{ tokenSymbol }} em {{networkName}}", @@ -1897,8 +1896,8 @@ "swap.warning.networkFee.message": "Este é o custo para processar sua transação no blockchain. A Uniswap não tem participação nestas tarifas.", "swap.warning.networkFee.message.uniswapX": "Este é o custo para processar sua transação no blockchain. A Uniswap não tem participação nestas tarifas. O UniswapX agrega fontes de liquidez para garantir melhores preços e trocas sem custos de gas.", "swap.warning.networkFee.wrap": "Fazer wrap de ETH", - "swap.warning.noRoutesFound.message": "There are currently no routes available for your selected tokens. Please try a different pair or check again later.", - "swap.warning.noRoutesFound.title": "No routes available", + "swap.warning.noRoutesFound.message": "No momento, não há rotas disponíveis para os tokens selecionados. Tente usar outro par ou verifique novamente mais tarde.", + "swap.warning.noRoutesFound.title": "Sem rotas disponíveis", "swap.warning.offline.message": "Talvez tenha ocorrido perda de conexão com a internet ou a rede não esteja operacional. Verifique sua conexão com a internet e tente novamente.", "swap.warning.offline.title": "Você está off-line", "swap.warning.priceImpact": "Esta transação resultará em um impacto de no preço de mercado deste pool. Deseja continuar?", @@ -1917,7 +1916,7 @@ "swap.warning.rateLimit.title": "O limite de taxa excedeu", "swap.warning.router.message": "Talvez tenha ocorrido perda de conexão ou a rede não esteja operacional. Se o problema persistir, tente novamente mais tarde.", "swap.warning.router.title": "Não é possível concluir esta negociação agora", - "swap.warning.tokenBlocked.button": "{{tokenSymbol}} is blocked", + "swap.warning.tokenBlocked.button": "{{tokenSymbol}} está bloqueado", "swap.warning.uniswapFee.message.default": "As tarifas são aplicadas para garantir a melhor experiência com a Uniswap. Não há tarifas associadas a esta troca.", "swap.warning.uniswapFee.message.included": "As tarifas são aplicadas para garantir a melhor experiência com a Uniswap e já foram consideradas nesta cotação.", "swap.warning.uniswapFee.title": "Tarifa da troca", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Em algumas testnets, não há suporte para a troca, o envio ou a compra de tokens.", "tdp.stats.unsupportedChainDescription": "Estatísticas e gráficos de token para {{chain}} estão disponíveis em {{infoLink}}", "tdp.symbolNotFound": "Símbolo não encontrado", + "testnet.modal.swapDeepLink.description.toProdMode": "Essa ação exige que o modo testnet esteja desativado. O modo testnet pode ser reativado a qualquer momento nas configurações.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "Essa ação exige que o modo testnet esteja ativado. Os tokens em redes de teste não têm nenhum valor real. O modo Testnet pode ser desativado a qualquer momento nas configurações.", + "testnet.modal.swapDeepLink.title.toProdMode": "Desativar modo testnet", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Ativar modo testnet", "testnet.unsupported": "Não há suporte para esta funcionalidade no modo testnet.", "themeToggle.theme": "Tema", "title.betterPricesMoreListings": "Melhores preços. Mais anúncios. Compre, venda e negocie NFTs nos principais mercados, como o OpenSea. Explore as coleções que estão em alta.", @@ -1977,12 +1980,16 @@ "token.links.website": "Site", "token.priceExplorer.error.description": "Algo deu errado.", "token.priceExplorer.error.title": "Não foi possível carregar o gráfico de preços", - "token.priceExplorer.timeRangeLabel.all": "All time", + "token.priceExplorer.timeRangeLabel.all": "Todo o período", "token.priceExplorer.timeRangeLabel.day": "1 dia", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 Day", "token.priceExplorer.timeRangeLabel.hour": "1 hora", "token.priceExplorer.timeRangeLabel.month": "1 mês", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 Month", "token.priceExplorer.timeRangeLabel.week": "1 semana", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 Week", "token.priceExplorer.timeRangeLabel.year": "1 ano", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 Year", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} não está disponível", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} e {{tokenSymbol1}} não estão disponíveis", "token.safety.fees.uniswapLabsDoesNotReceive": "A Uniswap Labs não recebe nenhuma dessas tarifas.", @@ -1992,31 +1999,31 @@ "token.safety.warning.blocked.description.named": "Você não pode negociar {{tokenSymbol}} usando o aplicativo Uniswap.", "token.safety.warning.dontShowWarningAgain": "Não mostrar este aviso novamente", "token.safety.warning.doYourOwnResearch": "Sempre faça sua própria pesquisa antes de prosseguir.", - "token.safety.warning.feeDescription": "Charges a when {{action}}", - "token.safety.warning.flaggedAsMalicious": "Flagged as malicious", - "token.safety.warning.fotHigh.title": "High fee detected", - "token.safety.warning.fotLow.title": "Fee detected", - "token.safety.warning.fotVeryHigh.title": "Very high fee detected", + "token.safety.warning.feeDescription": "Cobra uma quando {{action}}", + "token.safety.warning.flaggedAsMalicious": "Marcado como malicioso", + "token.safety.warning.fotHigh.title": "Tarifa alta detectada", + "token.safety.warning.fotLow.title": "Tarifa detectada", + "token.safety.warning.fotVeryHigh.title": "Tarifa muito alta detectada", "token.safety.warning.honeypot.message": "{{tokenSymbol}} foi sinalizado como invendável. Trocar esse token poderá resultar em perda de seus fundos.", "token.safety.warning.honeypot.title": "Tarifa de venda de 100% detectada", - "token.safety.warning.impersonator": "Impersonates another token", - "token.safety.warning.impersonator.title": "Impersonator token detected", + "token.safety.warning.impersonator": "Falsificação de outro token", + "token.safety.warning.impersonator.title": "Token falsificado detectado", "token.safety.warning.malicious.general.message": "{{tokenSymbol}} foi marcado como malicioso pela Blockaid.", "token.safety.warning.malicious.impersonator.message": "{{tokenSymbol}} foi marcado pela Blockaid por tentar copiar um token diferente. Este pode não ser o token que você quer fazer swap.", - "token.safety.warning.malicious.impersonator.message.short": "{{tokenSymbol}} may not be the token you are looking to swap.", + "token.safety.warning.malicious.impersonator.message.short": "{{tokenSymbol}} pode não ser o token que você quer transacionar.", "token.safety.warning.malicious.title": "Token malicioso detectado", - "token.safety.warning.mayResultInLoss": "Swapping it may result in a loss of funds.", + "token.safety.warning.mayResultInLoss": "Essa transação pode gerar prejuízo.", "token.safety.warning.medium.heading.default_one": "Este token não é negociado nas principais bolsas centralizadas dos EUA.", "token.safety.warning.medium.heading.default_other": "Estes tokens não são negociados nas principais bolsas centralizadas dos EUA.", "token.safety.warning.medium.heading.default_one_also": "Este token também não é negociado nas principais bolsas centralizadas dos EUA.", "token.safety.warning.medium.heading.default_other_also": "Estes tokens também não são negociados nas principais bolsas centralizadas dos EUA.", "token.safety.warning.medium.heading.named": "{{tokenSymbol}} não é negociado nas principais bolsas centralizadas dos EUA.", - "token.safety.warning.notListedOnExchanges": "Not listed on leading U.S. exchanges", + "token.safety.warning.notListedOnExchanges": "Não listado nas maiores bolsas americanas", "token.safety.warning.sellFee100.message": "{{ tokenSymbol }} foi marcado como incompatível para venda.", "token.safety.warning.sellFee100.title": "Tarifa de venda de 100% detectada", "token.safety.warning.spam.message": "{{tokenSymbol}} foi marcado como spam pela Blockaid.", "token.safety.warning.spam.title": "Token de spam detectado", - "token.safety.warning.spamsUsers": "Spams users", + "token.safety.warning.spamsUsers": "Envia spam a usuários", "token.safety.warning.strong.heading.default_one": "Este token não é negociado nas principais bolsas centralizadas dos EUA ou trocado com frequência na Uniswap.", "token.safety.warning.strong.heading.default_other": "Estes tokens não são negociados nas principais bolsas centralizadas dos EUA ou trocados com frequência na Uniswap.", "token.safety.warning.strong.heading.named": "{{tokenSymbol}} não é negociado nas principais bolsas centralizadas dos EUA ou trocado com frequência na Uniswap.", @@ -2261,7 +2268,7 @@ "unitags.username.error.chars": "Os nomes de usuário só podem conter letras e números", "unitags.username.error.max": "Os nomes de usuário devem ter, no máximo, {{number}} caracteres", "unitags.username.error.min": "Os nomes de usuário devem ter, pelo menos, {{number}} caracteres", - "unitags.username.error.uppercase": "Os nomes de usuário só podem conter letras minúsculas e números", + "unitags.username.error.uppercase": "Nomes de usuário só podem conter letras minúsculas e números", "uwulink.error.insufficientTokens": "Não há {{tokenSymbol}} suficiente em {{chain}}", "v2.notAvailable": "A Uniswap V2 não está disponível nesta rede.", "v2.switchTo": "Alterar para v2", diff --git a/packages/uniswap/src/i18n/locales/translations/ro-RO.json b/packages/uniswap/src/i18n/locales/translations/ro-RO.json index c435be356d4..e922ceef8d7 100644 --- a/packages/uniswap/src/i18n/locales/translations/ro-RO.json +++ b/packages/uniswap/src/i18n/locales/translations/ro-RO.json @@ -222,6 +222,7 @@ "common.button.disconnect": "Deconectat", "common.button.dismiss": "Respingeți", "common.button.done": "Terminat", + "common.button.edit": "Editați | ×", "common.button.enable": "Permite", "common.button.finish": "Termina", "common.button.goBack": "Întoarce-te", @@ -313,7 +314,6 @@ "common.custom": "Personalizat", "common.customRange": "Gamă personalizată", "common.dataOutdated": "Datele pot fi depășite", - "common.dataUnavailable": "Date indisponibile", "common.default": "Mod implicit", "common.defaultTradeOptions": "Opțiuni comerciale implicite", "common.delegate.cancelled": "Delegat anulat", @@ -461,6 +461,7 @@ "common.networkCost": "Costul rețelei", "common.neverMind": "Nu face nimic", "common.new": "Nou", + "common.new.exclamation": "Nou!", "common.nfts": "NFT-uri", "common.noActivity": "Nicio activitate încă", "common.noAmount.error": "Introduceți o sumă", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Căutați după țară sau regiune", "fiatOnRamp.region.title": "Selectați regiunea dvs", "fiatOnRamp.summary.total": "{{cryptoAmount}} pentru {{fiatAmount}}", - "forceUpgrade.action.confirm": "Actualizați aplicația", + "forceUpgrade.action.confirm": "Actualizați acum", "forceUpgrade.action.recoveryPhrase": "Vedeți fraza de recuperare", - "forceUpgrade.description": "Versiunea Uniswap Wallet pe care o utilizați este învechită și lipsesc actualizări critice. Dacă nu actualizați aplicația sau nu aveți notă fraza de recuperare, nu veți putea accesa activele dvs.", + "forceUpgrade.description": "Este disponibilă o nouă versiune a aplicației. Pentru a continua să utilizați portofelul Uniswap, actualizați-l la cea mai recentă versiune.", "forceUpgrade.label.recoveryPhrase": "Fraza de recuperare", - "forceUpgrade.title": "Actualizați aplicația pentru a continua", + "forceUpgrade.title": "Actualizați la cea mai recentă versiune", "globalPreferences.title": "Preferințe globale", "hero.scroll": "Derulați pentru a afla mai multe", "hero.subtitle": "Cea mai mare piață onchain. Cumpărați și vindeți cripto pe Ethereum și peste 11 alte lanțuri.", @@ -940,7 +941,6 @@ "home.feed.title": "A hrani", "home.label.buy": "Cumpără", "home.label.receive": "A primi", - "home.label.scan": "Scanează", "home.label.send": "Trimite", "home.label.swap": "Schimbați", "home.nfts.title": "NFT-uri", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Obțineți aplicația Uniswap Wallet", "mobileAppPromo.banner.title": "Uniswap: portofel Crypto și NFT", "moonpay.poweredBy": "Fiat onramp alimentat de MoonPay USA LLC", - "moonpay.rampIframe": "MoonPay fiat iframe pe rampă", "moonpay.restricted.region": "Moonpay nu este disponibil în unele regiuni. Faceți clic pentru a afla mai multe.", "nav.createAccount.button": "Creează cont", "nav.logIn.button": "Log in", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Vedeți fraza de recuperare", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 alt portofel", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} alte portofele", - "onboarding.import.onDeviceRecovery.warning.caption": "Asigurați-vă că ați făcut backup pentru toate celelalte portofele. Dacă doriți vreodată să le restaurați, veți avea nevoie de frazele lor de recuperare sau de copiile de rezervă iCloud corespunzătoare.", + "onboarding.import.onDeviceRecovery.warning.caption": "Asigurați-vă că ați făcut backup pentru toate celelalte portofele. Dacă doriți vreodată să le restaurați, veți avea nevoie de frazele lor de recuperare sau de copiile de rezervă corespunzătoare {{cloudProvider}} .", "onboarding.import.onDeviceRecovery.warning.title": "Esti sigur?", "onboarding.import.title": "Alegeți cum doriți să adăugați portofelul", "onboarding.importMnemonic.button.default": "Expresia mea de recuperare are 12 cuvinte", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Explorați Uniswap Analytics.", "pool.hideClosed": "Ascunde pozițiile închise", "pool.import": "Import pool", - "pool.import.v2": "Import V2 pool", + "pool.import.link.description": "Unele poziții v2 nu sunt afișate automat.", + "pool.import.positions.v2": "Importați poziții V2", + "pool.import.positions.v2.selectPair.description": "Unele poziții v2 nu sunt afișate automat. Selectați o pereche de jetoane pentru a vă importa și vizualiza pozițiile.", + "pool.import.success": "Pool importat", "pool.increaseLiquidity": "Creșteți lichiditatea", "pool.info": "Informații despre piscină", "pool.initialShare": "Prețurile inițiale și cota de la piscină", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "Volum de 30 de zile", "pool.volume.thirtyDay.short": "30D vol", "pool.yourv2": "Lichiditatea dvs. V2", - "poolFinder.connect": "Conectați-vă la un portofel pentru a găsi piscine.", - "poolFinder.create": "Creați piscină", - "poolFinder.found": "Piscina găsită!", - "poolFinder.managePool": "Gestionați acest bazin", - "poolFinder.noLiquidity": "Încă nu aveți lichidități în acest pool.", - "poolFinder.noPoolFound": "Nu a fost găsită nicio piscină.", - "poolFinder.selectToken": "Selectați un simbol pentru a vă găsi lichiditatea v2.", - "poolFinder.tip": "Sfat: Folosiți acest instrument pentru a găsi pool-uri v2 care nu apar automat în interfață.", + "poolFinder.availablePools": "Piscine disponibile", + "poolFinder.availablePools.found.description": "v2 pool-uri care se potrivesc cu selecția dvs. de pereche.", + "poolFinder.availablePools.notFound.description": "Nu s-au găsit pool-uri v2 care se potrivesc. Verificați din nou selecția de simboluri și asigurați-vă că sunteți conectat la portofelul corect.", "pools.approving.amount": "Se aprobă {{amount}}", "pools.explore": "Explorează piscinele", "position.addHook": "Adăugați un cârlig", @@ -1500,6 +1497,7 @@ "position.step.price": "Setați prețul inițial", "position.step.range": "Setați intervalul de preț", "position.step.select": "Selectați perechea de jetoane și taxe", + "position.value": "Valoarea poziției", "position.valueUnavailable": "Valoarea poziției este indisponibilă din cauza lichidității scăzute.", "position.your": "Pozitia ta", "positions.welcome": "Bine ați venit la pozițiile dvs", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "Tranzacția dvs. va reveni dacă este în așteptare mai mult de această perioadă de timp.", "swap.unsupportedAssets.readMore": "Citiți mai multe despre materialele neacceptate", "swap.warning.enterLargerAmount.title": "Introduceți o sumă mai mare", - "swap.warning.expectedFailure": "Se așteaptă ca această tranzacție să eșueze", + "swap.warning.expectedFailure.increaseSlippage": "Încercați să vă măriți alunecarea.", + "swap.warning.expectedFailure.titleMay": "Acest schimb poate eșua", "swap.warning.insufficientBalance.title": "Nu ai suficient {{currencySymbol}}", "swap.warning.insufficientGas.button": "Nu este suficient {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Schimbați cu {{ tokenSymbol }} pe {{networkName}}", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Unele rețele de testare nu acceptă schimbarea, trimiterea sau cumpărarea de jetoane.", "tdp.stats.unsupportedChainDescription": "Statisticile și graficele pentru token pentru {{chain}} sunt disponibile pe {{infoLink}}", "tdp.symbolNotFound": "Simbolul nu a fost găsit", + "testnet.modal.swapDeepLink.description.toProdMode": "Această acțiune necesită dezactivarea modului testnet. Modul Testnet poate fi reactivat oricând din setări.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "Această acțiune necesită activarea modului testnet. Tokenurile de pe rețelele de testare nu au nicio valoare reală. Modul Testnet poate fi dezactivat oricând din setări.", + "testnet.modal.swapDeepLink.title.toProdMode": "Dezactivați modul testnet", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Activați modul testnet", "testnet.unsupported": "Această funcționalitate nu este acceptată în modul testnet.", "themeToggle.theme": "Temă", "title.betterPricesMoreListings": "Preturi mai bune. Mai multe listări. Cumpărați, vindeți și tranzacționați NFT-uri pe piețele de top precum OpenSea. Explorați colecțiile la modă.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Nu s-a putut încărca graficul de preț", "token.priceExplorer.timeRangeLabel.all": "Tot timpul", "token.priceExplorer.timeRangeLabel.day": "1D", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 zi", "token.priceExplorer.timeRangeLabel.hour": "1H", "token.priceExplorer.timeRangeLabel.month": "1M", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 lună", "token.priceExplorer.timeRangeLabel.week": "1W", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 saptamana", "token.priceExplorer.timeRangeLabel.year": "1Y", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 an", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} nu este disponibil", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} și {{tokenSymbol1}} nu sunt disponibile", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs nu primește niciuna dintre aceste taxe.", diff --git a/packages/uniswap/src/i18n/locales/translations/ru-RU.json b/packages/uniswap/src/i18n/locales/translations/ru-RU.json index 663804d6056..8c7e1ee45c7 100644 --- a/packages/uniswap/src/i18n/locales/translations/ru-RU.json +++ b/packages/uniswap/src/i18n/locales/translations/ru-RU.json @@ -132,15 +132,15 @@ "addressInput.recipient": "Получатель", "analytics.allow": "Разрешить сбор аналитики", "analytics.allow.message": "Мы используем анонимные данные, чтобы улучшить ваш опыт работы с продуктами Uniswap Labs.", - "appRating.button.notReally": "Not really", - "appRating.description": "Let us know if you’re having a good experience with this app", - "appRating.extension.review.description": "Pick a star rating and leave a review on the Chrome Web Store.", - "appRating.extension.review.title": "Review Uniswap Extension?", - "appRating.extension.title": "Enjoying Uniswap Extension?", - "appRating.feedback.button.send": "Send feedback", - "appRating.feedback.description": "Let us know how we can improve your experience", - "appRating.feedback.title": "We’re sorry to hear that.", - "appRating.mobile.title": "Enjoying Uniswap Wallet?", + "appRating.button.notReally": "Не совсем", + "appRating.description": "Дайте нам знать, нравится ли вам работать в этом приложении", + "appRating.extension.review.description": "Поставьте оценку и оставьте отзыв в интернет-магазине Chrome.", + "appRating.extension.review.title": "Оценить расширение Uniswap?", + "appRating.extension.title": "Вам нравится расширение Uniswap?", + "appRating.feedback.button.send": "Отправить отзыв", + "appRating.feedback.description": "Дайте нам знать, как мы можем улучшить для вас приложение", + "appRating.feedback.title": "Нам жаль это слышать.", + "appRating.mobile.title": "Вам нравится кошелек Uniswap?", "bridging.estimatedTime.minutesAndSeconds": "прибл. {{minutes}} мин. {{seconds}} с.", "bridging.estimatedTime.minutesOnly": "прибл. {{minutes}} мин.", "bridging.estimatedTime.secondsOnly": "прибл. {{seconds}} с.", @@ -222,6 +222,7 @@ "common.button.disconnect": "Отключить", "common.button.dismiss": "Отклонить", "common.button.done": "Готово", + "common.button.edit": "Редактировать", "common.button.enable": "Включить", "common.button.finish": "Готово", "common.button.goBack": "Вернуться", @@ -313,7 +314,6 @@ "common.custom": "Индивидуальная настройка", "common.customRange": "Индивидуальный диапазон", "common.dataOutdated": "Данные могут быть устаревшими", - "common.dataUnavailable": "Данные недоступны", "common.default": "По умолчанию", "common.defaultTradeOptions": "Стандартные варианты торговли", "common.delegate.cancelled": "Делегирование отменено", @@ -461,6 +461,7 @@ "common.networkCost": "Комиссия сети", "common.neverMind": "Отмена", "common.new": "Новые", + "common.new.exclamation": "New!", "common.nfts": "NFT", "common.noActivity": "Пока нет активности", "common.noAmount.error": "Введите сумму", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Поиск по стране или региону", "fiatOnRamp.region.title": "Выберите регион", "fiatOnRamp.summary.total": "{{cryptoAmount}} на {{fiatAmount}}", - "forceUpgrade.action.confirm": "Обновить приложение", + "forceUpgrade.action.confirm": "Update now", "forceUpgrade.action.recoveryPhrase": "Просмотреть фразу восстановления", - "forceUpgrade.description": "Используемая вами версия кошелька Uniswap устарела, поэтому в ней отсутствуют важные обновления. Без обновления приложения или записанной фразы восстановления вы не сможете получить доступ к своим активам.", + "forceUpgrade.description": "A new version of the app is available. To continue using the Uniswap Wallet, please update it to the latest version.", "forceUpgrade.label.recoveryPhrase": "Фраза восстановления", - "forceUpgrade.title": "Чтобы продолжить, обновите приложение", + "forceUpgrade.title": "Update to the latest version", "globalPreferences.title": "Общие настройки", "hero.scroll": "Прокрутите страницу, чтобы узнать больше", "hero.subtitle": "Крупнейший ончейн-маркетплейс. Покупайте и продавайте криптовалюту на Эфириум и в более чем 11 других блокчейнах.", @@ -940,7 +941,6 @@ "home.feed.title": "Лента", "home.label.buy": "Купить", "home.label.receive": "Получить", - "home.label.scan": "Сканировать", "home.label.send": "Отправить", "home.label.swap": "Выполнить своп", "home.nfts.title": "NFT", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Загрузите приложение Uniswap Wallet", "mobileAppPromo.banner.title": "Uniswap: кошелек для криптовалюты и NFT", "moonpay.poweredBy": "Обмен традиционной валюты с помощью MoonPay USA LLC", - "moonpay.rampIframe": "Встроенный фрейм MoonPay для обмена традиционной валюты", "moonpay.restricted.region": "Сервис MoonPay недоступен в некоторых регионах. Нажмите здесь, чтобы узнать больше.", "nav.createAccount.button": "Создать аккаунт", "nav.logIn.button": "Вход", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Просмотреть фразу восстановления", "onboarding.import.onDeviceRecovery.wallet.count_one": "Еще один кошелек", "onboarding.import.onDeviceRecovery.wallet.count_other": "Еще столько кошельков: {{count}}", - "onboarding.import.onDeviceRecovery.warning.caption": "Убедитесь, что вы создали резервные копии для всех оставшихся кошельков. Если вы когда-нибудь захотите возобновить их, вам понадобятся фразы восстановления или соответствующие резервные копии iCloud.", + "onboarding.import.onDeviceRecovery.warning.caption": "Убедитесь, что вы создали резервные копии для всех оставшихся кошельков. Если вы когда-нибудь захотите возобновить их, вам понадобятся фразы восстановления или соответствующие резервные копии {{cloudProvider}}.", "onboarding.import.onDeviceRecovery.warning.title": "Вы уверены?", "onboarding.import.title": "Выберите способ добавления кошелька", "onboarding.importMnemonic.button.default": "Моя фраза восстановления состоит из 12 слов", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Изучите аналитику Uniswap.", "pool.hideClosed": "Скрыть закрытые позиции", "pool.import": "Импортировать пул", - "pool.import.v2": "Импортировать пул V2", + "pool.import.link.description": "Some v2 positions aren’t displayed automatically.", + "pool.import.positions.v2": "Import V2 positions", + "pool.import.positions.v2.selectPair.description": "Some v2 positions aren’t displayed automatically. Select a token pair to import and view your positions.", + "pool.import.success": "Pool imported", "pool.increaseLiquidity": "Увеличить ликвидность", "pool.info": "Сведения о пуле", "pool.initialShare": "Начальные цены и доля в пуле", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "Объем за 30 дней", "pool.volume.thirtyDay.short": "Объем за 30 дн.", "pool.yourv2": "Ваша ликвидность V2", - "poolFinder.connect": "Подключитесь к кошельку, чтобы найти пулы.", - "poolFinder.create": "Создать пул", - "poolFinder.found": "Пул найден", - "poolFinder.managePool": "Управлять этим пулом", - "poolFinder.noLiquidity": "У вас еще нет ликвидности в этом пуле.", - "poolFinder.noPoolFound": "Пул не найден.", - "poolFinder.selectToken": "Выберите токен, чтобы узнать свою ликвидность v2.", - "poolFinder.tip": "Совет: используйте этот инструмент, чтобы найти пулы v2, которые не отображаются в интерфейсе автоматически.", + "poolFinder.availablePools": "Available pools", + "poolFinder.availablePools.found.description": "v2 pools matching your pair selection.", + "poolFinder.availablePools.notFound.description": "No matching v2 pools found. Double-check your token selection and ensure you’re connected to the correct wallet.", "pools.approving.amount": "Утверждение {{amount}}", "pools.explore": "Исследование пулов", "position.addHook": "Добавить хук", @@ -1500,6 +1497,7 @@ "position.step.price": "Установить начальную цену", "position.step.range": "Установить ценовой диапазон", "position.step.select": "Выберите пару токенов и комиссии", + "position.value": "Position value", "position.valueUnavailable": "Стоимость позиции недоступна из-за низкой ликвидности.", "position.your": "Ваша позиция", "positions.welcome": "Добро пожаловать в раздел ваших позиций", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "Ваша транзакция будет отменена, если она будет находиться в состоянии ожидания дольше указанного периода времени.", "swap.unsupportedAssets.readMore": "Подробнее о неподдерживаемых активах…", "swap.warning.enterLargerAmount.title": "Введите большую сумму", - "swap.warning.expectedFailure": "Ожидается, что эта транзакция завершится неудачно", + "swap.warning.expectedFailure.increaseSlippage": "Попробуйте повысить уровень проскальзывания.", + "swap.warning.expectedFailure.titleMay": "This swap may fail", "swap.warning.insufficientBalance.title": "У вас недостаточно {{currencySymbol}}", "swap.warning.insufficientGas.button": "Недостаточно {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Обмен на {{ tokenSymbol }} в {{networkName}}", @@ -1917,7 +1916,7 @@ "swap.warning.rateLimit.title": "Превышен лимит запросов", "swap.warning.router.message": "Возможно, потеряно соединение или в сети случился сбой. Если проблема не устранена, повторите попытку позже.", "swap.warning.router.title": "На данный момент невозможно выполнить эту сделку", - "swap.warning.tokenBlocked.button": "{{tokenSymbol}} is blocked", + "swap.warning.tokenBlocked.button": "Токен {{tokenSymbol}} заблокирован", "swap.warning.uniswapFee.message.default": "Для обеспечения наилучшего опыта работы в Uniswap взимаются комиссии. Комиссия за этот своп не предусмотрена.", "swap.warning.uniswapFee.message.included": "Комиссия взимается для обеспечения наилучшего опыта работы в Uniswap и уже учтена в этой котировке.", "swap.warning.uniswapFee.title": "Комиссия за своп", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "В некоторых тестовых сетях не поддерживается обмен, отправка или покупка токенов.", "tdp.stats.unsupportedChainDescription": "Статистика и графики токенов для {{chain}} доступны на странице {{infoLink}}", "tdp.symbolNotFound": "Символ не найден", + "testnet.modal.swapDeepLink.description.toProdMode": "Для выполнения этого действия необходимо отключить режим тестовой сети. Его можно активировать повторно в любое время в настройках.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "Для выполнения этого действия необходимо включить режим тестовой сети. Токены в таких сетях не имеют никакой реальной ценности. Режим тестовой сети можно отключить в любое время в настройках.", + "testnet.modal.swapDeepLink.title.toProdMode": "Отключите режим тестовой сети", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Включите режим тестовой сети", "testnet.unsupported": "Эта функция не поддерживается в режиме тестовой сети.", "themeToggle.theme": "Тема", "title.betterPricesMoreListings": "Лучшие цены. Больше объявлений. Покупайте, продавайте и обменивайте NFT на ведущих маркетплейсах, таких как OpenSea. Изучайте трендовые коллекции.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Не удалось загрузить ценовой график", "token.priceExplorer.timeRangeLabel.all": "За все время", "token.priceExplorer.timeRangeLabel.day": "1 дн.", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 Day", "token.priceExplorer.timeRangeLabel.hour": "1 ч.", "token.priceExplorer.timeRangeLabel.month": "1 мес.", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 Month", "token.priceExplorer.timeRangeLabel.week": "1 нед.", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 Week", "token.priceExplorer.timeRangeLabel.year": "1 г.", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 Year", "token.safety.blocked.title.tokenNotAvailable": "Токен {{tokenSymbol}} недоступен", "token.safety.blocked.title.tokensNotAvailable": "Токены {{tokenSymbol0}} и {{tokenSymbol1}} недоступны", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs не получает никаких подобных комиссий.", diff --git a/packages/uniswap/src/i18n/locales/translations/sl-SI.json b/packages/uniswap/src/i18n/locales/translations/sl-SI.json index a1be68fb6dc..8bbc412030c 100644 --- a/packages/uniswap/src/i18n/locales/translations/sl-SI.json +++ b/packages/uniswap/src/i18n/locales/translations/sl-SI.json @@ -222,6 +222,7 @@ "common.button.disconnect": "Prekini povezavo", "common.button.dismiss": "Odpusti", "common.button.done": "Končano", + "common.button.edit": "Uredi", "common.button.enable": "Omogoči", "common.button.finish": "Končaj", "common.button.goBack": "Pojdi nazaj", @@ -313,7 +314,6 @@ "common.custom": "Po meri", "common.customRange": "Razpon po meri", "common.dataOutdated": "Podatki so lahko zastareli", - "common.dataUnavailable": "Podatki niso na voljo", "common.default": "Privzeto", "common.defaultTradeOptions": "Privzete trgovalne možnosti", "common.delegate.cancelled": "Delegat je preklican", @@ -461,6 +461,7 @@ "common.networkCost": "Stroški omrežja", "common.neverMind": "Pozabi", "common.new": "Novo", + "common.new.exclamation": "Novo!", "common.nfts": "NFT-ji", "common.noActivity": "Ni aktivnosti še", "common.noAmount.error": "Vnesite znesek", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Iskanje po državi ali regiji", "fiatOnRamp.region.title": "Izberite svojo regijo", "fiatOnRamp.summary.total": "{{cryptoAmount}} za {{fiatAmount}}", - "forceUpgrade.action.confirm": "Posodobi aplikacijo", + "forceUpgrade.action.confirm": "Posodobite zdaj", "forceUpgrade.action.recoveryPhrase": "Oglejte si frazo za obnovitev", - "forceUpgrade.description": "Različica Uniswap Wallet, ki jo uporabljate, je zastarela in nima kritičnih nadgradenj. Če ne posodobite aplikacije ali nimate zapisane fraze za obnovitev, ne boste mogli dostopati do svojih sredstev.", + "forceUpgrade.description": "Na voljo je nova različica aplikacije. Če želite še naprej uporabljati denarnico Uniswap, jo posodobite na najnovejšo različico.", "forceUpgrade.label.recoveryPhrase": "Fraza za obnovitev", - "forceUpgrade.title": "Za nadaljevanje posodobite aplikacijo", + "forceUpgrade.title": "Posodobite na najnovejšo različico", "globalPreferences.title": "Globalne nastavitve", "hero.scroll": "Pomaknite se, če želite izvedeti več", "hero.subtitle": "Največja onchain tržnica. Kupujte in prodajajte kripto v Ethereumu in 11+ drugih verigah.", @@ -940,7 +941,6 @@ "home.feed.title": "Krma", "home.label.buy": "Nakup", "home.label.receive": "Prejeti", - "home.label.scan": "Skeniraj", "home.label.send": "Pošlji", "home.label.swap": "Zamenjaj", "home.nfts.title": "NFT-ji", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Prenesite aplikacijo Uniswap Wallet", "mobileAppPromo.banner.title": "Uniswap: kripto in NFT denarnica", "moonpay.poweredBy": "Fiat onramp, ki ga poganja MoonPay USA LLC", - "moonpay.rampIframe": "MoonPay fiat na rampi iframe", "moonpay.restricted.region": "Moonpay ni na voljo v nekaterih regijah. Kliknite, če želite izvedeti več.", "nav.createAccount.button": "Ustvari račun", "nav.logIn.button": "Prijavite se", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Oglejte si frazo za obnovitev", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 druga denarnica", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} druge denarnice", - "onboarding.import.onDeviceRecovery.warning.caption": "Prepričajte se, da ste varnostno kopirali vse druge denarnice. Če jih boste kdaj želeli obnoviti, boste potrebovali njihove obnovitvene stavke ali ustrezne varnostne kopije iCloud.", + "onboarding.import.onDeviceRecovery.warning.caption": "Prepričajte se, da ste varnostno kopirali vse druge denarnice. Če jih boste kdaj želeli obnoviti, boste potrebovali njihove obnovitvene stavke ali ustrezne {{cloudProvider}} varnostne kopije.", "onboarding.import.onDeviceRecovery.warning.title": "Ali si prepričan?", "onboarding.import.title": "Izberite, kako želite dodati svojo denarnico", "onboarding.importMnemonic.button.default": "Moj stavek za obnovitev je 12 besed", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Raziščite Uniswap Analytics.", "pool.hideClosed": "Skrij zaprte pozicije", "pool.import": "Uvozni bazen", - "pool.import.v2": "Uvoz bazena V2", + "pool.import.link.description": "Nekateri položaji v2 niso prikazani samodejno.", + "pool.import.positions.v2": "Uvozi položaje V2", + "pool.import.positions.v2.selectPair.description": "Nekateri položaji v2 niso prikazani samodejno. Izberite par žetonov za uvoz in ogled svojih položajev.", + "pool.import.success": "Bazen uvožen", "pool.increaseLiquidity": "Povečajte likvidnost", "pool.info": "Informacije o bazenu", "pool.initialShare": "Začetne cene in delež skupine", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "30 dnevni volumen", "pool.volume.thirtyDay.short": "30D vol", "pool.yourv2": "Vaša likvidnost V2", - "poolFinder.connect": "Povežite se z denarnico in poiščite bazene.", - "poolFinder.create": "Ustvari bazen", - "poolFinder.found": "Bazen najden!", - "poolFinder.managePool": "Upravljaj ta bazen", - "poolFinder.noLiquidity": "V tem bazenu še nimate likvidnosti.", - "poolFinder.noPoolFound": "Ni bazena.", - "poolFinder.selectToken": "Izberite žeton, da poiščete svojo likvidnost v2.", - "poolFinder.tip": "Namig: uporabite to orodje za iskanje skupin v2, ki se ne prikažejo samodejno v vmesniku.", + "poolFinder.availablePools": "Na voljo bazeni", + "poolFinder.availablePools.found.description": "v2 bazeni, ki ustrezajo vaši izbiri para.", + "poolFinder.availablePools.notFound.description": "Ni ujemajočih se bazenov v2. Še enkrat preverite izbiro žetona in se prepričajte, da ste povezani s pravo denarnico.", "pools.approving.amount": "Odobritev {{amount}}", "pools.explore": "Raziščite bazene", "position.addHook": "Dodajte kavelj", @@ -1500,6 +1497,7 @@ "position.step.price": "Določite začetno ceno", "position.step.range": "Nastavite cenovni razpon", "position.step.select": "Izberite par žetonov in provizije", + "position.value": "Vrednost položaja", "position.valueUnavailable": "Vrednost pozicije ni na voljo zaradi nizke likvidnosti.", "position.your": "Tvoj položaj", "positions.welcome": "Dobrodošli na svojih položajih", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "Vaša transakcija bo razveljavljena, če je na čakanju dlje od tega časa.", "swap.unsupportedAssets.readMore": "Preberite več o nepodprtih sredstvih", "swap.warning.enterLargerAmount.title": "Vnesite večji znesek", - "swap.warning.expectedFailure": "Pričakuje se, da ta transakcija ne bo uspela", + "swap.warning.expectedFailure.increaseSlippage": "Poskusite povečati zdrs.", + "swap.warning.expectedFailure.titleMay": "Ta zamenjava morda ne uspe", "swap.warning.insufficientBalance.title": "Nimate dovolj {{currencySymbol}}", "swap.warning.insufficientGas.button": "Ni dovolj {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Zamenjaj za {{ tokenSymbol }} na {{networkName}}", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Nekatera testna omrežja ne podpirajo zamenjave, pošiljanja ali nakupa žetonov.", "tdp.stats.unsupportedChainDescription": "Statistika žetonov in grafikoni za {{chain}} so na voljo na {{infoLink}}", "tdp.symbolNotFound": "Simbola ni mogoče najti", + "testnet.modal.swapDeepLink.description.toProdMode": "To dejanje zahteva, da je način testnega omrežja onemogočen. Način Testnet lahko kadar koli znova omogočite v nastavitvah.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "To dejanje zahteva, da je omogočen način testnega omrežja. Žetoni v testnih omrežjih nimajo prave vrednosti. Način Testnet lahko kadar koli onemogočite v nastavitvah.", + "testnet.modal.swapDeepLink.title.toProdMode": "Onemogoči način testnega omrežja", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Omogoči način testnega omrežja", "testnet.unsupported": "Ta funkcija ni podprta v načinu testnega omrežja.", "themeToggle.theme": "Tema", "title.betterPricesMoreListings": "Boljše cene. Več oglasov. Kupujte, prodajajte in trgujte z NFT-ji na najboljših tržnicah, kot je OpenSea. Raziščite priljubljene kolekcije.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Grafa cene ni bilo mogoče naložiti", "token.priceExplorer.timeRangeLabel.all": "Ves čas", "token.priceExplorer.timeRangeLabel.day": "1D", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 dan", "token.priceExplorer.timeRangeLabel.hour": "1H", "token.priceExplorer.timeRangeLabel.month": "1M", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 mesec", "token.priceExplorer.timeRangeLabel.week": "1W", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 teden", "token.priceExplorer.timeRangeLabel.year": "1Y", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 leto", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} ni na voljo", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} in {{tokenSymbol1}} nista na voljo", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs ne prejme nobene od teh pristojbin.", diff --git a/packages/uniswap/src/i18n/locales/translations/sr-SP.json b/packages/uniswap/src/i18n/locales/translations/sr-SP.json index aa5c9899bb5..0b8a7045ad4 100644 --- a/packages/uniswap/src/i18n/locales/translations/sr-SP.json +++ b/packages/uniswap/src/i18n/locales/translations/sr-SP.json @@ -222,6 +222,7 @@ "common.button.disconnect": "Прекини везу", "common.button.dismiss": "Одбаци", "common.button.done": "Готово", + "common.button.edit": "Уредити", "common.button.enable": "Омогући", "common.button.finish": "Заврши", "common.button.goBack": "Вратити се", @@ -313,7 +314,6 @@ "common.custom": "Обичај", "common.customRange": "Прилагођени домет", "common.dataOutdated": "Подаци су можда застарели", - "common.dataUnavailable": "Data unavailable", "common.default": "Уобичајено", "common.defaultTradeOptions": "Подразумеване опције трговине", "common.delegate.cancelled": "Делегат је отказан", @@ -461,6 +461,7 @@ "common.networkCost": "Трошкови мреже", "common.neverMind": "Нема везе", "common.new": "Нови", + "common.new.exclamation": "New!", "common.nfts": "НФТс", "common.noActivity": "Још нема активности", "common.noAmount.error": "Унесите износ", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Претражујте по земљи или региону", "fiatOnRamp.region.title": "Изаберите свој регион", "fiatOnRamp.summary.total": "{{cryptoAmount}} за {{fiatAmount}}", - "forceUpgrade.action.confirm": "Ажурирајте апликацију", + "forceUpgrade.action.confirm": "Update now", "forceUpgrade.action.recoveryPhrase": "Прикажи фразу за опоравак", - "forceUpgrade.description": "Верзија Унисвап новчаника коју користите је застарела и недостају јој критичне надоградње. Ако не ажурирате апликацију или немате записану фразу за опоравак, нећете моћи да приступите својим средствима.", + "forceUpgrade.description": "A new version of the app is available. To continue using the Uniswap Wallet, please update it to the latest version.", "forceUpgrade.label.recoveryPhrase": "Фраза за опоравак", - "forceUpgrade.title": "Ажурирајте апликацију да бисте наставили", + "forceUpgrade.title": "Update to the latest version", "globalPreferences.title": "Глобалне преференције", "hero.scroll": "Померите се да бисте сазнали више", "hero.subtitle": "Највеће онцхаин тржиште. Купујте и продајте криптовалуте на Етхереум-у и 11+ других ланаца.", @@ -940,7 +941,6 @@ "home.feed.title": "Напајање", "home.label.buy": "Купи", "home.label.receive": "Примите", - "home.label.scan": "Скенирај", "home.label.send": "Пошаљи", "home.label.swap": "Свап", "home.nfts.title": "НФТс", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Преузмите апликацију Унисвап Валлет", "mobileAppPromo.banner.title": "Унисвап: Црипто & НФТ Валлет", "moonpay.poweredBy": "Фиат онрамп поверед би МоонПаи УСА ЛЛЦ", - "moonpay.rampIframe": "МоонПаи фиат на рампи ифраме", "moonpay.restricted.region": "Моонпаи није доступан у неким регионима. Кликните да сазнате више.", "nav.createAccount.button": "Креирајте налог", "nav.logIn.button": "Пријавите се", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Прикажи фразу за опоравак", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 други новчаник", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} други новчаници", - "onboarding.import.onDeviceRecovery.warning.caption": "Уверите се да сте направили резервну копију свих других новчаника. Ако икада пожелите да их вратите, биће вам потребне њихове фразе за опоравак или одговарајуће иЦлоуд резервне копије.", + "onboarding.import.onDeviceRecovery.warning.caption": "Please ensure you have backed up all of the other wallets. If you ever want to restore them, you’ll need their recovery phrases or corresponding {{cloudProvider}} backups.", "onboarding.import.onDeviceRecovery.warning.title": "Јеси ли сигуран?", "onboarding.import.title": "Изаберите како желите да додате свој новчаник", "onboarding.importMnemonic.button.default": "Моја фраза за опоравак је 12 речи", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Истражите Унисвап Аналитицс.", "pool.hideClosed": "Сакриј затворене позиције", "pool.import": "Увозни базен", - "pool.import.v2": "Увези В2 базен", + "pool.import.link.description": "Some v2 positions aren’t displayed automatically.", + "pool.import.positions.v2": "Import V2 positions", + "pool.import.positions.v2.selectPair.description": "Some v2 positions aren’t displayed automatically. Select a token pair to import and view your positions.", + "pool.import.success": "Pool imported", "pool.increaseLiquidity": "Повећајте ликвидност", "pool.info": "Pool info", "pool.initialShare": "Почетне цене и удео у базену", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "30 day volume", "pool.volume.thirtyDay.short": "30D vol", "pool.yourv2": "Ваша В2 ликвидност", - "poolFinder.connect": "Повежите се са новчаником да бисте пронашли базене.", - "poolFinder.create": "Направите базен", - "poolFinder.found": "Пронађен базен!", - "poolFinder.managePool": "Управљајте овим базеном", - "poolFinder.noLiquidity": "Још увек немате ликвидност у овом базену.", - "poolFinder.noPoolFound": "Није пронађен базен.", - "poolFinder.selectToken": "Изаберите токен да бисте пронашли своју в2 ликвидност.", - "poolFinder.tip": "Савет: Користите овај алат да пронађете в2 скупове који се не појављују аутоматски у интерфејсу.", + "poolFinder.availablePools": "Available pools", + "poolFinder.availablePools.found.description": "v2 pools matching your pair selection.", + "poolFinder.availablePools.notFound.description": "No matching v2 pools found. Double-check your token selection and ensure you’re connected to the correct wallet.", "pools.approving.amount": "Одобравање {{amount}}", "pools.explore": "Истражите базене", "position.addHook": "Додајте Хук", @@ -1500,6 +1497,7 @@ "position.step.price": "Подесите почетну цену", "position.step.range": "Поставите распон цена", "position.step.select": "Изаберите пар токена и накнаде", + "position.value": "Position value", "position.valueUnavailable": "Вредност позиције је недоступна због ниске ликвидности.", "position.your": "Твоја позиција", "positions.welcome": "Добродошли у ваше позиције", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "Ваша трансакција ће бити враћена ако је на чекању дуже од овог временског периода.", "swap.unsupportedAssets.readMore": "Прочитајте више о неподржаним средствима", "swap.warning.enterLargerAmount.title": "Унесите већи износ", - "swap.warning.expectedFailure": "Очекује се да ће ова трансакција пропасти", + "swap.warning.expectedFailure.increaseSlippage": "Try increasing your slippage.", + "swap.warning.expectedFailure.titleMay": "This swap may fail", "swap.warning.insufficientBalance.title": "Немате довољно {{currencySymbol}}", "swap.warning.insufficientGas.button": "Није довољно {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Замена за {{ tokenSymbol }} на {{networkName}}", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Неке тестне мреже не подржавају замену, слање или куповину токена.", "tdp.stats.unsupportedChainDescription": "Статистика токена и графикони за {{chain}} су доступни на {{infoLink}}", "tdp.symbolNotFound": "Симбол није пронађен", + "testnet.modal.swapDeepLink.description.toProdMode": "This action requires testnet mode to be disabled. Testnet mode can be reenabled at anytime within settings.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "This action requires testnet mode to be enabled. Tokens on testnets do not hold any real value. Testnet mode can be disabled at anytime within settings.", + "testnet.modal.swapDeepLink.title.toProdMode": "Disable testnet mode", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Enable testnet mode", "testnet.unsupported": "Ова функционалност није подржана у режиму тестне мреже.", "themeToggle.theme": "Тема", "title.betterPricesMoreListings": "Боље цене. Више огласа. Купујте, продајте и тргујте НФТ-овима на врхунским тржиштима као што је ОпенСеа. Истражите трендовске колекције.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Учитавање графикона цена није успело", "token.priceExplorer.timeRangeLabel.all": "Све време", "token.priceExplorer.timeRangeLabel.day": "1Д", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 Day", "token.priceExplorer.timeRangeLabel.hour": "1Х", "token.priceExplorer.timeRangeLabel.month": "1М", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 Month", "token.priceExplorer.timeRangeLabel.week": "1В", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 Week", "token.priceExplorer.timeRangeLabel.year": "1И", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 Year", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} није доступан", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} и {{tokenSymbol1}} нису доступни", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs не прима ниједну од ових накнада.", diff --git a/packages/uniswap/src/i18n/locales/translations/sv-SE.json b/packages/uniswap/src/i18n/locales/translations/sv-SE.json index bae5a2239dd..6ca836e63b1 100644 --- a/packages/uniswap/src/i18n/locales/translations/sv-SE.json +++ b/packages/uniswap/src/i18n/locales/translations/sv-SE.json @@ -222,6 +222,7 @@ "common.button.disconnect": "Koppla ifrån", "common.button.dismiss": "Avfärda", "common.button.done": "Gjort", + "common.button.edit": "Redigera", "common.button.enable": "Gör det möjligt", "common.button.finish": "Avsluta", "common.button.goBack": "Gå tillbaka", @@ -313,7 +314,6 @@ "common.custom": "Beställnings", "common.customRange": "Anpassat sortiment", "common.dataOutdated": "Data kan vara inaktuella", - "common.dataUnavailable": "Data inte tillgänglig", "common.default": "Standard", "common.defaultTradeOptions": "Standard handelsalternativ", "common.delegate.cancelled": "Delegat avbröts", @@ -461,6 +461,7 @@ "common.networkCost": "Nätverkskostnad", "common.neverMind": "Glöm det", "common.new": "Ny", + "common.new.exclamation": "Ny!", "common.nfts": "NFTs", "common.noActivity": "Ingen aktivitet ännu", "common.noAmount.error": "Ange ett belopp", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Sök efter land eller region", "fiatOnRamp.region.title": "Välj din region", "fiatOnRamp.summary.total": "{{cryptoAmount}} för {{fiatAmount}}", - "forceUpgrade.action.confirm": "Uppdatera appen", + "forceUpgrade.action.confirm": "Uppdatera nu", "forceUpgrade.action.recoveryPhrase": "Visa återställningsfras", - "forceUpgrade.description": "Den version av Uniswap Wallet du använder är inaktuell och saknar viktiga uppgraderingar. Om du inte uppdaterar appen eller om du inte har din återställningsfras nedskriven kommer du inte att kunna komma åt dina tillgångar.", + "forceUpgrade.description": "En ny version av appen är tillgänglig. För att fortsätta använda Uniswap Wallet, uppdatera den till den senaste versionen.", "forceUpgrade.label.recoveryPhrase": "Återställningsfras", - "forceUpgrade.title": "Uppdatera appen för att fortsätta", + "forceUpgrade.title": "Uppdatera till den senaste versionen", "globalPreferences.title": "Globala preferenser", "hero.scroll": "Bläddra för att lära dig mer", "hero.subtitle": "Den största onchain-marknadsplatsen. Köp och sälj krypto på Ethereum och 11+ andra kedjor.", @@ -940,7 +941,6 @@ "home.feed.title": "Utfodra", "home.label.buy": "köpa", "home.label.receive": "Motta", - "home.label.scan": "Skanna", "home.label.send": "Skicka", "home.label.swap": "Byta", "home.nfts.title": "NFTs", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Skaffa Uniswap Wallet-appen", "mobileAppPromo.banner.title": "Uniswap: Krypto- och NFT-plånbok", "moonpay.poweredBy": "Fiat onramp drivs av MoonPay USA LLC", - "moonpay.rampIframe": "MoonPay fiat on-ramp iframe", "moonpay.restricted.region": "Moonpay är inte tillgängligt i vissa regioner. Klicka för att lära mer.", "nav.createAccount.button": "Skapa konto", "nav.logIn.button": "Logga in", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Visa återställningsfras", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 annan plånbok", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} andra plånböcker", - "onboarding.import.onDeviceRecovery.warning.caption": "Se till att du har säkerhetskopierat alla andra plånböcker. Om du någonsin vill återställa dem behöver du deras återställningsfraser eller motsvarande iCloud-säkerhetskopior.", + "onboarding.import.onDeviceRecovery.warning.caption": "Se till att du har säkerhetskopierat alla andra plånböcker. Om du någonsin vill återställa dem behöver du deras återställningsfraser eller motsvarande {{cloudProvider}} säkerhetskopior.", "onboarding.import.onDeviceRecovery.warning.title": "Är du säker?", "onboarding.import.title": "Välj hur du vill lägga till din plånbok", "onboarding.importMnemonic.button.default": "Min återhämtningsfras är 12 ord", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Utforska Uniswap Analytics.", "pool.hideClosed": "Dölj stängda positioner", "pool.import": "Import pool", - "pool.import.v2": "Importera V2 pool", + "pool.import.link.description": "Vissa v2-positioner visas inte automatiskt.", + "pool.import.positions.v2": "Importera V2-positioner", + "pool.import.positions.v2.selectPair.description": "Vissa v2-positioner visas inte automatiskt. Välj ett tokenpar för att importera och se dina positioner.", + "pool.import.success": "Pool importerad", "pool.increaseLiquidity": "Öka likviditeten", "pool.info": "Poolinformation", "pool.initialShare": "Initiala priser och poolandel", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "30 dagars volym", "pool.volume.thirtyDay.short": "30D vol", "pool.yourv2": "Din V2-likviditet", - "poolFinder.connect": "Anslut till en plånbok för att hitta pooler.", - "poolFinder.create": "Skapa pool", - "poolFinder.found": "Pool hittad!", - "poolFinder.managePool": "Hantera denna pool", - "poolFinder.noLiquidity": "Du har inte likviditet i denna pool ännu.", - "poolFinder.noPoolFound": "Ingen pool hittades.", - "poolFinder.selectToken": "Välj en token för att hitta din v2-likviditet.", - "poolFinder.tip": "Tips: Använd det här verktyget för att hitta v2-pooler som inte automatiskt visas i gränssnittet.", + "poolFinder.availablePools": "Tillgängliga pooler", + "poolFinder.availablePools.found.description": "v2-pooler som matchar ditt parval.", + "poolFinder.availablePools.notFound.description": "Inga matchande v2-pooler hittades. Dubbelkolla ditt val av token och se till att du är ansluten till rätt plånbok.", "pools.approving.amount": "Godkänner {{amount}}", "pools.explore": "Utforska pooler", "position.addHook": "Lägg till en krok", @@ -1500,6 +1497,7 @@ "position.step.price": "Sätt initialt pris", "position.step.range": "Ställ in prisklass", "position.step.select": "Välj tokenpar och avgifter", + "position.value": "Positionsvärde", "position.valueUnavailable": "Positionsvärdet är inte tillgängligt på grund av låg likviditet.", "position.your": "Din position", "positions.welcome": "Välkommen till dina positioner", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "Din transaktion kommer att återställas om den väntar längre än denna tidsperiod.", "swap.unsupportedAssets.readMore": "Läs mer om tillgångar som inte stöds", "swap.warning.enterLargerAmount.title": "Ange ett större belopp", - "swap.warning.expectedFailure": "Denna transaktion förväntas misslyckas", + "swap.warning.expectedFailure.increaseSlippage": "Försök att öka din glidning.", + "swap.warning.expectedFailure.titleMay": "Detta byte kan misslyckas", "swap.warning.insufficientBalance.title": "Du har inte tillräckligt med {{currencySymbol}}", "swap.warning.insufficientGas.button": "Inte tillräckligt {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Byt mot {{ tokenSymbol }} på {{networkName}}", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Vissa testnät stöder inte att byta, skicka eller köpa tokens.", "tdp.stats.unsupportedChainDescription": "Tokenstatistik och diagram för {{chain}} finns på {{infoLink}}", "tdp.symbolNotFound": "Symbolen hittades inte", + "testnet.modal.swapDeepLink.description.toProdMode": "Den här åtgärden kräver att testnätläget är inaktiverat. Testnet-läget kan återaktiveras när som helst inom inställningarna.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "Denna åtgärd kräver att testnätläget är aktiverat. Tokens på testnät har inget verkligt värde. Testnet-läget kan inaktiveras när som helst inom inställningarna.", + "testnet.modal.swapDeepLink.title.toProdMode": "Inaktivera testnätläge", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Aktivera testnätläge", "testnet.unsupported": "Den här funktionen stöds inte i testnätläge.", "themeToggle.theme": "Tema", "title.betterPricesMoreListings": "Bättre priser. Fler listor. Köp, sälj och byt NFT på toppmarknadsplatser som OpenSea. Utforska trendiga samlingar.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Det gick inte att ladda prisdiagrammet", "token.priceExplorer.timeRangeLabel.all": "Hela tiden", "token.priceExplorer.timeRangeLabel.day": "1D", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 dag", "token.priceExplorer.timeRangeLabel.hour": "1H", "token.priceExplorer.timeRangeLabel.month": "1M", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 månad", "token.priceExplorer.timeRangeLabel.week": "1W", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 vecka", "token.priceExplorer.timeRangeLabel.year": "1Y", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 år", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} är inte tillgänglig", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} och {{tokenSymbol1}} är inte tillgängliga", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs tar inte emot några av dessa avgifter.", diff --git a/packages/uniswap/src/i18n/locales/translations/sw-TZ.json b/packages/uniswap/src/i18n/locales/translations/sw-TZ.json index fb76fca7c91..a24d9c0d888 100644 --- a/packages/uniswap/src/i18n/locales/translations/sw-TZ.json +++ b/packages/uniswap/src/i18n/locales/translations/sw-TZ.json @@ -222,6 +222,7 @@ "common.button.disconnect": "Tenganisha", "common.button.dismiss": "Ondoa", "common.button.done": "Imekamilika", + "common.button.edit": "Hariri", "common.button.enable": "Wezesha", "common.button.finish": "Maliza", "common.button.goBack": "Rudi nyuma", @@ -313,7 +314,6 @@ "common.custom": "Desturi", "common.customRange": "Anuwai maalum", "common.dataOutdated": "Data inaweza kuwa ya zamani", - "common.dataUnavailable": "Data unavailable", "common.default": "Chaguomsingi", "common.defaultTradeOptions": "Chaguo-msingi za biashara", "common.delegate.cancelled": "Mjumbe ameghairiwa", @@ -461,6 +461,7 @@ "common.networkCost": "Gharama ya mtandao", "common.neverMind": "Usijali", "common.new": "Mpya", + "common.new.exclamation": "New!", "common.nfts": "NFTs", "common.noActivity": "Hakuna shughuli bado", "common.noAmount.error": "Weka kiasi", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Tafuta kulingana na nchi au eneo", "fiatOnRamp.region.title": "Chagua eneo lako", "fiatOnRamp.summary.total": "{{cryptoAmount}} kwa {{fiatAmount}}", - "forceUpgrade.action.confirm": "Sasisha programu", + "forceUpgrade.action.confirm": "Update now", "forceUpgrade.action.recoveryPhrase": "Tazama maneno ya kurejesha", - "forceUpgrade.description": "Toleo la Uniswap Wallet unalotumia limepitwa na wakati na linakosa masasisho muhimu. Ikiwa hutasasisha programu au huna kifungu chako cha maneno ya urejeshi kilichoandikwa, hutaweza kufikia vipengee vyako.", + "forceUpgrade.description": "A new version of the app is available. To continue using the Uniswap Wallet, please update it to the latest version.", "forceUpgrade.label.recoveryPhrase": "Maneno ya kurejesha", - "forceUpgrade.title": "Sasisha programu ili kuendelea", + "forceUpgrade.title": "Update to the latest version", "globalPreferences.title": "Mapendeleo ya kimataifa", "hero.scroll": "Sogeza ili upate maelezo zaidi", "hero.subtitle": "Soko kubwa zaidi la onchain. Nunua na uuze cryptocurrency kwenye Ethereum na minyororo mingine 11+.", @@ -940,7 +941,6 @@ "home.feed.title": "Kulisha", "home.label.buy": "Nunua", "home.label.receive": "Pokea", - "home.label.scan": "Changanua", "home.label.send": "Tuma", "home.label.swap": "Badili", "home.nfts.title": "NFTs", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Pata programu ya Uniswap Wallet", "mobileAppPromo.banner.title": "Uniswap: Crypto & NFT Wallet", "moonpay.poweredBy": "Fiat onramp inayoendeshwa na MoonPay USA LLC", - "moonpay.rampIframe": "MoonPay fiat on-ramp iframe", "moonpay.restricted.region": "Moonpay haipatikani katika baadhi ya maeneo. Bofya ili kujifunza zaidi.", "nav.createAccount.button": "Unda akaunti", "nav.logIn.button": "Ingia", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Tazama maneno ya kurejesha", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 pochi nyingine", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} pochi zingine", - "onboarding.import.onDeviceRecovery.warning.caption": "Tafadhali hakikisha kuwa umeweka nakala rudufu za pochi zingine zote. Ikiwa ungependa kuzirejesha, utahitaji vifungu vyao vya urejeshaji au nakala rudufu zinazolingana za iCloud.", + "onboarding.import.onDeviceRecovery.warning.caption": "Please ensure you have backed up all of the other wallets. If you ever want to restore them, you’ll need their recovery phrases or corresponding {{cloudProvider}} backups.", "onboarding.import.onDeviceRecovery.warning.title": "Una uhakika?", "onboarding.import.title": "Chagua jinsi ungependa kuongeza pochi yako", "onboarding.importMnemonic.button.default": "Maneno yangu ya kurejesha ni maneno 12", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Gundua Takwimu za Uniswap.", "pool.hideClosed": "Ficha nafasi zilizofungwa", "pool.import": "Bwawa la kuagiza", - "pool.import.v2": "Ingiza bwawa la kuogelea la V2", + "pool.import.link.description": "Some v2 positions aren’t displayed automatically.", + "pool.import.positions.v2": "Import V2 positions", + "pool.import.positions.v2.selectPair.description": "Some v2 positions aren’t displayed automatically. Select a token pair to import and view your positions.", + "pool.import.success": "Pool imported", "pool.increaseLiquidity": "Kuongeza ukwasi", "pool.info": "Pool info", "pool.initialShare": "Bei za awali na hisa za pool", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "30 day volume", "pool.volume.thirtyDay.short": "30D vol", "pool.yourv2": "Ukwasi wako wa V2", - "poolFinder.connect": "Unganisha kwenye pochi ili kupata mabwawa.", - "poolFinder.create": "Unda bwawa", - "poolFinder.found": "Bwawa limepatikana!", - "poolFinder.managePool": "Dhibiti bwawa hili", - "poolFinder.noLiquidity": "Bado huna ukwasi katika bwawa hili.", - "poolFinder.noPoolFound": "Hakuna bwawa lililopatikana.", - "poolFinder.selectToken": "Chagua tokeni ili kupata ukwasi wako wa v2.", - "poolFinder.tip": "Kidokezo: Tumia zana hii kupata vidimbwi vya v2 ambavyo havionekani kiotomatiki kwenye kiolesura.", + "poolFinder.availablePools": "Available pools", + "poolFinder.availablePools.found.description": "v2 pools matching your pair selection.", + "poolFinder.availablePools.notFound.description": "No matching v2 pools found. Double-check your token selection and ensure you’re connected to the correct wallet.", "pools.approving.amount": "Inaidhinisha {{amount}}", "pools.explore": "Gundua mabwawa", "position.addHook": "Ongeza Hook", @@ -1500,6 +1497,7 @@ "position.step.price": "Weka bei ya awali", "position.step.range": "Weka anuwai ya bei", "position.step.select": "Chagua jozi ya tokeni na ada", + "position.value": "Position value", "position.valueUnavailable": "Thamani ya nafasi haipatikani kutokana na ukwasi wa chini.", "position.your": "Nafasi yako", "positions.welcome": "Karibu kwenye nafasi zako", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "Muamala wako utarejeshwa ikiwa unasubiri kwa zaidi ya kipindi hiki.", "swap.unsupportedAssets.readMore": "Soma zaidi kuhusu vipengee visivyotumika", "swap.warning.enterLargerAmount.title": "Weka kiasi kikubwa zaidi", - "swap.warning.expectedFailure": "Muamala huu unatarajiwa kushindwa", + "swap.warning.expectedFailure.increaseSlippage": "Try increasing your slippage.", + "swap.warning.expectedFailure.titleMay": "This swap may fail", "swap.warning.insufficientBalance.title": "Huna vya kutosha {{currencySymbol}}", "swap.warning.insufficientGas.button": "Haitoshi {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Badilisha kwa {{ tokenSymbol }} kwenye {{networkName}}", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Baadhi ya mitandao ya majaribio haiungi mkono kubadilisha, kutuma, au kununua tokeni.", "tdp.stats.unsupportedChainDescription": "Takwimu na chati za tokeni za {{chain}} zinapatikana kwenye {{infoLink}}", "tdp.symbolNotFound": "Alama haijapatikana", + "testnet.modal.swapDeepLink.description.toProdMode": "This action requires testnet mode to be disabled. Testnet mode can be reenabled at anytime within settings.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "This action requires testnet mode to be enabled. Tokens on testnets do not hold any real value. Testnet mode can be disabled at anytime within settings.", + "testnet.modal.swapDeepLink.title.toProdMode": "Disable testnet mode", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Enable testnet mode", "testnet.unsupported": "Kipengele hiki hakiungwi mkono katika hali ya testnet.", "themeToggle.theme": "Mandhari", "title.betterPricesMoreListings": "Bei bora. Orodha zaidi. Nunua, uza na ufanye biashara ya NFTs kwenye soko kuu kama OpenSea. Gundua mikusanyiko inayovuma.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Haikuweza kupakia chati ya bei", "token.priceExplorer.timeRangeLabel.all": "Muda wote", "token.priceExplorer.timeRangeLabel.day": "1S", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 Day", "token.priceExplorer.timeRangeLabel.hour": "1Saa", "token.priceExplorer.timeRangeLabel.month": "1Mwezi", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 Month", "token.priceExplorer.timeRangeLabel.week": "1Wiki", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 Week", "token.priceExplorer.timeRangeLabel.year": "1Mwaka", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 Year", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} haipatikani", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} na {{tokenSymbol1}} hazipatikani", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs haipokei ada yoyote kati ya hizi.", diff --git a/packages/uniswap/src/i18n/locales/translations/tr-TR.json b/packages/uniswap/src/i18n/locales/translations/tr-TR.json index 3e17e7bc87f..d2518cd47c0 100644 --- a/packages/uniswap/src/i18n/locales/translations/tr-TR.json +++ b/packages/uniswap/src/i18n/locales/translations/tr-TR.json @@ -132,15 +132,15 @@ "addressInput.recipient": "Alıcı", "analytics.allow": "Analizlere izin ver", "analytics.allow.message": "Uniswap Labs ürünleriyle deneyimini geliştirmek için anonimleştirilmiş veriler kullanıyoruz.", - "appRating.button.notReally": "Not really", - "appRating.description": "Let us know if you’re having a good experience with this app", - "appRating.extension.review.description": "Pick a star rating and leave a review on the Chrome Web Store.", - "appRating.extension.review.title": "Review Uniswap Extension?", - "appRating.extension.title": "Enjoying Uniswap Extension?", - "appRating.feedback.button.send": "Send feedback", - "appRating.feedback.description": "Let us know how we can improve your experience", - "appRating.feedback.title": "We’re sorry to hear that.", - "appRating.mobile.title": "Enjoying Uniswap Wallet?", + "appRating.button.notReally": "Tam olarak değil", + "appRating.description": "Bu uygulamayla iyi bir deneyim elde edip etmediğini bize bildir", + "appRating.extension.review.description": "Chrome Web Store'da yıldız seçerek puan ver ve değerlendirmeni yaz.", + "appRating.extension.review.title": "Uniswap Uzantısını değerlendirmek ister misin?", + "appRating.extension.title": "Uniswap Uzantısından memnun musun?", + "appRating.feedback.button.send": "Geri bildirim gönder", + "appRating.feedback.description": "Sana nasıl daha iyi bir deneyim sunabileceğimizi bize anlat", + "appRating.feedback.title": "Bunu duyduğumuza üzüldük.", + "appRating.mobile.title": "Uniswap Cüzdan'dan memnun musun?", "bridging.estimatedTime.minutesAndSeconds": "~{{minutes}} dk {{seconds}} sn", "bridging.estimatedTime.minutesOnly": "~{{minutes}} dk", "bridging.estimatedTime.secondsOnly": "~{{seconds}} sn", @@ -222,6 +222,7 @@ "common.button.disconnect": "Bağlantıyı kes", "common.button.dismiss": "Kapat", "common.button.done": "Bitti", + "common.button.edit": "Düzenle", "common.button.enable": "Etkinleştir", "common.button.finish": "Bitir", "common.button.goBack": "Geri dön", @@ -313,7 +314,6 @@ "common.custom": "Özel", "common.customRange": "Özel aralık", "common.dataOutdated": "Veriler güncel olmayabilir", - "common.dataUnavailable": "Veriler kullanılamıyor", "common.default": "Varsayılan", "common.defaultTradeOptions": "Varsayılan alım satım seçenekleri", "common.delegate.cancelled": "Devretme iptal edildi", @@ -461,6 +461,7 @@ "common.networkCost": "Ağ maliyeti", "common.neverMind": "Göz ardı et", "common.new": "Yeni", + "common.new.exclamation": "New!", "common.nfts": "NFT'ler", "common.noActivity": "Henüz etkinlik yok", "common.noAmount.error": "Bir tutar gir", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Ülkeye veya bölgeye göre ara", "fiatOnRamp.region.title": "Bölgeni seç", "fiatOnRamp.summary.total": "{{fiatAmount}} karşılığında {{cryptoAmount}}", - "forceUpgrade.action.confirm": "Uygulamayı güncelle", + "forceUpgrade.action.confirm": "Update now", "forceUpgrade.action.recoveryPhrase": "Kurtarma cümlesini görüntüle", - "forceUpgrade.description": "Kullandığın Uniswap Cüzdan sürümü güncel değil ve kritik yükseltmeleri içermiyor. Uygulamayı güncellemezsen veya kurtarma cümleni not etmezsen varlıklarına erişemezsin.", + "forceUpgrade.description": "A new version of the app is available. To continue using the Uniswap Wallet, please update it to the latest version.", "forceUpgrade.label.recoveryPhrase": "Kurtarma cümlesi", - "forceUpgrade.title": "Devam etmek için uygulamayı güncelle", + "forceUpgrade.title": "Update to the latest version", "globalPreferences.title": "Genel tercihler", "hero.scroll": "Daha fazlasını öğrenmek için kaydır", "hero.subtitle": "En büyük zincir içi pazar yeri. Ethereum ve 11'den fazla diğer zincirde kripto para alıp satabilirsin.", @@ -940,7 +941,6 @@ "home.feed.title": "Akış", "home.label.buy": "Al", "home.label.receive": "Al", - "home.label.scan": "Tara", "home.label.send": "Gönder", "home.label.swap": "Swap", "home.nfts.title": "NFT'ler", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Uniswap Cüzdan uygulamasını edin", "mobileAppPromo.banner.title": "Uniswap: Kripto Para ve NFT Cüzdanı", "moonpay.poweredBy": "İtibari para giriş rampası MoonPay USA LLC tarafından destekleniyor", - "moonpay.rampIframe": "MoonPay itibari para giriş rampası satır içi çerçeve", "moonpay.restricted.region": "Moonpay bazı bölgelerde kullanılamaz. Daha fazlasını öğrenmek için tıkla.", "nav.createAccount.button": "Hesap oluştur", "nav.logIn.button": "Giriş yap", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Kurtarma cümlesini görüntüle", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 diğer cüzdan", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} diğer cüzdan", - "onboarding.import.onDeviceRecovery.warning.caption": "Lütfen diğer tüm cüzdanlarını yedeklediğinden emin ol. Bunları geri yüklemek istersen kurtarma cümlelerine veya karşılık gelen iCloud yedeklerine ihtiyacın olacak.", + "onboarding.import.onDeviceRecovery.warning.caption": "Lütfen diğer tüm cüzdanlarını yedeklediğinden emin ol. Bunları geri yüklemek istersen kurtarma cümlelerine veya karşılık gelen {{cloudProvider}} yedeklerine ihtiyacın olacak.", "onboarding.import.onDeviceRecovery.warning.title": "Emin misin?", "onboarding.import.title": "Cüzdanını nasıl eklemek istediğini seç", "onboarding.importMnemonic.button.default": "Kurtarma cümlem 12 kelimeden oluşuyor", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Uniswap Analytics'i keşfet.", "pool.hideClosed": "Kapalı pozisyonları gizle", "pool.import": "Havuzu içe aktar", - "pool.import.v2": "V2 havuzunu içe aktar", + "pool.import.link.description": "Some v2 positions aren’t displayed automatically.", + "pool.import.positions.v2": "Import V2 positions", + "pool.import.positions.v2.selectPair.description": "Some v2 positions aren’t displayed automatically. Select a token pair to import and view your positions.", + "pool.import.success": "Pool imported", "pool.increaseLiquidity": "Likiditeyi artır", "pool.info": "Havuz bilgileri", "pool.initialShare": "Başlangıç fiyatları ve havuz payı", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "30 günlük hacim", "pool.volume.thirtyDay.short": "30 günlük hacim", "pool.yourv2": "V2 likiditen", - "poolFinder.connect": "Havuzları bulmak için bir cüzdana bağlan.", - "poolFinder.create": "Havuz oluştur", - "poolFinder.found": "Havuz bulundu!", - "poolFinder.managePool": "Bu havuzu yönet", - "poolFinder.noLiquidity": "Bu havuzda henüz likiditen yok.", - "poolFinder.noPoolFound": "Havuz bulunamadı.", - "poolFinder.selectToken": "v2 likiditeni bulmak için bir token seç.", - "poolFinder.tip": "İpucu: Arayüzde otomatik olarak görünmeyen v2 havuzlarını bulmak için bu aracı kullan.", + "poolFinder.availablePools": "Available pools", + "poolFinder.availablePools.found.description": "v2 pools matching your pair selection.", + "poolFinder.availablePools.notFound.description": "No matching v2 pools found. Double-check your token selection and ensure you’re connected to the correct wallet.", "pools.approving.amount": "{{amount}} onaylanıyor", "pools.explore": "Havuzları keşfet", "position.addHook": "Kanca Ekle", @@ -1500,6 +1497,7 @@ "position.step.price": "Başlangıç fiyatını belirle", "position.step.range": "Fiyat aralığını belirle", "position.step.select": "Token çiftini ve ücretleri seç", + "position.value": "Position value", "position.valueUnavailable": "Düşük likidite nedeniyle pozisyon değeri mevcut değil.", "position.your": "Pozisyonun", "positions.welcome": "Pozisyonlarına hoş geldin", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "İşlemin bu süreden daha uzun süre beklemede kalırsa geri alınır.", "swap.unsupportedAssets.readMore": "Desteklenmeyen varlıklar hakkında daha fazlasını oku", "swap.warning.enterLargerAmount.title": "Daha büyük bir tutar gir", - "swap.warning.expectedFailure": "Bu işlemin başarısız olması bekleniyor", + "swap.warning.expectedFailure.increaseSlippage": "Slipajını artırmayı dene.", + "swap.warning.expectedFailure.titleMay": "This swap may fail", "swap.warning.insufficientBalance.title": "Yeterli {{currencySymbol}} yok", "swap.warning.insufficientGas.button": "Yeterli {{currencySymbol}} yok", "swap.warning.insufficientGas.button.bridge": "{{networkName}} ağında {{ tokenSymbol }} karşılığında swap et", @@ -1917,7 +1916,7 @@ "swap.warning.rateLimit.title": "Oran limiti aşıldı", "swap.warning.router.message": "Bağlantın kesilmiş veya ağ çökmüş olabilir. Sorun devam ederse lütfen daha sonra tekrar dene.", "swap.warning.router.title": "Bu alım satım şu anda tamamlanamıyor", - "swap.warning.tokenBlocked.button": "{{tokenSymbol}} is blocked", + "swap.warning.tokenBlocked.button": "{{tokenSymbol}} engellendi", "swap.warning.uniswapFee.message.default": "Uniswap ile en iyi deneyimi elde etmen için ücretler uygulanır. Bu swap ile ilgili herhangi bir ücret yoktur.", "swap.warning.uniswapFee.message.included": "Uniswap ile en iyi deneyimi elde etmen için ücretler uygulanır ve bu, son fiyata zaten dâhil edilmiştir.", "swap.warning.uniswapFee.title": "Swap ücreti", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Bazı test ağları token'ların swap, gönderme veya alım işlemlerini desteklemez.", "tdp.stats.unsupportedChainDescription": "{{chain}} için token istatistikleri ve grafikleri {{infoLink}} adresinde mevcuttur", "tdp.symbolNotFound": "Sembol bulunamadı", + "testnet.modal.swapDeepLink.description.toProdMode": "Bu işlem için test ağı modunun devre dışı bırakılması gerekiyor. Test ağı modunu dilediğin zaman ayarlardan yeniden etkinleştirebilirsin.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "Bu işlem için test ağı modunun etkinleştirilmesi gerekiyor. Test ağlarındaki token'lar gerçek bir değere sahip değildir. Test ağı modunu dilediğin zaman ayarlardan devre dışı bırakabilirsin.", + "testnet.modal.swapDeepLink.title.toProdMode": "Test ağı modunu devre dışı bırak", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Test ağı modunu etkinleştir", "testnet.unsupported": "Bu işlevsellik test ağı modunda desteklenmiyor.", "themeToggle.theme": "Tema", "title.betterPricesMoreListings": "Daha iyi fiyatlar. Daha fazla listeleme. OpenSea gibi önde gelen pazar yerlerinde NFT alıp sat ve NFT'lerle işlem yap. Trend olan koleksiyonları keşfet.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Fiyat grafiği yüklenemedi", "token.priceExplorer.timeRangeLabel.all": "Her zaman", "token.priceExplorer.timeRangeLabel.day": "1 gün", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 Day", "token.priceExplorer.timeRangeLabel.hour": "1 sa", "token.priceExplorer.timeRangeLabel.month": "1 ay", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 Month", "token.priceExplorer.timeRangeLabel.week": "1 hf", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 Week", "token.priceExplorer.timeRangeLabel.year": "1 yıl", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 Year", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} mevcut değil", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} ve {{tokenSymbol1}} mevcut değil", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs bu ücretlerin hiçbirini almaz.", diff --git a/packages/uniswap/src/i18n/locales/translations/uk-UA.json b/packages/uniswap/src/i18n/locales/translations/uk-UA.json index afc63249e29..4887913d22c 100644 --- a/packages/uniswap/src/i18n/locales/translations/uk-UA.json +++ b/packages/uniswap/src/i18n/locales/translations/uk-UA.json @@ -222,6 +222,7 @@ "common.button.disconnect": "Відключити", "common.button.dismiss": "Відхилити", "common.button.done": "Готово", + "common.button.edit": "Редагувати", "common.button.enable": "Увімкнути", "common.button.finish": "Закінчити", "common.button.goBack": "Повертайся", @@ -313,7 +314,6 @@ "common.custom": "Custom", "common.customRange": "Спеціальний діапазон", "common.dataOutdated": "Дані можуть бути застарілими", - "common.dataUnavailable": "Дані недоступні", "common.default": "За замовчуванням", "common.defaultTradeOptions": "Опції торгівлі за замовчуванням", "common.delegate.cancelled": "Делегування скасовано", @@ -461,6 +461,7 @@ "common.networkCost": "Вартість мережі", "common.neverMind": "Не зважай", "common.new": "новий", + "common.new.exclamation": "Новинка!", "common.nfts": "NFT", "common.noActivity": "Активності ще немає", "common.noAmount.error": "Введіть суму", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Пошук за країною чи регіоном", "fiatOnRamp.region.title": "Виберіть свій регіон", "fiatOnRamp.summary.total": "{{cryptoAmount}} за {{fiatAmount}}", - "forceUpgrade.action.confirm": "Оновити додаток", + "forceUpgrade.action.confirm": "Оновіть зараз", "forceUpgrade.action.recoveryPhrase": "Переглянути фразу відновлення", - "forceUpgrade.description": "Версія Uniswap Wallet, якою ви користуєтеся, застаріла та не має важливих оновлень. Якщо ви не оновите додаток або не записаєте фразу для відновлення, ви не зможете отримати доступ до своїх ресурсів.", + "forceUpgrade.description": "Доступна нова версія програми. Щоб продовжити використовувати гаманець Uniswap, оновіть його до останньої версії.", "forceUpgrade.label.recoveryPhrase": "Фраза відновлення", - "forceUpgrade.title": "Щоб продовжити, оновіть додаток", + "forceUpgrade.title": "Оновіть до останньої версії", "globalPreferences.title": "Глобальні переваги", "hero.scroll": "Прокрутіть, щоб дізнатися більше", "hero.subtitle": "Найбільший ончейн-маркетплейс. Купуйте та продавайте криптовалюту в Ethereum та понад 11 інших мережах.", @@ -940,7 +941,6 @@ "home.feed.title": "годувати", "home.label.buy": "купити", "home.label.receive": "Отримати", - "home.label.scan": "Сканувати", "home.label.send": "Надіслати", "home.label.swap": "Обмін", "home.nfts.title": "NFT", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Отримайте програму Uniswap Wallet", "mobileAppPromo.banner.title": "Uniswap: крипто та NFT гаманець", "moonpay.poweredBy": "Fiat onramp на базі MoonPay USA LLC", - "moonpay.rampIframe": "MoonPay fiat on-ramp iframe", "moonpay.restricted.region": "Moonpay недоступний у деяких регіонах. Натисніть, щоб дізнатися більше.", "nav.createAccount.button": "Створити акаунт", "nav.logIn.button": "авторизуватися", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Переглянути фразу відновлення", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 інший гаманець", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} інші гаманці", - "onboarding.import.onDeviceRecovery.warning.caption": "Переконайтеся, що ви створили резервні копії всіх інших гаманців. Якщо ви захочете відновити їх, вам знадобляться їхні фрази відновлення або відповідні резервні копії iCloud.", + "onboarding.import.onDeviceRecovery.warning.caption": "Переконайтеся, що ви створили резервні копії всіх інших гаманців. Якщо ви захочете відновити їх, вам знадобляться їхні фрази відновлення або відповідні {{cloudProvider}} резервні копії.", "onboarding.import.onDeviceRecovery.warning.title": "Ти впевнений?", "onboarding.import.title": "Виберіть, як ви хочете додати свій гаманець", "onboarding.importMnemonic.button.default": "Моя фраза відновлення складається з 12 слів", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Дослідіть Uniswap Analytics.", "pool.hideClosed": "Приховати закриті позиції", "pool.import": "Імпортний пул", - "pool.import.v2": "Імпортувати пул V2", + "pool.import.link.description": "Деякі позиції версії 2 не відображаються автоматично.", + "pool.import.positions.v2": "Імпортувати позиції V2", + "pool.import.positions.v2.selectPair.description": "Деякі позиції версії 2 не відображаються автоматично. Виберіть пару токенів для імпорту та перегляду своїх позицій.", + "pool.import.success": "Басейн імпортний", "pool.increaseLiquidity": "Підвищення ліквідності", "pool.info": "Інформація про басейн", "pool.initialShare": "Початкові ціни та частка пулу", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "30-денний обсяг", "pool.volume.thirtyDay.short": "30D об", "pool.yourv2": "Ваша ліквідність V2", - "poolFinder.connect": "Підключіться до гаманця, щоб знайти пули.", - "poolFinder.create": "Створити пул", - "poolFinder.found": "Пул знайдено!", - "poolFinder.managePool": "Керуйте цим пулом", - "poolFinder.noLiquidity": "У вас ще немає ліквідності в цьому пулі.", - "poolFinder.noPoolFound": "Пулу не знайдено.", - "poolFinder.selectToken": "Виберіть токен, щоб знайти свою ліквідність v2.", - "poolFinder.tip": "Порада. Використовуйте цей інструмент, щоб знайти пули v2, які не з’являються автоматично в інтерфейсі.", + "poolFinder.availablePools": "Наявні басейни", + "poolFinder.availablePools.found.description": "пули v2, що відповідають вибраній вами парі.", + "poolFinder.availablePools.notFound.description": "Не знайдено відповідних пулів v2. Ще раз перевірте свій вибір маркера та переконайтеся, що ви підключені до правильного гаманця.", "pools.approving.amount": "Схвалення {{amount}}", "pools.explore": "Досліджуйте басейни", "position.addHook": "Додайте гачок", @@ -1500,6 +1497,7 @@ "position.step.price": "Встановити початкову ціну", "position.step.range": "Встановити діапазон цін", "position.step.select": "Виберіть пару токенів і комісію", + "position.value": "Значення позиції", "position.valueUnavailable": "Значення позиції недоступне через низьку ліквідність.", "position.your": "Ваша позиція", "positions.welcome": "Ласкаво просимо на ваші посади", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "Ваша трансакція буде скасована, якщо вона очікує на розгляд більше цього періоду часу.", "swap.unsupportedAssets.readMore": "Докладніше про непідтримувані активи", "swap.warning.enterLargerAmount.title": "Введіть більшу суму", - "swap.warning.expectedFailure": "Очікується, що ця транзакція буде невдалою", + "swap.warning.expectedFailure.increaseSlippage": "Спробуйте збільшити ковзання.", + "swap.warning.expectedFailure.titleMay": "Цей обмін може не вдатися", "swap.warning.insufficientBalance.title": "Вам не вистачає {{currencySymbol}}", "swap.warning.insufficientGas.button": "Недостатньо {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Поміняти {{ tokenSymbol }} на {{networkName}}", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Деякі тестові мережі не підтримують обмін, надсилання або купівлю токенів.", "tdp.stats.unsupportedChainDescription": "Статистика токенів і діаграми для {{chain}} доступні на {{infoLink}}", "tdp.symbolNotFound": "Символ не знайдено", + "testnet.modal.swapDeepLink.description.toProdMode": "Для цієї дії потрібно вимкнути режим тестової мережі. Режим тестової мережі можна будь-коли повторно ввімкнути в налаштуваннях.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "Для цієї дії потрібно ввімкнути режим тестової мережі. Токени в тестових мережах не мають реальної цінності. Режим тестової мережі можна будь-коли вимкнути в налаштуваннях.", + "testnet.modal.swapDeepLink.title.toProdMode": "Вимкніть режим testnet", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Увімкніть режим тестової мережі", "testnet.unsupported": "Ця функція не підтримується в режимі тестової мережі.", "themeToggle.theme": "Тема", "title.betterPricesMoreListings": "Кращі ціни. Більше оголошень. Купуйте, продавайте та торгуйте NFT на провідних ринках, таких як OpenSea. Досліджуйте трендові колекції.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Не вдалося завантажити графік цін", "token.priceExplorer.timeRangeLabel.all": "Весь час", "token.priceExplorer.timeRangeLabel.day": "1D", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 день", "token.priceExplorer.timeRangeLabel.hour": "1H", "token.priceExplorer.timeRangeLabel.month": "1М", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 місяць", "token.priceExplorer.timeRangeLabel.week": "1 Вт", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 тиждень", "token.priceExplorer.timeRangeLabel.year": "1 рік", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 рік", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} недоступний", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} і {{tokenSymbol1}} недоступні", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs не отримує жодної з цих комісій.", diff --git a/packages/uniswap/src/i18n/locales/translations/ur-PK.json b/packages/uniswap/src/i18n/locales/translations/ur-PK.json index 3bb442d8972..a6b782e9026 100644 --- a/packages/uniswap/src/i18n/locales/translations/ur-PK.json +++ b/packages/uniswap/src/i18n/locales/translations/ur-PK.json @@ -222,6 +222,7 @@ "common.button.disconnect": "منقطع کرنا", "common.button.dismiss": "برطرف کرنا", "common.button.done": "ہو گیا", + "common.button.edit": "ترمیم", "common.button.enable": "فعال", "common.button.finish": "ختم کرنا", "common.button.goBack": "واپس جاو", @@ -313,7 +314,6 @@ "common.custom": "اپنی مرضی کے مطابق", "common.customRange": "اپنی مرضی کی حد", "common.dataOutdated": "ڈیٹا پرانا ہو سکتا ہے۔", - "common.dataUnavailable": "ڈیٹا دستیاب نہیں ہے۔", "common.default": "طے شدہ", "common.defaultTradeOptions": "پہلے سے طے شدہ تجارتی اختیارات", "common.delegate.cancelled": "مندوب منسوخ کر دیا گیا۔", @@ -461,6 +461,7 @@ "common.networkCost": "نیٹ ورک کی قیمت", "common.neverMind": "کوئی بات نہیں", "common.new": "نیا", + "common.new.exclamation": "نیا!", "common.nfts": "NFTs", "common.noActivity": "ابھی تک کوئی سرگرمی نہیں ہے۔", "common.noAmount.error": "ایک رقم درج کریں۔", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "ملک یا علاقے کے لحاظ سے تلاش کریں۔", "fiatOnRamp.region.title": "اپنا علاقہ منتخب کریں۔", "fiatOnRamp.summary.total": "{{fiatAmount}}کے لیے {{cryptoAmount}}", - "forceUpgrade.action.confirm": "ایپ کو اپ ڈیٹ کریں۔", + "forceUpgrade.action.confirm": "ابھی اپ ڈیٹ کریں۔", "forceUpgrade.action.recoveryPhrase": "بحالی کا جملہ دیکھیں", - "forceUpgrade.description": "Uniswap Wallet کا جو ورژن آپ استعمال کر رہے ہیں وہ پرانا ہے اور اس میں اہم اپ گریڈ نہیں ہیں۔ اگر آپ ایپ کو اپ ڈیٹ نہیں کرتے ہیں یا آپ کے پاس اپنا بازیابی کا جملہ نہیں لکھا ہوا ہے، تو آپ اپنے اثاثوں تک رسائی حاصل نہیں کر پائیں گے۔", + "forceUpgrade.description": "ایپ کا نیا ورژن دستیاب ہے۔ Uniswap Wallet کا استعمال جاری رکھنے کے لیے، براہ کرم اسے تازہ ترین ورژن میں اپ ڈیٹ کریں۔", "forceUpgrade.label.recoveryPhrase": "بازیابی کا جملہ", - "forceUpgrade.title": "جاری رکھنے کے لیے ایپ کو اپ ڈیٹ کریں۔", + "forceUpgrade.title": "تازہ ترین ورژن میں اپ ڈیٹ کریں۔", "globalPreferences.title": "عالمی ترجیحات", "hero.scroll": "مزید جاننے کے لیے سکرول کریں۔", "hero.subtitle": "سب سے بڑا آنچین مارکیٹ پلیس۔ Ethereum اور 11+ دیگر زنجیروں پر کرپٹو خریدیں اور فروخت کریں۔", @@ -940,7 +941,6 @@ "home.feed.title": "کھانا کھلانا", "home.label.buy": "خریدنے", "home.label.receive": "وصول کریں۔", - "home.label.scan": "اسکین کریں۔", "home.label.send": "بھیجیں", "home.label.swap": "تبادلہ", "home.nfts.title": "NFTs", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Unswap Wallet ایپ حاصل کریں۔", "mobileAppPromo.banner.title": "بدلاؤ: کرپٹو اور این ایف ٹی والیٹ", "moonpay.poweredBy": "MoonPay USA LLC کے ذریعے تقویت یافتہ Fiat onramp", - "moonpay.rampIframe": "MoonPay fiat آن ریمپ iframe", "moonpay.restricted.region": "Moonpay کچھ علاقوں میں دستیاب نہیں ہے۔ مزید جاننے کے لیے کلک کریں۔", "nav.createAccount.button": "اکاؤنٹ بنائیں", "nav.logIn.button": "لاگ ان کریں۔", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "بحالی کا جملہ دیکھیں", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 دوسرا بٹوہ", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} دوسرے بٹوے", - "onboarding.import.onDeviceRecovery.warning.caption": "براہ کرم یقینی بنائیں کہ آپ نے دیگر تمام بٹوے کا بیک اپ لیا ہے۔ اگر آپ کبھی بھی انہیں بحال کرنا چاہتے ہیں، تو آپ کو ان کے بازیافت کے فقرے یا متعلقہ iCloud بیک اپ کی ضرورت ہوگی۔", + "onboarding.import.onDeviceRecovery.warning.caption": "براہ کرم یقینی بنائیں کہ آپ نے دیگر تمام بٹوے کا بیک اپ لیا ہے۔ اگر آپ کبھی بھی انہیں بحال کرنا چاہتے ہیں، تو آپ کو ان کے بازیابی کے فقرے یا متعلقہ {{cloudProvider}} بیک اپس کی ضرورت ہوگی۔", "onboarding.import.onDeviceRecovery.warning.title": "کیا تمہیں یقین ہے؟", "onboarding.import.title": "منتخب کریں کہ آپ اپنا بٹوہ کیسے شامل کرنا چاہتے ہیں۔", "onboarding.importMnemonic.button.default": "میرا بازیافت جملہ 12 الفاظ کا ہے۔", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Unswap Analytics کو دریافت کریں۔", "pool.hideClosed": "بند پوزیشنوں کو چھپائیں۔", "pool.import": "پول درآمد کریں۔", - "pool.import.v2": "V2 پول درآمد کریں۔", + "pool.import.link.description": "کچھ v2 پوزیشنز خود بخود ظاہر نہیں ہوتی ہیں۔", + "pool.import.positions.v2": "V2 پوزیشنیں درآمد کریں۔", + "pool.import.positions.v2.selectPair.description": "کچھ v2 پوزیشنز خود بخود ظاہر نہیں ہوتی ہیں۔ درآمد کرنے اور اپنی پوزیشن دیکھنے کے لیے ایک ٹوکن جوڑا منتخب کریں۔", + "pool.import.success": "پول درآمد شدہ", "pool.increaseLiquidity": "لیکویڈیٹی میں اضافہ کریں۔", "pool.info": "پول کی معلومات", "pool.initialShare": "ابتدائی قیمتیں اور پول شیئر", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "30 دن کا حجم", "pool.volume.thirtyDay.short": "30D والیوم", "pool.yourv2": "آپ کی V2 لیکویڈیٹی", - "poolFinder.connect": "پول تلاش کرنے کے لیے بٹوے سے جڑیں۔", - "poolFinder.create": "پول بنائیں", - "poolFinder.found": "پول مل گیا!", - "poolFinder.managePool": "اس پول کا انتظام کریں۔", - "poolFinder.noLiquidity": "آپ کے پاس ابھی تک اس پول میں لیکویڈیٹی نہیں ہے۔", - "poolFinder.noPoolFound": "کوئی تالاب نہیں ملا۔", - "poolFinder.selectToken": "اپنی v2 لیکویڈیٹی تلاش کرنے کے لیے ایک ٹوکن منتخب کریں۔", - "poolFinder.tip": "ٹپ: اس ٹول کو v2 پولز تلاش کرنے کے لیے استعمال کریں جو خود بخود انٹرفیس میں ظاہر نہیں ہوتے ہیں۔", + "poolFinder.availablePools": "دستیاب تالاب", + "poolFinder.availablePools.found.description": "آپ کے جوڑے کے انتخاب سے مماثل v2 پول۔", + "poolFinder.availablePools.notFound.description": "کوئی مماثل v2 پول نہیں ملا۔ اپنے ٹوکن کے انتخاب کو دو بار چیک کریں اور یقینی بنائیں کہ آپ صحیح بٹوے سے جڑے ہوئے ہیں۔", "pools.approving.amount": "{{amount}}کی منظوری دے رہا ہے۔", "pools.explore": "تالابوں کو دریافت کریں۔", "position.addHook": "ایک ہک شامل کریں۔", @@ -1500,6 +1497,7 @@ "position.step.price": "ابتدائی قیمت مقرر کریں۔", "position.step.range": "قیمت کی حد مقرر کریں۔", "position.step.select": "ٹوکن جوڑا اور فیس منتخب کریں۔", + "position.value": "پوزیشن کی قدر", "position.valueUnavailable": "کم لیکویڈیٹی کی وجہ سے پوزیشن ویلیو دستیاب نہیں ہے۔", "position.your": "آپ کی پوزیشن", "positions.welcome": "آپ کے عہدوں پر خوش آمدید", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "اگر آپ کا لین دین اس مدت سے زیادہ عرصے سے زیر التوا ہے تو وہ واپس آجائے گا۔", "swap.unsupportedAssets.readMore": "غیر تعاون یافتہ اثاثوں کے بارے میں مزید پڑھیں", "swap.warning.enterLargerAmount.title": "ایک بڑی رقم درج کریں۔", - "swap.warning.expectedFailure": "اس لین دین کے ناکام ہونے کی توقع ہے۔", + "swap.warning.expectedFailure.increaseSlippage": "اپنی پھسلن کو بڑھانے کی کوشش کریں۔", + "swap.warning.expectedFailure.titleMay": "یہ تبادلہ ناکام ہو سکتا ہے۔", "swap.warning.insufficientBalance.title": "آپ کے پاس کافی {{currencySymbol}}نہیں ہے۔", "swap.warning.insufficientGas.button": "کافی نہیں {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "{{networkName}}پر {{ tokenSymbol }} کے لیے تبادلہ کریں۔", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "کچھ ٹیسٹ نیٹ ٹوکن تبدیل کرنے، بھیجنے یا خریدنے کی حمایت نہیں کرتے ہیں۔", "tdp.stats.unsupportedChainDescription": "{{chain}} کے لیے ٹوکن کے اعدادوشمار اور چارٹ {{infoLink}}پر دستیاب ہیں", "tdp.symbolNotFound": "علامت نہیں ملی", + "testnet.modal.swapDeepLink.description.toProdMode": "اس کارروائی کے لیے ٹیسٹ نیٹ موڈ کو غیر فعال کرنے کی ضرورت ہے۔ ٹیسٹ نیٹ موڈ کو ترتیبات کے اندر کسی بھی وقت دوبارہ فعال کیا جا سکتا ہے۔", + "testnet.modal.swapDeepLink.description.toTestnetMode": "اس کارروائی کے لیے ٹیسٹ نیٹ وضع کو فعال کرنے کی ضرورت ہے۔ testnets پر ٹوکن کی کوئی حقیقی قدر نہیں ہوتی۔ ٹیسٹ نیٹ موڈ کو ترتیبات کے اندر کسی بھی وقت غیر فعال کیا جا سکتا ہے۔", + "testnet.modal.swapDeepLink.title.toProdMode": "ٹیسٹ نیٹ موڈ کو غیر فعال کریں۔", + "testnet.modal.swapDeepLink.title.toTestnetMode": "ٹیسٹ نیٹ موڈ کو فعال کریں۔", "testnet.unsupported": "یہ فعالیت ٹیسٹ نیٹ موڈ میں تعاون یافتہ نہیں ہے۔", "themeToggle.theme": "خیالیہ", "title.betterPricesMoreListings": "بہتر قیمتیں۔ مزید فہرستیں OpenSea جیسے بڑے بازاروں میں NFTs خریدیں، بیچیں اور تجارت کریں۔ رجحان ساز مجموعے دریافت کریں۔", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "قیمت کا چارٹ لوڈ نہیں ہو سکا", "token.priceExplorer.timeRangeLabel.all": "تمام وقت", "token.priceExplorer.timeRangeLabel.day": "1D", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 دن", "token.priceExplorer.timeRangeLabel.hour": "1 ایچ", "token.priceExplorer.timeRangeLabel.month": "1M", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 مہینہ", "token.priceExplorer.timeRangeLabel.week": "1W", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 ہفتہ", "token.priceExplorer.timeRangeLabel.year": "1Y", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 سال", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} دستیاب نہیں ہے۔", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} اور {{tokenSymbol1}} دستیاب نہیں ہیں۔", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs ان میں سے کوئی فیس وصول نہیں کرتی ہے۔", diff --git a/packages/uniswap/src/i18n/locales/translations/vi-VN.json b/packages/uniswap/src/i18n/locales/translations/vi-VN.json index 79a63d3ebc2..5941efdd5a7 100644 --- a/packages/uniswap/src/i18n/locales/translations/vi-VN.json +++ b/packages/uniswap/src/i18n/locales/translations/vi-VN.json @@ -132,15 +132,15 @@ "addressInput.recipient": "Người nhận", "analytics.allow": "Cho phép phân tích", "analytics.allow.message": "Chúng tôi sử dụng dữ liệu ẩn danh để nâng cao trải nghiệm của bạn với các sản phẩm của Uniswap Labs.", - "appRating.button.notReally": "Not really", - "appRating.description": "Let us know if you’re having a good experience with this app", - "appRating.extension.review.description": "Pick a star rating and leave a review on the Chrome Web Store.", - "appRating.extension.review.title": "Review Uniswap Extension?", - "appRating.extension.title": "Enjoying Uniswap Extension?", - "appRating.feedback.button.send": "Send feedback", - "appRating.feedback.description": "Let us know how we can improve your experience", - "appRating.feedback.title": "We’re sorry to hear that.", - "appRating.mobile.title": "Enjoying Uniswap Wallet?", + "appRating.button.notReally": "Không hẳn", + "appRating.description": "Hãy cho chúng tôi biết trải nghiệm của bạn với ứng dụng này có tốt không", + "appRating.extension.review.description": "Hãy đưa ra xếp hạng sao và để lại đánh giá trên Chrome Web Store.", + "appRating.extension.review.title": "Đánh giá Tiện ích mở rộng Uniswap?", + "appRating.extension.title": "Bạn thích Tiện ích mở rộng Uniswap chứ?", + "appRating.feedback.button.send": "Gửi phản hồi", + "appRating.feedback.description": "Hãy cho chúng tôi biết cách chúng tôi có thể nâng cao trải nghiệm của bạn", + "appRating.feedback.title": "Chúng tôi rất tiếc khi nghe điều đó.", + "appRating.mobile.title": "Bạn thích Ví Uniswap chứ?", "bridging.estimatedTime.minutesAndSeconds": "~{{minutes}} phút {{seconds}} giây", "bridging.estimatedTime.minutesOnly": "~{{minutes}} phút", "bridging.estimatedTime.secondsOnly": "~{{seconds}} giây", @@ -222,6 +222,7 @@ "common.button.disconnect": "Ngắt kết nối", "common.button.dismiss": "Bỏ qua", "common.button.done": "Xong", + "common.button.edit": "Chỉnh sửa", "common.button.enable": "Bật", "common.button.finish": "Hoàn tất", "common.button.goBack": "Quay lại", @@ -313,7 +314,6 @@ "common.custom": "Tùy chỉnh", "common.customRange": "Khoảng giá tùy chỉnh", "common.dataOutdated": "Dữ liệu có thể đã cũ", - "common.dataUnavailable": "Không có dữ liệu", "common.default": "Mặc định", "common.defaultTradeOptions": "Tùy chọn giao dịch mặc định", "common.delegate.cancelled": "Đã hủy ủy quyền", @@ -461,6 +461,7 @@ "common.networkCost": "Phí mạng", "common.neverMind": "Bỏ qua", "common.new": "Mới", + "common.new.exclamation": "New!", "common.nfts": "NFT", "common.noActivity": "Chưa có hoạt động nào", "common.noAmount.error": "Nhập số tiền", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "Tìm kiếm theo quốc gia hoặc khu vực", "fiatOnRamp.region.title": "Chọn khu vực của bạn", "fiatOnRamp.summary.total": "{{cryptoAmount}} cho {{fiatAmount}}", - "forceUpgrade.action.confirm": "Cập nhật ứng dụng", + "forceUpgrade.action.confirm": "Update now", "forceUpgrade.action.recoveryPhrase": "Xem cụm từ khôi phục", - "forceUpgrade.description": "Phiên bản Ví Uniswap bạn đang sử dụng đã cũ và thiếu các bản nâng cấp quan trọng. Nếu bạn không cập nhật ứng dụng hoặc chưa ghi lại cụm từ khôi phục, bạn sẽ không thể truy cập được tài sản của mình.", + "forceUpgrade.description": "A new version of the app is available. To continue using the Uniswap Wallet, please update it to the latest version.", "forceUpgrade.label.recoveryPhrase": "Cụm từ khôi phục", - "forceUpgrade.title": "Cập nhật ứng dụng để tiếp tục", + "forceUpgrade.title": "Update to the latest version", "globalPreferences.title": "Cài đặt chung", "hero.scroll": "Cuộn để tìm hiểu thêm", "hero.subtitle": "Chợ onchain lớn nhất. Mua và bán crypto trên Ethereum và hơn 11 blockchain khác.", @@ -940,7 +941,6 @@ "home.feed.title": "Bảng tin", "home.label.buy": "Mua", "home.label.receive": "Nhận", - "home.label.scan": "Quét", "home.label.send": "Gửi", "home.label.swap": "Hoán đổi", "home.nfts.title": "NFT", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "Tải ứng dụng Ví Uniswap", "mobileAppPromo.banner.title": "Uniswap: Ví Crypto & NFT", "moonpay.poweredBy": "Đổi tiền pháp định sang tiền mã hóa được cung cấp bởi MoonPay USA LLC", - "moonpay.rampIframe": "Khung đổi tiền pháp định sang tiền mã hóa của MoonPay", "moonpay.restricted.region": "Moonpay không khả dụng tại một số khu vực. Nhấp để tìm hiểu thêm.", "nav.createAccount.button": "Tạo tài khoản", "nav.logIn.button": "Đăng nhập", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "Xem cụm từ khôi phục", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 ví khác", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} ví khác", - "onboarding.import.onDeviceRecovery.warning.caption": "Hãy đảm bảo bạn đã sao lưu tất cả các ví khác. Nếu muốn khôi phục chúng, bạn sẽ cần cụm từ khôi phục hoặc bản sao lưu iCloud tương ứng.", + "onboarding.import.onDeviceRecovery.warning.caption": "Vui lòng đảm bảo bạn đã sao lưu tất cả các ví khác. Đến một thời điểm bạn muốn khôi phục các ví đó, bạn sẽ cần cụm từ khôi phục hoặc bản sao lưu {{cloudProvider}} tương ứng của chúng.", "onboarding.import.onDeviceRecovery.warning.title": "Bạn có chắc chắn không?", "onboarding.import.title": "Chọn cách thêm ví của bạn", "onboarding.importMnemonic.button.default": "Cụm từ khôi phục của tôi có 12 từ", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "Khám phá Phân tích Uniswap.", "pool.hideClosed": "Ẩn vị thế đã đóng", "pool.import": "Nhập pool", - "pool.import.v2": "Nhập pool V2", + "pool.import.link.description": "Some v2 positions aren’t displayed automatically.", + "pool.import.positions.v2": "Import V2 positions", + "pool.import.positions.v2.selectPair.description": "Some v2 positions aren’t displayed automatically. Select a token pair to import and view your positions.", + "pool.import.success": "Pool imported", "pool.increaseLiquidity": "Tăng thanh khoản", "pool.info": "Thông tin pool", "pool.initialShare": "Giá ban đầu và cổ phần trong pool", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "Khối lượng 30 ngày", "pool.volume.thirtyDay.short": "KL 30N", "pool.yourv2": "Thanh khoản V2 của bạn", - "poolFinder.connect": "Kết nối với ví để tìm pool.", - "poolFinder.create": "Tạo pool", - "poolFinder.found": "Đã tìm thấy pool!", - "poolFinder.managePool": "Quản lý pool này", - "poolFinder.noLiquidity": "Bạn chưa có thanh khoản trong pool này.", - "poolFinder.noPoolFound": "Không tìm thấy pool.", - "poolFinder.selectToken": "Chọn một token để tìm thanh khoản v2 của bạn.", - "poolFinder.tip": "Mẹo: Sử dụng công cụ này để tìm pool v2 không tự động xuất hiện trong giao diện.", + "poolFinder.availablePools": "Available pools", + "poolFinder.availablePools.found.description": "v2 pools matching your pair selection.", + "poolFinder.availablePools.notFound.description": "No matching v2 pools found. Double-check your token selection and ensure you’re connected to the correct wallet.", "pools.approving.amount": "Đang phê duyệt {{amount}}", "pools.explore": "Khám phá pool", "position.addHook": "Thêm Hook", @@ -1500,6 +1497,7 @@ "position.step.price": "Đặt giá ban đầu", "position.step.range": "Đặt khoảng giá", "position.step.select": "Chọn cặp token và phí", + "position.value": "Position value", "position.valueUnavailable": "Giá trị vị thế không khả dụng do thanh khoản thấp.", "position.your": "Vị thế của bạn", "positions.welcome": "Chào mừng đến với vị thế của bạn", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "Giao dịch của bạn sẽ hoàn tác nếu đang chờ xử lý quá thời gian này.", "swap.unsupportedAssets.readMore": "Đọc thêm về tài sản không được hỗ trợ", "swap.warning.enterLargerAmount.title": "Nhập số tiền lớn hơn", - "swap.warning.expectedFailure": "Giao dịch này dự kiến sẽ không thành công", + "swap.warning.expectedFailure.increaseSlippage": "Hãy thử tăng mức trượt giá.", + "swap.warning.expectedFailure.titleMay": "This swap may fail", "swap.warning.insufficientBalance.title": "Bạn không có đủ {{currencySymbol}}", "swap.warning.insufficientGas.button": "Không đủ {{currencySymbol}}", "swap.warning.insufficientGas.button.bridge": "Hoán đổi lấy {{ tokenSymbol }} trên {{networkName}}", @@ -1917,7 +1916,7 @@ "swap.warning.rateLimit.title": "Đã vượt quá giới hạn tỷ lệ", "swap.warning.router.message": "Bạn có thể đã mất kết nối hoặc mạng có thể gặp sự cố. Nếu vấn đề vẫn tiếp diễn, vui lòng thử lại sau.", "swap.warning.router.title": "Giao dịch này không thể hoàn tất ngay bây giờ", - "swap.warning.tokenBlocked.button": "{{tokenSymbol}} is blocked", + "swap.warning.tokenBlocked.button": "{{tokenSymbol}} bị chặn", "swap.warning.uniswapFee.message.default": "Phí được áp dụng để đảm bảo trải nghiệm tốt nhất với Uniswap. Không có phí liên quan đến hoán đổi này.", "swap.warning.uniswapFee.message.included": "Phí được áp dụng để đảm bảo trải nghiệm tốt nhất với Uniswap và đã được tính vào giá yết này.", "swap.warning.uniswapFee.title": "Phí hoán đổi", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "Một số mạng thử nghiệm không hỗ trợ hoán đổi, gửi hoặc mua token.", "tdp.stats.unsupportedChainDescription": "Thống kê và biểu đồ token cho {{chain}} khả dụng trên {{infoLink}}", "tdp.symbolNotFound": "Không tìm thấy ký hiệu", + "testnet.modal.swapDeepLink.description.toProdMode": "Bạn cần tắt chế độ mạng thử nghiệm để thực hiện hành động này. Bạn có thể bật lại chế độ mạng thử nghiệm bất cứ lúc nào trong phần cài đặt.", + "testnet.modal.swapDeepLink.description.toTestnetMode": "Bạn cần tắt chế độ mạng thử nghiệm để thực hiện hành động này. Các token trên mạng thử nghiệm không có giá trị thực tế. Bạn có thể tắt chế độ mạng thử nghiệm bất cứ lúc nào trong phần cài đặt.", + "testnet.modal.swapDeepLink.title.toProdMode": "Tắt chế độ mạng thử nghiệm", + "testnet.modal.swapDeepLink.title.toTestnetMode": "Bật chế độ mạng thử nghiệm", "testnet.unsupported": "Chức năng này không được hỗ trợ trong chế độ mạng thử nghiệm.", "themeToggle.theme": "Giao diện", "title.betterPricesMoreListings": "Giá tốt hơn. Nhiều niêm yết hơn. Mua, bán và giao dịch NFT trên các chợ hàng đầu như OpenSea. Khám phá bộ sưu tập thịnh hành.", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "Không thể tải biểu đồ giá", "token.priceExplorer.timeRangeLabel.all": "Mọi thời điểm", "token.priceExplorer.timeRangeLabel.day": "1 ngày", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 Day", "token.priceExplorer.timeRangeLabel.hour": "1 giờ", "token.priceExplorer.timeRangeLabel.month": "1 tháng", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 Month", "token.priceExplorer.timeRangeLabel.week": "1 tuần", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 Week", "token.priceExplorer.timeRangeLabel.year": "1 năm", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 Year", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} không khả dụng", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} và {{tokenSymbol1}} không khả dụng", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs không nhận bất kỳ khoản phí nào trong số này.", diff --git a/packages/uniswap/src/i18n/locales/translations/zh-CN.json b/packages/uniswap/src/i18n/locales/translations/zh-CN.json index dbba38039b1..5764f32a93c 100644 --- a/packages/uniswap/src/i18n/locales/translations/zh-CN.json +++ b/packages/uniswap/src/i18n/locales/translations/zh-CN.json @@ -132,15 +132,15 @@ "addressInput.recipient": "收款人", "analytics.allow": "允许分析", "analytics.allow.message": "我们使用匿名数据来增强你使用 Uniswap 实验室产品的体验。", - "appRating.button.notReally": "Not really", - "appRating.description": "Let us know if you’re having a good experience with this app", - "appRating.extension.review.description": "Pick a star rating and leave a review on the Chrome Web Store.", - "appRating.extension.review.title": "Review Uniswap Extension?", - "appRating.extension.title": "Enjoying Uniswap Extension?", - "appRating.feedback.button.send": "Send feedback", - "appRating.feedback.description": "Let us know how we can improve your experience", - "appRating.feedback.title": "We’re sorry to hear that.", - "appRating.mobile.title": "Enjoying Uniswap Wallet?", + "appRating.button.notReally": "不太喜欢", + "appRating.description": "你对使用这个应用的体验如何?我们希望听到你的反馈", + "appRating.extension.review.description": "请前往 Chrome Web Store,给出星级评分并留下评论。", + "appRating.extension.review.title": "评论一下 Uniswap 扩展?", + "appRating.extension.title": "喜欢 Uniswap 扩展吗?", + "appRating.feedback.button.send": "发送反馈", + "appRating.feedback.description": "请告知我们如何改善你的体验", + "appRating.feedback.title": "很抱歉。", + "appRating.mobile.title": "喜欢 Uniswap 钱包吗?", "bridging.estimatedTime.minutesAndSeconds": "~{{minutes}} 分钟 {{seconds}} 秒", "bridging.estimatedTime.minutesOnly": "~{{minutes}} 分钟", "bridging.estimatedTime.secondsOnly": "~{{seconds}} 秒", @@ -222,6 +222,7 @@ "common.button.disconnect": "断开连接", "common.button.dismiss": "消除", "common.button.done": "完成", + "common.button.edit": "编辑", "common.button.enable": "启用", "common.button.finish": "完成", "common.button.goBack": "返回", @@ -313,7 +314,6 @@ "common.custom": "自定义", "common.customRange": "定制范围", "common.dataOutdated": "数据可能已过时", - "common.dataUnavailable": "数据不可用", "common.default": "默认", "common.defaultTradeOptions": "默认交易选项", "common.delegate.cancelled": "委派已取消", @@ -461,6 +461,7 @@ "common.networkCost": "网络费用", "common.neverMind": "没关系", "common.new": "新", + "common.new.exclamation": "New!", "common.nfts": "NFT", "common.noActivity": "还没有活动", "common.noAmount.error": "输入金额", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "按国家或地区搜索", "fiatOnRamp.region.title": "选择你的地区", "fiatOnRamp.summary.total": "{{cryptoAmount}} 交换 {{fiatAmount}}", - "forceUpgrade.action.confirm": "更新应用", + "forceUpgrade.action.confirm": "Update now", "forceUpgrade.action.recoveryPhrase": "查看恢复短语", - "forceUpgrade.description": "你使用的 Uniswap 钱包版本已过时,缺少重要的升级。如果你不更新应用或不记下恢复短语,你将无法访问资产。", + "forceUpgrade.description": "A new version of the app is available. To continue using the Uniswap Wallet, please update it to the latest version.", "forceUpgrade.label.recoveryPhrase": "恢复短语", - "forceUpgrade.title": "更新应用以继续", + "forceUpgrade.title": "Update to the latest version", "globalPreferences.title": "全局首选项", "hero.scroll": "滚动查看更多", "hero.subtitle": "最大的链上市场。在以太坊及其他超过 11 个区块链上购买和出售加密货币。", @@ -940,7 +941,6 @@ "home.feed.title": "订阅源", "home.label.buy": "购买", "home.label.receive": "接收", - "home.label.scan": "扫码", "home.label.send": "发送", "home.label.swap": "兑换", "home.nfts.title": "NFT", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "获取 Uniswap 钱包应用", "mobileAppPromo.banner.title": "Uniswap:加密货币和 NFT 钱包", "moonpay.poweredBy": "由 MoonPay USA LLC 提供支持的法币通道", - "moonpay.rampIframe": "MoonPay 法币入口 iframe", "moonpay.restricted.region": "Moonpay 在某些地区不可用。点击了解更多。", "nav.createAccount.button": "创建账户", "nav.logIn.button": "登录", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "查看恢复短语", "onboarding.import.onDeviceRecovery.wallet.count_one": "另有 1 个钱包", "onboarding.import.onDeviceRecovery.wallet.count_other": "另有 {{count}} 个钱包", - "onboarding.import.onDeviceRecovery.warning.caption": "请确保你已备份所有其他钱包。如果你想恢复它们,你将需要它们的恢复短语或相应的 iCloud 备份。", + "onboarding.import.onDeviceRecovery.warning.caption": "请确保你已备份所有其他钱包。如果你想恢复它们,你将需要它们的恢复短语或相应的 {{cloudProvider}} 备份。", "onboarding.import.onDeviceRecovery.warning.title": "是否确定?", "onboarding.import.title": "选择要如何添加钱包", "onboarding.importMnemonic.button.default": "我的恢复短语是 12 个单词", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "探索 Uniswap 分析。", "pool.hideClosed": "隐藏已平仓头寸", "pool.import": "导入资金池", - "pool.import.v2": "导入 V2 资金池", + "pool.import.link.description": "Some v2 positions aren’t displayed automatically.", + "pool.import.positions.v2": "Import V2 positions", + "pool.import.positions.v2.selectPair.description": "Some v2 positions aren’t displayed automatically. Select a token pair to import and view your positions.", + "pool.import.success": "Pool imported", "pool.increaseLiquidity": "增加流动性", "pool.info": "资金池信息", "pool.initialShare": "初始价格和资金池份额", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "30 天交易量", "pool.volume.thirtyDay.short": "30 天交易量", "pool.yourv2": "你的 V2 流动性", - "poolFinder.connect": "连接到钱包来查找资金池。", - "poolFinder.create": "创建资金池", - "poolFinder.found": "找到资金池!", - "poolFinder.managePool": "管理此资金池", - "poolFinder.noLiquidity": "你在此资金池中还没有流动性。", - "poolFinder.noPoolFound": "未找到资金池。", - "poolFinder.selectToken": "选择一个代币来查找你的 v2 流动性。", - "poolFinder.tip": "提示:使用此工具查找不会自动出现在界面中的 v2 资金池。", + "poolFinder.availablePools": "Available pools", + "poolFinder.availablePools.found.description": "v2 pools matching your pair selection.", + "poolFinder.availablePools.notFound.description": "No matching v2 pools found. Double-check your token selection and ensure you’re connected to the correct wallet.", "pools.approving.amount": "批准 {{amount}}", "pools.explore": "探索资金池", "position.addHook": "添加 Hook", @@ -1500,6 +1497,7 @@ "position.step.price": "设定初始价格", "position.step.range": "设定价格范围", "position.step.select": "选择代币对和费用", + "position.value": "Position value", "position.valueUnavailable": "流动性低,无法提供头寸值。", "position.your": "你的头寸", "positions.welcome": "欢迎查看你的头寸", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "如果你的交易等待时间超过此时间段,则交易将撤销。", "swap.unsupportedAssets.readMore": "阅读更多关于不受支持资产的信息", "swap.warning.enterLargerAmount.title": "输入更大的金额", - "swap.warning.expectedFailure": "这笔交易预计将失败", + "swap.warning.expectedFailure.increaseSlippage": "尝试增加滑点。", + "swap.warning.expectedFailure.titleMay": "This swap may fail", "swap.warning.insufficientBalance.title": "你的 {{currencySymbol}} 不足", "swap.warning.insufficientGas.button": "{{currencySymbol}} 不足", "swap.warning.insufficientGas.button.bridge": "于 {{networkName}} 为 {{ tokenSymbol }} 交换", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "一些测试网不支持交换、发送或购买代币。", "tdp.stats.unsupportedChainDescription": "{{chain}} 的代币统计数据和图表可在 {{infoLink}} 上查阅", "tdp.symbolNotFound": "未找到符号", + "testnet.modal.swapDeepLink.description.toProdMode": "此操作需要禁用测试网模式。可随时在设置中重新启用测试网模式。", + "testnet.modal.swapDeepLink.description.toTestnetMode": "此操作需要启用测试网模式。测试网上的代币不具有任何实际价值。可随时在设置中禁用测试网模式。", + "testnet.modal.swapDeepLink.title.toProdMode": "禁用测试网模式", + "testnet.modal.swapDeepLink.title.toTestnetMode": "启用测试网模式", "testnet.unsupported": "测试网模式不支持此功能。", "themeToggle.theme": "主题", "title.betterPricesMoreListings": "更优惠的价格。更多挂牌。在 OpenSea 等顶级市场上购买、出售和交易 NFT。探索热门系列。", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "未能加载价格走势图", "token.priceExplorer.timeRangeLabel.all": "全部时间", "token.priceExplorer.timeRangeLabel.day": "1 天", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 Day", "token.priceExplorer.timeRangeLabel.hour": "1 小时", "token.priceExplorer.timeRangeLabel.month": "1 个月", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 Month", "token.priceExplorer.timeRangeLabel.week": "1 周", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 Week", "token.priceExplorer.timeRangeLabel.year": "1 年", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 Year", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} 不可用", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} 和 {{tokenSymbol1}} 不可用", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap 实验室不会收取任何这些费用。", diff --git a/packages/uniswap/src/i18n/locales/translations/zh-TW.json b/packages/uniswap/src/i18n/locales/translations/zh-TW.json index d1e122264a8..c9a9decee6c 100644 --- a/packages/uniswap/src/i18n/locales/translations/zh-TW.json +++ b/packages/uniswap/src/i18n/locales/translations/zh-TW.json @@ -132,15 +132,15 @@ "addressInput.recipient": "接收方", "analytics.allow": "允許分析", "analytics.allow.message": "我們使用匿名資料來增強你使用 Uniswap Labs 產品的體驗。", - "appRating.button.notReally": "Not really", - "appRating.description": "Let us know if you’re having a good experience with this app", - "appRating.extension.review.description": "Pick a star rating and leave a review on the Chrome Web Store.", - "appRating.extension.review.title": "Review Uniswap Extension?", - "appRating.extension.title": "Enjoying Uniswap Extension?", - "appRating.feedback.button.send": "Send feedback", - "appRating.feedback.description": "Let us know how we can improve your experience", - "appRating.feedback.title": "We’re sorry to hear that.", - "appRating.mobile.title": "Enjoying Uniswap Wallet?", + "appRating.button.notReally": "不太喜歡", + "appRating.description": "如果你對此 App 有良好的體驗,請告訴我們", + "appRating.extension.review.description": "請在 Chrome Web Store 上選擇星級評等並留下評論。", + "appRating.extension.review.title": "評論 Uniswap Extension?", + "appRating.extension.title": "喜歡 Uniswap Extension 嗎?", + "appRating.feedback.button.send": "傳送意見回饋", + "appRating.feedback.description": "讓我們知道如何改善你的體驗", + "appRating.feedback.title": "我們很遺憾聽到你這樣說。", + "appRating.mobile.title": "喜歡 Uniswap 錢包嗎?", "bridging.estimatedTime.minutesAndSeconds": "~{{minutes}} 分 {{seconds}} 秒", "bridging.estimatedTime.minutesOnly": "~{{minutes}} 分鐘", "bridging.estimatedTime.secondsOnly": "~{{seconds}} 秒", @@ -222,6 +222,7 @@ "common.button.disconnect": "中斷連線", "common.button.dismiss": "關閉", "common.button.done": "完成", + "common.button.edit": "編輯", "common.button.enable": "啟用", "common.button.finish": "結束", "common.button.goBack": "返回", @@ -313,7 +314,6 @@ "common.custom": "自訂", "common.customRange": "定制範圍", "common.dataOutdated": "資料可能已過時", - "common.dataUnavailable": "資料無法使用", "common.default": "預設", "common.defaultTradeOptions": "預設交易選項", "common.delegate.cancelled": "已取消委託", @@ -461,6 +461,7 @@ "common.networkCost": "網路費", "common.neverMind": "沒關係", "common.new": "新", + "common.new.exclamation": "New!", "common.nfts": "NFT", "common.noActivity": "尚無活動", "common.noAmount.error": "輸入金額", @@ -904,11 +905,11 @@ "fiatOnRamp.region.placeholder": "依國家或地區搜尋", "fiatOnRamp.region.title": "選擇你的地區", "fiatOnRamp.summary.total": "{{cryptoAmount}} 換 {{fiatAmount}}", - "forceUpgrade.action.confirm": "更新 App", + "forceUpgrade.action.confirm": "Update now", "forceUpgrade.action.recoveryPhrase": "檢視助記詞", - "forceUpgrade.description": "你使用的 Uniswap 錢包版本已過期,並且未進行重要升級。如果不更新 App 或沒有寫下助記詞,將無法存取資產。", + "forceUpgrade.description": "A new version of the app is available. To continue using the Uniswap Wallet, please update it to the latest version.", "forceUpgrade.label.recoveryPhrase": "助記詞", - "forceUpgrade.title": "更新 App 以繼續", + "forceUpgrade.title": "Update to the latest version", "globalPreferences.title": "全域偏好設定", "hero.scroll": "捲動以了解更多", "hero.subtitle": "最大的鏈上市場。在乙太幣和其他超過 11 個區塊鏈上購買和出售加密貨幣。", @@ -940,7 +941,6 @@ "home.feed.title": "動態消息", "home.label.buy": "購買", "home.label.receive": "接收", - "home.label.scan": "掃描", "home.label.send": "傳送", "home.label.swap": "交換", "home.nfts.title": "NFT", @@ -1064,7 +1064,6 @@ "mobileAppPromo.banner.getTheApp.link": "取得 Uniswap 錢包應用程式", "mobileAppPromo.banner.title": "Uniswap:加密貨幣與 NFT 錢包", "moonpay.poweredBy": "由 MoonPay USA LLC 提供支援的法幣交換通道", - "moonpay.rampIframe": "MoonPay 法幣交換通道 iframe", "moonpay.restricted.region": "Moonpay 在某些地區無法使用。按一下了解更多。", "nav.createAccount.button": "建立帳戶", "nav.logIn.button": "登入", @@ -1269,7 +1268,7 @@ "onboarding.import.onDeviceRecovery.wallet.button": "檢視助記詞", "onboarding.import.onDeviceRecovery.wallet.count_one": "+1 個其他錢包", "onboarding.import.onDeviceRecovery.wallet.count_other": "+{{count}} 個其他錢包", - "onboarding.import.onDeviceRecovery.warning.caption": "請確認你已備份所有其他錢包。如果你想要進行還原,你將需要其助記詞或相應的 iCloud 備份。", + "onboarding.import.onDeviceRecovery.warning.caption": "請確認你已備份所有其他錢包。如果你想要進行還原,你將需要其助記詞或相應的 {{cloudProvider}} 備份。", "onboarding.import.onDeviceRecovery.warning.title": "確定繼續?", "onboarding.import.title": "選擇想要增加錢包的方式", "onboarding.importMnemonic.button.default": "我的助記詞是 12 個字詞", @@ -1370,7 +1369,10 @@ "pool.exporeAnalytics": "探索 Uniswap 分析。", "pool.hideClosed": "隱藏已平倉部位", "pool.import": "匯入資產池", - "pool.import.v2": "匯入 V2 資產池", + "pool.import.link.description": "Some v2 positions aren’t displayed automatically.", + "pool.import.positions.v2": "Import V2 positions", + "pool.import.positions.v2.selectPair.description": "Some v2 positions aren’t displayed automatically. Select a token pair to import and view your positions.", + "pool.import.success": "Pool imported", "pool.increaseLiquidity": "新增流動資產", "pool.info": "資產池資訊", "pool.initialShare": "初始價格和資產池份額", @@ -1450,14 +1452,9 @@ "pool.volume.thirtyDay": "30 天交易量", "pool.volume.thirtyDay.short": "30 天交易量", "pool.yourv2": "你的 V2 流動資產", - "poolFinder.connect": "連線至錢包以尋找資產池。", - "poolFinder.create": "建立資產池", - "poolFinder.found": "已找到資產池!", - "poolFinder.managePool": "管理此資產池", - "poolFinder.noLiquidity": "你在該資產池中還沒有流動資產。", - "poolFinder.noPoolFound": "找不到資產池。", - "poolFinder.selectToken": "選擇一個代幣來找出你的 v2 流動資產。", - "poolFinder.tip": "提示:使用此工具並尋找未自動出現在介面中的 v2 資產池。", + "poolFinder.availablePools": "Available pools", + "poolFinder.availablePools.found.description": "v2 pools matching your pair selection.", + "poolFinder.availablePools.notFound.description": "No matching v2 pools found. Double-check your token selection and ensure you’re connected to the correct wallet.", "pools.approving.amount": "核准 {{amount}}", "pools.explore": "探索資產池", "position.addHook": "新增一個掛鉤", @@ -1500,6 +1497,7 @@ "position.step.price": "設定初始價格", "position.step.range": "設定價格範圍", "position.step.select": "選擇代幣對和交易費用", + "position.value": "Position value", "position.valueUnavailable": "由於流動資產低,部位值不可用。", "position.your": "你的部位", "positions.welcome": "歡迎來到你的部位", @@ -1883,7 +1881,8 @@ "swap.transaction.revertAfter": "如果你的交易等待處理時間超過此時段,你的交易將會還原。", "swap.unsupportedAssets.readMore": "了解有關不支援的資產的更多資訊", "swap.warning.enterLargerAmount.title": "輸入更大的金額", - "swap.warning.expectedFailure": "這筆交易預計會失敗", + "swap.warning.expectedFailure.increaseSlippage": "嘗試增加滑價。", + "swap.warning.expectedFailure.titleMay": "This swap may fail", "swap.warning.insufficientBalance.title": "你的 {{currencySymbol}} 不足", "swap.warning.insufficientGas.button": "{{currencySymbol}} 不足", "swap.warning.insufficientGas.button.bridge": "在 {{networkName}} 上交換 {{ tokenSymbol }}", @@ -1936,6 +1935,10 @@ "tdp.noTestnetSupportDescription": "某些測試網不支援交換、發送或購買代幣。", "tdp.stats.unsupportedChainDescription": "{{chain}} 的代幣統計資料和圖表可在 {{infoLink}} 上找到", "tdp.symbolNotFound": "找不到 Symbol", + "testnet.modal.swapDeepLink.description.toProdMode": "你需要停用測試網模式才可進行此操作。你可在設定中隨時重新啟用測試網模式。", + "testnet.modal.swapDeepLink.description.toTestnetMode": "你需要啟用測試網模式才可進行此操作。測試網上的代幣不具有任何實際價值。你可在設定中隨時停用測試網模式。", + "testnet.modal.swapDeepLink.title.toProdMode": "停用測試網模式", + "testnet.modal.swapDeepLink.title.toTestnetMode": "啟用測試網模式", "testnet.unsupported": "測試網模式不支援此功能。", "themeToggle.theme": "主題", "title.betterPricesMoreListings": "更好的價格。更多商品。在 OpenSea 等頂級市集上購買、出售和交易 NFT。探索熱門系列。", @@ -1979,10 +1982,14 @@ "token.priceExplorer.error.title": "無法載入價格圖表", "token.priceExplorer.timeRangeLabel.all": "歷來全部", "token.priceExplorer.timeRangeLabel.day": "1 天", + "token.priceExplorer.timeRangeLabel.day.verbose": "1 Day", "token.priceExplorer.timeRangeLabel.hour": "1 小時", "token.priceExplorer.timeRangeLabel.month": "1 個月", + "token.priceExplorer.timeRangeLabel.month.verbose": "1 Month", "token.priceExplorer.timeRangeLabel.week": "1 星期", + "token.priceExplorer.timeRangeLabel.week.verbose": "1 Week", "token.priceExplorer.timeRangeLabel.year": "1 年", + "token.priceExplorer.timeRangeLabel.year.verbose": "1 Year", "token.safety.blocked.title.tokenNotAvailable": "{{tokenSymbol}} 不可用", "token.safety.blocked.title.tokensNotAvailable": "{{tokenSymbol0}} 和 {{tokenSymbol1}} 不可用", "token.safety.fees.uniswapLabsDoesNotReceive": "Uniswap Labs 不收取任何此類交易費用。", diff --git a/packages/uniswap/src/react-native-dotenv.d.ts b/packages/uniswap/src/react-native-dotenv.d.ts index 3cf09439c61..ae102892756 100644 --- a/packages/uniswap/src/react-native-dotenv.d.ts +++ b/packages/uniswap/src/react-native-dotenv.d.ts @@ -20,6 +20,7 @@ declare module 'react-native-dotenv' { export const QUICKNODE_BLAST_RPC_URL: string export const QUICKNODE_BNB_RPC_URL: string export const QUICKNODE_CELO_RPC_URL: string + export const QUICKNODE_MONAD_TESTNET_RPC_URL: string export const QUICKNODE_OP_RPC_URL: string export const QUICKNODE_POLYGON_RPC_URL: string export const QUICKNODE_ZORA_RPC_URL: string diff --git a/packages/uniswap/src/state/uniswapMigrations.ts b/packages/uniswap/src/state/uniswapMigrations.ts index e69de29bb2d..1c1a0f749ec 100644 --- a/packages/uniswap/src/state/uniswapMigrations.ts +++ b/packages/uniswap/src/state/uniswapMigrations.ts @@ -0,0 +1,31 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { SerializedTokenMap } from 'uniswap/src/features/tokens/slice/types' +import { getValidAddress } from 'uniswap/src/utils/addresses' + +// Mobile: 82 +// Extension: 18 +// Web: 21 +export function unchecksumDismissedTokenWarningKeys(state: any): any { + if (!state?.tokens?.dismissedTokenWarnings) { + return state + } + + const newDismissedWarnings: SerializedTokenMap = Object.entries(state.tokens.dismissedTokenWarnings).reduce( + (acc, [chainId, warningsForChain]) => ({ + ...acc, + [chainId]: Object.entries(warningsForChain as Record).reduce((chainAcc, [address, warning]) => { + const lowercasedAddress = getValidAddress(address, false) + return lowercasedAddress ? { ...chainAcc, [lowercasedAddress]: warning } : chainAcc + }, {}), + }), + {}, + ) + + return { + ...state, + tokens: { + ...state.tokens, + dismissedTokenWarnings: newDismissedWarnings, + }, + } +} diff --git a/packages/uniswap/src/state/uniswapReducer.ts b/packages/uniswap/src/state/uniswapReducer.ts index 664834d2536..ff9e69aa965 100644 --- a/packages/uniswap/src/state/uniswapReducer.ts +++ b/packages/uniswap/src/state/uniswapReducer.ts @@ -7,6 +7,7 @@ import { searchHistoryReducer } from 'uniswap/src/features/search/searchHistoryS import { userSettingsReducer } from 'uniswap/src/features/settings/slice' import { timingReducer } from 'uniswap/src/features/timing/slice' import { tokensReducer } from 'uniswap/src/features/tokens/slice/slice' +import { transactionSettingsReducer } from 'uniswap/src/features/transactions/settings/slice' import { transactionReducer } from 'uniswap/src/features/transactions/slice' export const uniswapReducers = { @@ -17,6 +18,7 @@ export const uniswapReducers = { timing: timingReducer, tokens: tokensReducer, transactions: transactionReducer, + transactionSettings: transactionSettingsReducer, uniswapBehaviorHistory: uniswapBehaviorHistoryReducer, userSettings: userSettingsReducer, } as const diff --git a/packages/uniswap/src/test/fixtures/tradingApi.ts b/packages/uniswap/src/test/fixtures/tradingApi.ts index 89059362d3f..7b01950ea46 100644 --- a/packages/uniswap/src/test/fixtures/tradingApi.ts +++ b/packages/uniswap/src/test/fixtures/tradingApi.ts @@ -9,6 +9,7 @@ export const createGasFeeEstimates = (): GasFeeEstimates => { type: FeeType.LEGACY, strategy: { limitInflationFactor: 1, + displayLimitInflationFactor: 1, priceInflationFactor: 1, percentileThresholdFor1559Fee: 1, }, @@ -22,6 +23,7 @@ export const createGasFeeEstimates = (): GasFeeEstimates => { type: FeeType.EIP1559, strategy: { limitInflationFactor: 1, + displayLimitInflationFactor: 1, priceInflationFactor: 1, percentileThresholdFor1559Fee: 1, }, diff --git a/packages/uniswap/src/test/fixtures/wallet/currencies.ts b/packages/uniswap/src/test/fixtures/wallet/currencies.ts index 7d4519307be..92597acfbcb 100644 --- a/packages/uniswap/src/test/fixtures/wallet/currencies.ts +++ b/packages/uniswap/src/test/fixtures/wallet/currencies.ts @@ -9,6 +9,7 @@ import { currencyId } from 'uniswap/src/utils/currencyId' export const MAINNET_CURRENCY = NativeCurrency.onChain(UniverseChainId.Mainnet) export const BASE_CURRENCY = NativeCurrency.onChain(UniverseChainId.Base) export const ARBITRUM_CURRENCY = NativeCurrency.onChain(UniverseChainId.ArbitrumOne) +export const MONAD_TESTNET_CURRENCY = NativeCurrency.onChain(UniverseChainId.MonadTestnet) export const OPTIMISM_CURRENCY = NativeCurrency.onChain(UniverseChainId.Optimism) export const POLYGON_CURRENCY = NativeCurrency.onChain(UniverseChainId.Polygon) export const CELO_CURRENCY = NativeCurrency.onChain(UniverseChainId.Celo) diff --git a/packages/uniswap/src/utils/cloud-backup/getCloudProviderName.ts b/packages/uniswap/src/utils/cloud-backup/getCloudProviderName.ts index fcc5aa9899b..59d4245be9a 100644 --- a/packages/uniswap/src/utils/cloud-backup/getCloudProviderName.ts +++ b/packages/uniswap/src/utils/cloud-backup/getCloudProviderName.ts @@ -1,7 +1,7 @@ -import { isWebAndroid } from 'utilities/src/platform' +import { isAndroid } from 'utilities/src/platform' export function getCloudProviderName(): string { - if (isWebAndroid) { + if (isAndroid) { return 'Google Drive' } return 'iCloud' diff --git a/packages/utilities/package.json b/packages/utilities/package.json index 4c6b49b2fa3..a7d097be286 100644 --- a/packages/utilities/package.json +++ b/packages/utilities/package.json @@ -22,7 +22,7 @@ "@sentry/react": "7.80.0", "@uniswap/analytics": "1.7.0", "@uniswap/analytics-events": "2.40.0", - "@uniswap/sdk-core": "6.0.0", + "@uniswap/sdk-core": "6.1.0", "aws-appsync-auth-link": "3.0.7", "aws-appsync-subscription-link": "3.1.3", "dayjs": "1.11.7", diff --git a/packages/utilities/src/environment/constants.ts b/packages/utilities/src/environment/constants.ts index 753890691f8..6bdef89b9c9 100644 --- a/packages/utilities/src/environment/constants.ts +++ b/packages/utilities/src/environment/constants.ts @@ -1,9 +1,10 @@ export const isDetoxBuild = Boolean(process.env.DETOX_MODE) export const isJestRun = !!process.env.JEST_WORKER_ID -export const isNonJestDev = __DEV__ && !isJestRun +export const isNonJestDev = window.__DEV__ && !isJestRun /** * When enabled, all sessions and resources will be tracked in * DataDog RUM. Logs that are sent to productions will also be * sent from your local development. */ export const localDevDatadogEnabled = false +export const datadogEnabled = localDevDatadogEnabled || !window.__DEV__ diff --git a/packages/utilities/src/logger/logger.ts b/packages/utilities/src/logger/logger.ts index 4b03f3fa4cf..3411a5c29f0 100644 --- a/packages/utilities/src/logger/logger.ts +++ b/packages/utilities/src/logger/logger.ts @@ -1,5 +1,5 @@ import { Extras } from '@sentry/types' -import { localDevDatadogEnabled } from 'utilities/src/environment/constants' +import { datadogEnabled, localDevDatadogEnabled } from 'utilities/src/environment/constants' import { logErrorToDatadog, logToDatadog, logWarningToDatadog } from 'utilities/src/logger/Datadog' import { Sentry } from 'utilities/src/logger/Sentry' import { LogLevel, LoggerErrorContext, OverridesSentryFingerprint } from 'utilities/src/logger/types' @@ -20,7 +20,6 @@ declare global { const SENTRY_CHAR_LIMIT = 8192 let walletDatadogEnabled = false -const skipLogUpload = __DEV__ && !localDevDatadogEnabled /** * Logs a message to console. Additionally sends log to Sentry and Datadog if using 'error', 'warn', or 'info'. @@ -55,11 +54,20 @@ function logMessage( ): void { // Log to console directly for dev builds or interface for debugging if (__DEV__ || isInterface) { - // eslint-disable-next-line no-console - console[level](...formatMessage(level, fileName, functionName, message), ...args) + if (isMobileApp && ['log', 'debug', 'warn'].includes(level)) { + // `log`, `debug`, and `warn` are all logged with `console.log` on mobile + // because `console.debug` and `console.warn` only support one single argument in Reactotron. + // Alternatively, we could improve this in the future by removing the Reactotron log plugin and instead + // manually call `Reactotron.display(...)` here with some custom formatting. + // eslint-disable-next-line no-console + console.log(...formatMessage(level, fileName, functionName, message), ...args) + } else { + // eslint-disable-next-line no-console + console[level](...formatMessage(level, fileName, functionName, message), ...args) + } } - if (skipLogUpload) { + if (!datadogEnabled) { return } @@ -108,7 +116,7 @@ function logException(error: unknown, captureContext: LoggerErrorContext): void console.error(error) } - if (skipLogUpload) { + if (!datadogEnabled) { return } diff --git a/packages/utilities/src/react/delayUtils.ts b/packages/utilities/src/react/delayUtils.ts new file mode 100644 index 00000000000..892ff46799b --- /dev/null +++ b/packages/utilities/src/react/delayUtils.ts @@ -0,0 +1,23 @@ +/** + * Workaround for performance issues where a user action may result in a heavy + * rerender which can seem like the first action has hung. + * + * For example, if a user selects an item on a dropdown, the first call that closes + * the dropdown may hang if the second action is called in the same batch. + * + * @param firstAction Action to prioritize + * @param secondAction Action to delay + * @param frames Number of frames to delay the second action. + */ +export function executeWithFrameDelay(firstAction: () => void, secondAction: () => void, frames: number = 4): void { + firstAction() + + const executeAfterFrames = (remainingFrames: number): void => { + if (remainingFrames <= 0) { + secondAction() + } else { + requestAnimationFrame(() => executeAfterFrames(remainingFrames - 1)) + } + } + executeAfterFrames(frames) +} diff --git a/packages/wallet/jest-setup.js b/packages/wallet/jest-setup.js index 2bcbcf484e8..4c1306618b3 100644 --- a/packages/wallet/jest-setup.js +++ b/packages/wallet/jest-setup.js @@ -26,6 +26,7 @@ jest.mock('wallet/src/features/appearance/hooks', () => { jest.mock('uniswap/src/features/gas/hooks', () => ({ useActiveGasStrategy: jest.fn().mockReturnValue({ limitInflationFactor: 1.15, + displayLimitInflationFactor: 1, priceInflationFactor: 1.5, percentileThresholdFor1559Fee: 75, }), diff --git a/packages/wallet/package.json b/packages/wallet/package.json index 4cfc3f826af..3db607a8df1 100644 --- a/packages/wallet/package.json +++ b/packages/wallet/package.json @@ -27,7 +27,7 @@ "@uniswap/analytics-events": "2.40.0", "@uniswap/permit2-sdk": "1.3.0", "@uniswap/router-sdk": "1.15.0", - "@uniswap/sdk-core": "6.0.0", + "@uniswap/sdk-core": "6.1.0", "@uniswap/uniswapx-sdk": "2.1.0-beta.18", "@uniswap/universal-router-sdk": "4.7.0", "@uniswap/v3-sdk": "3.19.0", diff --git a/packages/wallet/src/components/accounts/AnimatedUnitagDisplayName.native.tsx b/packages/wallet/src/components/accounts/AnimatedUnitagDisplayName.native.tsx new file mode 100644 index 00000000000..42ce9d0a780 --- /dev/null +++ b/packages/wallet/src/components/accounts/AnimatedUnitagDisplayName.native.tsx @@ -0,0 +1,162 @@ +import { SharedEventName } from '@uniswap/analytics-events' +import { BaseSyntheticEvent, memo, useCallback, useMemo, useRef, useState } from 'react' +import { LayoutChangeEvent } from 'react-native' +import { useDispatch } from 'react-redux' +import { AnimatePresence, Flex, Text, TouchableArea, getTokenValue } from 'ui/src' +import { CopyAlt, Unitag } from 'ui/src/components/icons' +import { pushNotification } from 'uniswap/src/features/notifications/slice' +import { AppNotificationType, CopyNotificationType } from 'uniswap/src/features/notifications/types' +import { ElementName } from 'uniswap/src/features/telemetry/constants' +import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' +import { UNITAG_SUFFIX } from 'uniswap/src/features/unitags/constants' +import { TestID } from 'uniswap/src/test/fixtures/testIDs' +import { ExtensionScreens } from 'uniswap/src/types/screens/extension' +import { MobileScreens } from 'uniswap/src/types/screens/mobile' +import { sanitizeAddressText } from 'uniswap/src/utils/addresses' +import { setClipboard } from 'uniswap/src/utils/clipboard' +import { shortenAddress } from 'utilities/src/addresses' +import { isExtension, isMobileApp } from 'utilities/src/platform' +import { AnimatedUnitagDisplayNameProps } from 'wallet/src/components/accounts/AnimatedUnitagDisplayName' +import { DisplayNameType } from 'wallet/src/features/wallet/types' + +/** + * Used in the account header that displays the user's unitag and name if available and + * address. The unitag is animated which shows the unitag suffix. + */ +function _AnimatedUnitagDisplayName({ + displayName, + unitagIconSize = '$icon.24', + address, +}: AnimatedUnitagDisplayNameProps): JSX.Element { + const dispatch = useDispatch() + const [showUnitagSuffix, setShowUnitagSuffix] = useState(false) + const isUnitag = displayName?.type === DisplayNameType.Unitag + + const { width: nameTextWidth, onLayout: onNameTextLayout } = useInitialLayoutWidth() + const { width: unitagSuffixTextWidth, onLayout: onUnitagSuffixTextLayout } = useInitialLayoutWidth() + const { width: viewWidth, onLayout: onViewWidthLayout } = useInitialLayoutWidth() + + const onPressUnitag = (): void => setShowUnitagSuffix(!showUnitagSuffix) + + const onPressCopyAddress = useCallback( + async (e: BaseSyntheticEvent): Promise => { + if (!address) { + return + } + + e.stopPropagation() + await setClipboard(address) + dispatch( + pushNotification({ + type: AppNotificationType.Copied, + copyType: CopyNotificationType.Address, + }), + ) + sendAnalyticsEvent(SharedEventName.ELEMENT_CLICKED, { + element: ElementName.CopyAddress, + screen: isExtension ? ExtensionScreens.Home : isMobileApp ? MobileScreens.Home : undefined, + }) + }, + [address, dispatch], + ) + + const isLayoutReady = viewWidth > 0 + + /** + * We have two animation modes. If the name is too long the animation replaces the + * tail of the name with the unitag suffix. Otherwise it slides extends the unitag suffix. + **/ + const shouldAnimateSlide = nameTextWidth + unitagSuffixTextWidth + getTokenValue(unitagIconSize) < viewWidth + const slideConfig = useMemo(() => { + return shouldAnimateSlide + ? { + paddingRight: 0, + widthAdjust: 0, + unitagOffset: -unitagSuffixTextWidth, + unitagSlideX: showUnitagSuffix ? unitagSuffixTextWidth : 0, + } + : { + paddingRight: isUnitag ? (shouldAnimateSlide ? getTokenValue('$spacing16') : 0) : 0, + widthAdjust: showUnitagSuffix ? unitagSuffixTextWidth : 0, + unitagOffset: showUnitagSuffix ? 0 : -unitagSuffixTextWidth, + unitagSlideX: 0, + } + }, [shouldAnimateSlide, unitagSuffixTextWidth, showUnitagSuffix, isUnitag]) + + return ( + + + + {displayName?.name} + + + {isUnitag && ( + + + {/* + We need to calculate this width in order to animate the suffix in and out, + but we don't want the initial render to show the suffix nor use the space and push other elements to the right. + So we set it to `position: absolute` on first render and then switch it to `relative` once we have the width. + */} + + + {UNITAG_SUFFIX} + + + + + + + + )} + + + {address && ( + + + + {sanitizeAddressText(shortenAddress(address))} + + + + + )} + + ) +} + +/** + * Returns a width and a callback to be used in a `onLayout` handler. + * The width is set to the initial width only once if it's not already set. + */ +export function useInitialLayoutWidth(initialWidth = 0): { + width: number + onLayout: (event: LayoutChangeEvent) => void +} { + const [width, setWidth] = useState(initialWidth) + const isWidthSet = useRef(false) + + const onLayout = (event: LayoutChangeEvent): void => { + if (!isWidthSet.current) { + setWidth(event.nativeEvent.layout.width) + isWidthSet.current = true + } + } + + return { width, onLayout } +} + +export const AnimatedUnitagDisplayName = memo(_AnimatedUnitagDisplayName) diff --git a/packages/wallet/src/components/accounts/AnimatedUnitagDisplayName.tsx b/packages/wallet/src/components/accounts/AnimatedUnitagDisplayName.tsx index f076c5bfb00..0a0d1beb7af 100644 --- a/packages/wallet/src/components/accounts/AnimatedUnitagDisplayName.tsx +++ b/packages/wallet/src/components/accounts/AnimatedUnitagDisplayName.tsx @@ -1,111 +1,16 @@ -import { SharedEventName } from '@uniswap/analytics-events' -import { BaseSyntheticEvent, useState } from 'react' -import { LayoutChangeEvent } from 'react-native' -import { useDispatch } from 'react-redux' -import { AnimatePresence, Flex, Text, TouchableArea } from 'ui/src' -import { CopyAlt, Unitag } from 'ui/src/components/icons' import { IconSizeTokens } from 'ui/src/theme' -import { pushNotification } from 'uniswap/src/features/notifications/slice' -import { AppNotificationType, CopyNotificationType } from 'uniswap/src/features/notifications/types' -import { ElementName } from 'uniswap/src/features/telemetry/constants' -import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' -import { UNITAG_SUFFIX } from 'uniswap/src/features/unitags/constants' -import { TestID } from 'uniswap/src/test/fixtures/testIDs' -import { ExtensionScreens } from 'uniswap/src/types/screens/extension' -import { MobileScreens } from 'uniswap/src/types/screens/mobile' -import { sanitizeAddressText } from 'uniswap/src/utils/addresses' -import { setClipboard } from 'uniswap/src/utils/clipboard' -import { shortenAddress } from 'utilities/src/addresses' -import { isExtension, isMobileApp } from 'utilities/src/platform' -import { DisplayName, DisplayNameType } from 'wallet/src/features/wallet/types' +import { PlatformSplitStubError } from 'utilities/src/errors' +import { DisplayName } from 'wallet/src/features/wallet/types' -type AnimatedUnitagDisplayNameProps = { +export type AnimatedUnitagDisplayNameProps = { displayName: DisplayName - unitagIconSize?: IconSizeTokens | number + unitagIconSize?: IconSizeTokens address?: string } -export function AnimatedUnitagDisplayName({ - displayName, - unitagIconSize = '$icon.24', - address, -}: AnimatedUnitagDisplayNameProps): JSX.Element { - const dispatch = useDispatch() - const [showUnitagSuffix, setShowUnitagSuffix] = useState(false) - const [textWidth, setTextWidth] = useState(0) - const isUnitag = displayName?.type === DisplayNameType.Unitag - - const onTextLayout = (event: LayoutChangeEvent): void => { - setTextWidth(event.nativeEvent.layout.width) - } - - const onPressUnitag = (): void => { - setShowUnitagSuffix(!showUnitagSuffix) - } - - const onPressCopyAddress = async (e: BaseSyntheticEvent): Promise => { - if (!address) { - return - } - - e.stopPropagation() - await setClipboard(address) - dispatch( - pushNotification({ - type: AppNotificationType.Copied, - copyType: CopyNotificationType.Address, - }), - ) - sendAnalyticsEvent(SharedEventName.ELEMENT_CLICKED, { - element: ElementName.CopyAddress, - screen: isExtension ? ExtensionScreens.Home : isMobileApp ? MobileScreens.Home : undefined, - }) - } - - const isLayoutReady = textWidth > 0 - - return ( - - - {displayName.name} - - - - - {/* - We need to calculate this width in order to animate the suffix in and out, - but we don't want the initial render to show the suffix nor use the space and push other elements to the right. - So we set it to `position: absolute` on first render and then switch it to `relative` once we have the width. - */} - - - {UNITAG_SUFFIX} - - - - {isUnitag ? ( - - - - ) : null} - - {address && ( - - - - {sanitizeAddressText(shortenAddress(address))} - - - - - )} - - - - ) +/** + * Renders as a bottom sheet modal on mobile app/mweb & a dialog modal on desktop web/extension. + */ +export function AnimatedUnitagDisplayName(_: AnimatedUnitagDisplayNameProps): JSX.Element { + throw new PlatformSplitStubError('AnimatedUnitagDisplayName') } diff --git a/packages/wallet/src/components/accounts/AnimatedUnitagDisplayName.web.tsx b/packages/wallet/src/components/accounts/AnimatedUnitagDisplayName.web.tsx new file mode 100644 index 00000000000..b2dfae95562 --- /dev/null +++ b/packages/wallet/src/components/accounts/AnimatedUnitagDisplayName.web.tsx @@ -0,0 +1,105 @@ +import { SharedEventName } from '@uniswap/analytics-events' +import { BaseSyntheticEvent, useState } from 'react' +import { LayoutChangeEvent } from 'react-native' +import { useDispatch } from 'react-redux' +import { AnimatePresence, Flex, Text, TouchableArea } from 'ui/src' +import { CopyAlt, Unitag } from 'ui/src/components/icons' +import { pushNotification } from 'uniswap/src/features/notifications/slice' +import { AppNotificationType, CopyNotificationType } from 'uniswap/src/features/notifications/types' +import { ElementName } from 'uniswap/src/features/telemetry/constants' +import { sendAnalyticsEvent } from 'uniswap/src/features/telemetry/send' +import { UNITAG_SUFFIX } from 'uniswap/src/features/unitags/constants' +import { TestID } from 'uniswap/src/test/fixtures/testIDs' +import { ExtensionScreens } from 'uniswap/src/types/screens/extension' +import { MobileScreens } from 'uniswap/src/types/screens/mobile' +import { sanitizeAddressText } from 'uniswap/src/utils/addresses' +import { setClipboard } from 'uniswap/src/utils/clipboard' +import { shortenAddress } from 'utilities/src/addresses' +import { isExtension, isMobileApp } from 'utilities/src/platform' +import { AnimatedUnitagDisplayNameProps } from 'wallet/src/components/accounts/AnimatedUnitagDisplayName' +import { DisplayNameType } from 'wallet/src/features/wallet/types' + +export function AnimatedUnitagDisplayName({ + displayName, + unitagIconSize = '$icon.24', + address, +}: AnimatedUnitagDisplayNameProps): JSX.Element { + const dispatch = useDispatch() + const [showUnitagSuffix, setShowUnitagSuffix] = useState(false) + const [textWidth, setTextWidth] = useState(0) + const isUnitag = displayName?.type === DisplayNameType.Unitag + + const onTextLayout = (event: LayoutChangeEvent): void => { + setTextWidth(event.nativeEvent.layout.width) + } + + const onPressUnitag = (): void => { + setShowUnitagSuffix(!showUnitagSuffix) + } + + const onPressCopyAddress = async (e: BaseSyntheticEvent): Promise => { + if (!address) { + return + } + + e.stopPropagation() + await setClipboard(address) + dispatch( + pushNotification({ + type: AppNotificationType.Copied, + copyType: CopyNotificationType.Address, + }), + ) + sendAnalyticsEvent(SharedEventName.ELEMENT_CLICKED, { + element: ElementName.CopyAddress, + screen: isExtension ? ExtensionScreens.Home : isMobileApp ? MobileScreens.Home : undefined, + }) + } + + const isLayoutReady = textWidth > 0 + + return ( + + + {displayName.name} + + + + + {/* + We need to calculate this width in order to animate the suffix in and out, + but we don't want the initial render to show the suffix nor use the space and push other elements to the right. + So we set it to `position: absolute` on first render and then switch it to `relative` once we have the width. + */} + + + {UNITAG_SUFFIX} + + + + {isUnitag ? ( + + + + ) : null} + + {address && ( + + + + {sanitizeAddressText(shortenAddress(address))} + + + + + )} + + + + ) +} diff --git a/packages/wallet/src/components/introCards/IntroCard.tsx b/packages/wallet/src/components/introCards/IntroCard.tsx index 3c5dae78a93..33346813339 100644 --- a/packages/wallet/src/components/introCards/IntroCard.tsx +++ b/packages/wallet/src/components/introCards/IntroCard.tsx @@ -7,6 +7,7 @@ import { GeneratedIcon, IconProps, Text, + View, ViewProps, useIsDarkMode, useShadowPropsShort, @@ -184,42 +185,46 @@ export function IntroCard({ return ( - - {GraphicElement} - - - - - : undefined} - /> - - - {topRightElement} + + {GraphicElement} + + + + + : undefined} + /> + + + {topRightElement} + + + {description} + - - {description} - - + ) } diff --git a/packages/wallet/src/components/menu/ContextMenu.tsx b/packages/wallet/src/components/menu/ContextMenu.tsx index f5ba188eadb..09f9831d746 100644 --- a/packages/wallet/src/components/menu/ContextMenu.tsx +++ b/packages/wallet/src/components/menu/ContextMenu.tsx @@ -7,6 +7,8 @@ import { usePrevious } from 'utilities/src/react/hooks' import { MenuContent } from 'wallet/src/components/menu/MenuContent' import { MenuContentItem } from 'wallet/src/components/menu/types' +const DEFAULT_OFFSET_TOKEN_BALANCE_HEIGHT = 60 + type ContextMenuProps = { menuOptions: MenuContentItem[] itemId: string @@ -52,10 +54,12 @@ export function ContextMenu({ // Ignore if any values besides default are passed const triggerContainerRef = useRef(null) const { offset: customOffset, placement } = rest - const offset = - customOffset || (placement && placement !== 'bottom-end') - ? customOffset - : -(triggerContainerRef.current?.offsetHeight ?? 0) + const isOffsetProvided = customOffset || (placement !== 'bottom-end' && placement) + const triggerOffsetHeight = triggerContainerRef.current?.offsetHeight ?? 0 + const triggerBottomPosition = triggerContainerRef.current?.getBoundingClientRect().bottom ?? 0 + const isTriggerBelowViewport = window.innerHeight - triggerBottomPosition < 0 + const fallbackOffset = -triggerOffsetHeight + (triggerOffsetHeight || DEFAULT_OFFSET_TOKEN_BALANCE_HEIGHT) + const offset = isOffsetProvided ? customOffset : isTriggerBelowViewport ? fallbackOffset : -triggerOffsetHeight const contentShadowProps = { shadowColor: colors.shadowColor.val, diff --git a/packages/wallet/src/components/nfts/NftViewWithContextMenu.web.tsx b/packages/wallet/src/components/nfts/NftViewWithContextMenu.web.tsx index 6961f52a262..34cd2ab1bef 100644 --- a/packages/wallet/src/components/nfts/NftViewWithContextMenu.web.tsx +++ b/packages/wallet/src/components/nfts/NftViewWithContextMenu.web.tsx @@ -19,6 +19,7 @@ export function NftViewWithContextMenu(props: NftViewWithContextMenuProps): JSX. tokenId: item.tokenId, owner, isSpam: item.isSpam, + showNotification: true, chainId: fromGraphQLChain(item.chain) ?? defaultChainId, }) diff --git a/packages/wallet/src/features/fiatOnRamp/api.ts b/packages/wallet/src/features/fiatOnRamp/api.ts index c0da38d2f36..0eb90ebd98d 100644 --- a/packages/wallet/src/features/fiatOnRamp/api.ts +++ b/packages/wallet/src/features/fiatOnRamp/api.ts @@ -2,7 +2,11 @@ import dayjs from 'dayjs' import { uniswapUrls } from 'uniswap/src/constants/urls' import { objectToQueryString } from 'uniswap/src/data/utils' import { FOR_API_HEADERS } from 'uniswap/src/features/fiatOnRamp/constants' -import { FORTransactionResponse, FiatOnRampTransactionDetails } from 'uniswap/src/features/fiatOnRamp/types' +import { + FORTransactionResponse, + FiatOnRampTransactionDetails, + OffRampTransferDetailsResponse, +} from 'uniswap/src/features/fiatOnRamp/types' import { FeatureFlags } from 'uniswap/src/features/gating/flags' import { getFeatureFlag } from 'uniswap/src/features/gating/hooks' import { TransactionStatus } from 'uniswap/src/features/transactions/types/transactionDetails' @@ -73,3 +77,20 @@ export async function fetchFiatOnRampTransaction( return extractFiatOnRampTransactionDetails(transaction) } + +export async function fetchOffRampTransferDetails(sessionId: string): Promise { + // TODO: support moonpay once backend is ready + const requestParams = { + meldDetails: { + sessionId, + }, + } + + const res = await fetch(`${uniswapUrls.forApiUrl}/OffRampTransferDetails`, { + headers: FOR_API_HEADERS, + method: 'POST', + body: JSON.stringify(requestParams), + }) + + return res.json() as Promise +} diff --git a/packages/wallet/src/features/gas/hooks.ts b/packages/wallet/src/features/gas/hooks.ts index e0c08f77d08..f901d73a43b 100644 --- a/packages/wallet/src/features/gas/hooks.ts +++ b/packages/wallet/src/features/gas/hooks.ts @@ -12,7 +12,7 @@ import { getCancelOrderTxRequest } from 'wallet/src/features/transactions/cancel export type CancelationGasFeeDetails = { cancelRequest: providers.TransactionRequest - cancelationGasFee: string + cancelationGasFeeDisplayValue: string } /** @@ -37,13 +37,16 @@ export function useCancelationGasFeeInfo(transaction: TransactionDetails): Cance const baseTxGasFee = useTransactionGasFee(classicCancelRequest, /* skip = */ isUniswapXTx) return useMemo(() => { if (isUniswapXTx) { - if (!uniswapXCancelRequest.data || !uniswapXGasFee.value) { + if (!uniswapXCancelRequest.data || !uniswapXGasFee.value || !uniswapXGasFee.displayValue) { return undefined } - return { cancelRequest: uniswapXCancelRequest.data, cancelationGasFee: uniswapXGasFee.value } + return { + cancelRequest: uniswapXCancelRequest.data, + cancelationGasFeeDisplayValue: uniswapXGasFee.displayValue, + } } - if (!baseTxGasFee.params) { + if (!baseTxGasFee.params || !baseTxGasFee.value || !baseTxGasFee.displayValue) { return undefined } @@ -68,27 +71,47 @@ export function useCancelationGasFeeInfo(transaction: TransactionDetails): Cance gasLimit: baseTxGasFee.params.gasLimit, } + const cancelationGasFeeDisplayValue = getCancellationGasFeeDisplayValue( + adjustedFeeDetails, + baseTxGasFee.params.gasLimit, + baseTxGasFee.value, + baseTxGasFee.displayValue, + ) + return { cancelRequest, - cancelationGasFee: getCancelationGasFee(adjustedFeeDetails, baseTxGasFee.params.gasLimit), + cancelationGasFeeDisplayValue, } }, [ isUniswapXTx, baseTxGasFee.params, + baseTxGasFee.value, + baseTxGasFee.displayValue, classicCancelRequest, transaction, uniswapXCancelRequest.data, uniswapXGasFee.value, + uniswapXGasFee.displayValue, ]) } -function getCancelationGasFee(adjustedFeeDetails: FeeDetails, gasLimit: string): string { +function getCancellationGasFeeDisplayValue( + adjustedFeeDetails: FeeDetails, + gasLimit: string, + previousValue: string, + previousDisplayValue: string, +): string { + // Use the original ratio of displayValue to value to maintain consistency with original gas fees + return getCancelationGasFee(adjustedFeeDetails, gasLimit).mul(previousDisplayValue).div(previousValue).toString() +} + +function getCancelationGasFee(adjustedFeeDetails: FeeDetails, gasLimit: string): BigNumber { // doing object destructuring here loses ts checks based on FeeDetails.type >:( if (adjustedFeeDetails.type === FeeType.LEGACY) { - return BigNumber.from(gasLimit).mul(adjustedFeeDetails.params.gasPrice).toString() + return BigNumber.from(gasLimit).mul(adjustedFeeDetails.params.gasPrice) } - return BigNumber.from(adjustedFeeDetails.params.maxFeePerGas).mul(gasLimit).toString() + return BigNumber.from(adjustedFeeDetails.params.maxFeePerGas).mul(gasLimit) } function useUniswapXCancelRequest(transaction: TransactionDetails): { diff --git a/packages/wallet/src/features/nfts/useNftContextMenu.tsx b/packages/wallet/src/features/nfts/useNftContextMenu.tsx index dfca8dc0527..99fa7aa67f7 100644 --- a/packages/wallet/src/features/nfts/useNftContextMenu.tsx +++ b/packages/wallet/src/features/nfts/useNftContextMenu.tsx @@ -77,7 +77,7 @@ export function useNFTContextMenu({ return } - if (!hidden) { + if (hidden === false) { dispatch(toggleNftVisibility({ nftKey, isSpam: true })) } diff --git a/packages/wallet/src/features/transactions/SummaryCards/SummaryItems/CancelConfirmationView.tsx b/packages/wallet/src/features/transactions/SummaryCards/SummaryItems/CancelConfirmationView.tsx index 7d19b3226fd..83a1cabb355 100644 --- a/packages/wallet/src/features/transactions/SummaryCards/SummaryItems/CancelConfirmationView.tsx +++ b/packages/wallet/src/features/transactions/SummaryCards/SummaryItems/CancelConfirmationView.tsx @@ -29,7 +29,10 @@ export function CancelConfirmationView({ const { convertFiatAmountFormatted } = useLocalizationContext() const cancelationGasFeeInfo = useCancelationGasFeeInfo(transactionDetails) - const { value: gasFeeUSD } = useUSDValueOfGasFee(transactionDetails.chainId, cancelationGasFeeInfo?.cancelationGasFee) + const { value: gasFeeUSD } = useUSDValueOfGasFee( + transactionDetails.chainId, + cancelationGasFeeInfo?.cancelationGasFeeDisplayValue, + ) const gasFee = convertFiatAmountFormatted(gasFeeUSD, NumberType.FiatGasPrice) const onCancelConfirm = useCallback(() => { diff --git a/packages/wallet/src/features/transactions/TransactionRequest/NetworkFeeFooter.tsx b/packages/wallet/src/features/transactions/TransactionRequest/NetworkFeeFooter.tsx index 8849d580465..f0e226a04cc 100644 --- a/packages/wallet/src/features/transactions/TransactionRequest/NetworkFeeFooter.tsx +++ b/packages/wallet/src/features/transactions/TransactionRequest/NetworkFeeFooter.tsx @@ -4,7 +4,7 @@ import { iconSizes } from 'ui/src/theme' import { NetworkLogo } from 'uniswap/src/components/CurrencyLogo/NetworkLogo' import { UniswapXFee } from 'uniswap/src/components/gas/NetworkFee' import { UniverseChainId } from 'uniswap/src/features/chains/types' -import { useGasFeeFormattedAmounts } from 'uniswap/src/features/gas/hooks' +import { useGasFeeFormattedDisplayAmounts } from 'uniswap/src/features/gas/hooks' import { GasFeeResult } from 'uniswap/src/features/gas/types' import { isMobileApp } from 'utilities/src/platform' import { ContentRow } from 'wallet/src/features/transactions/TransactionRequest/ContentRow' @@ -25,7 +25,7 @@ export function NetworkFeeFooter({ const { t } = useTranslation() const variant = isMobileApp ? 'body3' : 'body4' - const { gasFeeFormatted } = useGasFeeFormattedAmounts({ + const { gasFeeFormatted } = useGasFeeFormattedDisplayAmounts({ gasFee, chainId, placeholder: '-', diff --git a/packages/wallet/src/features/transactions/contexts/SendContext.tsx b/packages/wallet/src/features/transactions/contexts/SendContext.tsx index bbf7c9a04af..09676a910e2 100644 --- a/packages/wallet/src/features/transactions/contexts/SendContext.tsx +++ b/packages/wallet/src/features/transactions/contexts/SendContext.tsx @@ -61,6 +61,7 @@ export function SendContextProvider({ // state const [sendForm, setSendForm] = useState(prefilledTransactionState || defaultSendState) + const updateSendForm = useCallback( (newState: Parameters[0]): void => { setSendForm((prevState) => ({ ...prevState, ...newState })) @@ -83,7 +84,7 @@ export function SendContextProvider({ const gasWarning = useTransactionGasWarning({ account, derivedInfo: derivedSendInfo, - gasFee: gasFee?.value, + gasFee: gasFee.value, }) const allSendWarnings = useMemo(() => { return !gasWarning ? warnings : [...warnings, gasWarning] @@ -126,27 +127,29 @@ export function SendContextProvider({ showRecipientSelector: sendForm.showRecipientSelector, selectedProtocols: sendForm.selectedProtocols, customSlippageTolerance: sendForm.customSlippageTolerance, + fiatOffRampMetaData: sendForm.fiatOffRampMetaData, } }, [ derivedSendInfo, gasFee, parsedSendWarnings, - sendForm.customSlippageTolerance, - sendForm.exactAmountFiat, + txRequestWithGasSettings, + onSelectCurrency, + updateSendForm, + sendForm.txId, + sendForm.input, + sendForm.output, sendForm.exactAmountToken, + sendForm.exactAmountFiat, sendForm.exactCurrencyField, sendForm.focusOnCurrencyField, - sendForm.input, - sendForm.isFiatInput, - sendForm.output, sendForm.recipient, + sendForm.isFiatInput, sendForm.selectingCurrencyField, sendForm.showRecipientSelector, + sendForm.customSlippageTolerance, sendForm.selectedProtocols, - sendForm.txId, - txRequestWithGasSettings, - onSelectCurrency, - updateSendForm, + sendForm.fiatOffRampMetaData, ]) return {children} } diff --git a/packages/wallet/src/features/transactions/send/GasFeeRow.tsx b/packages/wallet/src/features/transactions/send/GasFeeRow.tsx index 7e12d59174d..b43900c76fb 100644 --- a/packages/wallet/src/features/transactions/send/GasFeeRow.tsx +++ b/packages/wallet/src/features/transactions/send/GasFeeRow.tsx @@ -5,7 +5,7 @@ import { Gas } from 'ui/src/components/icons' import { AnimatedFlex } from 'ui/src/components/layout/AnimatedFlex' import { iconSizes } from 'ui/src/theme' import { UniverseChainId } from 'uniswap/src/features/chains/types' -import { useGasFeeFormattedAmounts } from 'uniswap/src/features/gas/hooks' +import { useGasFeeFormattedDisplayAmounts } from 'uniswap/src/features/gas/hooks' import { GasFeeResult } from 'uniswap/src/features/gas/types' import { NetworkFeeWarning } from 'uniswap/src/features/transactions/swap/modals/NetworkFeeWarning' @@ -15,7 +15,7 @@ type GasFeeRowProps = { } export function GasFeeRow({ gasFee, chainId }: GasFeeRowProps): JSX.Element | null { - const { gasFeeFormatted } = useGasFeeFormattedAmounts({ + const { gasFeeFormatted } = useGasFeeFormattedDisplayAmounts({ gasFee, chainId, placeholder: undefined, diff --git a/packages/wallet/src/features/transactions/send/SendReviewDetails.tsx b/packages/wallet/src/features/transactions/send/SendReviewDetails.tsx index e0339e877c3..326eede26f1 100644 --- a/packages/wallet/src/features/transactions/send/SendReviewDetails.tsx +++ b/packages/wallet/src/features/transactions/send/SendReviewDetails.tsx @@ -1,3 +1,4 @@ +/* eslint-disable complexity */ import { useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' import { useDispatch } from 'react-redux' @@ -28,6 +29,7 @@ import { import { useUSDCValue } from 'uniswap/src/features/transactions/swap/hooks/useUSDCPrice' import { CurrencyField } from 'uniswap/src/types/currency' import { currencyAddress } from 'uniswap/src/utils/currencyId' +import { shortenAddress } from 'utilities/src/addresses' import { NumberType } from 'utilities/src/format/types' import { logger } from 'utilities/src/logger/logger' import { AccountIcon } from 'wallet/src/components/accounts/AccountIcon' @@ -59,7 +61,7 @@ export function SendReviewDetails({ const { navigateToAccountActivityList } = useWalletNavigation() const { setScreen } = useTransactionModalContext() - const { derivedSendInfo, warnings, txRequest, gasFee, isFiatInput } = useSendContext() + const { derivedSendInfo, warnings, txRequest, gasFee, isFiatInput, fiatOffRampMetaData } = useSendContext() const { txId, chainId, recipient, currencyInInfo, currencyAmounts, nftIn, exactAmountFiat } = derivedSendInfo const { avatar } = useAvatar(recipient) @@ -174,7 +176,19 @@ export function SendReviewDetails({ NumberType.FiatTokenQuantity, ) + const { navigateToFiatOnRamp } = useWalletNavigation() + const onPrev = (): void => { + if (fiatOffRampMetaData) { + onCloseModal?.() + navigateToFiatOnRamp({ + prefilledCurrency: { + currencyInfo: currencyInInfo, + moonpayCurrencyCode: fiatOffRampMetaData.moonpayCurrencyCode, + meldCurrencyCode: fiatOffRampMetaData.meldCurrencyCode, + }, + }) + } setScreen(TransactionScreen.Form) } @@ -245,14 +259,29 @@ export function SendReviewDetails({ {recipient && ( - + + {fiatOffRampMetaData.name} + + + {shortenAddress(recipient)} + + + ) : ( + + )} + - )} diff --git a/packages/wallet/src/features/transactions/swap/WalletSwapFlow.tsx b/packages/wallet/src/features/transactions/swap/WalletSwapFlow.tsx index c161f81edff..569c7efc7a4 100644 --- a/packages/wallet/src/features/transactions/swap/WalletSwapFlow.tsx +++ b/packages/wallet/src/features/transactions/swap/WalletSwapFlow.tsx @@ -1,4 +1,5 @@ import { TransactionSettingsContextProvider } from 'uniswap/src/features/transactions/settings/contexts/TransactionSettingsContext' +import { TransactionSettingKey } from 'uniswap/src/features/transactions/settings/slice' import { SwapFlow, SwapFlowProps } from 'uniswap/src/features/transactions/swap/SwapFlow' import { SwapFormContextProvider } from 'uniswap/src/features/transactions/swap/contexts/SwapFormContext' import { ProtocolPreference } from 'uniswap/src/features/transactions/swap/settings/configs/ProtocolPreference' @@ -16,7 +17,7 @@ export function WalletSwapFlow({ onSubmitSwap, ...props }: WalletSwapFlowProps): const wrapCallback = useWrapCallback() return ( - + any, pre const result = migration(prevSchema) expect(result.wallet.settings.tokensOrderBy).toEqual(RankingType.Volume) } + +export function testUnchecksumDismissedTokenWarningKeys(migration: (state: any) => any, prevSchema: any): void { + const prevSchemaWithWarnings = { + ...prevSchema, + tokens: { + dismissedTokenWarnings: { + '1': { + '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': { + address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + chainId: 1, + }, + '0x6B175474E89094C44Da98b954EedeAC495271d0F': { + address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + chainId: 1, + }, + }, + '137': { + '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174': { + address: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', + chainId: 137, + }, + }, + }, + }, + } + + const result = migration(prevSchemaWithWarnings) + + // Verify addresses are converted to lowercase + expect(result.tokens.dismissedTokenWarnings['1']).toHaveProperty('0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48') + expect(result.tokens.dismissedTokenWarnings['1']).toHaveProperty('0x6b175474e89094c44da98b954eedeac495271d0f') + expect(result.tokens.dismissedTokenWarnings['137']).toHaveProperty('0x2791bca1f2de4661ed88a30c99a7a9449aa84174') + + // Verify the rest of the data structure is maintained + expect(result.tokens.dismissedTokenWarnings['1']['0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48']).toEqual({ + address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + chainId: 1, + }) +} diff --git a/yarn.lock b/yarn.lock index 555a7f5ba6f..e27a2bb5752 100644 --- a/yarn.lock +++ b/yarn.lock @@ -75,10 +75,10 @@ __metadata: languageName: node linkType: hard -"@adobe/css-tools@npm:^4.0.1": - version: 4.3.1 - resolution: "@adobe/css-tools@npm:4.3.1" - checksum: ad43456379ff391132aff687ece190cb23ea69395e23c9b96690eeabe2468da89a4aaf266e4f8b6eaab53db3d1064107ce0f63c3a974e864f4a04affc768da3f +"@adobe/css-tools@npm:^4.0.1, @adobe/css-tools@npm:^4.4.0": + version: 4.4.1 + resolution: "@adobe/css-tools@npm:4.4.1" + checksum: bbded8a03c314afee0fb0b42922f664f437e0e2f0b86eeeb06dee9d02cd8fc958cf87aa3314952b00074e0b22fc5b8da23f45b61b6f8291c8aaa7cffc56a76e9 languageName: node linkType: hard @@ -1144,7 +1144,7 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.25.9, @babel/code-frame@npm:^7.26.0, @babel/code-frame@npm:^7.8.3": +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.16.7, @babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.25.9, @babel/code-frame@npm:^7.26.0, @babel/code-frame@npm:^7.26.2, @babel/code-frame@npm:^7.8.3": version: 7.26.2 resolution: "@babel/code-frame@npm:7.26.2" dependencies: @@ -1185,7 +1185,7 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.1.0, @babel/core@npm:^7.11.1, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.13.16, @babel/core@npm:^7.14.0, @babel/core@npm:^7.16.0, @babel/core@npm:^7.20.0, @babel/core@npm:^7.20.7, @babel/core@npm:^7.21.3, @babel/core@npm:^7.25.2, @babel/core@npm:^7.7.2, @babel/core@npm:^7.8.0": +"@babel/core@npm:^7.1.0, @babel/core@npm:^7.11.1, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.13.16, @babel/core@npm:^7.14.0, @babel/core@npm:^7.16.0, @babel/core@npm:^7.18.9, @babel/core@npm:^7.20.0, @babel/core@npm:^7.20.7, @babel/core@npm:^7.21.3, @babel/core@npm:^7.25.2, @babel/core@npm:^7.7.2, @babel/core@npm:^7.8.0": version: 7.26.0 resolution: "@babel/core@npm:7.26.0" dependencies: @@ -1209,29 +1209,29 @@ __metadata: linkType: hard "@babel/eslint-parser@npm:^7.16.3, @babel/eslint-parser@npm:^7.18.2": - version: 7.23.9 - resolution: "@babel/eslint-parser@npm:7.23.9" + version: 7.25.9 + resolution: "@babel/eslint-parser@npm:7.25.9" dependencies: "@nicolo-ribaudo/eslint-scope-5-internals": 5.1.1-v1 eslint-visitor-keys: ^2.1.0 semver: ^6.3.1 peerDependencies: "@babel/core": ^7.11.0 - eslint: ^7.5.0 || ^8.0.0 - checksum: cfb87bc48d005f181807ae8f8357ba9eeb3ece38480084fb5d997bac03ebb4cf709ee197d697f506de8faa7f665fa07579b9b9c2045d86d6c17174b6c1b0c5c9 + eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 + checksum: dd2afa122b62a5b07c1e71d1c23b2cd4d655d96609eb2ba1b1ae3ec6f415f4365b77d6669ff859aa7b75952fb63a1d29c5db6e5811fc4012841491cb2dee36e4 languageName: node linkType: hard -"@babel/generator@npm:^7.14.0, @babel/generator@npm:^7.18.13, @babel/generator@npm:^7.20.0, @babel/generator@npm:^7.20.5, @babel/generator@npm:^7.23.6, @babel/generator@npm:^7.25.5, @babel/generator@npm:^7.25.9, @babel/generator@npm:^7.26.0, @babel/generator@npm:^7.7.2": - version: 7.26.2 - resolution: "@babel/generator@npm:7.26.2" +"@babel/generator@npm:^7.14.0, @babel/generator@npm:^7.18.13, @babel/generator@npm:^7.20.0, @babel/generator@npm:^7.20.5, @babel/generator@npm:^7.23.6, @babel/generator@npm:^7.25.5, @babel/generator@npm:^7.26.0, @babel/generator@npm:^7.26.3, @babel/generator@npm:^7.7.2": + version: 7.26.3 + resolution: "@babel/generator@npm:7.26.3" dependencies: - "@babel/parser": ^7.26.2 - "@babel/types": ^7.26.0 + "@babel/parser": ^7.26.3 + "@babel/types": ^7.26.3 "@jridgewell/gen-mapping": ^0.3.5 "@jridgewell/trace-mapping": ^0.3.25 jsesc: ^3.0.2 - checksum: 6ff850b7d6082619f8c2f518d993cf7254cfbaa20b026282cbef5c9b2197686d076a432b18e36c4d1a42721c016df4f77a8f62c67600775d9683621d534b91b4 + checksum: fb09fa55c66f272badf71c20a3a2cee0fa1a447fed32d1b84f16a668a42aff3e5f5ddc6ed5d832dda1e952187c002ca1a5cdd827022efe591b6ac44cada884ea languageName: node linkType: hard @@ -1311,6 +1311,21 @@ __metadata: languageName: node linkType: hard +"@babel/helper-define-polyfill-provider@npm:^0.6.2, @babel/helper-define-polyfill-provider@npm:^0.6.3": + version: 0.6.3 + resolution: "@babel/helper-define-polyfill-provider@npm:0.6.3" + dependencies: + "@babel/helper-compilation-targets": ^7.22.6 + "@babel/helper-plugin-utils": ^7.22.5 + debug: ^4.1.1 + lodash.debounce: ^4.0.8 + resolve: ^1.14.2 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: 710e6d8a5391736b9f53f09d0494575c2e03de199ad8d1349bc8e514cb85251ea1f1842c2ff44830849d482052ddb42ae931101002a87a263b12f649c2e57c01 + languageName: node + linkType: hard + "@babel/helper-environment-visitor@npm:^7.18.9, @babel/helper-environment-visitor@npm:^7.22.20": version: 7.22.20 resolution: "@babel/helper-environment-visitor@npm:7.22.20" @@ -1347,7 +1362,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-imports@npm:^7.0.0, @babel/helper-module-imports@npm:^7.10.4, @babel/helper-module-imports@npm:^7.14.5, @babel/helper-module-imports@npm:^7.22.15, @babel/helper-module-imports@npm:^7.22.5, @babel/helper-module-imports@npm:^7.24.1, @babel/helper-module-imports@npm:^7.25.9": +"@babel/helper-module-imports@npm:^7.0.0, @babel/helper-module-imports@npm:^7.10.4, @babel/helper-module-imports@npm:^7.14.5, @babel/helper-module-imports@npm:^7.22.5, @babel/helper-module-imports@npm:^7.24.1, @babel/helper-module-imports@npm:^7.25.9": version: 7.25.9 resolution: "@babel/helper-module-imports@npm:7.25.9" dependencies: @@ -1412,15 +1427,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-simple-access@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-simple-access@npm:7.22.5" - dependencies: - "@babel/types": ^7.22.5 - checksum: fe9686714caf7d70aedb46c3cce090f8b915b206e09225f1e4dbc416786c2fdbbee40b38b23c268b7ccef749dd2db35f255338fb4f2444429874d900dede5ad2 - languageName: node - linkType: hard - "@babel/helper-skip-transparent-expression-wrappers@npm:^7.20.0, @babel/helper-skip-transparent-expression-wrappers@npm:^7.22.5, @babel/helper-skip-transparent-expression-wrappers@npm:^7.25.9": version: 7.25.9 resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.25.9" @@ -1431,15 +1437,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-split-export-declaration@npm:^7.22.6": - version: 7.22.6 - resolution: "@babel/helper-split-export-declaration@npm:7.22.6" - dependencies: - "@babel/types": ^7.22.5 - checksum: e141cace583b19d9195f9c2b8e17a3ae913b7ee9b8120246d0f9ca349ca6f03cb2c001fd5ec57488c544347c0bb584afec66c936511e447fd20a360e591ac921 - languageName: node - linkType: hard - "@babel/helper-string-parser@npm:^7.25.9": version: 7.25.9 resolution: "@babel/helper-string-parser@npm:7.25.9" @@ -1454,7 +1451,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-validator-option@npm:^7.21.0, @babel/helper-validator-option@npm:^7.22.15, @babel/helper-validator-option@npm:^7.23.5, @babel/helper-validator-option@npm:^7.25.9": +"@babel/helper-validator-option@npm:^7.21.0, @babel/helper-validator-option@npm:^7.22.15, @babel/helper-validator-option@npm:^7.25.9": version: 7.25.9 resolution: "@babel/helper-validator-option@npm:7.25.9" checksum: 9491b2755948ebbdd68f87da907283698e663b5af2d2b1b02a2765761974b1120d5d8d49e9175b167f16f72748ffceec8c9cf62acfbee73f4904507b246e2b3d @@ -1494,14 +1491,14 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.0.0, @babel/parser@npm:^7.1.0, @babel/parser@npm:^7.1.6, @babel/parser@npm:^7.13.16, @babel/parser@npm:^7.14.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.16.8, @babel/parser@npm:^7.20.0, @babel/parser@npm:^7.21.4, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.23.5, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.25.4, @babel/parser@npm:^7.25.9, @babel/parser@npm:^7.26.0, @babel/parser@npm:^7.26.2": - version: 7.26.2 - resolution: "@babel/parser@npm:7.26.2" +"@babel/parser@npm:^7.0.0, @babel/parser@npm:^7.1.0, @babel/parser@npm:^7.1.6, @babel/parser@npm:^7.13.16, @babel/parser@npm:^7.14.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.16.8, @babel/parser@npm:^7.20.0, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.21.4, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.23.5, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.25.4, @babel/parser@npm:^7.25.9, @babel/parser@npm:^7.26.0, @babel/parser@npm:^7.26.3": + version: 7.26.3 + resolution: "@babel/parser@npm:7.26.3" dependencies: - "@babel/types": ^7.26.0 + "@babel/types": ^7.26.3 bin: parser: ./bin/babel-parser.js - checksum: c88b5ea0adf357ef909cdc2c31e284a154943edc59f63f6e8a4c20bf773a1b2f3d8c2205e59c09ca7cdad91e7466300114548876529277a80651b6436a48d5d9 + checksum: e2bff2e9fa6540ee18fecc058bc74837eda2ddcecbe13454667314a93fc0ba26c1fb862c812d84f6d5f225c3bd8d191c3a42d4296e287a882c4e1f82ff2815ff languageName: node linkType: hard @@ -1568,17 +1565,15 @@ __metadata: linkType: hard "@babel/plugin-proposal-decorators@npm:^7.12.9, @babel/plugin-proposal-decorators@npm:^7.16.4": - version: 7.23.3 - resolution: "@babel/plugin-proposal-decorators@npm:7.23.3" + version: 7.25.9 + resolution: "@babel/plugin-proposal-decorators@npm:7.25.9" dependencies: - "@babel/helper-create-class-features-plugin": ^7.22.15 - "@babel/helper-plugin-utils": ^7.22.5 - "@babel/helper-replace-supers": ^7.22.20 - "@babel/helper-split-export-declaration": ^7.22.6 - "@babel/plugin-syntax-decorators": ^7.23.3 + "@babel/helper-create-class-features-plugin": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/plugin-syntax-decorators": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 5c11da45eafe11105e87f83f48d9eb1c95a5f78c01041729e4a8d1726ee0068ee8d98743aaaa24e30bf8eac446aa3db4a44943cc53e5707b5fdfb50a2189d899 + checksum: ff598127818ac8e704009f1a9a207766ada5f84f6ca74e9de662cb6ce32bcb846c28fd52d6c5df9c55b4eac9a2a3492aa71fbd5cef0569a14b6f12003df22af2 languageName: node linkType: hard @@ -1785,14 +1780,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-decorators@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-syntax-decorators@npm:7.23.3" +"@babel/plugin-syntax-decorators@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-syntax-decorators@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 07f6e488df0a061428e02629af9a1908b2e8abdcac2e5cfaa267be66dc30897be6e29df7c7f952d33f3679f9585ac9fcf6318f9c827790ab0b0928d5514305cd + checksum: aaf58b17e6aa08f41f93897daa93c601a486233a0375b4231799fc5c4e7c98480aaad3c1c44cf391a62e428c5f6546f76488a1023a4036bb87cd61fa79f1173b languageName: node linkType: hard @@ -1829,14 +1824,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-flow@npm:^7.0.0, @babel/plugin-syntax-flow@npm:^7.12.1, @babel/plugin-syntax-flow@npm:^7.18.0, @babel/plugin-syntax-flow@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-syntax-flow@npm:7.24.1" +"@babel/plugin-syntax-flow@npm:^7.0.0, @babel/plugin-syntax-flow@npm:^7.12.1, @babel/plugin-syntax-flow@npm:^7.18.0, @babel/plugin-syntax-flow@npm:^7.25.9": + version: 7.26.0 + resolution: "@babel/plugin-syntax-flow@npm:7.26.0" dependencies: - "@babel/helper-plugin-utils": ^7.24.0 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 87dfe32f3a3ea77941034fb2a39fdfc9ea18a994b8df40c3659a11c8787b2bc5adea029259c4eafc03cd35f11628f6533aa2a06381db7fcbe3b2cc3c2a2bb54f + checksum: fdc0d0a7b512e00d933e12cf93c785ea4645a193f4b539230b7601cfaa8c704410199318ce9ea14e5fca7d13e9027822f7d81a7871d3e854df26b6af04cc3c6c languageName: node linkType: hard @@ -2190,14 +2185,14 @@ __metadata: linkType: hard "@babel/plugin-transform-flow-strip-types@npm:^7.0.0, @babel/plugin-transform-flow-strip-types@npm:^7.16.0, @babel/plugin-transform-flow-strip-types@npm:^7.20.0, @babel/plugin-transform-flow-strip-types@npm:^7.21.0": - version: 7.24.1 - resolution: "@babel/plugin-transform-flow-strip-types@npm:7.24.1" + version: 7.25.9 + resolution: "@babel/plugin-transform-flow-strip-types@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.0 - "@babel/plugin-syntax-flow": ^7.24.1 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/plugin-syntax-flow": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 83faac90c934e15a8fe813d90cbfdf8aa2cb2cc9108f55e4a1ecda1c3097735af6a0b6623057f059153b572bc1dd088aeb2ff24217e9de82ad2390ab1210d01b + checksum: 7f51cd5cc0c3a5ce2fe31c689458706ed40284a1c59b017167c3cbef953550a843450c5cfe6896b154fb645f141a930a4fd925f46b2215d0fcc66e7758202c38 languageName: node linkType: hard @@ -2283,16 +2278,15 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-modules-commonjs@npm:^7.0.0, @babel/plugin-transform-modules-commonjs@npm:^7.13.8, @babel/plugin-transform-modules-commonjs@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-modules-commonjs@npm:7.23.3" +"@babel/plugin-transform-modules-commonjs@npm:^7.0.0, @babel/plugin-transform-modules-commonjs@npm:^7.13.8, @babel/plugin-transform-modules-commonjs@npm:^7.23.3, @babel/plugin-transform-modules-commonjs@npm:^7.25.9": + version: 7.26.3 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.26.3" dependencies: - "@babel/helper-module-transforms": ^7.23.3 - "@babel/helper-plugin-utils": ^7.22.5 - "@babel/helper-simple-access": ^7.22.5 + "@babel/helper-module-transforms": ^7.26.0 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 720a231ceade4ae4d2632478db4e7fecf21987d444942b72d523487ac8d715ca97de6c8f415c71e939595e1a4776403e7dc24ed68fe9125ad4acf57753c9bff7 + checksum: 0ac9aa4e5fe9fe34b58ee174881631e5e1c89eee5b1ebfd1147934686be92fc5fbfdc11119f0b607b3743d36a1cbcb7c36f18e0dd4424d6d7b749b1b9a18808a languageName: node linkType: hard @@ -2469,35 +2463,35 @@ __metadata: linkType: hard "@babel/plugin-transform-react-constant-elements@npm:^7.12.1, @babel/plugin-transform-react-constant-elements@npm:^7.21.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-react-constant-elements@npm:7.23.3" + version: 7.25.9 + resolution: "@babel/plugin-transform-react-constant-elements@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: f386fe59657910a00c5d276918765c6a74e52c9a223d79463a4eecd652b4da4a6c0a16710fcf5e17b838c336e0c46b552b79e47c1d6eeebc74a813788e0611f7 + checksum: ed59464c96cd4014f636852b4de398d2ffc22ffe3177a6c2a6058447a72839bb66a346a1db525ab60dcc5dd48ec59113a8325f785593689900358a15136e05c3 languageName: node linkType: hard -"@babel/plugin-transform-react-display-name@npm:^7.0.0, @babel/plugin-transform-react-display-name@npm:^7.16.0, @babel/plugin-transform-react-display-name@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-react-display-name@npm:7.24.1" +"@babel/plugin-transform-react-display-name@npm:^7.0.0, @babel/plugin-transform-react-display-name@npm:^7.16.0, @babel/plugin-transform-react-display-name@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-react-display-name@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.0 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: d87ac36073f923a25de0ed3cffac067ec5abc4cde63f7f4366881388fbea6dcbced0e4fefd3b7e99edfe58a4ce32ea4d4c523a577d2b9f0515b872ed02b3d8c3 + checksum: cd7020494e6f31c287834e8929e6a718d5b0ace21232fa30feb48622c2312045504c34b347dcff9e88145c349882b296a7d6b6cc3d3447d8c85502f16471747c languageName: node linkType: hard -"@babel/plugin-transform-react-jsx-development@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-react-jsx-development@npm:7.22.5" +"@babel/plugin-transform-react-jsx-development@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-react-jsx-development@npm:7.25.9" dependencies: - "@babel/plugin-transform-react-jsx": ^7.22.5 + "@babel/plugin-transform-react-jsx": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 36bc3ff0b96bb0ef4723070a50cfdf2e72cfd903a59eba448f9fe92fea47574d6f22efd99364413719e1f3fb3c51b6c9b2990b87af088f8486a84b2a5f9e4560 + checksum: 537d38369537f1eb56041c4b770bc0733fde1801a7f5ffef40a1217ea448f33ee2fa8e6098a58a82fd00e432c1b9426a66849496da419020c9eca3b1b1a23779 languageName: node linkType: hard @@ -2523,7 +2517,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-react-jsx@npm:^7.0.0, @babel/plugin-transform-react-jsx@npm:^7.22.5, @babel/plugin-transform-react-jsx@npm:^7.23.4, @babel/plugin-transform-react-jsx@npm:^7.25.2": +"@babel/plugin-transform-react-jsx@npm:^7.0.0, @babel/plugin-transform-react-jsx@npm:^7.25.2, @babel/plugin-transform-react-jsx@npm:^7.25.9": version: 7.25.9 resolution: "@babel/plugin-transform-react-jsx@npm:7.25.9" dependencies: @@ -2538,15 +2532,15 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-react-pure-annotations@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-react-pure-annotations@npm:7.24.1" +"@babel/plugin-transform-react-pure-annotations@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-react-pure-annotations@npm:7.25.9" dependencies: - "@babel/helper-annotate-as-pure": ^7.22.5 - "@babel/helper-plugin-utils": ^7.24.0 + "@babel/helper-annotate-as-pure": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 06a6bfe80f1f36408d07dd80c48cf9f61177c8e5d814e80ddbe88cfad81a8b86b3110e1fe9d1ac943db77e74497daa7f874b5490c788707106ad26ecfbe44813 + checksum: 9995c0fc7c25d3aaaa0ce84233de02eab2564ea111d0813ec5baa538eb21520402879cc787ad1ad4c2061b99cebc3beb09910e64c9592e8ccb42ae62d9e4fd9a languageName: node linkType: hard @@ -2574,18 +2568,18 @@ __metadata: linkType: hard "@babel/plugin-transform-runtime@npm:^7.0.0, @babel/plugin-transform-runtime@npm:^7.16.4": - version: 7.23.4 - resolution: "@babel/plugin-transform-runtime@npm:7.23.4" + version: 7.25.9 + resolution: "@babel/plugin-transform-runtime@npm:7.25.9" dependencies: - "@babel/helper-module-imports": ^7.22.15 - "@babel/helper-plugin-utils": ^7.22.5 - babel-plugin-polyfill-corejs2: ^0.4.6 - babel-plugin-polyfill-corejs3: ^0.8.5 - babel-plugin-polyfill-regenerator: ^0.5.3 + "@babel/helper-module-imports": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 + babel-plugin-polyfill-corejs2: ^0.4.10 + babel-plugin-polyfill-corejs3: ^0.10.6 + babel-plugin-polyfill-regenerator: ^0.6.1 semver: ^6.3.1 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: a1693d27cd5ce17d0917280942a62bbf4ee27f6f0fe7beb33789bdc699cda21e5253997663248b32e8e36c01ccd202f96246413b9328b70a05d4cf64faa3191e + checksum: db7f20a7a7324dbfe3b43a09f0095c69dadcf8b08567fa7c7fa6e245d97c66cdcdc330e97733b7589261c0e1046bc5cc36741b932ac5dd7757374495b57e7b02 languageName: node linkType: hard @@ -2645,9 +2639,9 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-typescript@npm:^7.23.3, @babel/plugin-transform-typescript@npm:^7.5.0": - version: 7.25.9 - resolution: "@babel/plugin-transform-typescript@npm:7.25.9" +"@babel/plugin-transform-typescript@npm:^7.23.3, @babel/plugin-transform-typescript@npm:^7.25.9, @babel/plugin-transform-typescript@npm:^7.5.0": + version: 7.26.3 + resolution: "@babel/plugin-transform-typescript@npm:7.26.3" dependencies: "@babel/helper-annotate-as-pure": ^7.25.9 "@babel/helper-create-class-features-plugin": ^7.25.9 @@ -2656,7 +2650,7 @@ __metadata: "@babel/plugin-syntax-typescript": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 6dd1303f1b9f314e22c6c54568a8b9709a081ce97be757d4004f960e3e73d6b819e6b49cee6cf1fc8455511e41127a8b580fa34602de62d17ab8a0b2d0ccf183 + checksum: 38ab210e80d4fc4eaa27e88705a961d53f5eae1dcd0ef8794affe3002fec557404e8bb29ca22d18e691a75690e3bcadbfeb8207a830f15cf83231ab5fd1ea08b languageName: node linkType: hard @@ -2824,22 +2818,22 @@ __metadata: linkType: hard "@babel/preset-react@npm:^7.12.5, @babel/preset-react@npm:^7.16.0, @babel/preset-react@npm:^7.18.6, @babel/preset-react@npm:^7.22.15": - version: 7.24.1 - resolution: "@babel/preset-react@npm:7.24.1" + version: 7.26.3 + resolution: "@babel/preset-react@npm:7.26.3" dependencies: - "@babel/helper-plugin-utils": ^7.24.0 - "@babel/helper-validator-option": ^7.23.5 - "@babel/plugin-transform-react-display-name": ^7.24.1 - "@babel/plugin-transform-react-jsx": ^7.23.4 - "@babel/plugin-transform-react-jsx-development": ^7.22.5 - "@babel/plugin-transform-react-pure-annotations": ^7.24.1 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/helper-validator-option": ^7.25.9 + "@babel/plugin-transform-react-display-name": ^7.25.9 + "@babel/plugin-transform-react-jsx": ^7.25.9 + "@babel/plugin-transform-react-jsx-development": ^7.25.9 + "@babel/plugin-transform-react-pure-annotations": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 70e146a6de480cb4b6c5eb197003960a2d148d513e1f5b5d04ee954f255d68c935c2800da13e550267f47b894bd0214b2548181467b52a4bdc0a85020061b68c + checksum: 9c76f145026715c8e4a1f6c44f208918e700227d8d8a8068f4ae10d87031d23eb8b483e508cd4452d65066f731b7a8169527e66e83ffe165595e8db7899dd859 languageName: node linkType: hard -"@babel/preset-typescript@npm:7.23.3, @babel/preset-typescript@npm:^7.13.0, @babel/preset-typescript@npm:^7.16.0, @babel/preset-typescript@npm:^7.16.7, @babel/preset-typescript@npm:^7.21.0": +"@babel/preset-typescript@npm:7.23.3": version: 7.23.3 resolution: "@babel/preset-typescript@npm:7.23.3" dependencies: @@ -2854,6 +2848,21 @@ __metadata: languageName: node linkType: hard +"@babel/preset-typescript@npm:^7.13.0, @babel/preset-typescript@npm:^7.16.0, @babel/preset-typescript@npm:^7.16.7, @babel/preset-typescript@npm:^7.21.0": + version: 7.26.0 + resolution: "@babel/preset-typescript@npm:7.26.0" + dependencies: + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/helper-validator-option": ^7.25.9 + "@babel/plugin-syntax-jsx": ^7.25.9 + "@babel/plugin-transform-modules-commonjs": ^7.25.9 + "@babel/plugin-transform-typescript": ^7.25.9 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 6d8641fa6efd0e10eec5e8f92cd164b916a06d57131cfa5216c281404289c87d2b4995140a1c1d9c3bad171ff6ef2226be5f0585e09577ffff349706e991ec71 + languageName: node + linkType: hard + "@babel/register@npm:^7.13.16": version: 7.18.9 resolution: "@babel/register@npm:7.18.9" @@ -2895,7 +2904,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.19.4, @babel/runtime@npm:^7.20.0, @babel/runtime@npm:^7.20.6, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.7, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.25.4, @babel/runtime@npm:^7.4.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.9.2": +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.19.4, @babel/runtime@npm:^7.20.0, @babel/runtime@npm:^7.20.6, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.7, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.25.4, @babel/runtime@npm:^7.4.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.9.2": version: 7.26.0 resolution: "@babel/runtime@npm:7.26.0" dependencies: @@ -2915,28 +2924,28 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.1.6, @babel/traverse@npm:^7.14.0, @babel/traverse@npm:^7.16.8, @babel/traverse@npm:^7.20.0, @babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.23.9, @babel/traverse@npm:^7.25.0, @babel/traverse@npm:^7.25.4, @babel/traverse@npm:^7.25.9, @babel/traverse@npm:^7.4.5, @babel/traverse@npm:^7.7.2": - version: 7.25.9 - resolution: "@babel/traverse@npm:7.25.9" +"@babel/traverse@npm:^7.1.6, @babel/traverse@npm:^7.14.0, @babel/traverse@npm:^7.16.8, @babel/traverse@npm:^7.18.9, @babel/traverse@npm:^7.20.0, @babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.23.9, @babel/traverse@npm:^7.25.0, @babel/traverse@npm:^7.25.4, @babel/traverse@npm:^7.25.9, @babel/traverse@npm:^7.4.5, @babel/traverse@npm:^7.7.2": + version: 7.26.4 + resolution: "@babel/traverse@npm:7.26.4" dependencies: - "@babel/code-frame": ^7.25.9 - "@babel/generator": ^7.25.9 - "@babel/parser": ^7.25.9 + "@babel/code-frame": ^7.26.2 + "@babel/generator": ^7.26.3 + "@babel/parser": ^7.26.3 "@babel/template": ^7.25.9 - "@babel/types": ^7.25.9 + "@babel/types": ^7.26.3 debug: ^4.3.1 globals: ^11.1.0 - checksum: 901d325662ff1dd9bc51de00862e01055fa6bc374f5297d7e3731f2f0e268bbb1d2141f53fa82860aa308ee44afdcf186a948f16c83153927925804b95a9594d + checksum: dcdf51b27ab640291f968e4477933465c2910bfdcbcff8f5315d1f29b8ff861864f363e84a71fb489f5e9708e8b36b7540608ce019aa5e57ef7a4ba537e62700 languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.1.6, @babel/types@npm:^7.12.6, @babel/types@npm:^7.16.8, @babel/types@npm:^7.18.13, @babel/types@npm:^7.20.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.3, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.9, @babel/types@npm:^7.25.4, @babel/types@npm:^7.25.9, @babel/types@npm:^7.26.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4": - version: 7.26.0 - resolution: "@babel/types@npm:7.26.0" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.1.6, @babel/types@npm:^7.12.6, @babel/types@npm:^7.16.8, @babel/types@npm:^7.18.13, @babel/types@npm:^7.18.9, @babel/types@npm:^7.20.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.3, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.9, @babel/types@npm:^7.25.4, @babel/types@npm:^7.25.9, @babel/types@npm:^7.26.0, @babel/types@npm:^7.26.3, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4": + version: 7.26.3 + resolution: "@babel/types@npm:7.26.3" dependencies: "@babel/helper-string-parser": ^7.25.9 "@babel/helper-validator-identifier": ^7.25.9 - checksum: a3dd37dabac693018872da96edb8c1843a605c1bfacde6c3f504fba79b972426a6f24df70aa646356c0c1b19bdd2c722c623c684a996c002381071680602280d + checksum: 195f428080dcaadbcecc9445df7f91063beeaa91b49ccd78f38a5af6b75a6a58391d0c6614edb1ea322e57889a1684a0aab8e667951f820196901dd341f931e9 languageName: node linkType: hard @@ -2968,6 +2977,21 @@ __metadata: languageName: node linkType: hard +"@chromatic-com/storybook@npm:3.2.2": + version: 3.2.2 + resolution: "@chromatic-com/storybook@npm:3.2.2" + dependencies: + chromatic: ^11.15.0 + filesize: ^10.0.12 + jsonfile: ^6.1.0 + react-confetti: ^6.1.0 + strip-ansi: ^7.1.0 + peerDependencies: + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + checksum: 8f1d03b32e131d391d41913b346d3898e5f2661c54dbe057f05fb1bce2d9b94581942bc5f90efe599b819d1f05d92c50a9be1e0cba2962be797f9a9551b568da + languageName: node + linkType: hard + "@cloudflare/kv-asset-handler@npm:^0.2.0": version: 0.2.0 resolution: "@cloudflare/kv-asset-handler@npm:0.2.0" @@ -3315,9 +3339,9 @@ __metadata: linkType: hard "@csstools/normalize.css@npm:*": - version: 12.0.0 - resolution: "@csstools/normalize.css@npm:12.0.0" - checksum: fbef0f7fe4edbc3ce31b41257f0fa06e0442f11260e41c082a98de9b824997786a16900e7a5c0f4ca8f736dcd25dfd01c153d1c994a07d42c93c0a526ce0774d + version: 12.1.1 + resolution: "@csstools/normalize.css@npm:12.1.1" + checksum: a356ee0fcb922f3e0bc23df4468bb4f27fc26c767e25359c079455fe30301d253d8a60c443859b04350c8174393edbb11bad2a9ef2f8cce0e371f6abf6c7ef36 languageName: node linkType: hard @@ -4862,15 +4886,15 @@ __metadata: linkType: hard "@eslint-community/regexpp@npm:^4.4.0, @eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.1": - version: 4.10.0 - resolution: "@eslint-community/regexpp@npm:4.10.0" - checksum: 2a6e345429ea8382aaaf3a61f865cae16ed44d31ca917910033c02dc00d505d939f10b81e079fa14d43b51499c640138e153b7e40743c4c094d9df97d4e56f7b + version: 4.12.1 + resolution: "@eslint-community/regexpp@npm:4.12.1" + checksum: 0d628680e204bc316d545b4993d3658427ca404ae646ce541fcc65306b8c712c340e5e573e30fb9f85f4855c0c5f6dca9868931f2fcced06417fbe1a0c6cd2d6 languageName: node linkType: hard -"@eslint/eslintrc@npm:^2.1.0, @eslint/eslintrc@npm:^2.1.3": - version: 2.1.3 - resolution: "@eslint/eslintrc@npm:2.1.3" +"@eslint/eslintrc@npm:^2.1.0, @eslint/eslintrc@npm:^2.1.4": + version: 2.1.4 + resolution: "@eslint/eslintrc@npm:2.1.4" dependencies: ajv: ^6.12.4 debug: ^4.3.2 @@ -4881,7 +4905,7 @@ __metadata: js-yaml: ^4.1.0 minimatch: ^3.1.2 strip-json-comments: ^3.1.1 - checksum: 5c6c3878192fe0ddffa9aff08b4e2f3bcc8f1c10d6449b7295a5f58b662019896deabfc19890455ffd7e60a5bd28d25d0eaefb2f78b2d230aae3879af92b89e5 + checksum: 10957c7592b20ca0089262d8c2a8accbad14b4f6507e35416c32ee6b4dbf9cad67dfb77096bbd405405e9ada2b107f3797fe94362e1c55e0b09d6e90dd149127 languageName: node linkType: hard @@ -4892,10 +4916,10 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:8.53.0": - version: 8.53.0 - resolution: "@eslint/js@npm:8.53.0" - checksum: e0d5cfb0000aaee237c8e6d6d6e366faa60b1ef7f928ce17778373aa44d3b886368f6d5e1f97f913f0f16801aad016db8b8df78418c9d18825c15590328028af +"@eslint/js@npm:8.57.1": + version: 8.57.1 + resolution: "@eslint/js@npm:8.57.1" + checksum: 2afb77454c06e8316793d2e8e79a0154854d35e6782a1217da274ca60b5044d2c69d6091155234ed0551a1e408f86f09dd4ece02752c59568fa403e60611e880 languageName: node linkType: hard @@ -7570,7 +7594,7 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.11.10, @humanwhocodes/config-array@npm:^0.11.13": +"@humanwhocodes/config-array@npm:^0.11.10": version: 0.11.13 resolution: "@humanwhocodes/config-array@npm:0.11.13" dependencies: @@ -7581,6 +7605,17 @@ __metadata: languageName: node linkType: hard +"@humanwhocodes/config-array@npm:^0.13.0": + version: 0.13.0 + resolution: "@humanwhocodes/config-array@npm:0.13.0" + dependencies: + "@humanwhocodes/object-schema": ^2.0.3 + debug: ^4.3.1 + minimatch: ^3.0.5 + checksum: eae69ff9134025dd2924f0b430eb324981494be26f0fddd267a33c28711c4db643242cf9fddf7dadb9d16c96b54b2d2c073e60a56477df86e0173149313bd5d6 + languageName: node + linkType: hard + "@humanwhocodes/module-importer@npm:^1.0.1": version: 1.0.1 resolution: "@humanwhocodes/module-importer@npm:1.0.1" @@ -7588,10 +7623,10 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/object-schema@npm:^2.0.1": - version: 2.0.1 - resolution: "@humanwhocodes/object-schema@npm:2.0.1" - checksum: 24929487b1ed48795d2f08346a0116cc5ee4634848bce64161fb947109352c562310fd159fc64dda0e8b853307f5794605191a9547f7341158559ca3c8262a45 +"@humanwhocodes/object-schema@npm:^2.0.1, @humanwhocodes/object-schema@npm:^2.0.3": + version: 2.0.3 + resolution: "@humanwhocodes/object-schema@npm:2.0.3" + checksum: d3b78f6c5831888c6ecc899df0d03bcc25d46f3ad26a11d7ea52944dc36a35ef543fad965322174238d677a43d5c694434f6607532cff7077062513ad7022631 languageName: node linkType: hard @@ -7602,6 +7637,20 @@ __metadata: languageName: node linkType: hard +"@isaacs/cliui@npm:^8.0.2": + version: 8.0.2 + resolution: "@isaacs/cliui@npm:8.0.2" + dependencies: + string-width: ^5.1.2 + string-width-cjs: "npm:string-width@^4.2.0" + strip-ansi: ^7.0.1 + strip-ansi-cjs: "npm:strip-ansi@^6.0.1" + wrap-ansi: ^8.1.0 + wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" + checksum: 4a473b9b32a7d4d3cfb7a614226e555091ff0c5a29a1734c28c72a182c2f6699b26fc6b5c2131dfd841e86b185aea714c72201d7c98c2fba5f17709333a67aeb + languageName: node + linkType: hard + "@isaacs/ttlcache@npm:^1.4.1": version: 1.4.1 resolution: "@isaacs/ttlcache@npm:1.4.1" @@ -8461,6 +8510,18 @@ __metadata: languageName: node linkType: hard +"@mdx-js/react@npm:^3.0.0": + version: 3.1.0 + resolution: "@mdx-js/react@npm:3.1.0" + dependencies: + "@types/mdx": ^2.0.0 + peerDependencies: + "@types/react": ">=16" + react: ">=16" + checksum: c5a9c495f43f498ece24a768762a1743abe2be33d050d7eab731beb754e631700547f039198c6262c998d9a443906bd78811c3fa38bc2fb37659848161dac331 + languageName: node + linkType: hard + "@metamask/eth-json-rpc-provider@npm:^1.0.0": version: 1.0.1 resolution: "@metamask/eth-json-rpc-provider@npm:1.0.1" @@ -9502,7 +9563,14 @@ __metadata: languageName: node linkType: hard -"@pmmmwh/react-refresh-webpack-plugin@npm:0.5.11, @pmmmwh/react-refresh-webpack-plugin@npm:^0.5.3": +"@pkgjs/parseargs@npm:^0.11.0": + version: 0.11.0 + resolution: "@pkgjs/parseargs@npm:0.11.0" + checksum: 6ad6a00fc4f2f2cfc6bff76fb1d88b8ee20bc0601e18ebb01b6d4be583733a860239a521a7fbca73b612e66705078809483549d2b18f370eb346c5155c8e4a0f + languageName: node + linkType: hard + +"@pmmmwh/react-refresh-webpack-plugin@npm:0.5.11": version: 0.5.11 resolution: "@pmmmwh/react-refresh-webpack-plugin@npm:0.5.11" dependencies: @@ -9541,6 +9609,43 @@ __metadata: languageName: node linkType: hard +"@pmmmwh/react-refresh-webpack-plugin@npm:^0.5.1, @pmmmwh/react-refresh-webpack-plugin@npm:^0.5.3": + version: 0.5.15 + resolution: "@pmmmwh/react-refresh-webpack-plugin@npm:0.5.15" + dependencies: + ansi-html: ^0.0.9 + core-js-pure: ^3.23.3 + error-stack-parser: ^2.0.6 + html-entities: ^2.1.0 + loader-utils: ^2.0.4 + schema-utils: ^4.2.0 + source-map: ^0.7.3 + peerDependencies: + "@types/webpack": 4.x || 5.x + react-refresh: ">=0.10.0 <1.0.0" + sockjs-client: ^1.4.0 + type-fest: ">=0.17.0 <5.0.0" + webpack: ">=4.43.0 <6.0.0" + webpack-dev-server: 3.x || 4.x || 5.x + webpack-hot-middleware: 2.x + webpack-plugin-serve: 0.x || 1.x + peerDependenciesMeta: + "@types/webpack": + optional: true + sockjs-client: + optional: true + type-fest: + optional: true + webpack-dev-server: + optional: true + webpack-hot-middleware: + optional: true + webpack-plugin-serve: + optional: true + checksum: 82df6244146209d63a12f0ca2e70b05274ee058c7e6d6eb4ced1228afde3b039a7f3f3cc0c76f1bb4b28deadbcf08bc2821c814f0bfee06979128578300fff3d + languageName: node + linkType: hard + "@polka/url@npm:^1.0.0-next.24": version: 1.0.0-next.25 resolution: "@polka/url@npm:1.0.0-next.25" @@ -10570,13 +10675,20 @@ __metadata: languageName: node linkType: hard -"@rushstack/eslint-patch@npm:1.5.1, @rushstack/eslint-patch@npm:^1.1.0": +"@rushstack/eslint-patch@npm:1.5.1": version: 1.5.1 resolution: "@rushstack/eslint-patch@npm:1.5.1" checksum: e4c25322312dbaa29e835a7ab4fbac53c8731dd0da65e46646e38945e296429e7fb91c2ef3da5af5d5938d44b0cde1d5290438ebb3dcb015e02b80b5e2530d24 languageName: node linkType: hard +"@rushstack/eslint-patch@npm:^1.1.0": + version: 1.10.4 + resolution: "@rushstack/eslint-patch@npm:1.10.4" + checksum: ec17ac954ed01e9c714e29ae00da29099234a71615d6f61f2da5c7beeef283f5619132114faf9481cb1ca7b4417aed74c05a54d416e4d8facc189bb216d49066 + languageName: node + linkType: hard + "@safe-global/safe-apps-provider@npm:0.18.1": version: 0.18.1 resolution: "@safe-global/safe-apps-provider@npm:0.18.1" @@ -11883,6 +11995,47 @@ __metadata: languageName: node linkType: hard +"@storybook/addon-actions@npm:8.4.2": + version: 8.4.2 + resolution: "@storybook/addon-actions@npm:8.4.2" + dependencies: + "@storybook/global": ^5.0.0 + "@types/uuid": ^9.0.1 + dequal: ^2.0.2 + polished: ^4.2.2 + uuid: ^9.0.0 + peerDependencies: + storybook: ^8.4.2 + checksum: 7ede8f0404a890c12879b2c2c33fd32e61eb3435461b922391c266d0e268976069be478f92630edfdb9e680f4b901896a9fa12b03c63e2ccb2fc1b6f6d378870 + languageName: node + linkType: hard + +"@storybook/addon-backgrounds@npm:8.4.2": + version: 8.4.2 + resolution: "@storybook/addon-backgrounds@npm:8.4.2" + dependencies: + "@storybook/global": ^5.0.0 + memoizerific: ^1.11.3 + ts-dedent: ^2.0.0 + peerDependencies: + storybook: ^8.4.2 + checksum: 889f4ecea5c6d9ca67e95a4d46925c7be3d7ced1657f2279bdf8717c5830074595638196e9c93f21dc63ec2cbc462680cf17602dddcb3f428669e667c8f5becd + languageName: node + linkType: hard + +"@storybook/addon-controls@npm:8.4.2": + version: 8.4.2 + resolution: "@storybook/addon-controls@npm:8.4.2" + dependencies: + "@storybook/global": ^5.0.0 + dequal: ^2.0.2 + ts-dedent: ^2.0.0 + peerDependencies: + storybook: ^8.4.2 + checksum: 721a179745e9c5cd0fbedb80f7f9578d99a48a4673c8227ae5b5634db9824f6de144223e4bc179e35a3ef206eed93cef51d8ad43d2c9b08edaee57f4f3c93ea2 + languageName: node + linkType: hard + "@storybook/addon-controls@npm:^8.4.2": version: 8.4.5 resolution: "@storybook/addon-controls@npm:8.4.5" @@ -11896,6 +12049,92 @@ __metadata: languageName: node linkType: hard +"@storybook/addon-docs@npm:8.4.2": + version: 8.4.2 + resolution: "@storybook/addon-docs@npm:8.4.2" + dependencies: + "@mdx-js/react": ^3.0.0 + "@storybook/blocks": 8.4.2 + "@storybook/csf-plugin": 8.4.2 + "@storybook/react-dom-shim": 8.4.2 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + ts-dedent: ^2.0.0 + peerDependencies: + storybook: ^8.4.2 + checksum: bf24f21b56729bb1cfa7b17e3200c440151597a45f3dccdf183a1ad6f225394d6f98b54082276798c6062d11a2c15a7633b4058cac849010918f60481458fce9 + languageName: node + linkType: hard + +"@storybook/addon-essentials@npm:8.4.2": + version: 8.4.2 + resolution: "@storybook/addon-essentials@npm:8.4.2" + dependencies: + "@storybook/addon-actions": 8.4.2 + "@storybook/addon-backgrounds": 8.4.2 + "@storybook/addon-controls": 8.4.2 + "@storybook/addon-docs": 8.4.2 + "@storybook/addon-highlight": 8.4.2 + "@storybook/addon-measure": 8.4.2 + "@storybook/addon-outline": 8.4.2 + "@storybook/addon-toolbars": 8.4.2 + "@storybook/addon-viewport": 8.4.2 + ts-dedent: ^2.0.0 + peerDependencies: + storybook: ^8.4.2 + checksum: 951da2192a63d985e9af2e1e803bbe8bd6d64a87f50644034a55eb8bdc2ad0844e87836437d5c494eff3e94c8eae894d5f28bbef4b9cb99ef7e5fad573e1980d + languageName: node + linkType: hard + +"@storybook/addon-highlight@npm:8.4.2": + version: 8.4.2 + resolution: "@storybook/addon-highlight@npm:8.4.2" + dependencies: + "@storybook/global": ^5.0.0 + peerDependencies: + storybook: ^8.4.2 + checksum: 436a49e909866a263a1db0445d5498d3f551dab0af70789d22f9913fa562d8be9ae3ac9c6f08e46658cf4b5d9582a7a7be357e5511636088a57ae05a52743d2a + languageName: node + linkType: hard + +"@storybook/addon-interactions@npm:8.4.2": + version: 8.4.2 + resolution: "@storybook/addon-interactions@npm:8.4.2" + dependencies: + "@storybook/global": ^5.0.0 + "@storybook/instrumenter": 8.4.2 + "@storybook/test": 8.4.2 + polished: ^4.2.2 + ts-dedent: ^2.2.0 + peerDependencies: + storybook: ^8.4.2 + checksum: 80a41d9782594ac543fd4bb934cb572e19a0ec738f693f804b27aac63667f102cec5c3746c5d1472366530530534b47a2d470e374c486f17b18fcebc880e3d16 + languageName: node + linkType: hard + +"@storybook/addon-measure@npm:8.4.2": + version: 8.4.2 + resolution: "@storybook/addon-measure@npm:8.4.2" + dependencies: + "@storybook/global": ^5.0.0 + tiny-invariant: ^1.3.1 + peerDependencies: + storybook: ^8.4.2 + checksum: fb03d27a828ac035e88de4c035cb1fbc070a7fe6c3e8cf0422a2480f0fb62223d6e2d3ab966b04e3c8372c8258aa487431532c766111fbd268beec8b280bd4ec + languageName: node + linkType: hard + +"@storybook/addon-onboarding@npm:8.4.2": + version: 8.4.2 + resolution: "@storybook/addon-onboarding@npm:8.4.2" + dependencies: + react-confetti: ^6.1.0 + peerDependencies: + storybook: ^8.4.2 + checksum: 631d5261d092366b38d4edb745775dc5493ee1217806303b5fc7499d5ebf3b15768a6ce6b44672bb3dd6fe1da5411a7b004aafbb603877d966f07c96251e41ef + languageName: node + linkType: hard + "@storybook/addon-ondevice-controls@npm:8.4.2": version: 8.4.2 resolution: "@storybook/addon-ondevice-controls@npm:8.4.2" @@ -11919,6 +12158,96 @@ __metadata: languageName: node linkType: hard +"@storybook/addon-outline@npm:8.4.2": + version: 8.4.2 + resolution: "@storybook/addon-outline@npm:8.4.2" + dependencies: + "@storybook/global": ^5.0.0 + ts-dedent: ^2.0.0 + peerDependencies: + storybook: ^8.4.2 + checksum: f7397522f7c4568bc1d6fe858ba9fa3c4ce4afbdbfd47761ebb841c8678a2472f4bbff4078fd557224b54b353e0164b97fef49d668e9b6ab8388b99bc312d3a0 + languageName: node + linkType: hard + +"@storybook/addon-toolbars@npm:8.4.2": + version: 8.4.2 + resolution: "@storybook/addon-toolbars@npm:8.4.2" + peerDependencies: + storybook: ^8.4.2 + checksum: 0b19b49ca00e952a50052f323b7e5fd144331f5b719e4d7053c266c32db1a0f30d3a28f6aafe4f5d239a5402cb0195bb295361adfc2e7d3abb9b27a888816c8e + languageName: node + linkType: hard + +"@storybook/addon-viewport@npm:8.4.2": + version: 8.4.2 + resolution: "@storybook/addon-viewport@npm:8.4.2" + dependencies: + memoizerific: ^1.11.3 + peerDependencies: + storybook: ^8.4.2 + checksum: fabb338c37ce560b1c67baf36fbefc7aca544e62e4b27b128e70c142d0cb1ebd320bf774208888e53879b4183c3899565edf0cdc2e80e55f9bcdee7a032a4da1 + languageName: node + linkType: hard + +"@storybook/blocks@npm:8.4.2": + version: 8.4.2 + resolution: "@storybook/blocks@npm:8.4.2" + dependencies: + "@storybook/csf": ^0.1.11 + "@storybook/icons": ^1.2.12 + ts-dedent: ^2.0.0 + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + storybook: ^8.4.2 + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + checksum: 649bb81cdb5229b49aa7b913952974cbad533bf854f7bd400dc535b0f4781f90bf1b04df009fc6bcedbf111d7dbeeb375da38dbca8fa8f5306eeab8990dd342e + languageName: node + linkType: hard + +"@storybook/builder-webpack5@npm:8.4.2": + version: 8.4.2 + resolution: "@storybook/builder-webpack5@npm:8.4.2" + dependencies: + "@storybook/core-webpack": 8.4.2 + "@types/node": ^22.0.0 + "@types/semver": ^7.3.4 + browser-assert: ^1.2.1 + case-sensitive-paths-webpack-plugin: ^2.4.0 + cjs-module-lexer: ^1.2.3 + constants-browserify: ^1.0.0 + css-loader: ^6.7.1 + es-module-lexer: ^1.5.0 + fork-ts-checker-webpack-plugin: ^8.0.0 + html-webpack-plugin: ^5.5.0 + magic-string: ^0.30.5 + path-browserify: ^1.0.1 + process: ^0.11.10 + semver: ^7.3.7 + style-loader: ^3.3.1 + terser-webpack-plugin: ^5.3.1 + ts-dedent: ^2.0.0 + url: ^0.11.0 + util: ^0.12.4 + util-deprecate: ^1.0.2 + webpack: 5 + webpack-dev-middleware: ^6.1.2 + webpack-hot-middleware: ^2.25.1 + webpack-virtual-modules: ^0.6.0 + peerDependencies: + storybook: ^8.4.2 + peerDependenciesMeta: + typescript: + optional: true + checksum: a41b0b2b9316a35107794948da1a5cad84b76218db9a1d6a5d51d0de71afc9cf1b602d1aa28f755695186eb4c9ee22ac28c762d2d9203fbe98fa71477f59fe08 + languageName: node + linkType: hard + "@storybook/components@npm:8.4.2": version: 8.4.2 resolution: "@storybook/components@npm:8.4.2" @@ -11937,6 +12266,42 @@ __metadata: languageName: node linkType: hard +"@storybook/core-webpack@npm:8.4.2": + version: 8.4.2 + resolution: "@storybook/core-webpack@npm:8.4.2" + dependencies: + "@types/node": ^22.0.0 + ts-dedent: ^2.0.0 + peerDependencies: + storybook: ^8.4.2 + checksum: a1d42dab59627237e585f829480338f5f439210e74254da3c4014b10526adad2bc4458c722147a1f7dfbd7caa1dcc1c640b2dd89dc0b5edb445538237b92374e + languageName: node + linkType: hard + +"@storybook/core@npm:8.4.2": + version: 8.4.2 + resolution: "@storybook/core@npm:8.4.2" + dependencies: + "@storybook/csf": ^0.1.11 + better-opn: ^3.0.2 + browser-assert: ^1.2.1 + esbuild: ^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 + esbuild-register: ^3.5.0 + jsdoc-type-pratt-parser: ^4.0.0 + process: ^0.11.10 + recast: ^0.23.5 + semver: ^7.6.2 + util: ^0.12.5 + ws: ^8.2.3 + peerDependencies: + prettier: ^2 || ^3 + peerDependenciesMeta: + prettier: + optional: true + checksum: f8b29275f452772ae8663f568d7e00b3384465860df710a130ef72d3b15b767f04cd496949fb1f345d06698310f68c4bfc3f35577f76b87fee14b770d50dc12c + languageName: node + linkType: hard + "@storybook/core@npm:8.4.5, @storybook/core@npm:^8.4.2": version: 8.4.5 resolution: "@storybook/core@npm:8.4.5" @@ -11961,6 +12326,26 @@ __metadata: languageName: node linkType: hard +"@storybook/csf-plugin@npm:8.4.2": + version: 8.4.2 + resolution: "@storybook/csf-plugin@npm:8.4.2" + dependencies: + unplugin: ^1.3.1 + peerDependencies: + storybook: ^8.4.2 + checksum: ec787be0a4fe2928a2675fe6bca5799f0bff8c66e50cea7bed198a188b19ee57257266b0255c5226a7da97928758b86c978afecc3ee0e2bb1f21fe0e7fdaf0c5 + languageName: node + linkType: hard + +"@storybook/csf@npm:^0.0.1": + version: 0.0.1 + resolution: "@storybook/csf@npm:0.0.1" + dependencies: + lodash: ^4.17.15 + checksum: fb57fa028b08a51edf44e1a2bf4be40a4607f5c6ccb58aae8924f476a42b9bbd61a0ad521cfc82196f23e6a912caae0a615e70a755e6800b284c91c509fd2de6 + languageName: node + linkType: hard + "@storybook/csf@npm:^0.1.1, @storybook/csf@npm:^0.1.11": version: 0.1.11 resolution: "@storybook/csf@npm:0.1.11" @@ -11977,6 +12362,28 @@ __metadata: languageName: node linkType: hard +"@storybook/icons@npm:^1.2.12": + version: 1.2.12 + resolution: "@storybook/icons@npm:1.2.12" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + checksum: a4c87cbfadfa1369680c4acc9d5ef90b9ff23e2ad603b6c0aba0dafe89780e5643c567160eb0544fe33f3b9f157adda2621ae45b4036ac001139a34926e00102 + languageName: node + linkType: hard + +"@storybook/instrumenter@npm:8.4.2": + version: 8.4.2 + resolution: "@storybook/instrumenter@npm:8.4.2" + dependencies: + "@storybook/global": ^5.0.0 + "@vitest/utils": ^2.1.1 + peerDependencies: + storybook: ^8.4.2 + checksum: 9f4a70ecd5b8aa75aa51f88f829a7585831148c3d38db3f954be46c40a01b47135577d38e84ff7298cbad5efa5a2aaa3a57946d2d03edbf64008c6d2250d0d5d + languageName: node + linkType: hard + "@storybook/manager-api@npm:8.4.2": version: 8.4.2 resolution: "@storybook/manager-api@npm:8.4.2" @@ -11995,6 +12402,49 @@ __metadata: languageName: node linkType: hard +"@storybook/preset-create-react-app@npm:8.4.2": + version: 8.4.2 + resolution: "@storybook/preset-create-react-app@npm:8.4.2" + dependencies: + "@pmmmwh/react-refresh-webpack-plugin": ^0.5.1 + "@storybook/react-docgen-typescript-plugin": 1.0.6--canary.9.0c3f3b7.0 + "@types/semver": ^7.5.6 + pnp-webpack-plugin: ^1.7.0 + semver: ^7.5.4 + peerDependencies: + react-scripts: ">=5.0.0" + storybook: ^8.4.2 + checksum: cc807c466cfecb66b53ca0269d2f6154148603bb2c65d00611ab3e27a7b24c34cb3791175fc5f34395ebc7432e75b937223f5882c9ce38305d77be980707f5ea + languageName: node + linkType: hard + +"@storybook/preset-react-webpack@npm:8.4.2": + version: 8.4.2 + resolution: "@storybook/preset-react-webpack@npm:8.4.2" + dependencies: + "@storybook/core-webpack": 8.4.2 + "@storybook/react": 8.4.2 + "@storybook/react-docgen-typescript-plugin": 1.0.6--canary.9.0c3f3b7.0 + "@types/node": ^22.0.0 + "@types/semver": ^7.3.4 + find-up: ^5.0.0 + magic-string: ^0.30.5 + react-docgen: ^7.0.0 + resolve: ^1.22.8 + semver: ^7.3.7 + tsconfig-paths: ^4.2.0 + webpack: 5 + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + storybook: ^8.4.2 + peerDependenciesMeta: + typescript: + optional: true + checksum: ea5911e60d0067d97d85c10623a31a446a807653247c9e2b16dc64f065cfcc355beefef8d219372f50f93c9d2f7e1812fd23a55352656f8e3879e4201b6068ba + languageName: node + linkType: hard + "@storybook/preview-api@npm:8.4.2": version: 8.4.2 resolution: "@storybook/preview-api@npm:8.4.2" @@ -12013,6 +12463,24 @@ __metadata: languageName: node linkType: hard +"@storybook/react-docgen-typescript-plugin@npm:1.0.6--canary.9.0c3f3b7.0": + version: 1.0.6--canary.9.0c3f3b7.0 + resolution: "@storybook/react-docgen-typescript-plugin@npm:1.0.6--canary.9.0c3f3b7.0" + dependencies: + debug: ^4.1.1 + endent: ^2.0.1 + find-cache-dir: ^3.3.1 + flat-cache: ^3.0.4 + micromatch: ^4.0.2 + react-docgen-typescript: ^2.2.2 + tslib: ^2.0.0 + peerDependencies: + typescript: ">= 4.x" + webpack: ">= 4" + checksum: 38c59c1dd7f9cdf5533e5ffe1991034f563f8d33c59e3cd33fa86719c72f5fe922276fde50315dd24f23f225d1ad5f3a261ecf4c70e82522805d09782272faff + languageName: node + linkType: hard + "@storybook/react-dom-shim@npm:8.4.2": version: 8.4.2 resolution: "@storybook/react-dom-shim@npm:8.4.2" @@ -12106,6 +12574,26 @@ __metadata: languageName: node linkType: hard +"@storybook/react-webpack5@npm:8.4.2": + version: 8.4.2 + resolution: "@storybook/react-webpack5@npm:8.4.2" + dependencies: + "@storybook/builder-webpack5": 8.4.2 + "@storybook/preset-react-webpack": 8.4.2 + "@storybook/react": 8.4.2 + "@types/node": ^22.0.0 + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + storybook: ^8.4.2 + typescript: ">= 4.2.x" + peerDependenciesMeta: + typescript: + optional: true + checksum: deccd9278bc9a90aa9952056a65a7c0bf0faf106423dd82e8abdf9174cafece1b37be746f590fda090b11a849b7689b42a6adb13d87f11b4c13ad06ab331f893 + languageName: node + linkType: hard + "@storybook/react@npm:8.4.2": version: 8.4.2 resolution: "@storybook/react@npm:8.4.2" @@ -12156,6 +12644,24 @@ __metadata: languageName: node linkType: hard +"@storybook/test@npm:8.4.2": + version: 8.4.2 + resolution: "@storybook/test@npm:8.4.2" + dependencies: + "@storybook/csf": ^0.1.11 + "@storybook/global": ^5.0.0 + "@storybook/instrumenter": 8.4.2 + "@testing-library/dom": 10.4.0 + "@testing-library/jest-dom": 6.5.0 + "@testing-library/user-event": 14.5.2 + "@vitest/expect": 2.0.5 + "@vitest/spy": 2.0.5 + peerDependencies: + storybook: ^8.4.2 + checksum: 24dcd0c7bd28b6feb176116ba265c4b68444d479208175edfc2e42a4e0a344788b2c3d07710424e88e51b8ccad9cdc6a6a40f520ddcb43d3d4861149418d4d63 + languageName: node + linkType: hard + "@storybook/theming@npm:8.4.2": version: 8.4.2 resolution: "@storybook/theming@npm:8.4.2" @@ -12667,6 +13173,13 @@ __metadata: languageName: node linkType: hard +"@swc/core-darwin-arm64@npm:1.10.0": + version: 1.10.0 + resolution: "@swc/core-darwin-arm64@npm:1.10.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@swc/core-darwin-arm64@npm:1.3.72": version: 1.3.72 resolution: "@swc/core-darwin-arm64@npm:1.3.72" @@ -12674,10 +13187,10 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.9.2": - version: 1.9.2 - resolution: "@swc/core-darwin-arm64@npm:1.9.2" - conditions: os=darwin & cpu=arm64 +"@swc/core-darwin-x64@npm:1.10.0": + version: 1.10.0 + resolution: "@swc/core-darwin-x64@npm:1.10.0" + conditions: os=darwin & cpu=x64 languageName: node linkType: hard @@ -12688,10 +13201,10 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.9.2": - version: 1.9.2 - resolution: "@swc/core-darwin-x64@npm:1.9.2" - conditions: os=darwin & cpu=x64 +"@swc/core-linux-arm-gnueabihf@npm:1.10.0": + version: 1.10.0 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.10.0" + conditions: os=linux & cpu=arm languageName: node linkType: hard @@ -12702,10 +13215,10 @@ __metadata: languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.9.2": - version: 1.9.2 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.9.2" - conditions: os=linux & cpu=arm +"@swc/core-linux-arm64-gnu@npm:1.10.0": + version: 1.10.0 + resolution: "@swc/core-linux-arm64-gnu@npm:1.10.0" + conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard @@ -12716,10 +13229,10 @@ __metadata: languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.9.2": - version: 1.9.2 - resolution: "@swc/core-linux-arm64-gnu@npm:1.9.2" - conditions: os=linux & cpu=arm64 & libc=glibc +"@swc/core-linux-arm64-musl@npm:1.10.0": + version: 1.10.0 + resolution: "@swc/core-linux-arm64-musl@npm:1.10.0" + conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard @@ -12730,10 +13243,10 @@ __metadata: languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.9.2": - version: 1.9.2 - resolution: "@swc/core-linux-arm64-musl@npm:1.9.2" - conditions: os=linux & cpu=arm64 & libc=musl +"@swc/core-linux-x64-gnu@npm:1.10.0": + version: 1.10.0 + resolution: "@swc/core-linux-x64-gnu@npm:1.10.0" + conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard @@ -12744,10 +13257,10 @@ __metadata: languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.9.2": - version: 1.9.2 - resolution: "@swc/core-linux-x64-gnu@npm:1.9.2" - conditions: os=linux & cpu=x64 & libc=glibc +"@swc/core-linux-x64-musl@npm:1.10.0": + version: 1.10.0 + resolution: "@swc/core-linux-x64-musl@npm:1.10.0" + conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard @@ -12758,10 +13271,10 @@ __metadata: languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.9.2": - version: 1.9.2 - resolution: "@swc/core-linux-x64-musl@npm:1.9.2" - conditions: os=linux & cpu=x64 & libc=musl +"@swc/core-win32-arm64-msvc@npm:1.10.0": + version: 1.10.0 + resolution: "@swc/core-win32-arm64-msvc@npm:1.10.0" + conditions: os=win32 & cpu=arm64 languageName: node linkType: hard @@ -12772,10 +13285,10 @@ __metadata: languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.9.2": - version: 1.9.2 - resolution: "@swc/core-win32-arm64-msvc@npm:1.9.2" - conditions: os=win32 & cpu=arm64 +"@swc/core-win32-ia32-msvc@npm:1.10.0": + version: 1.10.0 + resolution: "@swc/core-win32-ia32-msvc@npm:1.10.0" + conditions: os=win32 & cpu=ia32 languageName: node linkType: hard @@ -12786,10 +13299,10 @@ __metadata: languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.9.2": - version: 1.9.2 - resolution: "@swc/core-win32-ia32-msvc@npm:1.9.2" - conditions: os=win32 & cpu=ia32 +"@swc/core-win32-x64-msvc@npm:1.10.0": + version: 1.10.0 + resolution: "@swc/core-win32-x64-msvc@npm:1.10.0" + conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -12800,13 +13313,6 @@ __metadata: languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.9.2": - version: 1.9.2 - resolution: "@swc/core-win32-x64-msvc@npm:1.9.2" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - "@swc/core@npm:1.3.72": version: 1.3.72 resolution: "@swc/core@npm:1.3.72" @@ -12852,21 +13358,21 @@ __metadata: linkType: hard "@swc/core@npm:^1.5.25, @swc/core@npm:^1.7.21": - version: 1.9.2 - resolution: "@swc/core@npm:1.9.2" - dependencies: - "@swc/core-darwin-arm64": 1.9.2 - "@swc/core-darwin-x64": 1.9.2 - "@swc/core-linux-arm-gnueabihf": 1.9.2 - "@swc/core-linux-arm64-gnu": 1.9.2 - "@swc/core-linux-arm64-musl": 1.9.2 - "@swc/core-linux-x64-gnu": 1.9.2 - "@swc/core-linux-x64-musl": 1.9.2 - "@swc/core-win32-arm64-msvc": 1.9.2 - "@swc/core-win32-ia32-msvc": 1.9.2 - "@swc/core-win32-x64-msvc": 1.9.2 + version: 1.10.0 + resolution: "@swc/core@npm:1.10.0" + dependencies: + "@swc/core-darwin-arm64": 1.10.0 + "@swc/core-darwin-x64": 1.10.0 + "@swc/core-linux-arm-gnueabihf": 1.10.0 + "@swc/core-linux-arm64-gnu": 1.10.0 + "@swc/core-linux-arm64-musl": 1.10.0 + "@swc/core-linux-x64-gnu": 1.10.0 + "@swc/core-linux-x64-musl": 1.10.0 + "@swc/core-win32-arm64-msvc": 1.10.0 + "@swc/core-win32-ia32-msvc": 1.10.0 + "@swc/core-win32-x64-msvc": 1.10.0 "@swc/counter": ^0.1.3 - "@swc/types": ^0.1.15 + "@swc/types": ^0.1.17 peerDependencies: "@swc/helpers": "*" dependenciesMeta: @@ -12893,7 +13399,7 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: 325afca1473e371804cc420d096553a0c6b19d01296b46b23e3b75a797c8b139c712ad79bc5c876cfc6d7bd6d60014a9f81286a2e888e94f0dec70903893f0b6 + checksum: c86b7ead4f71f8b2065b4d11f979d49e248a0a721aac0469c4f3a209de3a71a7f1dca604559f034aeabd3ea9e00b7a574a7d8fc08fad786242b160098f2c7b3b languageName: node linkType: hard @@ -12932,12 +13438,12 @@ __metadata: languageName: node linkType: hard -"@swc/types@npm:^0.1.15": - version: 0.1.15 - resolution: "@swc/types@npm:0.1.15" +"@swc/types@npm:^0.1.17": + version: 0.1.17 + resolution: "@swc/types@npm:0.1.17" dependencies: "@swc/counter": ^0.1.3 - checksum: 19889eed42d28f5dcef7c16f3b0cf4375890984b106aca46d9455d1f5ba364156d206a8e1f73962718ee408ff9e460b84aaa79025bf8dc30e0d6ded471e1e2d2 + checksum: 6cc87b8ddfb540096abdf40bc29742df0b7d068f97c1ce6c32cd1b7073cde263ed7bc3bae1fba7bf0e1a0f5d63336e9fa092e05a54f6d9b3570df956d2acaff6 languageName: node linkType: hard @@ -14460,6 +14966,22 @@ __metadata: languageName: node linkType: hard +"@testing-library/dom@npm:10.4.0": + version: 10.4.0 + resolution: "@testing-library/dom@npm:10.4.0" + dependencies: + "@babel/code-frame": ^7.10.4 + "@babel/runtime": ^7.12.5 + "@types/aria-query": ^5.0.1 + aria-query: 5.3.0 + chalk: ^4.1.0 + dom-accessibility-api: ^0.5.9 + lz-string: ^1.5.0 + pretty-format: ^27.0.2 + checksum: bb128b90be0c8cd78c5f5e67aa45f53de614cc048a2b50b230e736ec710805ac6c73375af354b83c74d710b3928d52b83a273a4cb89de4eb3efe49e91e706837 + languageName: node + linkType: hard + "@testing-library/dom@npm:7.31.2, @testing-library/dom@npm:^7.11.0": version: 7.31.2 resolution: "@testing-library/dom@npm:7.31.2" @@ -14509,6 +15031,21 @@ __metadata: languageName: node linkType: hard +"@testing-library/jest-dom@npm:6.5.0": + version: 6.5.0 + resolution: "@testing-library/jest-dom@npm:6.5.0" + dependencies: + "@adobe/css-tools": ^4.4.0 + aria-query: ^5.0.0 + chalk: ^3.0.0 + css.escape: ^1.5.1 + dom-accessibility-api: ^0.6.3 + lodash: ^4.17.21 + redent: ^3.0.0 + checksum: c2d14103ebe3358852ec527ff7512f64207a39932b2f7b6dff7e73ba91296b01a71bad9a9584b6ee010681380a906c1740af50470adc6db660e1c7585d012ebf + languageName: node + linkType: hard + "@testing-library/jest-native@npm:5.4.2": version: 5.4.2 resolution: "@testing-library/jest-native@npm:5.4.2" @@ -14588,6 +15125,15 @@ __metadata: languageName: node linkType: hard +"@testing-library/user-event@npm:14.5.2": + version: 14.5.2 + resolution: "@testing-library/user-event@npm:14.5.2" + peerDependencies: + "@testing-library/dom": ">=7.21.4" + checksum: d76937dffcf0082fbf3bb89eb2b81a31bf5448048dd61c33928c5f10e33a58e035321d39145cefd469bb5a499c68a5b4086b22f1a44e3e7c7e817dc5f6782867 + languageName: node + linkType: hard + "@tootallnate/once@npm:1": version: 1.1.2 resolution: "@tootallnate/once@npm:1.1.2" @@ -14701,16 +15247,16 @@ __metadata: languageName: node linkType: hard -"@types/babel__core@npm:^7.0.0, @types/babel__core@npm:^7.1.14": - version: 7.1.20 - resolution: "@types/babel__core@npm:7.1.20" +"@types/babel__core@npm:^7.0.0, @types/babel__core@npm:^7.1.14, @types/babel__core@npm:^7.18.0": + version: 7.20.5 + resolution: "@types/babel__core@npm:7.20.5" dependencies: - "@babel/parser": ^7.1.0 - "@babel/types": ^7.0.0 + "@babel/parser": ^7.20.7 + "@babel/types": ^7.20.7 "@types/babel__generator": "*" "@types/babel__template": "*" "@types/babel__traverse": "*" - checksum: a09c4f0456552547a5b8a5a009a3daec4d362f622168f8e08bda0ded2da0a65ab0b1642e23c433b3616721f5701dc34a996c5bde5baeaea53eda98f438043f2c + checksum: a3226f7930b635ee7a5e72c8d51a357e799d19cbf9d445710fa39ab13804f79ab1a54b72ea7d8e504659c7dfc50675db974b526142c754398d7413aa4bc30845 languageName: node linkType: hard @@ -14733,12 +15279,12 @@ __metadata: languageName: node linkType: hard -"@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.4, @types/babel__traverse@npm:^7.0.6": - version: 7.20.4 - resolution: "@types/babel__traverse@npm:7.20.4" +"@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.4, @types/babel__traverse@npm:^7.0.6, @types/babel__traverse@npm:^7.18.0": + version: 7.20.6 + resolution: "@types/babel__traverse@npm:7.20.6" dependencies: "@babel/types": ^7.20.7 - checksum: f044ba80e00d07e46ee917c44f96cfc268fcf6d3871f7dfb8db8d3c6dab1508302f3e6bc508352a4a3ae627d2522e3fc500fa55907e0410a08e2e0902a8f3576 + checksum: 2bdc65eb62232c2d5c1086adeb0c31e7980e6fd7e50a3483b4a724a1a1029c84d9cb59749cf8de612f9afa2bc14c85b8f50e64e21f8a4398fa77eb9059a4283c languageName: node linkType: hard @@ -15173,6 +15719,13 @@ __metadata: languageName: node linkType: hard +"@types/doctrine@npm:^0.0.9": + version: 0.0.9 + resolution: "@types/doctrine@npm:0.0.9" + checksum: 3909eaca42e7386b2ab866f082b78da3e00718d2fa323597e254feb0556c678b41f2c490729067433630083ac9c806ec6ae1e146754f7f8ba7d3e43ed68d6500 + languageName: node + linkType: hard + "@types/dom-screen-wake-lock@npm:^1.0.0": version: 1.0.3 resolution: "@types/dom-screen-wake-lock@npm:1.0.3" @@ -15180,30 +15733,30 @@ __metadata: languageName: node linkType: hard -"@types/eslint-scope@npm:^3.7.3": - version: 3.7.4 - resolution: "@types/eslint-scope@npm:3.7.4" +"@types/eslint-scope@npm:^3.7.3, @types/eslint-scope@npm:^3.7.7": + version: 3.7.7 + resolution: "@types/eslint-scope@npm:3.7.7" dependencies: "@types/eslint": "*" "@types/estree": "*" - checksum: ea6a9363e92f301cd3888194469f9ec9d0021fe0a397a97a6dd689e7545c75de0bd2153dfb13d3ab532853a278b6572c6f678ce846980669e41029d205653460 + checksum: e2889a124aaab0b89af1bab5959847c5bec09809209255de0e63b9f54c629a94781daa04adb66bffcdd742f5e25a17614fb933965093c0eea64aacda4309380e languageName: node linkType: hard "@types/eslint@npm:*, @types/eslint@npm:^7.29.0 || ^8.4.1": - version: 8.44.7 - resolution: "@types/eslint@npm:8.44.7" + version: 8.56.12 + resolution: "@types/eslint@npm:8.56.12" dependencies: "@types/estree": "*" "@types/json-schema": "*" - checksum: 72a52f74477fbe7cc95ad290b491f51f0bc547cb7ea3672c68da3ffd3fb21ba86145bc36823a37d0a186caedeaee15b2d2a6b4c02c6c55819ff746053bd28310 + checksum: 0f7710ee02a256c499514251f527f84de964bb29487db840408e4cde79283124a38935597636d2265756c34dd1d902e1b00ae78930d4a0b55111909cb7b80d84 languageName: node linkType: hard -"@types/estree@npm:*, @types/estree@npm:^1.0.5": - version: 1.0.5 - resolution: "@types/estree@npm:1.0.5" - checksum: dd8b5bed28e6213b7acd0fb665a84e693554d850b0df423ac8076cc3ad5823a6bc26b0251d080bdc545af83179ede51dd3f6fa78cad2c46ed1f29624ddf3e41a +"@types/estree@npm:*, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.5, @types/estree@npm:^1.0.6": + version: 1.0.6 + resolution: "@types/estree@npm:1.0.6" + checksum: 8825d6e729e16445d9a1dd2fb1db2edc5ed400799064cd4d028150701031af012ba30d6d03fe9df40f4d7a437d0de6d2b256020152b7b09bde9f2e420afdffd9 languageName: node linkType: hard @@ -15280,11 +15833,11 @@ __metadata: linkType: hard "@types/graceful-fs@npm:^4.1.2, @types/graceful-fs@npm:^4.1.3": - version: 4.1.5 - resolution: "@types/graceful-fs@npm:4.1.5" + version: 4.1.9 + resolution: "@types/graceful-fs@npm:4.1.9" dependencies: "@types/node": "*" - checksum: d076bb61f45d0fc42dee496ef8b1c2f8742e15d5e47e90e20d0243386e426c04d4efd408a48875ab432f7960b4ce3414db20ed0fbbfc7bcc89d84e574f6e045a + checksum: 79d746a8f053954bba36bd3d94a90c78de995d126289d656fb3271dd9f1229d33f678da04d10bce6be440494a5a73438e2e363e92802d16b8315b051036c5256 languageName: node linkType: hard @@ -15458,6 +16011,13 @@ __metadata: languageName: node linkType: hard +"@types/mdx@npm:^2.0.0": + version: 2.0.13 + resolution: "@types/mdx@npm:2.0.13" + checksum: 195137b548e75a85f0558bb1ca5088aff1c01ae0fc64454da06085b7513a043356d0bb51ed559d3cbc7ad724ccd8cef2a7d07d014b89a47a74dff8875ceb3b15 + languageName: node + linkType: hard + "@types/mime@npm:*": version: 3.0.1 resolution: "@types/mime@npm:3.0.1" @@ -15528,12 +16088,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:>=12.12.47, @types/node@npm:>=13.7.0": - version: 22.7.4 - resolution: "@types/node@npm:22.7.4" +"@types/node@npm:*, @types/node@npm:>=12.12.47, @types/node@npm:>=13.7.0, @types/node@npm:^22.0.0": + version: 22.10.1 + resolution: "@types/node@npm:22.10.1" dependencies: - undici-types: ~6.19.2 - checksum: a3f4154147639369aed08fe6f8d62eff637cf87b187bb252d7bbccdc82884626007af424b08a653c53f2182adfa0340001b4888cb7cbb942cef351210fc742a5 + undici-types: ~6.20.0 + checksum: 5a9b81500f288a8fb757b61bd939f99f72b6cb59347a5bae52dd1c2c87100ebbaa9da4256ef3cb9add2090e8704cda1d9a1ffc14ccd5db47a6466c8bae10ebcb languageName: node linkType: hard @@ -15612,9 +16172,9 @@ __metadata: linkType: hard "@types/prettier@npm:^2.1.1, @types/prettier@npm:^2.1.5": - version: 2.7.1 - resolution: "@types/prettier@npm:2.7.1" - checksum: 5e3f58e229d6c73b5f5cae2e8f96c1c4a5b5805f83459e17a045ba8e96152b1d38e86b63e3172fb159dac923388699660862b75b2d37e54220805f0e691e26f1 + version: 2.7.3 + resolution: "@types/prettier@npm:2.7.3" + checksum: 705384209cea6d1433ff6c187c80dcc0b95d99d5c5ce21a46a9a58060c527973506822e428789d842761e0280d25e3359300f017fbe77b9755bc772ab3dc2f83 languageName: node linkType: hard @@ -15626,9 +16186,9 @@ __metadata: linkType: hard "@types/q@npm:^1.5.1": - version: 1.5.5 - resolution: "@types/q@npm:1.5.5" - checksum: 3bd386fb97a0e5f1ce1ed7a14e39b60e469b5ca9d920a7f69e0cdb58d22c0f5bdd16637d8c3a5bfeda76663c023564dd47a65389ee9aaabd65aee54803d5ba45 + version: 1.5.8 + resolution: "@types/q@npm:1.5.8" + checksum: ff3b7f09c2746d068dee8d39501f09dbf71728c4facdc9cb0e266ea6615ad97e61267c0606ab3da88d11ef1609ce904cef45a9c56b2b397f742388d7f15bb740 languageName: node linkType: hard @@ -15816,6 +16376,13 @@ __metadata: languageName: node linkType: hard +"@types/resolve@npm:^1.20.2": + version: 1.20.6 + resolution: "@types/resolve@npm:1.20.6" + checksum: dc35f5517606b6687cd971c0281ac58bdee2c50c051b030f04647d3991688be2259c304ee97e5b5d4b9936072c36767eb5933b54611a407d6557972bb6fea4f6 + languageName: node + linkType: hard + "@types/responselike@npm:^1.0.0": version: 1.0.0 resolution: "@types/responselike@npm:1.0.0" @@ -15855,10 +16422,10 @@ __metadata: languageName: node linkType: hard -"@types/semver@npm:^7.3.12, @types/semver@npm:^7.5.0": - version: 7.5.6 - resolution: "@types/semver@npm:7.5.6" - checksum: 563a0120ec0efcc326567db2ed920d5d98346f3638b6324ea6b50222b96f02a8add3c51a916b6897b51523aad8ac227d21d3dcf8913559f1bfc6c15b14d23037 +"@types/semver@npm:^7.3.12, @types/semver@npm:^7.3.4, @types/semver@npm:^7.5.0, @types/semver@npm:^7.5.6": + version: 7.5.8 + resolution: "@types/semver@npm:7.5.8" + checksum: ea6f5276f5b84c55921785a3a27a3cd37afee0111dfe2bcb3e03c31819c197c782598f17f0b150a69d453c9584cd14c4c4d7b9a55d2c5e6cacd4d66fdb3b3663 languageName: node linkType: hard @@ -16019,6 +16586,13 @@ __metadata: languageName: node linkType: hard +"@types/uuid@npm:^9.0.1": + version: 9.0.8 + resolution: "@types/uuid@npm:9.0.8" + checksum: b8c60b7ba8250356b5088302583d1704a4e1a13558d143c549c408bf8920535602ffc12394ede77f8a8083511b023704bc66d1345792714002bfa261b17c5275 + languageName: node + linkType: hard + "@types/warning@npm:^3.0.0": version: 3.0.3 resolution: "@types/warning@npm:3.0.3" @@ -16151,13 +16725,13 @@ __metadata: linkType: hard "@typescript-eslint/experimental-utils@npm:^5.0.0": - version: 5.30.7 - resolution: "@typescript-eslint/experimental-utils@npm:5.30.7" + version: 5.62.0 + resolution: "@typescript-eslint/experimental-utils@npm:5.62.0" dependencies: - "@typescript-eslint/utils": 5.30.7 + "@typescript-eslint/utils": 5.62.0 peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: 3417491dc04cc1b81809d6727133387bb75dca1f6bec1bce0ac2c10855e39584244c3b3c971c1569a4ccd000b28f77a38103013284895969e3a7d4dd060c1aff + checksum: ce55d9f74eac5cb94d66d5db9ead9a5d734f4301519fb5956a57f4b405a5318a115b0316195a3c039e0111489138680411709cb769085d71e1e1db1376ea0949 languageName: node linkType: hard @@ -16196,16 +16770,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:5.30.7": - version: 5.30.7 - resolution: "@typescript-eslint/scope-manager@npm:5.30.7" - dependencies: - "@typescript-eslint/types": 5.30.7 - "@typescript-eslint/visitor-keys": 5.30.7 - checksum: 434ce7a13a8f3bffae2af2b7fe19bab6e490c78114584212519f50cd1b91fbdcddc8ad93bdb3cacdc8cecca5a8c5d2eb606557e66bd3fcd9d3040846846c22ff - languageName: node - linkType: hard - "@typescript-eslint/scope-manager@npm:5.62.0": version: 5.62.0 resolution: "@typescript-eslint/scope-manager@npm:5.62.0" @@ -16226,16 +16790,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.15.0": - version: 8.15.0 - resolution: "@typescript-eslint/scope-manager@npm:8.15.0" - dependencies: - "@typescript-eslint/types": 8.15.0 - "@typescript-eslint/visitor-keys": 8.15.0 - checksum: a7f89a2ee39d0abeed5f18f675e152032d968110e7bfc3c08ed71ada1d9e7fd5addb8f3c4f6871da0016c859141a6c36f16a9c0ff85d63f94740f1d182123b06 - languageName: node - linkType: hard - "@typescript-eslint/type-utils@npm:5.62.0": version: 5.62.0 resolution: "@typescript-eslint/type-utils@npm:5.62.0" @@ -16277,13 +16831,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:5.30.7": - version: 5.30.7 - resolution: "@typescript-eslint/types@npm:5.30.7" - checksum: 2f6345bf0e2e9f392c1f62a5f96c630d4565574230a000508d923444229e51c1a05e07cef042935ca30f4f35755dbf3871b8b9da808911f578d63e6a4b897b79 - languageName: node - linkType: hard - "@typescript-eslint/types@npm:5.62.0": version: 5.62.0 resolution: "@typescript-eslint/types@npm:5.62.0" @@ -16298,31 +16845,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:8.15.0": - version: 8.15.0 - resolution: "@typescript-eslint/types@npm:8.15.0" - checksum: e44b3bbb928dfa56a982a74fda463338520a31696665c38714d40c2c1fe92fdc6cae4eff3d90b8d28c5d2d814e492042282959c3cbe6c01a773990daa1a64712 - languageName: node - linkType: hard - -"@typescript-eslint/typescript-estree@npm:5.30.7": - version: 5.30.7 - resolution: "@typescript-eslint/typescript-estree@npm:5.30.7" - dependencies: - "@typescript-eslint/types": 5.30.7 - "@typescript-eslint/visitor-keys": 5.30.7 - debug: ^4.3.4 - globby: ^11.1.0 - is-glob: ^4.0.3 - semver: ^7.3.7 - tsutils: ^3.21.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 7cff83a9b9c91a89bcbb677d539b7122b2a423a66f575364858b4635d7e53a25b9329cd20a5adfb732758a41d1c6801d4bfa3eb798a192f351aafb11eedc58b6 - languageName: node - linkType: hard - "@typescript-eslint/typescript-estree@npm:5.62.0, @typescript-eslint/typescript-estree@npm:^5.55.0": version: 5.62.0 resolution: "@typescript-eslint/typescript-estree@npm:5.62.0" @@ -16360,25 +16882,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:8.15.0": - version: 8.15.0 - resolution: "@typescript-eslint/typescript-estree@npm:8.15.0" - dependencies: - "@typescript-eslint/types": 8.15.0 - "@typescript-eslint/visitor-keys": 8.15.0 - debug: ^4.3.4 - fast-glob: ^3.3.2 - is-glob: ^4.0.3 - minimatch: ^9.0.4 - semver: ^7.6.0 - ts-api-utils: ^1.3.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 4adfa103ec28ccc5ad7783f0ead2de495fb3510a8fbc8779af83908124163ed07ecfd60bca8f53cde8f88420091b5bfde953ec39461f6560d6bf35e048c94ed2 - languageName: node - linkType: hard - "@typescript-eslint/typescript-estree@npm:^4.33.0": version: 4.33.0 resolution: "@typescript-eslint/typescript-estree@npm:4.33.0" @@ -16397,23 +16900,7 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:5.30.7": - version: 5.30.7 - resolution: "@typescript-eslint/utils@npm:5.30.7" - dependencies: - "@types/json-schema": ^7.0.9 - "@typescript-eslint/scope-manager": 5.30.7 - "@typescript-eslint/types": 5.30.7 - "@typescript-eslint/typescript-estree": 5.30.7 - eslint-scope: ^5.1.1 - eslint-utils: ^3.0.0 - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: 77b0baf069f70290214294d74fdf7c46a7ddeab322ef53f65766b0c8e59f0e6f8074beb19233be34faca5beb390ac1b932dd1c983337355674c4437b4b1e2b44 - languageName: node - linkType: hard - -"@typescript-eslint/utils@npm:5.62.0, @typescript-eslint/utils@npm:^5.10.0, @typescript-eslint/utils@npm:^5.58.0": +"@typescript-eslint/utils@npm:5.62.0, @typescript-eslint/utils@npm:^5.10.0, @typescript-eslint/utils@npm:^5.58.0, @typescript-eslint/utils@npm:^5.62.0": version: 5.62.0 resolution: "@typescript-eslint/utils@npm:5.62.0" dependencies: @@ -16448,23 +16935,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:^8.8.1": - version: 8.15.0 - resolution: "@typescript-eslint/utils@npm:8.15.0" - dependencies: - "@eslint-community/eslint-utils": ^4.4.0 - "@typescript-eslint/scope-manager": 8.15.0 - "@typescript-eslint/types": 8.15.0 - "@typescript-eslint/typescript-estree": 8.15.0 - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 0101e0a09e9e31b484650f51b5bd2673e16df552d6763cea183112ceb3283da602dbeff4c6de1c17d8b5b1591114a438a489bd52f80804e4721cb6308c6bf52f - languageName: node - linkType: hard - "@typescript-eslint/visitor-keys@npm:4.33.0": version: 4.33.0 resolution: "@typescript-eslint/visitor-keys@npm:4.33.0" @@ -16475,16 +16945,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:5.30.7": - version: 5.30.7 - resolution: "@typescript-eslint/visitor-keys@npm:5.30.7" - dependencies: - "@typescript-eslint/types": 5.30.7 - eslint-visitor-keys: ^3.3.0 - checksum: f322972aeda3143d4c24826436357937131f7fbad102d48cfa6dfca70ac245f93b20cf7beb5f1809bda4fe8f454676a6cabf8f73e39af6724076f2b2c213ee80 - languageName: node - linkType: hard - "@typescript-eslint/visitor-keys@npm:5.62.0": version: 5.62.0 resolution: "@typescript-eslint/visitor-keys@npm:5.62.0" @@ -16505,20 +16965,10 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.15.0": - version: 8.15.0 - resolution: "@typescript-eslint/visitor-keys@npm:8.15.0" - dependencies: - "@typescript-eslint/types": 8.15.0 - eslint-visitor-keys: ^4.2.0 - checksum: 393a5ff4e796224a8950c18ac7db9bfa1ca50bed4e0d5d6f521dc0f8c65d55c6ddca5da5926f61a4af3aa51f7f0eb195e27f4b414a1daf9b0fac88d4d69cf0f3 - languageName: node - linkType: hard - "@ungap/structured-clone@npm:^1.2.0": - version: 1.2.0 - resolution: "@ungap/structured-clone@npm:1.2.0" - checksum: 4f656b7b4672f2ce6e272f2427d8b0824ed11546a601d8d5412b9d7704e83db38a8d9f402ecdf2b9063fc164af842ad0ec4a55819f621ed7e7ea4d1efcc74524 + version: 1.2.1 + resolution: "@ungap/structured-clone@npm:1.2.1" + checksum: 1e3b9fef293118861f0b2159b3695fc7f3793c0707095888ebb3ac7183f78c390e68f04cd4b4cf9ac979ae0da454505e08b3aae887cdd639609a3fe529e19e59 languageName: node linkType: hard @@ -16594,7 +17044,7 @@ __metadata: eslint-plugin-react-native: 4.1.0 eslint-plugin-security: 1.5.0 eslint-plugin-spellcheck: 0.0.20 - eslint-plugin-storybook: 0.11.1 + eslint-plugin-storybook: 0.8.0 eslint-plugin-unused-imports: 2.0.0 jest: 29.7.0 typescript: 5.3.3 @@ -16646,6 +17096,7 @@ __metadata: clean-webpack-plugin: 4.0.0 concurrently: 8.2.2 copy-webpack-plugin: 11.0.0 + css-loader: 6.11.0 dotenv-webpack: 8.0.1 esbuild-loader: 3.2.0 eslint: 8.44.0 @@ -16677,6 +17128,7 @@ __metadata: redux-saga: 1.2.2 serve: 14.2.4 statsig-js: 4.41.0 + style-loader: 3.3.2 swc-loader: 0.2.6 symbol-observable: 4.0.0 tamagui-loader: 1.114.4 @@ -16702,6 +17154,7 @@ __metadata: "@amplitude/analytics-browser": 1.12.1 "@apollo/client": 3.10.4 "@babel/preset-env": 7.23.3 + "@chromatic-com/storybook": 3.2.2 "@cloudflare/workers-types": 4.20231025.0 "@craco/craco": 7.1.0 "@crowdin/cli": 3.14.0 @@ -16725,6 +17178,15 @@ __metadata: "@sentry/core": 7.80.0 "@sentry/react": 7.80.0 "@sentry/types": 7.80.0 + "@storybook/addon-essentials": 8.4.2 + "@storybook/addon-interactions": 8.4.2 + "@storybook/addon-onboarding": 8.4.2 + "@storybook/blocks": 8.4.2 + "@storybook/preset-create-react-app": 8.4.2 + "@storybook/react": 8.4.2 + "@storybook/react-webpack5": 8.4.2 + "@storybook/test": 8.4.2 + "@svgr/webpack": 8.0.1 "@swc/core": 1.3.72 "@swc/jest": 0.2.29 "@swc/plugin-styled-components": 1.5.97 @@ -16773,7 +17235,7 @@ __metadata: "@uniswap/permit2-sdk": 1.3.0 "@uniswap/redux-multicall": 1.1.8 "@uniswap/router-sdk": 1.15.0 - "@uniswap/sdk-core": 6.0.0 + "@uniswap/sdk-core": 6.1.0 "@uniswap/smart-order-router": 3.17.3 "@uniswap/token-lists": 1.0.0-beta.33 "@uniswap/uniswapx-sdk": 2.1.0-beta.18 @@ -16814,12 +17276,14 @@ __metadata: cypress-hardhat: 2.5.3 d3: 7.6.1 date-fns: 2.30.0 + depcheck: 1.4.7 dotenv: 16.0.3 dotenv-cli: 7.1.0 esbuild-register: 3.6.0 eslint: 8.44.0 eslint-plugin-import: 2.27.5 eslint-plugin-rulesdir: 0.2.2 + eslint-plugin-storybook: 0.8.0 ethers: 5.7.2 expo-crypto: 12.8.1 fancy-canvas: 2.1.0 @@ -16853,6 +17317,7 @@ __metadata: polyfill-object.fromentries: 1.0.1 postinstall-postinstall: 2.1.0 process: 0.11.10 + prop-types: 15.8.1 qs: 6.11.0 query-string: 7.1.3 rc-slider: 10.4.0 @@ -16883,6 +17348,7 @@ __metadata: source-map-explorer: 2.5.3 start-server-and-test: 2.0.0 statsig-react: 1.32.0 + storybook: 8.4.2 styled-components: 5.3.11 swc-loader: 0.2.6 tamagui: 1.114.4 @@ -16890,6 +17356,7 @@ __metadata: terser-webpack-plugin: 5.3.9 tiny-invariant: 1.3.1 ts-jest: 29.2.5 + ts-loader: 9.5.1 tsafe: 1.6.4 typed-redux-saga: 1.5.0 typescript: 5.3.3 @@ -16993,6 +17460,7 @@ __metadata: "@storybook/react": 8.4.2 "@storybook/react-native": 8.4.2 "@tamagui/babel-plugin": 1.114.4 + "@tanstack/react-query": 5.51.16 "@testing-library/react-native": 11.5.0 "@types/redux-mock-store": 1.0.6 "@uniswap/analytics": 1.7.0 @@ -17000,7 +17468,7 @@ __metadata: "@uniswap/client-explore": 0.0.12 "@uniswap/eslint-config": "workspace:^" "@uniswap/ethers-rs-mobile": 0.0.5 - "@uniswap/sdk-core": 6.0.0 + "@uniswap/sdk-core": 6.1.0 "@walletconnect/core": 2.17.1 "@walletconnect/react-native-compat": 2.17.1 "@walletconnect/types": 2.17.1 @@ -17136,9 +17604,9 @@ __metadata: languageName: node linkType: hard -"@uniswap/sdk-core@npm:6.0.0": - version: 6.0.0 - resolution: "@uniswap/sdk-core@npm:6.0.0" +"@uniswap/sdk-core@npm:6.1.0": + version: 6.1.0 + resolution: "@uniswap/sdk-core@npm:6.1.0" dependencies: "@ethersproject/address": ^5.0.2 "@ethersproject/bytes": ^5.7.0 @@ -17149,7 +17617,7 @@ __metadata: jsbi: ^3.1.4 tiny-invariant: ^1.1.0 toformat: ^2.0.0 - checksum: 395808ddb8425a98226fd5d19783067c29bdda6c8e6b05032a57a6c66db58870f8f6766b0d1c93bd9e15e4c646f283712bea8cb177aca7818234c3b3c743db2d + checksum: 0bd5a60239a4b41fa70119028eb65740a65c0b6a790fa599951b2098c7ee2cfcf239d4da80c00dfa16a4444eb79557aed7fb9ac9b50b2fdc20a568839a1958c8 languageName: node linkType: hard @@ -17599,6 +18067,68 @@ __metadata: languageName: node linkType: hard +"@vitest/expect@npm:2.0.5": + version: 2.0.5 + resolution: "@vitest/expect@npm:2.0.5" + dependencies: + "@vitest/spy": 2.0.5 + "@vitest/utils": 2.0.5 + chai: ^5.1.1 + tinyrainbow: ^1.2.0 + checksum: 0c65eb24c2fd9ef5735d1e65dc8fee59936e6cab1d6ab24a95e014b8337be5598242fceae4e8ec2974e2ae70a30c1906ad41208bf6de6cdf2043594cdb65e627 + languageName: node + linkType: hard + +"@vitest/pretty-format@npm:2.0.5": + version: 2.0.5 + resolution: "@vitest/pretty-format@npm:2.0.5" + dependencies: + tinyrainbow: ^1.2.0 + checksum: d60346001180e5bb3c53be4b4d0b6d9352648b066641d5aba7b97d7c97a8e252dc934204d58818330262a65f07127455fc5f3b5f7e3647c60f6ff302a725733b + languageName: node + linkType: hard + +"@vitest/pretty-format@npm:2.1.8": + version: 2.1.8 + resolution: "@vitest/pretty-format@npm:2.1.8" + dependencies: + tinyrainbow: ^1.2.0 + checksum: 2214ca317a19220a5f308a4e77fe403fa091c2f006d1f5b1bd91e8fad6e167db2fdc7882e564da3518d5b2cd9dedb1e97067bb666a820519c54f1c26ac9b0c5a + languageName: node + linkType: hard + +"@vitest/spy@npm:2.0.5": + version: 2.0.5 + resolution: "@vitest/spy@npm:2.0.5" + dependencies: + tinyspy: ^3.0.0 + checksum: a010dec99146832a2586c639fccf533b194482f6f25ffb2d64367598a4e77d094aedd3d82cdb55fc1a3971649577a039513ccf8dc1571492e5982482c530c7b9 + languageName: node + linkType: hard + +"@vitest/utils@npm:2.0.5": + version: 2.0.5 + resolution: "@vitest/utils@npm:2.0.5" + dependencies: + "@vitest/pretty-format": 2.0.5 + estree-walker: ^3.0.3 + loupe: ^3.1.1 + tinyrainbow: ^1.2.0 + checksum: 6867556dd7e376437e454b96c7e596ec16e141fb00b002b6ce435611ab3d9d1e3f38ebf48b1fc49f4c97f9754ed37abb602de8bf122f4ac0de621a4dbe0a314e + languageName: node + linkType: hard + +"@vitest/utils@npm:^2.1.1": + version: 2.1.8 + resolution: "@vitest/utils@npm:2.1.8" + dependencies: + "@vitest/pretty-format": 2.1.8 + loupe: ^3.1.2 + tinyrainbow: ^1.2.0 + checksum: 711e7998ba9785880ed416d08b478e2b881cd218d37c3d773b26477adaa6aab91758e01ac039f839175f446111118fb5aa041317b619eeeb05537e3912159eb7 + languageName: node + linkType: hard + "@vue/compiler-core@npm:3.3.13": version: 3.3.13 resolution: "@vue/compiler-core@npm:3.3.13" @@ -18134,154 +18664,154 @@ __metadata: languageName: node linkType: hard -"@webassemblyjs/ast@npm:1.11.6, @webassemblyjs/ast@npm:^1.11.5": - version: 1.11.6 - resolution: "@webassemblyjs/ast@npm:1.11.6" +"@webassemblyjs/ast@npm:1.14.1, @webassemblyjs/ast@npm:^1.11.5, @webassemblyjs/ast@npm:^1.14.1": + version: 1.14.1 + resolution: "@webassemblyjs/ast@npm:1.14.1" dependencies: - "@webassemblyjs/helper-numbers": 1.11.6 - "@webassemblyjs/helper-wasm-bytecode": 1.11.6 - checksum: 38ef1b526ca47c210f30975b06df2faf1a8170b1636ce239fc5738fc231ce28389dd61ecedd1bacfc03cbe95b16d1af848c805652080cb60982836eb4ed2c6cf + "@webassemblyjs/helper-numbers": 1.13.2 + "@webassemblyjs/helper-wasm-bytecode": 1.13.2 + checksum: f9154ad9ea14f6f2374ebe918c221fd69a4d4514126a1acc6fa4966e8d27ab28cb550a5e6880032cf620e19640578658a7e5a55bd2aad1e3db4e9d598b8f2099 languageName: node linkType: hard -"@webassemblyjs/floating-point-hex-parser@npm:1.11.6": - version: 1.11.6 - resolution: "@webassemblyjs/floating-point-hex-parser@npm:1.11.6" - checksum: 29b08758841fd8b299c7152eda36b9eb4921e9c584eb4594437b5cd90ed6b920523606eae7316175f89c20628da14326801090167cc7fbffc77af448ac84b7e2 +"@webassemblyjs/floating-point-hex-parser@npm:1.13.2": + version: 1.13.2 + resolution: "@webassemblyjs/floating-point-hex-parser@npm:1.13.2" + checksum: e866ec8433f4a70baa511df5e8f2ebcd6c24f4e2cc6274c7c5aabe2bcce3459ea4680e0f35d450e1f3602acf3913b6b8e4f15069c8cfd34ae8609fb9a7d01795 languageName: node linkType: hard -"@webassemblyjs/helper-api-error@npm:1.11.6": - version: 1.11.6 - resolution: "@webassemblyjs/helper-api-error@npm:1.11.6" - checksum: e8563df85161096343008f9161adb138a6e8f3c2cc338d6a36011aa55eabb32f2fd138ffe63bc278d009ada001cc41d263dadd1c0be01be6c2ed99076103689f +"@webassemblyjs/helper-api-error@npm:1.13.2": + version: 1.13.2 + resolution: "@webassemblyjs/helper-api-error@npm:1.13.2" + checksum: 48b5df7fd3095bb252f59a139fe2cbd999a62ac9b488123e9a0da3906ad8a2f2da7b2eb21d328c01a90da987380928706395c2897d1f3ed9e2125b6d75a920d0 languageName: node linkType: hard -"@webassemblyjs/helper-buffer@npm:1.11.6": - version: 1.11.6 - resolution: "@webassemblyjs/helper-buffer@npm:1.11.6" - checksum: b14d0573bf680d22b2522e8a341ec451fddd645d1f9c6bd9012ccb7e587a2973b86ab7b89fe91e1c79939ba96095f503af04369a3b356c8023c13a5893221644 +"@webassemblyjs/helper-buffer@npm:1.14.1": + version: 1.14.1 + resolution: "@webassemblyjs/helper-buffer@npm:1.14.1" + checksum: b611e981dfd6a797c3d8fc3a772de29a6e55033737c2c09c31bb66c613bdbb2d25f915df1dee62a602c6acc057ca71128432fa8c3e22a893e1219dc454f14ede languageName: node linkType: hard -"@webassemblyjs/helper-numbers@npm:1.11.6": - version: 1.11.6 - resolution: "@webassemblyjs/helper-numbers@npm:1.11.6" +"@webassemblyjs/helper-numbers@npm:1.13.2": + version: 1.13.2 + resolution: "@webassemblyjs/helper-numbers@npm:1.13.2" dependencies: - "@webassemblyjs/floating-point-hex-parser": 1.11.6 - "@webassemblyjs/helper-api-error": 1.11.6 + "@webassemblyjs/floating-point-hex-parser": 1.13.2 + "@webassemblyjs/helper-api-error": 1.13.2 "@xtuc/long": 4.2.2 - checksum: f4b562fa219f84368528339e0f8d273ad44e047a07641ffcaaec6f93e5b76fd86490a009aa91a294584e1436d74b0a01fa9fde45e333a4c657b58168b04da424 + checksum: 49e2c9bf9b66997e480f6b44d80f895b3cde4de52ac135921d28e144565edca6903a519f627f4089b5509de1d7f9e5023f0e1a94ff78a36c9e2eb30e7c18ffd2 languageName: node linkType: hard -"@webassemblyjs/helper-wasm-bytecode@npm:1.11.6": - version: 1.11.6 - resolution: "@webassemblyjs/helper-wasm-bytecode@npm:1.11.6" - checksum: 3535ef4f1fba38de3475e383b3980f4bbf3de72bbb631c2b6584c7df45be4eccd62c6ff48b5edd3f1bcff275cfd605a37679ec199fc91fd0a7705d7f1e3972dc +"@webassemblyjs/helper-wasm-bytecode@npm:1.13.2": + version: 1.13.2 + resolution: "@webassemblyjs/helper-wasm-bytecode@npm:1.13.2" + checksum: 8e059e1c1f0294f4fc3df8e4eaff3c5ef6e2e1358f34ebc118eaf5070ed59e56ed7fc92b28be734ebde17c8d662d5d27e06ade686c282445135da083ae11c128 languageName: node linkType: hard -"@webassemblyjs/helper-wasm-section@npm:1.11.6": - version: 1.11.6 - resolution: "@webassemblyjs/helper-wasm-section@npm:1.11.6" +"@webassemblyjs/helper-wasm-section@npm:1.14.1": + version: 1.14.1 + resolution: "@webassemblyjs/helper-wasm-section@npm:1.14.1" dependencies: - "@webassemblyjs/ast": 1.11.6 - "@webassemblyjs/helper-buffer": 1.11.6 - "@webassemblyjs/helper-wasm-bytecode": 1.11.6 - "@webassemblyjs/wasm-gen": 1.11.6 - checksum: b2cf751bf4552b5b9999d27bbb7692d0aca75260140195cb58ea6374d7b9c2dc69b61e10b211a0e773f66209c3ddd612137ed66097e3684d7816f854997682e9 + "@webassemblyjs/ast": 1.14.1 + "@webassemblyjs/helper-buffer": 1.14.1 + "@webassemblyjs/helper-wasm-bytecode": 1.13.2 + "@webassemblyjs/wasm-gen": 1.14.1 + checksum: 0a08d454a63192cd66abf91b6f060ac4b466cef341262246e9dcc828dd4c8536195dea9b46a1244b1eac65b59b8b502164a771a190052a92ff0a0a2ded0f8f53 languageName: node linkType: hard -"@webassemblyjs/ieee754@npm:1.11.6": - version: 1.11.6 - resolution: "@webassemblyjs/ieee754@npm:1.11.6" +"@webassemblyjs/ieee754@npm:1.13.2": + version: 1.13.2 + resolution: "@webassemblyjs/ieee754@npm:1.13.2" dependencies: "@xtuc/ieee754": ^1.2.0 - checksum: 13574b8e41f6ca39b700e292d7edf102577db5650fe8add7066a320aa4b7a7c09a5056feccac7a74eb68c10dea9546d4461412af351f13f6b24b5f32379b49de + checksum: d7e3520baa37a7309fa7db4d73d69fb869878853b1ebd4b168821bd03fcc4c0e1669c06231315b0039035d9a7a462e53de3ad982da4a426a4b0743b5888e8673 languageName: node linkType: hard -"@webassemblyjs/leb128@npm:1.11.6": - version: 1.11.6 - resolution: "@webassemblyjs/leb128@npm:1.11.6" +"@webassemblyjs/leb128@npm:1.13.2": + version: 1.13.2 + resolution: "@webassemblyjs/leb128@npm:1.13.2" dependencies: "@xtuc/long": 4.2.2 - checksum: 7ea942dc9777d4b18a5ebfa3a937b30ae9e1d2ce1fee637583ed7f376334dd1d4274f813d2e250056cca803e0952def4b954913f1a3c9068bcd4ab4ee5143bf0 + checksum: 64083507f7cff477a6d71a9e325d95665cea78ec8df99ca7c050e1cfbe300fbcf0842ca3dcf3b4fa55028350135588a4f879398d3dd2b6a8de9913ce7faf5333 languageName: node linkType: hard -"@webassemblyjs/utf8@npm:1.11.6": - version: 1.11.6 - resolution: "@webassemblyjs/utf8@npm:1.11.6" - checksum: 807fe5b5ce10c390cfdd93e0fb92abda8aebabb5199980681e7c3743ee3306a75729bcd1e56a3903980e96c885ee53ef901fcbaac8efdfa480f9c0dae1d08713 +"@webassemblyjs/utf8@npm:1.13.2": + version: 1.13.2 + resolution: "@webassemblyjs/utf8@npm:1.13.2" + checksum: 95ec6052f30eefa8d50c9b2a3394d08b17d53a4aa52821451d41d774c126fa8f39b988fbf5bff56da86852a87c16d676e576775a4071e5e5ccf020cc85a4b281 languageName: node linkType: hard -"@webassemblyjs/wasm-edit@npm:^1.11.5": - version: 1.11.6 - resolution: "@webassemblyjs/wasm-edit@npm:1.11.6" +"@webassemblyjs/wasm-edit@npm:^1.11.5, @webassemblyjs/wasm-edit@npm:^1.14.1": + version: 1.14.1 + resolution: "@webassemblyjs/wasm-edit@npm:1.14.1" dependencies: - "@webassemblyjs/ast": 1.11.6 - "@webassemblyjs/helper-buffer": 1.11.6 - "@webassemblyjs/helper-wasm-bytecode": 1.11.6 - "@webassemblyjs/helper-wasm-section": 1.11.6 - "@webassemblyjs/wasm-gen": 1.11.6 - "@webassemblyjs/wasm-opt": 1.11.6 - "@webassemblyjs/wasm-parser": 1.11.6 - "@webassemblyjs/wast-printer": 1.11.6 - checksum: 29ce75870496d6fad864d815ebb072395a8a3a04dc9c3f4e1ffdc63fc5fa58b1f34304a1117296d8240054cfdbc38aca88e71fb51483cf29ffab0a61ef27b481 + "@webassemblyjs/ast": 1.14.1 + "@webassemblyjs/helper-buffer": 1.14.1 + "@webassemblyjs/helper-wasm-bytecode": 1.13.2 + "@webassemblyjs/helper-wasm-section": 1.14.1 + "@webassemblyjs/wasm-gen": 1.14.1 + "@webassemblyjs/wasm-opt": 1.14.1 + "@webassemblyjs/wasm-parser": 1.14.1 + "@webassemblyjs/wast-printer": 1.14.1 + checksum: 9341c3146bb1b7863f03d6050c2a66990f20384ca137388047bbe1feffacb599e94fca7b7c18287d17e2449ffb4005fdc7f41f674a6975af9ad8522756f8ffff languageName: node linkType: hard -"@webassemblyjs/wasm-gen@npm:1.11.6": - version: 1.11.6 - resolution: "@webassemblyjs/wasm-gen@npm:1.11.6" +"@webassemblyjs/wasm-gen@npm:1.14.1": + version: 1.14.1 + resolution: "@webassemblyjs/wasm-gen@npm:1.14.1" dependencies: - "@webassemblyjs/ast": 1.11.6 - "@webassemblyjs/helper-wasm-bytecode": 1.11.6 - "@webassemblyjs/ieee754": 1.11.6 - "@webassemblyjs/leb128": 1.11.6 - "@webassemblyjs/utf8": 1.11.6 - checksum: a645a2eecbea24833c3260a249704a7f554ef4a94c6000984728e94bb2bc9140a68dfd6fd21d5e0bbb09f6dfc98e083a45760a83ae0417b41a0196ff6d45a23a + "@webassemblyjs/ast": 1.14.1 + "@webassemblyjs/helper-wasm-bytecode": 1.13.2 + "@webassemblyjs/ieee754": 1.13.2 + "@webassemblyjs/leb128": 1.13.2 + "@webassemblyjs/utf8": 1.13.2 + checksum: 401b12bec7431c4fc29d9414bbe40d3c6dc5be04d25a116657c42329f5481f0129f3b5834c293f26f0e42681ceac9157bf078ce9bdb6a7f78037c650373f98b2 languageName: node linkType: hard -"@webassemblyjs/wasm-opt@npm:1.11.6": - version: 1.11.6 - resolution: "@webassemblyjs/wasm-opt@npm:1.11.6" +"@webassemblyjs/wasm-opt@npm:1.14.1": + version: 1.14.1 + resolution: "@webassemblyjs/wasm-opt@npm:1.14.1" dependencies: - "@webassemblyjs/ast": 1.11.6 - "@webassemblyjs/helper-buffer": 1.11.6 - "@webassemblyjs/wasm-gen": 1.11.6 - "@webassemblyjs/wasm-parser": 1.11.6 - checksum: b4557f195487f8e97336ddf79f7bef40d788239169aac707f6eaa2fa5fe243557c2d74e550a8e57f2788e70c7ae4e7d32f7be16101afe183d597b747a3bdd528 + "@webassemblyjs/ast": 1.14.1 + "@webassemblyjs/helper-buffer": 1.14.1 + "@webassemblyjs/wasm-gen": 1.14.1 + "@webassemblyjs/wasm-parser": 1.14.1 + checksum: 60c697a9e9129d8d23573856df0791ba33cea4a3bc2339044cae73128c0983802e5e50a42157b990eeafe1237eb8e7653db6de5f02b54a0ae7b81b02dcdf2ae9 languageName: node linkType: hard -"@webassemblyjs/wasm-parser@npm:1.11.6, @webassemblyjs/wasm-parser@npm:^1.11.5": - version: 1.11.6 - resolution: "@webassemblyjs/wasm-parser@npm:1.11.6" +"@webassemblyjs/wasm-parser@npm:1.14.1, @webassemblyjs/wasm-parser@npm:^1.11.5, @webassemblyjs/wasm-parser@npm:^1.14.1": + version: 1.14.1 + resolution: "@webassemblyjs/wasm-parser@npm:1.14.1" dependencies: - "@webassemblyjs/ast": 1.11.6 - "@webassemblyjs/helper-api-error": 1.11.6 - "@webassemblyjs/helper-wasm-bytecode": 1.11.6 - "@webassemblyjs/ieee754": 1.11.6 - "@webassemblyjs/leb128": 1.11.6 - "@webassemblyjs/utf8": 1.11.6 - checksum: 8200a8d77c15621724a23fdabe58d5571415cda98a7058f542e670ea965dd75499f5e34a48675184947c66f3df23adf55df060312e6d72d57908e3f049620d8a + "@webassemblyjs/ast": 1.14.1 + "@webassemblyjs/helper-api-error": 1.13.2 + "@webassemblyjs/helper-wasm-bytecode": 1.13.2 + "@webassemblyjs/ieee754": 1.13.2 + "@webassemblyjs/leb128": 1.13.2 + "@webassemblyjs/utf8": 1.13.2 + checksum: 93f1fe2676da465b4e824419d9812a3d7218de4c3addd4e916c04bc86055fa134416c1b67e4b7cbde8d728c0dce2721d06cc0bfe7a7db7c093a0898009937405 languageName: node linkType: hard -"@webassemblyjs/wast-printer@npm:1.11.6": - version: 1.11.6 - resolution: "@webassemblyjs/wast-printer@npm:1.11.6" +"@webassemblyjs/wast-printer@npm:1.14.1": + version: 1.14.1 + resolution: "@webassemblyjs/wast-printer@npm:1.14.1" dependencies: - "@webassemblyjs/ast": 1.11.6 + "@webassemblyjs/ast": 1.14.1 "@xtuc/long": 4.2.2 - checksum: d2fa6a4c427325ec81463e9c809aa6572af6d47f619f3091bf4c4a6fc34f1da3df7caddaac50b8e7a457f8784c62cd58c6311b6cb69b0162ccd8d4c072f79cf8 + checksum: 517881a0554debe6945de719d100b2d8883a2d24ddf47552cdeda866341e2bb153cd824a864bc7e2a61190a4b66b18f9899907e0074e9e820d2912ac0789ea60 languageName: node linkType: hard @@ -18632,12 +19162,12 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.0.4, acorn@npm:^8.1.0, acorn@npm:^8.11.3, acorn@npm:^8.2.4, acorn@npm:^8.4.1, acorn@npm:^8.7.1, acorn@npm:^8.8.0, acorn@npm:^8.8.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": - version: 8.11.3 - resolution: "acorn@npm:8.11.3" +"acorn@npm:^8.0.4, acorn@npm:^8.1.0, acorn@npm:^8.11.3, acorn@npm:^8.14.0, acorn@npm:^8.2.4, acorn@npm:^8.4.1, acorn@npm:^8.7.1, acorn@npm:^8.8.0, acorn@npm:^8.8.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": + version: 8.14.0 + resolution: "acorn@npm:8.14.0" bin: acorn: bin/acorn - checksum: 76d8e7d559512566b43ab4aadc374f11f563f0a9e21626dd59cb2888444e9445923ae9f3699972767f18af61df89cd89f5eaaf772d1327b055b45cb829b4a88c + checksum: 8755074ba55fff94e84e81c72f1013c2d9c78e973c31231c8ae505a5f966859baf654bddd75046bffd73ce816b149298977fff5077a3033dedba0ae2aad152d4 languageName: node linkType: hard @@ -18868,7 +19398,7 @@ __metadata: languageName: node linkType: hard -"ansi-html-community@npm:^0.0.8": +"ansi-html-community@npm:0.0.8, ansi-html-community@npm:^0.0.8": version: 0.0.8 resolution: "ansi-html-community@npm:0.0.8" bin: @@ -18877,6 +19407,15 @@ __metadata: languageName: node linkType: hard +"ansi-html@npm:^0.0.9": + version: 0.0.9 + resolution: "ansi-html@npm:0.0.9" + bin: + ansi-html: bin/ansi-html + checksum: a03754d6f66bae33938ed8bb3dd98174b7f4895ebe45226185036ed4a1388a7aaf2f2b9581608f0626432ba7add92cfc590aa6475a78bbb90d9d1e1d1af8cbe6 + languageName: node + linkType: hard + "ansi-regex@npm:^2.0.0": version: 2.1.1 resolution: "ansi-regex@npm:2.1.1" @@ -19107,6 +19646,15 @@ __metadata: languageName: node linkType: hard +"aria-query@npm:5.3.0": + version: 5.3.0 + resolution: "aria-query@npm:5.3.0" + dependencies: + dequal: ^2.0.3 + checksum: 305bd73c76756117b59aba121d08f413c7ff5e80fa1b98e217a3443fcddb9a232ee790e24e432b59ae7625aebcf4c47cb01c2cac872994f0b426f5bdfcd96ba9 + languageName: node + linkType: hard + "aria-query@npm:^4.2.2": version: 4.2.2 resolution: "aria-query@npm:4.2.2" @@ -19117,12 +19665,10 @@ __metadata: languageName: node linkType: hard -"aria-query@npm:^5.0.0, aria-query@npm:^5.1.3": - version: 5.3.0 - resolution: "aria-query@npm:5.3.0" - dependencies: - dequal: ^2.0.3 - checksum: 305bd73c76756117b59aba121d08f413c7ff5e80fa1b98e217a3443fcddb9a232ee790e24e432b59ae7625aebcf4c47cb01c2cac872994f0b426f5bdfcd96ba9 +"aria-query@npm:^5.0.0, aria-query@npm:^5.3.2": + version: 5.3.2 + resolution: "aria-query@npm:5.3.2" + checksum: d971175c85c10df0f6d14adfe6f1292409196114ab3c62f238e208b53103686f46cc70695a4f775b73bc65f6a09b6a092fd963c4f3a5a7d690c8fc5094925717 languageName: node linkType: hard @@ -19182,7 +19728,7 @@ __metadata: languageName: node linkType: hard -"array-includes@npm:^3.1.5, array-includes@npm:^3.1.6, array-includes@npm:^3.1.7": +"array-includes@npm:^3.1.6, array-includes@npm:^3.1.7, array-includes@npm:^3.1.8": version: 3.1.8 resolution: "array-includes@npm:3.1.8" dependencies: @@ -19219,7 +19765,7 @@ __metadata: languageName: node linkType: hard -"array.prototype.findlast@npm:^1.2.4": +"array.prototype.findlast@npm:^1.2.4, array.prototype.findlast@npm:^1.2.5": version: 1.2.5 resolution: "array.prototype.findlast@npm:1.2.5" dependencies: @@ -19257,6 +19803,21 @@ __metadata: languageName: node linkType: hard +"array.prototype.reduce@npm:^1.0.6": + version: 1.0.7 + resolution: "array.prototype.reduce@npm:1.0.7" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-array-method-boxes-properly: ^1.0.0 + es-errors: ^1.3.0 + es-object-atoms: ^1.0.0 + is-string: ^1.0.7 + checksum: 90303617bd70c8e9a81ebff041d3e10fad1a97f163699cb015b7c84a3f9e6960d9bb161a30f1d0309d6e476f166af5668c1e24f7add3202213d25f7c7f15475d + languageName: node + linkType: hard + "array.prototype.toreversed@npm:^1.1.2": version: 1.1.2 resolution: "array.prototype.toreversed@npm:1.1.2" @@ -19269,16 +19830,16 @@ __metadata: languageName: node linkType: hard -"array.prototype.tosorted@npm:^1.1.3": - version: 1.1.3 - resolution: "array.prototype.tosorted@npm:1.1.3" +"array.prototype.tosorted@npm:^1.1.3, array.prototype.tosorted@npm:^1.1.4": + version: 1.1.4 + resolution: "array.prototype.tosorted@npm:1.1.4" dependencies: - call-bind: ^1.0.5 + call-bind: ^1.0.7 define-properties: ^1.2.1 - es-abstract: ^1.22.3 - es-errors: ^1.1.0 + es-abstract: ^1.23.3 + es-errors: ^1.3.0 es-shim-unscopables: ^1.0.2 - checksum: 555e8808086bbde9e634c5dc5a8c0a2f1773075447b43b2fa76ab4f94f4e90f416d2a4f881024e1ce1a2931614caf76cd6b408af901c9d7cd13061d0d268f5af + checksum: e4142d6f556bcbb4f393c02e7dbaea9af8f620c040450c2be137c9cbbd1a17f216b9c688c5f2c08fbb038ab83f55993fa6efdd9a05881d84693c7bcb5422127a languageName: node linkType: hard @@ -19379,6 +19940,13 @@ __metadata: languageName: node linkType: hard +"assertion-error@npm:^2.0.1": + version: 2.0.1 + resolution: "assertion-error@npm:2.0.1" + checksum: a0789dd882211b87116e81e2648ccb7f60340b34f19877dd020b39ebb4714e475eb943e14ba3e22201c221ef6645b7bfe10297e76b6ac95b48a9898c1211ce66 + languageName: node + linkType: hard + "ast-module-types@npm:^2.7.1": version: 2.7.1 resolution: "ast-module-types@npm:2.7.1" @@ -19400,10 +19968,10 @@ __metadata: languageName: node linkType: hard -"ast-types-flow@npm:^0.0.7": - version: 0.0.7 - resolution: "ast-types-flow@npm:0.0.7" - checksum: a26dcc2182ffee111cad7c471759b0bda22d3b7ebacf27c348b22c55f16896b18ab0a4d03b85b4020dce7f3e634b8f00b593888f622915096ea1927fa51866c4 +"ast-types-flow@npm:^0.0.8": + version: 0.0.8 + resolution: "ast-types-flow@npm:0.0.8" + checksum: 0a64706609a179233aac23817837abab614f3548c252a2d3d79ea1e10c74aa28a0846e11f466cf72771b6ed8713abc094dcf8c40c3ec4207da163efa525a94a8 languageName: node linkType: hard @@ -19527,20 +20095,20 @@ __metadata: linkType: hard "autoprefixer@npm:^10.4.12, autoprefixer@npm:^10.4.13": - version: 10.4.16 - resolution: "autoprefixer@npm:10.4.16" + version: 10.4.20 + resolution: "autoprefixer@npm:10.4.20" dependencies: - browserslist: ^4.21.10 - caniuse-lite: ^1.0.30001538 - fraction.js: ^4.3.6 + browserslist: ^4.23.3 + caniuse-lite: ^1.0.30001646 + fraction.js: ^4.3.7 normalize-range: ^0.1.2 - picocolors: ^1.0.0 + picocolors: ^1.0.1 postcss-value-parser: ^4.2.0 peerDependencies: postcss: ^8.1.0 bin: autoprefixer: bin/autoprefixer - checksum: 45fad7086495048dacb14bb7b00313e70e135b5d8e8751dcc60548889400763705ab16fc2d99ea628b44c3472698fb0e39598f595ba28409c965ab159035afde + checksum: 187cec2ec356631932b212f76dc64f4419c117fdb2fb9eeeb40867d38ba5ca5ba734e6ceefc9e3af4eec8258e60accdf5cbf2b7708798598fde35cdc3de562d6 languageName: node linkType: hard @@ -19602,10 +20170,10 @@ __metadata: languageName: node linkType: hard -"axe-core@npm:^4.6.2": - version: 4.6.3 - resolution: "axe-core@npm:4.6.3" - checksum: d0c46be92b9707c48b88a53cd5f471b155a2bfc8bf6beffb514ecd14e30b4863e340b5fc4f496d82a3c562048088c1f3ff5b93b9b3b026cb9c3bfacfd535da10 +"axe-core@npm:^4.10.0": + version: 4.10.2 + resolution: "axe-core@npm:4.10.2" + checksum: 2b9b1c93ea73ea9f206604e4e17bd771d2d835f077bde54517d73028b8865c69b209460e73d5b109968cbdb39ab3d28943efa5695189bd79e16421ce1706719e languageName: node linkType: hard @@ -19650,12 +20218,10 @@ __metadata: languageName: node linkType: hard -"axobject-query@npm:^3.1.1": - version: 3.1.1 - resolution: "axobject-query@npm:3.1.1" - dependencies: - deep-equal: ^2.0.5 - checksum: c12a5da10dc7bab75e1cda9b6a3b5fcf10eba426ddf1a17b71ef65a434ed707ede7d1c4f013ba1609e970bc8c0cddac01365080d376204314e9b294719acd8a5 +"axobject-query@npm:^4.1.0": + version: 4.1.0 + resolution: "axobject-query@npm:4.1.0" + checksum: 7d1e87bf0aa7ae7a76cd39ab627b7c48fda3dc40181303d9adce4ba1d5b5ce73b5e5403ee6626ec8e91090448c887294d6144e24b6741a976f5be9347e3ae1df languageName: node linkType: hard @@ -19749,17 +20315,17 @@ __metadata: linkType: hard "babel-loader@npm:^8.2.3": - version: 8.3.0 - resolution: "babel-loader@npm:8.3.0" + version: 8.4.1 + resolution: "babel-loader@npm:8.4.1" dependencies: find-cache-dir: ^3.3.1 - loader-utils: ^2.0.0 + loader-utils: ^2.0.4 make-dir: ^3.1.0 schema-utils: ^2.6.5 peerDependencies: "@babel/core": ^7.0.0 webpack: ">=2" - checksum: d48bcf9e030e598656ad3ff5fb85967db2eaaf38af5b4a4b99d25618a2057f9f100e6b231af2a46c1913206db506115ca7a8cbdf52c9c73d767070dae4352ab5 + checksum: fa02db1a7d3ebb7b4aab83e926fb51e627a00427943c9dd1b3302c8099c67fa6a242a2adeed37d95abcd39ba619edf558a1dec369ce0849c5a87dc290c90fe2f languageName: node linkType: hard @@ -19871,16 +20437,28 @@ __metadata: languageName: node linkType: hard -"babel-plugin-polyfill-corejs2@npm:^0.4.6": - version: 0.4.6 - resolution: "babel-plugin-polyfill-corejs2@npm:0.4.6" +"babel-plugin-polyfill-corejs2@npm:^0.4.10, babel-plugin-polyfill-corejs2@npm:^0.4.6": + version: 0.4.12 + resolution: "babel-plugin-polyfill-corejs2@npm:0.4.12" dependencies: "@babel/compat-data": ^7.22.6 - "@babel/helper-define-polyfill-provider": ^0.4.3 + "@babel/helper-define-polyfill-provider": ^0.6.3 semver: ^6.3.1 peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: 08896811df31530be6a9bcdd630cb9fd4b5ae5181039d18db3796efbc54e38d57a42af460845c10a04434e1bc45c0d47743c7e6c860383cc6b141083cde22030 + checksum: 6e6e6a8b85fec80a310ded2f5c151385e4ac59118909dd6a952e1025e4a478eb79dda45a5a6322cc2e598fd696eb07d4e2fa52418b4101f3dc370bdf8c8939ba + languageName: node + linkType: hard + +"babel-plugin-polyfill-corejs3@npm:^0.10.6": + version: 0.10.6 + resolution: "babel-plugin-polyfill-corejs3@npm:0.10.6" + dependencies: + "@babel/helper-define-polyfill-provider": ^0.6.2 + core-js-compat: ^3.38.0 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: f762f29f7acca576897c63149c850f0a72babd3fb9ea436a2e36f0c339161c4b912a77828541d8188ce8a91e50965c6687120cf36071eabb1b7aa92f279e2164 languageName: node linkType: hard @@ -19907,6 +20485,17 @@ __metadata: languageName: node linkType: hard +"babel-plugin-polyfill-regenerator@npm:^0.6.1": + version: 0.6.3 + resolution: "babel-plugin-polyfill-regenerator@npm:0.6.3" + dependencies: + "@babel/helper-define-polyfill-provider": ^0.6.3 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: d12696e6b3f280eb78fac551619ca4389262db62c7352cd54bf679d830df8b35596eef2de77cf00db6648eada1c99d49c4f40636dbc9c335a1e5420cfef96750 + languageName: node + linkType: hard + "babel-plugin-react-native-web@npm:0.17.5": version: 0.17.5 resolution: "babel-plugin-react-native-web@npm:0.17.5" @@ -20453,12 +21042,12 @@ __metadata: languageName: node linkType: hard -"braces@npm:^3.0.2, braces@npm:~3.0.2": - version: 3.0.2 - resolution: "braces@npm:3.0.2" +"braces@npm:^3.0.2, braces@npm:^3.0.3, braces@npm:~3.0.2": + version: 3.0.3 + resolution: "braces@npm:3.0.3" dependencies: - fill-range: ^7.0.1 - checksum: e2a8e769a863f3d4ee887b5fe21f63193a891c68b612ddb4b68d82d1b5f3ff9073af066c343e9867a393fe4c2555dcb33e89b937195feb9c1613d259edfcd459 + fill-range: ^7.1.1 + checksum: b95aa0b3bd909f6cd1720ffcf031aeaf46154dd88b4da01f9a1d3f7ea866a79eba76a6d01cbc3c422b2ee5cdc39a4f02491058d5df0d7bf6e6a162a832df1f69 languageName: node linkType: hard @@ -20617,7 +21206,7 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.0.0, browserslist@npm:^4.18.1, browserslist@npm:^4.21.10, browserslist@npm:^4.21.4, browserslist@npm:^4.22.1, browserslist@npm:^4.22.2, browserslist@npm:^4.24.0": +"browserslist@npm:^4.0.0, browserslist@npm:^4.18.1, browserslist@npm:^4.21.10, browserslist@npm:^4.21.4, browserslist@npm:^4.22.2, browserslist@npm:^4.23.3, browserslist@npm:^4.24.0, browserslist@npm:^4.24.2": version: 4.24.2 resolution: "browserslist@npm:4.24.2" dependencies: @@ -21158,10 +21747,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001538, caniuse-lite@npm:^1.0.30001669": - version: 1.0.30001680 - resolution: "caniuse-lite@npm:1.0.30001680" - checksum: 2641d2b18c5ab0a6663cb350c5adc81e5ede1a7677d1c7518a8053ada87bf6f206419e1820a2608f76fa5e4f7bea327cbe47df423783e571569a88c0ea645270 +"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001646, caniuse-lite@npm:^1.0.30001669": + version: 1.0.30001687 + resolution: "caniuse-lite@npm:1.0.30001687" + checksum: 20fea782da99d7ff964a9f0573c9eb02762eee2783522f5db5c0a20ba9d9d1cf294aae4162b5ef2f47f729916e6bd0ba457118c6d086c1132d19a46d2d1c61e7 languageName: node linkType: hard @@ -21233,6 +21822,19 @@ __metadata: languageName: node linkType: hard +"chai@npm:^5.1.1": + version: 5.1.2 + resolution: "chai@npm:5.1.2" + dependencies: + assertion-error: ^2.0.1 + check-error: ^2.1.1 + deep-eql: ^5.0.1 + loupe: ^3.1.0 + pathval: ^2.0.0 + checksum: f2341967ab5632612548d372c27b46219adad3af35021d8cba2ae3c262f588de2c60cb3f004e6ad40e363a9cad6d20d0de51f00e7e9ac31cce17fb05d4efa316 + languageName: node + linkType: hard + "chalk-template@npm:0.4.0": version: 0.4.0 resolution: "chalk-template@npm:0.4.0" @@ -21411,6 +22013,13 @@ __metadata: languageName: node linkType: hard +"check-error@npm:^2.1.1": + version: 2.1.1 + resolution: "check-error@npm:2.1.1" + checksum: d785ed17b1d4a4796b6e75c765a9a290098cf52ff9728ce0756e8ffd4293d2e419dd30c67200aee34202463b474306913f2fcfaf1890641026d9fc6966fea27a + languageName: node + linkType: hard + "check-more-types@npm:2.24.0, check-more-types@npm:^2.24.0": version: 2.24.0 resolution: "check-more-types@npm:2.24.0" @@ -21484,7 +22093,7 @@ __metadata: languageName: node linkType: hard -"chokidar@npm:^3.4.2, chokidar@npm:^3.5.1, chokidar@npm:^3.5.2, chokidar@npm:^3.5.3": +"chokidar@npm:^3.4.2, chokidar@npm:^3.5.1, chokidar@npm:^3.5.2, chokidar@npm:^3.5.3, chokidar@npm:^3.6.0": version: 3.6.0 resolution: "chokidar@npm:3.6.0" dependencies: @@ -21526,6 +22135,25 @@ __metadata: languageName: node linkType: hard +"chromatic@npm:^11.15.0": + version: 11.20.0 + resolution: "chromatic@npm:11.20.0" + peerDependencies: + "@chromatic-com/cypress": ^0.*.* || ^1.0.0 + "@chromatic-com/playwright": ^0.*.* || ^1.0.0 + peerDependenciesMeta: + "@chromatic-com/cypress": + optional: true + "@chromatic-com/playwright": + optional: true + bin: + chroma: dist/bin.js + chromatic: dist/bin.js + chromatic-cli: dist/bin.js + checksum: 71f4097731d6528f001527dc5dde6d4b6b5ee35b1a681e8bb38464183eedcc31c0375218a028a15f757bcdc29d256cf3e460457c977ea74e72986ed25cc56196 + languageName: node + linkType: hard + "chrome-launcher@npm:^0.15.2": version: 0.15.2 resolution: "chrome-launcher@npm:0.15.2" @@ -21613,10 +22241,10 @@ __metadata: languageName: node linkType: hard -"cjs-module-lexer@npm:^1.0.0": - version: 1.2.2 - resolution: "cjs-module-lexer@npm:1.2.2" - checksum: 977f3f042bd4f08e368c890d91eecfbc4f91da0bc009a3c557bc4dfbf32022ad1141244ac1178d44de70fc9f3dea7add7cd9a658a34b9fae98a55d8f92331ce5 +"cjs-module-lexer@npm:^1.0.0, cjs-module-lexer@npm:^1.2.3": + version: 1.4.1 + resolution: "cjs-module-lexer@npm:1.4.1" + checksum: 2556807a99aec1f9daac60741af96cd613a707f343174ae7967da46402c91dced411bf830d209f2e93be4cecea46fc75cecf1f17c799d7d8a9e1dd6204bfcd22 languageName: node linkType: hard @@ -22452,12 +23080,12 @@ __metadata: languageName: node linkType: hard -"core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.33.1": - version: 3.33.2 - resolution: "core-js-compat@npm:3.33.2" +"core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.33.1, core-js-compat@npm:^3.38.0": + version: 3.39.0 + resolution: "core-js-compat@npm:3.39.0" dependencies: - browserslist: ^4.22.1 - checksum: 4206d3ff282a9188399e9003301fa4b96844152afcea7b9c9accc653542f40f581f77bf079b8be67f614e305da1f29e868a49ceebb6dbe3f5fb4a28bd2dbf431 + browserslist: ^4.24.2 + checksum: 2d7d087c3271d711d03a55203d4756f6288317a1ce35cdc8bafaf1833ef21fd67a92a50cff8dcf7df1325ac63720906ab3cf514c85b238c95f65fca1040f6ad6 languageName: node linkType: hard @@ -22476,9 +23104,9 @@ __metadata: linkType: hard "core-js@npm:^3.19.2, core-js@npm:^3.8.2": - version: 3.33.2 - resolution: "core-js@npm:3.33.2" - checksum: 71de081acbd060ff985afdcdf2552de4a00ab3ac4695c77f3535b72ddf4526920dcd0cb73e72e57c2ae16e384838a6d55790e138f0a19d60afcf851f89d0064d + version: 3.39.0 + resolution: "core-js@npm:3.39.0" + checksum: 7a3670e9a2a89e0a049daa288d742d09f6e16d27a8945c5e2ef6fc45dc57e5c4bc5db589da05947486f54ae978d14cf27bd3fb1db0b9907000a611e8af37355b languageName: node linkType: hard @@ -22880,21 +23508,27 @@ __metadata: languageName: node linkType: hard -"css-loader@npm:^6.5.1": - version: 6.8.1 - resolution: "css-loader@npm:6.8.1" +"css-loader@npm:6.11.0, css-loader@npm:^6.5.1, css-loader@npm:^6.7.1": + version: 6.11.0 + resolution: "css-loader@npm:6.11.0" dependencies: icss-utils: ^5.1.0 - postcss: ^8.4.21 - postcss-modules-extract-imports: ^3.0.0 - postcss-modules-local-by-default: ^4.0.3 - postcss-modules-scope: ^3.0.0 + postcss: ^8.4.33 + postcss-modules-extract-imports: ^3.1.0 + postcss-modules-local-by-default: ^4.0.5 + postcss-modules-scope: ^3.2.0 postcss-modules-values: ^4.0.0 postcss-value-parser: ^4.2.0 - semver: ^7.3.8 + semver: ^7.5.4 peerDependencies: + "@rspack/core": 0.x || 1.x webpack: ^5.0.0 - checksum: 7c1784247bdbe76dc5c55fb1ac84f1d4177a74c47259942c9cfdb7a8e6baef11967a0bc85ac285f26bd26d5059decb848af8154a03fdb4f4894f41212f45eef3 + peerDependenciesMeta: + "@rspack/core": + optional: true + webpack: + optional: true + checksum: 5c8d35975a7121334905394e88e28f05df72f037dbed2fb8fec4be5f0b313ae73a13894ba791867d4a4190c35896da84a7fd0c54fb426db55d85ba5e714edbe3 languageName: node linkType: hard @@ -23052,9 +23686,9 @@ __metadata: linkType: hard "cssdb@npm:^7.1.0": - version: 7.9.0 - resolution: "cssdb@npm:7.9.0" - checksum: 83c2e3192336345bfcfb824f94f46afb5e0cd8b9a9755690bc0eecf004de57a1e031c31437be74bf957f348c4808cc5c8e378f4fb910ab3fd150ac69f30ae38a + version: 7.11.2 + resolution: "cssdb@npm:7.11.2" + checksum: 79b2c3b6de1d80c7f3e40f28c06138b7f1ca27fe5d9173195cc781d8acc0261c2bdeccdf141bd035b13709655cf724c8ad4757ddf12a3d21b6d002368c9cb027 languageName: node linkType: hard @@ -24076,6 +24710,13 @@ __metadata: languageName: node linkType: hard +"deep-eql@npm:^5.0.1": + version: 5.0.2 + resolution: "deep-eql@npm:5.0.2" + checksum: 6aaaadb4c19cbce42e26b2bbe5bd92875f599d2602635dc97f0294bae48da79e89470aedee05f449e0ca8c65e9fd7e7872624d1933a1db02713d99c2ca8d1f24 + languageName: node + linkType: hard + "deep-equal@npm:^1.0.1": version: 1.1.2 resolution: "deep-equal@npm:1.1.2" @@ -24203,7 +24844,7 @@ __metadata: languageName: node linkType: hard -"define-properties@npm:^1.1.2, define-properties@npm:^1.1.3, define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": +"define-properties@npm:^1.1.3, define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": version: 1.2.1 resolution: "define-properties@npm:1.2.1" dependencies: @@ -24899,6 +25540,13 @@ __metadata: languageName: node linkType: hard +"dom-accessibility-api@npm:^0.6.3": + version: 0.6.3 + resolution: "dom-accessibility-api@npm:0.6.3" + checksum: c325b5144bb406df23f4affecffc117dbaec9af03daad9ee6b510c5be647b14d28ef0a4ea5ca06d696d8ab40bb777e5fed98b985976fdef9d8790178fa1d573f + languageName: node + linkType: hard + "dom-converter@npm:^0.2.0": version: 0.2.0 resolution: "dom-converter@npm:0.2.0" @@ -25420,6 +26068,17 @@ __metadata: languageName: node linkType: hard +"endent@npm:^2.0.1": + version: 2.1.0 + resolution: "endent@npm:2.1.0" + dependencies: + dedent: ^0.7.0 + fast-json-parse: ^1.0.3 + objectorarray: ^1.0.5 + checksum: c352831088fce745a39ddbd5f87a17e073ea6556e7e96e9010d945a3f3020f836b9a84657123fa01e897db9216f4b080d950b5ded9bf3a8227f14a34efaaaf7c + languageName: node + linkType: hard + "engine.io-client@npm:~6.5.2": version: 6.5.3 resolution: "engine.io-client@npm:6.5.3" @@ -25440,13 +26099,13 @@ __metadata: languageName: node linkType: hard -"enhanced-resolve@npm:^5.15.0, enhanced-resolve@npm:^5.8.3": - version: 5.15.0 - resolution: "enhanced-resolve@npm:5.15.0" +"enhanced-resolve@npm:^5.0.0, enhanced-resolve@npm:^5.15.0, enhanced-resolve@npm:^5.17.1, enhanced-resolve@npm:^5.8.3": + version: 5.17.1 + resolution: "enhanced-resolve@npm:5.17.1" dependencies: graceful-fs: ^4.2.4 tapable: ^2.2.0 - checksum: fbd8cdc9263be71cc737aa8a7d6c57b43d6aa38f6cc75dde6fcd3598a130cc465f979d2f4d01bb3bf475acb43817749c79f8eef9be048683602ca91ab52e4f11 + checksum: 4bc38cf1cea96456f97503db7280394177d1bc46f8f87c267297d04f795ac5efa81e48115a2f5b6273c781027b5b6bfc5f62b54df629e4d25fa7001a86624f59 languageName: node linkType: hard @@ -25546,9 +26205,9 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.19.1, es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3": - version: 1.23.3 - resolution: "es-abstract@npm:1.23.3" +"es-abstract@npm:^1.17.2, es-abstract@npm:^1.17.5, es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3": + version: 1.23.5 + resolution: "es-abstract@npm:1.23.5" dependencies: array-buffer-byte-length: ^1.0.1 arraybuffer.prototype.slice: ^1.0.3 @@ -25565,7 +26224,7 @@ __metadata: function.prototype.name: ^1.1.6 get-intrinsic: ^1.2.4 get-symbol-description: ^1.0.2 - globalthis: ^1.0.3 + globalthis: ^1.0.4 gopd: ^1.0.1 has-property-descriptors: ^1.0.2 has-proto: ^1.0.3 @@ -25581,10 +26240,10 @@ __metadata: is-string: ^1.0.7 is-typed-array: ^1.1.13 is-weakref: ^1.0.2 - object-inspect: ^1.13.1 + object-inspect: ^1.13.3 object-keys: ^1.1.1 object.assign: ^4.1.5 - regexp.prototype.flags: ^1.5.2 + regexp.prototype.flags: ^1.5.3 safe-array-concat: ^1.1.2 safe-regex-test: ^1.0.3 string.prototype.trim: ^1.2.9 @@ -25596,7 +26255,14 @@ __metadata: typed-array-length: ^1.0.6 unbox-primitive: ^1.0.2 which-typed-array: ^1.1.15 - checksum: f840cf161224252512f9527306b57117192696571e07920f777cb893454e32999206198b4f075516112af6459daca282826d1735c450528470356d09eff3a9ae + checksum: 17c81f8a42f0322fd11e0025d3c2229ecfd7923560c710906b8e68660e19c42322750dcedf8ba5cf28bae50d5befd8174d3903ac50dbabb336d3efc3aabed2ee + languageName: node + linkType: hard + +"es-array-method-boxes-properly@npm:^1.0.0": + version: 1.0.0 + resolution: "es-array-method-boxes-properly@npm:1.0.0" + checksum: 2537fcd1cecf187083890bc6f5236d3a26bf39237433587e5bf63392e88faae929dbba78ff0120681a3f6f81c23fe3816122982c160d63b38c95c830b633b826 languageName: node linkType: hard @@ -25609,7 +26275,7 @@ __metadata: languageName: node linkType: hard -"es-errors@npm:^1.1.0, es-errors@npm:^1.2.1, es-errors@npm:^1.3.0": +"es-errors@npm:^1.2.1, es-errors@npm:^1.3.0": version: 1.3.0 resolution: "es-errors@npm:1.3.0" checksum: ec1414527a0ccacd7f15f4a3bc66e215f04f595ba23ca75cdae0927af099b5ec865f9f4d33e9d7e86f512f252876ac77d4281a7871531a50678132429b1271b5 @@ -25633,9 +26299,9 @@ __metadata: languageName: node linkType: hard -"es-iterator-helpers@npm:^1.0.17": - version: 1.0.19 - resolution: "es-iterator-helpers@npm:1.0.19" +"es-iterator-helpers@npm:^1.0.17, es-iterator-helpers@npm:^1.1.0": + version: 1.2.0 + resolution: "es-iterator-helpers@npm:1.2.0" dependencies: call-bind: ^1.0.7 define-properties: ^1.2.1 @@ -25644,21 +26310,22 @@ __metadata: es-set-tostringtag: ^2.0.3 function-bind: ^1.1.2 get-intrinsic: ^1.2.4 - globalthis: ^1.0.3 + globalthis: ^1.0.4 + gopd: ^1.0.1 has-property-descriptors: ^1.0.2 has-proto: ^1.0.3 has-symbols: ^1.0.3 internal-slot: ^1.0.7 - iterator.prototype: ^1.1.2 + iterator.prototype: ^1.1.3 safe-array-concat: ^1.1.2 - checksum: 7ae112b88359fbaf4b9d7d1d1358ae57c5138768c57ba3a8fb930393662653b0512bfd7917c15890d1471577fb012fee8b73b4465e59b331739e6ee94f961683 + checksum: c5f5ff10d57f956539581aca7a2d8726c5a8a3e49e6285700d74dcd8b64c7a337b9ab5e81b459b079dac745d2fe02e4f6b80a842e3df45d9cfe3f12325fda8c0 languageName: node linkType: hard -"es-module-lexer@npm:^1.2.1": - version: 1.4.1 - resolution: "es-module-lexer@npm:1.4.1" - checksum: a11b5a256d4e8e9c7d94c2fd87415ccd1591617b6edd847e064503f8eaece2d25e2e9078a02c5ce3ed5e83bb748f5b4820efbe78072c8beb07ac619c2edec35d +"es-module-lexer@npm:^1.2.1, es-module-lexer@npm:^1.5.0": + version: 1.5.4 + resolution: "es-module-lexer@npm:1.5.4" + checksum: a0cf04fb92d052647ac7d818d1913b98d3d3d0f5b9d88f0eafb993436e4c3e2c958599db68839d57f2dfa281fdf0f60e18d448eb78fc292c33c0f25635b6854f languageName: node linkType: hard @@ -26564,28 +27231,27 @@ __metadata: linkType: hard "eslint-plugin-jsx-a11y@npm:^6.5.1": - version: 6.7.1 - resolution: "eslint-plugin-jsx-a11y@npm:6.7.1" + version: 6.10.2 + resolution: "eslint-plugin-jsx-a11y@npm:6.10.2" dependencies: - "@babel/runtime": ^7.20.7 - aria-query: ^5.1.3 - array-includes: ^3.1.6 - array.prototype.flatmap: ^1.3.1 - ast-types-flow: ^0.0.7 - axe-core: ^4.6.2 - axobject-query: ^3.1.1 + aria-query: ^5.3.2 + array-includes: ^3.1.8 + array.prototype.flatmap: ^1.3.2 + ast-types-flow: ^0.0.8 + axe-core: ^4.10.0 + axobject-query: ^4.1.0 damerau-levenshtein: ^1.0.8 emoji-regex: ^9.2.2 - has: ^1.0.3 - jsx-ast-utils: ^3.3.3 - language-tags: =1.0.5 + hasown: ^2.0.2 + jsx-ast-utils: ^3.3.5 + language-tags: ^1.0.9 minimatch: ^3.1.2 - object.entries: ^1.1.6 - object.fromentries: ^2.0.6 - semver: ^6.3.0 + object.fromentries: ^2.0.8 + safe-regex-test: ^1.0.3 + string.prototype.includes: ^2.0.1 peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - checksum: f166dd5fe7257c7b891c6692e6a3ede6f237a14043ae3d97581daf318fc5833ddc6b4871aa34ab7656187430170500f6d806895747ea17ecdf8231a666c3c2fd + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 + checksum: 0cc861398fa26ada61ed5703eef5b335495fcb96253263dcd5e399488ff019a2636372021baacc040e3560d1a34bfcd5d5ad9f1754f44cd0509c956f7df94050 languageName: node linkType: hard @@ -26627,7 +27293,7 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-react-hooks@npm:4.6.0, eslint-plugin-react-hooks@npm:^4.3.0, eslint-plugin-react-hooks@npm:^4.6.0": +"eslint-plugin-react-hooks@npm:4.6.0": version: 4.6.0 resolution: "eslint-plugin-react-hooks@npm:4.6.0" peerDependencies: @@ -26636,6 +27302,15 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-react-hooks@npm:^4.3.0, eslint-plugin-react-hooks@npm:^4.6.0": + version: 4.6.2 + resolution: "eslint-plugin-react-hooks@npm:4.6.2" + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + checksum: 395c433610f59577cfcf3f2e42bcb130436c8a0b3777ac64f441d88c5275f4fcfc89094cedab270f2822daf29af1079151a7a6579a8e9ea8cee66540ba0384c4 + languageName: node + linkType: hard + "eslint-plugin-react-native-globals@npm:^0.1.1": version: 0.1.2 resolution: "eslint-plugin-react-native-globals@npm:0.1.2" @@ -26654,7 +27329,7 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-react@npm:7.34.1, eslint-plugin-react@npm:^7.27.1, eslint-plugin-react@npm:^7.30.1": +"eslint-plugin-react@npm:7.34.1": version: 7.34.1 resolution: "eslint-plugin-react@npm:7.34.1" dependencies: @@ -26682,6 +27357,34 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-react@npm:^7.27.1, eslint-plugin-react@npm:^7.30.1": + version: 7.37.2 + resolution: "eslint-plugin-react@npm:7.37.2" + dependencies: + array-includes: ^3.1.8 + array.prototype.findlast: ^1.2.5 + array.prototype.flatmap: ^1.3.2 + array.prototype.tosorted: ^1.1.4 + doctrine: ^2.1.0 + es-iterator-helpers: ^1.1.0 + estraverse: ^5.3.0 + hasown: ^2.0.2 + jsx-ast-utils: ^2.4.1 || ^3.0.0 + minimatch: ^3.1.2 + object.entries: ^1.1.8 + object.fromentries: ^2.0.8 + object.values: ^1.2.0 + prop-types: ^15.8.1 + resolve: ^2.0.0-next.5 + semver: ^6.3.1 + string.prototype.matchall: ^4.0.11 + string.prototype.repeat: ^1.0.0 + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + checksum: 7f5203afee7fbe3702b27fdd2b9a3c0ccbbb47d0672f58311b9d8a08dea819c9da4a87c15e8bd508f2562f327a9d29ee8bd9cd189bf758d8dc903de5648b0bfa + languageName: node + linkType: hard + "eslint-plugin-rulesdir@npm:0.2.2": version: 0.2.2 resolution: "eslint-plugin-rulesdir@npm:0.2.2" @@ -26711,16 +27414,17 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-storybook@npm:0.11.1": - version: 0.11.1 - resolution: "eslint-plugin-storybook@npm:0.11.1" +"eslint-plugin-storybook@npm:0.8.0": + version: 0.8.0 + resolution: "eslint-plugin-storybook@npm:0.8.0" dependencies: - "@storybook/csf": ^0.1.11 - "@typescript-eslint/utils": ^8.8.1 + "@storybook/csf": ^0.0.1 + "@typescript-eslint/utils": ^5.62.0 + requireindex: ^1.2.0 ts-dedent: ^2.2.0 peerDependencies: eslint: ">=6" - checksum: 8b8eb30b598f3c44c2bbf921e318215338f1159c1fba2d2f6cd5bc0b2ec14515655cf1760b5e11355baddabc2ac8446d4dc18ee6df6d2252555b126ff649a421 + checksum: 71e4b064259e09a6353360ca4a3ec929df0ea3aabe1dc83a40b9264fe5c16bcecb94d097e7403f6916622b8fdb739e91f1268bbad220d838fcbc2b9a901345ec languageName: node linkType: hard @@ -26788,17 +27492,6 @@ __metadata: languageName: node linkType: hard -"eslint-utils@npm:^3.0.0": - version: 3.0.0 - resolution: "eslint-utils@npm:3.0.0" - dependencies: - eslint-visitor-keys: ^2.0.0 - peerDependencies: - eslint: ">=5" - checksum: 0668fe02f5adab2e5a367eee5089f4c39033af20499df88fe4e6aba2015c20720404d8c3d6349b6f716b08fdf91b9da4e5d5481f265049278099c4c836ccb619 - languageName: node - linkType: hard - "eslint-visitor-keys@npm:^2.0.0, eslint-visitor-keys@npm:^2.1.0": version: 2.1.0 resolution: "eslint-visitor-keys@npm:2.1.0" @@ -26813,13 +27506,6 @@ __metadata: languageName: node linkType: hard -"eslint-visitor-keys@npm:^4.2.0": - version: 4.2.0 - resolution: "eslint-visitor-keys@npm:4.2.0" - checksum: 779c604672b570bb4da84cef32f6abb085ac78379779c1122d7879eade8bb38ae715645324597cf23232d03cef06032c9844d25c73625bc282a5bfd30247e5b5 - languageName: node - linkType: hard - "eslint-webpack-plugin@npm:^3.1.1": version: 3.2.0 resolution: "eslint-webpack-plugin@npm:3.2.0" @@ -26886,14 +27572,14 @@ __metadata: linkType: hard "eslint@npm:^8.3.0": - version: 8.53.0 - resolution: "eslint@npm:8.53.0" + version: 8.57.1 + resolution: "eslint@npm:8.57.1" dependencies: "@eslint-community/eslint-utils": ^4.2.0 "@eslint-community/regexpp": ^4.6.1 - "@eslint/eslintrc": ^2.1.3 - "@eslint/js": 8.53.0 - "@humanwhocodes/config-array": ^0.11.13 + "@eslint/eslintrc": ^2.1.4 + "@eslint/js": 8.57.1 + "@humanwhocodes/config-array": ^0.13.0 "@humanwhocodes/module-importer": ^1.0.1 "@nodelib/fs.walk": ^1.2.8 "@ungap/structured-clone": ^1.2.0 @@ -26929,7 +27615,7 @@ __metadata: text-table: ^0.2.0 bin: eslint: bin/eslint.js - checksum: 2da808655c7aa4b33f8970ba30d96b453c3071cc4d6cd60d367163430677e32ff186b65270816b662d29139283138bff81f28dddeb2e73265495245a316ed02c + checksum: e2489bb7f86dd2011967759a09164e65744ef7688c310bc990612fc26953f34cc391872807486b15c06833bdff737726a23e9b4cdba5de144c311377dc41d91b languageName: node linkType: hard @@ -27031,6 +27717,15 @@ __metadata: languageName: node linkType: hard +"estree-walker@npm:^3.0.3": + version: 3.0.3 + resolution: "estree-walker@npm:3.0.3" + dependencies: + "@types/estree": ^1.0.0 + checksum: a65728d5727b71de172c5df323385755a16c0fdab8234dc756c3854cfee343261ddfbb72a809a5660fac8c75d960bb3e21aa898c2d7e9b19bb298482ca58a3af + languageName: node + linkType: hard + "esutils@npm:^2.0.2": version: 2.0.3 resolution: "esutils@npm:2.0.3" @@ -27971,6 +28666,13 @@ __metadata: languageName: node linkType: hard +"fast-json-parse@npm:^1.0.3": + version: 1.0.3 + resolution: "fast-json-parse@npm:1.0.3" + checksum: c19117c56ec18a9aa133c8ebf450c99d1037117e47a3cb9aff91b60580ba48d0fd8484b696c26749a1b9cb4914084177b3fa9ebef72063a74dee7d9ead987603 + languageName: node + linkType: hard + "fast-json-patch@npm:^3.0.0-1": version: 3.1.1 resolution: "fast-json-patch@npm:3.1.1" @@ -28213,6 +28915,13 @@ __metadata: languageName: node linkType: hard +"filesize@npm:^10.0.12": + version: 10.1.6 + resolution: "filesize@npm:10.1.6" + checksum: a797a9d41c8f27a9ae334d23f99fc5d903eac5d03c82190dc163901205435b56626fe1260c779ba3e87a2a34d426f19ff264c3f7d956e00f2d3ac69760b52e33 + languageName: node + linkType: hard + "filesize@npm:^8.0.6": version: 8.0.7 resolution: "filesize@npm:8.0.7" @@ -28243,12 +28952,12 @@ __metadata: languageName: node linkType: hard -"fill-range@npm:^7.0.1": - version: 7.0.1 - resolution: "fill-range@npm:7.0.1" +"fill-range@npm:^7.1.1": + version: 7.1.1 + resolution: "fill-range@npm:7.1.1" dependencies: to-regex-range: ^5.0.1 - checksum: cc283f4e65b504259e64fd969bcf4def4eb08d85565e906b7d36516e87819db52029a76b6363d0f02d0d532f0033c9603b9e2d943d56ee3b0d4f7ad3328ff917 + checksum: b4abfbca3839a3d55e4ae5ec62e131e2e356bf4859ce8480c64c4876100f4df292a63e5bb1618e1d7460282ca2b305653064f01654474aa35c68000980f17798 languageName: node linkType: hard @@ -28559,6 +29268,16 @@ __metadata: languageName: node linkType: hard +"foreground-child@npm:^3.1.0": + version: 3.3.0 + resolution: "foreground-child@npm:3.3.0" + dependencies: + cross-spawn: ^7.0.0 + signal-exit: ^4.0.1 + checksum: 1989698488f725b05b26bc9afc8a08f08ec41807cd7b92ad85d96004ddf8243fd3e79486b8348c64a3011ae5cc2c9f0936af989e1f28339805d8bc178a75b451 + languageName: node + linkType: hard + "forever-agent@npm:~0.6.1": version: 0.6.1 resolution: "forever-agent@npm:0.6.1" @@ -28597,6 +29316,29 @@ __metadata: languageName: node linkType: hard +"fork-ts-checker-webpack-plugin@npm:^8.0.0": + version: 8.0.0 + resolution: "fork-ts-checker-webpack-plugin@npm:8.0.0" + dependencies: + "@babel/code-frame": ^7.16.7 + chalk: ^4.1.2 + chokidar: ^3.5.3 + cosmiconfig: ^7.0.1 + deepmerge: ^4.2.2 + fs-extra: ^10.0.0 + memfs: ^3.4.1 + minimatch: ^3.0.4 + node-abort-controller: ^3.0.1 + schema-utils: ^3.1.1 + semver: ^7.3.5 + tapable: ^2.2.1 + peerDependencies: + typescript: ">3.6.0" + webpack: ^5.11.0 + checksum: aad4cbc5b802e6281a2700a379837697c93ad95288468f9595219d91d9c26674736d37852bb4c4341e9122f26181e9e05fc1a362e8d029fdd88e99de7816037b + languageName: node + linkType: hard + "form-data-encoder@npm:1.7.2, form-data-encoder@npm:^1.7.1": version: 1.7.2 resolution: "form-data-encoder@npm:1.7.2" @@ -28679,7 +29421,7 @@ __metadata: languageName: node linkType: hard -"fraction.js@npm:^4.3.6": +"fraction.js@npm:^4.3.7": version: 4.3.7 resolution: "fraction.js@npm:4.3.7" checksum: e1553ae3f08e3ba0e8c06e43a3ab20b319966dfb7ddb96fd9b5d0ee11a66571af7f993229c88ebbb0d4a816eb813a24ed48207b140d442a8f76f33763b8d1f3f @@ -29441,6 +30183,22 @@ __metadata: languageName: node linkType: hard +"glob@npm:^10.3.10": + version: 10.4.5 + resolution: "glob@npm:10.4.5" + dependencies: + foreground-child: ^3.1.0 + jackspeak: ^3.1.2 + minimatch: ^9.0.4 + minipass: ^7.1.2 + package-json-from-dist: ^1.0.0 + path-scurry: ^1.11.1 + bin: + glob: dist/esm/bin.mjs + checksum: 0bc725de5e4862f9f387fd0f2b274baf16850dcd2714502ccf471ee401803997983e2c05590cb65f9675a3c6f2a58e7a53f9e365704108c6ad3cbf1d60934c4a + languageName: node + linkType: hard + "glob@npm:^6.0.1": version: 6.0.4 resolution: "glob@npm:6.0.4" @@ -29570,12 +30328,13 @@ __metadata: languageName: node linkType: hard -"globalthis@npm:^1.0.1, globalthis@npm:^1.0.3": - version: 1.0.3 - resolution: "globalthis@npm:1.0.3" +"globalthis@npm:^1.0.1, globalthis@npm:^1.0.3, globalthis@npm:^1.0.4": + version: 1.0.4 + resolution: "globalthis@npm:1.0.4" dependencies: - define-properties: ^1.1.3 - checksum: fbd7d760dc464c886d0196166d92e5ffb4c84d0730846d6621a39fbbc068aeeb9c8d1421ad330e94b7bca4bb4ea092f5f21f3d36077812af5d098b4dc006c998 + define-properties: ^1.2.1 + gopd: ^1.0.1 + checksum: 39ad667ad9f01476474633a1834a70842041f70a55571e8dcef5fb957980a92da5022db5430fca8aecc5d47704ae30618c0bc877a579c70710c904e9ef06108a languageName: node linkType: hard @@ -29758,7 +30517,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.0.0, graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.3, graceful-fs@npm:^4.1.5, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": +"graceful-fs@npm:^4.0.0, graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.3, graceful-fs@npm:^4.1.5, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: ac85f94da92d8eb6b7f5a8b20ce65e43d66761c55ce85ac96df6865308390da45a8d3f0296dd3a663de65d30ba497bd46c696cc1e248c72b13d6d567138a4fc7 @@ -30087,10 +30846,10 @@ __metadata: languageName: node linkType: hard -"has-symbols@npm:^1.0.2, has-symbols@npm:^1.0.3": - version: 1.0.3 - resolution: "has-symbols@npm:1.0.3" - checksum: a054c40c631c0d5741a8285010a0777ea0c068f99ed43e5d6eb12972da223f8af553a455132fdb0801bdcfa0e0f443c0c03a68d8555aa529b3144b446c3f2410 +"has-symbols@npm:^1.0.1, has-symbols@npm:^1.0.2, has-symbols@npm:^1.0.3": + version: 1.1.0 + resolution: "has-symbols@npm:1.1.0" + checksum: b2316c7302a0e8ba3aaba215f834e96c22c86f192e7310bdf689dd0e6999510c89b00fbc5742571507cebf25764d68c988b3a0da217369a73596191ac0ce694b languageName: node linkType: hard @@ -32139,16 +32898,29 @@ __metadata: languageName: node linkType: hard -"iterator.prototype@npm:^1.1.2": - version: 1.1.2 - resolution: "iterator.prototype@npm:1.1.2" +"iterator.prototype@npm:^1.1.3": + version: 1.1.3 + resolution: "iterator.prototype@npm:1.1.3" dependencies: define-properties: ^1.2.1 get-intrinsic: ^1.2.1 has-symbols: ^1.0.3 reflect.getprototypeof: ^1.0.4 set-function-name: ^2.0.1 - checksum: d8a507e2ccdc2ce762e8a1d3f4438c5669160ac72b88b648e59a688eec6bc4e64b22338e74000518418d9e693faf2a092d2af21b9ec7dbf7763b037a54701168 + checksum: 7d2a1f8bcbba7b76f72e956faaf7b25405f4de54430c9d099992e6fb9d571717c3044604e8cdfb8e624cb881337d648030ee8b1541d544af8b338835e3f47ebe + languageName: node + linkType: hard + +"jackspeak@npm:^3.1.2": + version: 3.4.3 + resolution: "jackspeak@npm:3.4.3" + dependencies: + "@isaacs/cliui": ^8.0.2 + "@pkgjs/parseargs": ^0.11.0 + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: be31027fc72e7cc726206b9f560395604b82e0fddb46c4cbf9f97d049bcef607491a5afc0699612eaa4213ca5be8fd3e1e7cd187b3040988b65c9489838a7c00 languageName: node linkType: hard @@ -33417,12 +34189,12 @@ __metadata: languageName: node linkType: hard -"jiti@npm:^1.17.1, jiti@npm:^1.19.1, jiti@npm:^1.21.0": - version: 1.21.0 - resolution: "jiti@npm:1.21.0" +"jiti@npm:^1.17.1, jiti@npm:^1.21.0, jiti@npm:^1.21.6": + version: 1.21.6 + resolution: "jiti@npm:1.21.6" bin: jiti: bin/jiti.js - checksum: a7bd5d63921c170eaec91eecd686388181c7828e1fa0657ab374b9372bfc1f383cf4b039e6b272383d5cb25607509880af814a39abdff967322459cca41f2961 + checksum: 9ea4a70a7bb950794824683ed1c632e2ede26949fbd348e2ba5ec8dc5efa54dc42022d85ae229cadaa60d4b95012e80ea07d625797199b688cc22ab0e8891d32 languageName: node linkType: hard @@ -33919,7 +34691,7 @@ __metadata: languageName: node linkType: hard -"jsonfile@npm:^6.0.1": +"jsonfile@npm:^6.0.1, jsonfile@npm:^6.1.0": version: 6.1.0 resolution: "jsonfile@npm:6.1.0" dependencies: @@ -33988,13 +34760,15 @@ __metadata: languageName: node linkType: hard -"jsx-ast-utils@npm:^2.4.1 || ^3.0.0, jsx-ast-utils@npm:^3.3.3": - version: 3.3.3 - resolution: "jsx-ast-utils@npm:3.3.3" +"jsx-ast-utils@npm:^2.4.1 || ^3.0.0, jsx-ast-utils@npm:^3.3.5": + version: 3.3.5 + resolution: "jsx-ast-utils@npm:3.3.5" dependencies: - array-includes: ^3.1.5 - object.assign: ^4.1.3 - checksum: a2ed78cac49a0f0c4be8b1eafe3c5257a1411341d8e7f1ac740debae003de04e5f6372bfcfbd9d082e954ffd99aac85bcda85b7c6bc11609992483f4cdc0f745 + array-includes: ^3.1.6 + array.prototype.flat: ^1.3.1 + object.assign: ^4.1.4 + object.values: ^1.1.6 + checksum: f4b05fa4d7b5234230c905cfa88d36dc8a58a6666975a3891429b1a8cdc8a140bca76c297225cb7a499fad25a2c052ac93934449a2c31a44fc9edd06c773780a languageName: node linkType: hard @@ -34117,19 +34891,19 @@ __metadata: languageName: node linkType: hard -"language-subtag-registry@npm:~0.3.2": - version: 0.3.22 - resolution: "language-subtag-registry@npm:0.3.22" - checksum: 8ab70a7e0e055fe977ac16ea4c261faec7205ac43db5e806f72e5b59606939a3b972c4bd1e10e323b35d6ffa97c3e1c4c99f6553069dad2dfdd22020fa3eb56a +"language-subtag-registry@npm:^0.3.20": + version: 0.3.23 + resolution: "language-subtag-registry@npm:0.3.23" + checksum: 0b64c1a6c5431c8df648a6d25594ff280613c886f4a1a542d9b864e5472fb93e5c7856b9c41595c38fac31370328fc79fcc521712e89ea6d6866cbb8e0995d81 languageName: node linkType: hard -"language-tags@npm:=1.0.5": - version: 1.0.5 - resolution: "language-tags@npm:1.0.5" +"language-tags@npm:^1.0.9": + version: 1.0.9 + resolution: "language-tags@npm:1.0.9" dependencies: - language-subtag-registry: ~0.3.2 - checksum: c81b5d8b9f5f9cfd06ee71ada6ddfe1cf83044dd5eeefcd1e420ad491944da8957688db4a0a9bc562df4afdc2783425cbbdfd152c01d93179cf86888903123cf + language-subtag-registry: ^0.3.20 + checksum: 57c530796dc7179914dee71bc94f3747fd694612480241d0453a063777265dfe3a951037f7acb48f456bf167d6eb419d4c00263745326b3ba1cdcf4657070e78 languageName: node linkType: hard @@ -34347,13 +35121,20 @@ __metadata: languageName: node linkType: hard -"lilconfig@npm:2.1.0, lilconfig@npm:^2.0.3, lilconfig@npm:^2.0.5, lilconfig@npm:^2.0.6, lilconfig@npm:^2.1.0": +"lilconfig@npm:2.1.0, lilconfig@npm:^2.0.3, lilconfig@npm:^2.0.6": version: 2.1.0 resolution: "lilconfig@npm:2.1.0" checksum: 8549bb352b8192375fed4a74694cd61ad293904eee33f9d4866c2192865c44c4eb35d10782966242634e0cbc1e91fe62b1247f148dc5514918e3a966da7ea117 languageName: node linkType: hard +"lilconfig@npm:^3.0.0, lilconfig@npm:^3.1.3": + version: 3.1.3 + resolution: "lilconfig@npm:3.1.3" + checksum: 644eb10830350f9cdc88610f71a921f510574ed02424b57b0b3abb66ea725d7a082559552524a842f4e0272c196b88dfe1ff7d35ffcc6f45736777185cd67c9a + languageName: node + linkType: hard + "linebreak@npm:^1.1.0": version: 1.1.0 resolution: "linebreak@npm:1.1.0" @@ -34566,9 +35347,9 @@ __metadata: linkType: hard "loader-utils@npm:^3.2.0, loader-utils@npm:^3.2.1": - version: 3.2.1 - resolution: "loader-utils@npm:3.2.1" - checksum: 4e3ea054cdc8be1ab1f1238f49f42fdf0483039eff920fb1d442039f3f0ad4ebd11fb8e584ccdf2cb7e3c56b3d40c1832416e6408a55651b843da288960cc792 + version: 3.3.1 + resolution: "loader-utils@npm:3.3.1" + checksum: d35808e081635e5bc50228a52ed79f83e2c82bd8f7578818c12b1b4cf0b7f409d72d9b93a683ec36b9eaa93346693d3f3c8380183ba2ff81599b0829d685de39 languageName: node linkType: hard @@ -34873,6 +35654,13 @@ __metadata: languageName: node linkType: hard +"loupe@npm:^3.1.0, loupe@npm:^3.1.1, loupe@npm:^3.1.2": + version: 3.1.2 + resolution: "loupe@npm:3.1.2" + checksum: 4a75bbe8877a1ced3603e08b1095cd6f4c987c50fe63719fdc3009029560f91e07a915e7f6eff1322bb62bfb2a2beeef06b13ccb3c12f81bda9f3674434dcab9 + languageName: node + linkType: hard + "lower-case-first@npm:^2.0.2": version: 2.0.2 resolution: "lower-case-first@npm:2.0.2" @@ -34905,10 +35693,10 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^10.0.2, lru-cache@npm:^9.1.1 || ^10.0.0": - version: 10.1.0 - resolution: "lru-cache@npm:10.1.0" - checksum: 58056d33e2500fbedce92f8c542e7c11b50d7d086578f14b7074d8c241422004af0718e08a6eaae8705cee09c77e39a61c1c79e9370ba689b7010c152e6a76ab +"lru-cache@npm:^10.0.2, lru-cache@npm:^10.2.0": + version: 10.4.3 + resolution: "lru-cache@npm:10.4.3" + checksum: 6476138d2125387a6d20f100608c2583d415a4f64a0fecf30c9e2dda976614f09cad4baa0842447bd37dd459a7bd27f57d9d8f8ce558805abd487c583f3d774a languageName: node linkType: hard @@ -35294,7 +36082,7 @@ __metadata: languageName: node linkType: hard -"memfs@npm:^3.1.2, memfs@npm:^3.4.3": +"memfs@npm:^3.1.2, memfs@npm:^3.4.1, memfs@npm:^3.4.12, memfs@npm:^3.4.3": version: 3.5.3 resolution: "memfs@npm:3.5.3" dependencies: @@ -35646,7 +36434,7 @@ __metadata: languageName: node linkType: hard -"micromatch@npm:4.0.5, micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5": +"micromatch@npm:4.0.5": version: 4.0.5 resolution: "micromatch@npm:4.0.5" dependencies: @@ -35656,6 +36444,16 @@ __metadata: languageName: node linkType: hard +"micromatch@npm:^4.0.0, micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5, micromatch@npm:^4.0.8": + version: 4.0.8 + resolution: "micromatch@npm:4.0.8" + dependencies: + braces: ^3.0.3 + picomatch: ^2.3.1 + checksum: 79920eb634e6f400b464a954fcfa589c4e7c7143209488e44baf627f9affc8b1e306f41f4f0deedde97e69cb725920879462d3e750ab3bd3c1aed675bb3a8966 + languageName: node + linkType: hard + "miller-rabin@npm:^4.0.0": version: 4.0.1 resolution: "miller-rabin@npm:4.0.1" @@ -35771,14 +36569,14 @@ __metadata: languageName: node linkType: hard -"min-indent@npm:^1.0.0": +"min-indent@npm:^1.0.0, min-indent@npm:^1.0.1": version: 1.0.1 resolution: "min-indent@npm:1.0.1" checksum: bfc6dd03c5eaf623a4963ebd94d087f6f4bbbfd8c41329a7f09706b0cb66969c4ddd336abeb587bc44bc6f08e13bf90f0b374f9d71f9f01e04adc2cd6f083ef1 languageName: node linkType: hard -"mini-css-extract-plugin@npm:2.9.1, mini-css-extract-plugin@npm:^2.4.5": +"mini-css-extract-plugin@npm:2.9.1": version: 2.9.1 resolution: "mini-css-extract-plugin@npm:2.9.1" dependencies: @@ -35790,6 +36588,18 @@ __metadata: languageName: node linkType: hard +"mini-css-extract-plugin@npm:^2.4.5": + version: 2.9.2 + resolution: "mini-css-extract-plugin@npm:2.9.2" + dependencies: + schema-utils: ^4.0.0 + tapable: ^2.2.1 + peerDependencies: + webpack: ^5.0.0 + checksum: 67a1f75359371a7776108999d472ae0942ccd904401e364e3a2c710d4b6fec61c4f53288594fcac35891f009e6df8825a00dfd3bfe4bcec0f862081d1f7cad50 + languageName: node + linkType: hard + "miniflare@npm:3.20231025.0": version: 3.20231025.0 resolution: "miniflare@npm:3.20231025.0" @@ -35998,10 +36808,10 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0": - version: 7.0.4 - resolution: "minipass@npm:7.0.4" - checksum: 87585e258b9488caf2e7acea242fd7856bbe9a2c84a7807643513a338d66f368c7d518200ad7b70a508664d408aa000517647b2930c259a8b1f9f0984f344a21 +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.1.2": + version: 7.1.2 + resolution: "minipass@npm:7.1.2" + checksum: 2bfd325b95c555f2b4d2814d49325691c7bee937d753814861b0b49d5edcda55cbbf22b6b6a60bb91eddac8668771f03c5ff647dcd9d0f798e9548b9cdc46ee3 languageName: node linkType: hard @@ -36529,7 +37339,7 @@ __metadata: languageName: node linkType: hard -"node-abort-controller@npm:^3.1.1": +"node-abort-controller@npm:^3.0.1, node-abort-controller@npm:^3.1.1": version: 3.1.1 resolution: "node-abort-controller@npm:3.1.1" checksum: 2c340916af9710328b11c0828223fc65ba320e0d082214a211311bf64c2891028e42ef276b9799188c4ada9e6e1c54cf7a0b7c05dd9d59fcdc8cd633304c8047 @@ -36989,9 +37799,9 @@ __metadata: linkType: hard "nwsapi@npm:^2.2.0, nwsapi@npm:^2.2.2": - version: 2.2.7 - resolution: "nwsapi@npm:2.2.7" - checksum: cab25f7983acec7e23490fec3ef7be608041b460504229770e3bfcf9977c41d6fe58f518994d3bd9aa3a101f501089a3d4a63536f4ff8ae4b8c4ca23bdbfda4e + version: 2.2.16 + resolution: "nwsapi@npm:2.2.16" + checksum: 467b36a74b7b8647d53fd61d05ca7d6c73a4a5d1b94ea84f770c03150b00ef46d38076cf8e708936246ae450c42a1f21e28e153023719784dc4d1a19b1737d47 languageName: node linkType: hard @@ -37027,10 +37837,10 @@ __metadata: languageName: node linkType: hard -"object-inspect@npm:^1.13.1": - version: 1.13.1 - resolution: "object-inspect@npm:1.13.1" - checksum: 7d9fa9221de3311dcb5c7c307ee5dc011cdd31dc43624b7c184b3840514e118e05ef0002be5388304c416c0eb592feb46e983db12577fc47e47d5752fbbfb61f +"object-inspect@npm:^1.13.1, object-inspect@npm:^1.13.3": + version: 1.13.3 + resolution: "object-inspect@npm:1.13.3" + checksum: 8c962102117241e18ea403b84d2521f78291b774b03a29ee80a9863621d88265ffd11d0d7e435c4c2cea0dc2a2fbf8bbc92255737a05536590f2df2e8756f297 languageName: node linkType: hard @@ -37051,7 +37861,7 @@ __metadata: languageName: node linkType: hard -"object.assign@npm:^4.0.4, object.assign@npm:^4.1.3, object.assign@npm:^4.1.4, object.assign@npm:^4.1.5": +"object.assign@npm:^4.0.4, object.assign@npm:^4.1.4, object.assign@npm:^4.1.5": version: 4.1.5 resolution: "object.assign@npm:4.1.5" dependencies: @@ -37063,7 +37873,7 @@ __metadata: languageName: node linkType: hard -"object.entries@npm:^1.1.6, object.entries@npm:^1.1.7": +"object.entries@npm:^1.1.7, object.entries@npm:^1.1.8": version: 1.1.8 resolution: "object.entries@npm:1.1.8" dependencies: @@ -37074,7 +37884,7 @@ __metadata: languageName: node linkType: hard -"object.fromentries@npm:^2.0.6, object.fromentries@npm:^2.0.7": +"object.fromentries@npm:^2.0.7, object.fromentries@npm:^2.0.8": version: 2.0.8 resolution: "object.fromentries@npm:2.0.8" dependencies: @@ -37086,14 +37896,18 @@ __metadata: languageName: node linkType: hard -"object.getownpropertydescriptors@npm:^2.0.3": - version: 2.1.3 - resolution: "object.getownpropertydescriptors@npm:2.1.3" +"object.getownpropertydescriptors@npm:^2.1.0": + version: 2.1.8 + resolution: "object.getownpropertydescriptors@npm:2.1.8" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.3 - es-abstract: ^1.19.1 - checksum: 1467873456fd367a0eb91350caff359a8f05ceb069b4535a1846aa1f74f477a49ae704f6c89c0c14cc0ae1518ee3a0aa57c7f733a8e7b2b06b34a818e9593d2f + array.prototype.reduce: ^1.0.6 + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-object-atoms: ^1.0.0 + gopd: ^1.0.1 + safe-array-concat: ^1.1.2 + checksum: 073e492700a7f61ff6c471a2ed96e72473b030a7a105617f03cab192fb4bbc0e6068ef76534ec56afd34baf26b5dc5408de59cb0140ec8abde781e00faa3e63e languageName: node linkType: hard @@ -37108,7 +37922,7 @@ __metadata: languageName: node linkType: hard -"object.values@npm:^1.1.0, object.values@npm:^1.1.6, object.values@npm:^1.1.7": +"object.values@npm:^1.1.0, object.values@npm:^1.1.6, object.values@npm:^1.1.7, object.values@npm:^1.2.0": version: 1.2.0 resolution: "object.values@npm:1.2.0" dependencies: @@ -37119,6 +37933,13 @@ __metadata: languageName: node linkType: hard +"objectorarray@npm:^1.0.5": + version: 1.0.5 + resolution: "objectorarray@npm:1.0.5" + checksum: 8fd776aa495d113e217837f4adc1d53e63f656498237094d25f84c3e2c038b34b71d6fd85c4b60c7ae5f558790e5042426a400fae3eac35f297e11be12643a78 + languageName: node + linkType: hard + "obliterator@npm:^2.0.0": version: 2.0.0 resolution: "obliterator@npm:2.0.0" @@ -37555,6 +38376,13 @@ __metadata: languageName: node linkType: hard +"package-json-from-dist@npm:^1.0.0": + version: 1.0.1 + resolution: "package-json-from-dist@npm:1.0.1" + checksum: 58ee9538f2f762988433da00e26acc788036914d57c71c246bf0be1b60cdbd77dd60b6a3e1a30465f0b248aeb80079e0b34cb6050b1dfa18c06953bb1cbc7602 + languageName: node + linkType: hard + "package-json@npm:^4.0.0": version: 4.0.1 resolution: "package-json@npm:4.0.1" @@ -37935,13 +38763,13 @@ __metadata: languageName: node linkType: hard -"path-scurry@npm:^1.6.1": - version: 1.10.1 - resolution: "path-scurry@npm:1.10.1" +"path-scurry@npm:^1.11.1, path-scurry@npm:^1.6.1": + version: 1.11.1 + resolution: "path-scurry@npm:1.11.1" dependencies: - lru-cache: ^9.1.1 || ^10.0.0 + lru-cache: ^10.2.0 minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 - checksum: e2557cff3a8fb8bc07afdd6ab163a92587884f9969b05bbbaf6fe7379348bfb09af9ed292af12ed32398b15fb443e81692047b786d1eeb6d898a51eb17ed7d90 + checksum: 890d5abcd593a7912dcce7cf7c6bf7a0b5648e3dee6caf0712c126ca0a65c7f3d7b9d769072a4d1baf370f61ce493ab5b038d59988688e0c5f3f646ee3c69023 languageName: node linkType: hard @@ -37980,6 +38808,13 @@ __metadata: languageName: node linkType: hard +"pathval@npm:^2.0.0": + version: 2.0.0 + resolution: "pathval@npm:2.0.0" + checksum: 682b6a6289de7990909effef7dae9aa7bb6218c0426727bccf66a35b34e7bfbc65615270c5e44e3c9557a5cb44b1b9ef47fc3cb18bce6ad3ba92bcd28467ed7d + languageName: node + linkType: hard + "pause-stream@npm:0.0.11": version: 0.0.11 resolution: "pause-stream@npm:0.0.11" @@ -38030,7 +38865,7 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:^1.0.0, picocolors@npm:^1.1.0": +"picocolors@npm:^1.0.0, picocolors@npm:^1.0.1, picocolors@npm:^1.1.0, picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" checksum: e1cf46bf84886c79055fdfa9dcb3e4711ad259949e3565154b004b260cd356c5d54b31a1437ce9782624bf766272fe6b0154f5f0c744fb7af5d454d2b60db045 @@ -38262,6 +39097,15 @@ __metadata: languageName: node linkType: hard +"pnp-webpack-plugin@npm:^1.7.0": + version: 1.7.0 + resolution: "pnp-webpack-plugin@npm:1.7.0" + dependencies: + ts-pnp: ^1.1.6 + checksum: a41716d13607be5a3e06ba58b17e9e619cf07da3a0a7b10bd41cd89362873041054fd2b7966ad30a1b26b826cfb8fecc0469a95902d5b1b8ba8f591e2fe6b96d + languageName: node + linkType: hard + "poisson-disk-sampling@npm:2.3.1": version: 2.3.1 resolution: "poisson-disk-sampling@npm:2.3.1" @@ -38280,7 +39124,7 @@ __metadata: languageName: node linkType: hard -"polished@npm:^4.3.1": +"polished@npm:^4.2.2, polished@npm:^4.3.1": version: 4.3.1 resolution: "polished@npm:4.3.1" dependencies: @@ -38633,12 +39477,12 @@ __metadata: languageName: node linkType: hard -"postcss-load-config@npm:^4.0.1": - version: 4.0.1 - resolution: "postcss-load-config@npm:4.0.1" +"postcss-load-config@npm:^4.0.2": + version: 4.0.2 + resolution: "postcss-load-config@npm:4.0.2" dependencies: - lilconfig: ^2.0.5 - yaml: ^2.1.1 + lilconfig: ^3.0.0 + yaml: ^2.3.4 peerDependencies: postcss: ">=8.0.9" ts-node: ">=9.0.0" @@ -38647,7 +39491,7 @@ __metadata: optional: true ts-node: optional: true - checksum: b61f890499ed7dcda1e36c20a9582b17d745bad5e2b2c7bc96942465e406bc43ae03f270c08e60d1e29dab1ee50cb26970b5eb20c9aae30e066e20bd607ae4e4 + checksum: 7c27dd3801db4eae207a5116fed2db6b1ebb780b40c3dd62a3e57e087093a8e6a14ee17ada729fee903152d6ef4826c6339eb135bee6208e0f3140d7e8090185 languageName: node linkType: hard @@ -38757,36 +39601,36 @@ __metadata: languageName: node linkType: hard -"postcss-modules-extract-imports@npm:^3.0.0": - version: 3.0.0 - resolution: "postcss-modules-extract-imports@npm:3.0.0" +"postcss-modules-extract-imports@npm:^3.1.0": + version: 3.1.0 + resolution: "postcss-modules-extract-imports@npm:3.1.0" peerDependencies: postcss: ^8.1.0 - checksum: 4b65f2f1382d89c4bc3c0a1bdc5942f52f3cb19c110c57bd591ffab3a5fee03fcf831604168205b0c1b631a3dce2255c70b61aaae3ef39d69cd7eb450c2552d2 + checksum: b9192e0f4fb3d19431558be6f8af7ca45fc92baaad9b2778d1732a5880cd25c3df2074ce5484ae491e224f0d21345ffc2d419bd51c25b019af76d7a7af88c17f languageName: node linkType: hard -"postcss-modules-local-by-default@npm:^4.0.3": - version: 4.0.3 - resolution: "postcss-modules-local-by-default@npm:4.0.3" +"postcss-modules-local-by-default@npm:^4.0.5": + version: 4.1.0 + resolution: "postcss-modules-local-by-default@npm:4.1.0" dependencies: icss-utils: ^5.0.0 - postcss-selector-parser: ^6.0.2 + postcss-selector-parser: ^7.0.0 postcss-value-parser: ^4.1.0 peerDependencies: postcss: ^8.1.0 - checksum: 2f8083687f3d6067885f8863dd32dbbb4f779cfcc7e52c17abede9311d84faf6d3ed8760e7c54c6380281732ae1f78e5e56a28baf3c271b33f450a11c9e30485 + checksum: 64ac4803c21dd82e227179cf0a8489c645ea99a8c514475da028c9afe5d5b915485d00d8efbe94295d688a23a172965cc15f20d550168d1fed272dbdbbe053f0 languageName: node linkType: hard -"postcss-modules-scope@npm:^3.0.0": - version: 3.0.0 - resolution: "postcss-modules-scope@npm:3.0.0" +"postcss-modules-scope@npm:^3.2.0": + version: 3.2.1 + resolution: "postcss-modules-scope@npm:3.2.1" dependencies: - postcss-selector-parser: ^6.0.4 + postcss-selector-parser: ^7.0.0 peerDependencies: postcss: ^8.1.0 - checksum: 330b9398dbd44c992c92b0dc612c0626135e2cc840fee41841eb61247a6cfed95af2bd6f67ead9dd9d0bb41f5b0367129d93c6e434fa3e9c58ade391d9a5a138 + checksum: 085f65863bb7d8bf08209a979ceb22b2b07bb466574e0e698d34aaad832d614957bb05f2418348a14e4035f65e23b2be2951369d26ea429dd5762c6a020f0f7c languageName: node linkType: hard @@ -38801,14 +39645,14 @@ __metadata: languageName: node linkType: hard -"postcss-nested@npm:^6.0.1": - version: 6.0.1 - resolution: "postcss-nested@npm:6.0.1" +"postcss-nested@npm:^6.2.0": + version: 6.2.0 + resolution: "postcss-nested@npm:6.2.0" dependencies: - postcss-selector-parser: ^6.0.11 + postcss-selector-parser: ^6.1.1 peerDependencies: postcss: ^8.2.14 - checksum: 7ddb0364cd797de01e38f644879189e0caeb7ea3f78628c933d91cc24f327c56d31269384454fc02ecaf503b44bfa8e08870a7c4cc56b23bc15640e1894523fa + checksum: 2c86ecf2d0ce68f27c87c7e24ae22dc6dd5515a89fcaf372b2627906e11f5c1f36e4a09e4c15c20fd4a23d628b3d945c35839f44496fbee9a25866258006671b languageName: node linkType: hard @@ -39102,13 +39946,23 @@ __metadata: languageName: node linkType: hard -"postcss-selector-parser@npm:^6.0.10, postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4, postcss-selector-parser@npm:^6.0.5, postcss-selector-parser@npm:^6.0.9": - version: 6.0.13 - resolution: "postcss-selector-parser@npm:6.0.13" +"postcss-selector-parser@npm:^6.0.10, postcss-selector-parser@npm:^6.0.4, postcss-selector-parser@npm:^6.0.5, postcss-selector-parser@npm:^6.0.9, postcss-selector-parser@npm:^6.1.1, postcss-selector-parser@npm:^6.1.2": + version: 6.1.2 + resolution: "postcss-selector-parser@npm:6.1.2" + dependencies: + cssesc: ^3.0.0 + util-deprecate: ^1.0.2 + checksum: ce9440fc42a5419d103f4c7c1847cb75488f3ac9cbe81093b408ee9701193a509f664b4d10a2b4d82c694ee7495e022f8f482d254f92b7ffd9ed9dea696c6f84 + languageName: node + linkType: hard + +"postcss-selector-parser@npm:^7.0.0": + version: 7.0.0 + resolution: "postcss-selector-parser@npm:7.0.0" dependencies: cssesc: ^3.0.0 util-deprecate: ^1.0.2 - checksum: f89163338a1ce3b8ece8e9055cd5a3165e79a15e1c408e18de5ad8f87796b61ec2d48a2902d179ae0c4b5de10fccd3a325a4e660596549b040bc5ad1b465f096 + checksum: f906b7449fcbe9fa6ae739b6fc324ee3c6201aaf5224f26da27de64ccba68d878d734dd182a467881e463f7ede08972d0129b0cc4d6b671d78c6492cddcef154 languageName: node linkType: hard @@ -39176,14 +40030,14 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.1.7, postcss@npm:^8.3.5, postcss@npm:^8.4.21, postcss@npm:^8.4.23, postcss@npm:^8.4.27, postcss@npm:^8.4.32, postcss@npm:^8.4.4, postcss@npm:~8.4.32": - version: 8.4.38 - resolution: "postcss@npm:8.4.38" +"postcss@npm:^8.1.7, postcss@npm:^8.3.5, postcss@npm:^8.4.23, postcss@npm:^8.4.27, postcss@npm:^8.4.32, postcss@npm:^8.4.33, postcss@npm:^8.4.4, postcss@npm:^8.4.47, postcss@npm:~8.4.32": + version: 8.4.49 + resolution: "postcss@npm:8.4.49" dependencies: nanoid: ^3.3.7 - picocolors: ^1.0.0 - source-map-js: ^1.2.0 - checksum: 649f9e60a763ca4b5a7bbec446a069edf07f057f6d780a5a0070576b841538d1ecf7dd888f2fbfd1f76200e26c969e405aeeae66332e6927dbdc8bdcb90b9451 + picocolors: ^1.1.1 + source-map-js: ^1.2.1 + checksum: eb5d6cbdca24f50399aafa5d2bea489e4caee4c563ea1edd5a2485bc5f84e9ceef3febf170272bc83a99c31d23a316ad179213e853f34c2a7a8ffa534559d63a languageName: node linkType: hard @@ -40090,6 +40944,17 @@ __metadata: languageName: node linkType: hard +"react-confetti@npm:^6.1.0": + version: 6.1.0 + resolution: "react-confetti@npm:6.1.0" + dependencies: + tween-functions: ^1.2.0 + peerDependencies: + react: ^16.3.0 || ^17.0.1 || ^18.0.0 + checksum: 24b6975df144d2bf09d8e1c95ddc49e547775f911efaa8d96b49e522659d931539e9d9e48cc0db3a01f3a671be7e3824e6e728db85096f5527db5d1c69ebb153 + languageName: node + linkType: hard + "react-dev-utils@npm:^12.0.1": version: 12.0.1 resolution: "react-dev-utils@npm:12.0.1" @@ -40158,6 +41023,33 @@ __metadata: languageName: node linkType: hard +"react-docgen-typescript@npm:^2.2.2": + version: 2.2.2 + resolution: "react-docgen-typescript@npm:2.2.2" + peerDependencies: + typescript: ">= 4.3.x" + checksum: a9826459ea44e818f21402728dd47f5cae60bd936574cefd4f90ad101ff3eebacd67b6e017b793309734ce62c037aa3072dbc855d2b0e29bad1a38cbf5bac115 + languageName: node + linkType: hard + +"react-docgen@npm:^7.0.0": + version: 7.1.0 + resolution: "react-docgen@npm:7.1.0" + dependencies: + "@babel/core": ^7.18.9 + "@babel/traverse": ^7.18.9 + "@babel/types": ^7.18.9 + "@types/babel__core": ^7.18.0 + "@types/babel__traverse": ^7.18.0 + "@types/doctrine": ^0.0.9 + "@types/resolve": ^1.20.2 + doctrine: ^3.0.0 + resolve: ^1.22.1 + strip-indent: ^4.0.0 + checksum: dfdec82a4d695e8b1e31b77eef4ceac0f60e00f13725f0a18886d2737595531e58a54f4dde5db4657276d194597bd5e67a1792ca52eb42a59b67943105f24893 + languageName: node + linkType: hard + "react-dom@npm:18.2.0": version: 18.2.0 resolution: "react-dom@npm:18.2.0" @@ -41618,9 +42510,9 @@ __metadata: linkType: hard "regex-parser@npm:^2.2.11": - version: 2.2.11 - resolution: "regex-parser@npm:2.2.11" - checksum: 78200331ec0cc372302d287a4946c38681eb5fe435453fca572cb53cac0ba579e5eb3b9e25eac24c0c80a555fb3ea7a637814a35da1e9bc88e8819110ae5de24 + version: 2.3.0 + resolution: "regex-parser@npm:2.3.0" + checksum: bcd1eb7e9b0775b6f44928ceb0280ad5b6e4da91e1070d3e9a653fcf72d2d04873c44190fb569141b6897fe94e9514fee1f3ac7ba112ccd9c9b5ad6eabab6bbd languageName: node linkType: hard @@ -41633,7 +42525,7 @@ __metadata: languageName: node linkType: hard -"regexp.prototype.flags@npm:^1.4.3, regexp.prototype.flags@npm:^1.5.1, regexp.prototype.flags@npm:^1.5.2": +"regexp.prototype.flags@npm:^1.4.3, regexp.prototype.flags@npm:^1.5.1, regexp.prototype.flags@npm:^1.5.2, regexp.prototype.flags@npm:^1.5.3": version: 1.5.3 resolution: "regexp.prototype.flags@npm:1.5.3" dependencies: @@ -41927,6 +42819,13 @@ __metadata: languageName: node linkType: hard +"requireindex@npm:^1.2.0": + version: 1.2.0 + resolution: "requireindex@npm:1.2.0" + checksum: 50d8b10a1ff1fdf6aea7a1870bc7bd238b0fb1917d8d7ca17fd03afc38a65dcd7a8a4eddd031f89128b5f0065833d5c92c4fef67f2c04e8624057fe626c9cf94 + languageName: node + linkType: hard + "requireindex@npm:~1.1.0": version: 1.1.0 resolution: "requireindex@npm:1.1.0" @@ -42358,8 +43257,8 @@ __metadata: linkType: hard "rollup@npm:^2.43.1": - version: 2.79.1 - resolution: "rollup@npm:2.79.1" + version: 2.79.2 + resolution: "rollup@npm:2.79.2" dependencies: fsevents: ~2.3.2 dependenciesMeta: @@ -42367,7 +43266,7 @@ __metadata: optional: true bin: rollup: dist/bin/rollup - checksum: 6a2bf167b3587d4df709b37d149ad0300692cc5deb510f89ac7bdc77c8738c9546ae3de9322b0968e1ed2b0e984571f5f55aae28fa7de4cfcb1bc5402a4e2be6 + checksum: df7aa4c8b95245dede157b06ab71e1921de6080757d30e9bf31f8fb142064d12dda865e2bafbab4349588f43425b2965a290c9a5da1c048246a70fc21734ebd7 languageName: node linkType: hard @@ -42669,15 +43568,15 @@ __metadata: languageName: node linkType: hard -"schema-utils@npm:^4.0.0": - version: 4.0.1 - resolution: "schema-utils@npm:4.0.1" +"schema-utils@npm:^4.0.0, schema-utils@npm:^4.2.0": + version: 4.2.0 + resolution: "schema-utils@npm:4.2.0" dependencies: "@types/json-schema": ^7.0.9 ajv: ^8.9.0 ajv-formats: ^2.1.1 ajv-keywords: ^5.1.0 - checksum: 745e7293c6b6c84940de16753c207311da821aa9911b9e2d158cfd9ffc5bf1f880147abbbe775b96cb8cd3c7f48890950fe0164f54eed9a8aabb948ebf8a3fdd + checksum: 26a0463d47683258106e6652e9aeb0823bf0b85843039e068b57da1892f7ae6b6b1094d48e9ed5ba5cbe9f7166469d880858b9d91abe8bd249421eb813850cde languageName: node linkType: hard @@ -43101,7 +44000,7 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^4.1.0": +"signal-exit@npm:^4.0.1, signal-exit@npm:^4.1.0": version: 4.1.0 resolution: "signal-exit@npm:4.1.0" checksum: 64c757b498cb8629ffa5f75485340594d2f8189e9b08700e69199069c8e3070fb3e255f7ab873c05dc0b3cec412aea7402e10a5990cb6a050bd33ba062a6c549 @@ -43391,10 +44290,10 @@ __metadata: languageName: node linkType: hard -"source-map-js@npm:^1.0.1, source-map-js@npm:^1.0.2, source-map-js@npm:^1.2.0": - version: 1.2.0 - resolution: "source-map-js@npm:1.2.0" - checksum: 791a43306d9223792e84293b00458bf102a8946e7188f3db0e4e22d8d530b5f80a4ce468eb5ec0bf585443ad55ebbd630bf379c98db0b1f317fd902500217f97 +"source-map-js@npm:^1.0.1, source-map-js@npm:^1.0.2, source-map-js@npm:^1.2.1": + version: 1.2.1 + resolution: "source-map-js@npm:1.2.1" + checksum: 4eb0cd997cdf228bc253bcaff9340afeb706176e64868ecd20efbe6efea931465f43955612346d6b7318789e5265bdc419bc7669c1cebe3db0eb255f57efa76b languageName: node linkType: hard @@ -43925,6 +44824,24 @@ __metadata: languageName: node linkType: hard +"storybook@npm:8.4.2": + version: 8.4.2 + resolution: "storybook@npm:8.4.2" + dependencies: + "@storybook/core": 8.4.2 + peerDependencies: + prettier: ^2 || ^3 + peerDependenciesMeta: + prettier: + optional: true + bin: + getstorybook: ./bin/index.cjs + sb: ./bin/index.cjs + storybook: ./bin/index.cjs + checksum: 8fe9013ea95d0f10493b3ba6c0b1599b6c1efdb9f5e59e36c1f4b4ec6200640581ab37b415d4aa86c0a70bd4cb919d25d6411f906580d0a7ca42542e8032d8de + languageName: node + linkType: hard + "storybook@npm:^8.4.2": version: 8.4.5 resolution: "storybook@npm:8.4.5" @@ -44108,6 +45025,17 @@ __metadata: languageName: node linkType: hard +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.0.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.2, string-width@npm:^4.2.3": + version: 4.2.3 + resolution: "string-width@npm:4.2.3" + dependencies: + emoji-regex: ^8.0.0 + is-fullwidth-code-point: ^3.0.0 + strip-ansi: ^6.0.1 + checksum: e52c10dc3fbfcd6c3a15f159f54a90024241d0f149cf8aed2982a2d801d2e64df0bf1dc351cf8e95c3319323f9f220c16e740b06faecd53e2462df1d2b5443fb + languageName: node + linkType: hard + "string-width@npm:^1.0.1": version: 1.0.2 resolution: "string-width@npm:1.0.2" @@ -44119,17 +45047,6 @@ __metadata: languageName: node linkType: hard -"string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.0.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.2, string-width@npm:^4.2.3": - version: 4.2.3 - resolution: "string-width@npm:4.2.3" - dependencies: - emoji-regex: ^8.0.0 - is-fullwidth-code-point: ^3.0.0 - strip-ansi: ^6.0.1 - checksum: e52c10dc3fbfcd6c3a15f159f54a90024241d0f149cf8aed2982a2d801d2e64df0bf1dc351cf8e95c3319323f9f220c16e740b06faecd53e2462df1d2b5443fb - languageName: node - linkType: hard - "string-width@npm:^2.0.0, string-width@npm:^2.1.1": version: 2.1.1 resolution: "string-width@npm:2.1.1" @@ -44158,7 +45075,18 @@ __metadata: languageName: node linkType: hard -"string.prototype.matchall@npm:^4.0.10, string.prototype.matchall@npm:^4.0.6": +"string.prototype.includes@npm:^2.0.1": + version: 2.0.1 + resolution: "string.prototype.includes@npm:2.0.1" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.3 + checksum: ed4b7058b092f30d41c4df1e3e805eeea92479d2c7a886aa30f42ae32fde8924a10cc99cccc99c29b8e18c48216608a0fe6bf887f8b4aadf9559096a758f313a + languageName: node + linkType: hard + +"string.prototype.matchall@npm:^4.0.10, string.prototype.matchall@npm:^4.0.11, string.prototype.matchall@npm:^4.0.6": version: 4.0.11 resolution: "string.prototype.matchall@npm:4.0.11" dependencies: @@ -44178,6 +45106,16 @@ __metadata: languageName: node linkType: hard +"string.prototype.repeat@npm:^1.0.0": + version: 1.0.0 + resolution: "string.prototype.repeat@npm:1.0.0" + dependencies: + define-properties: ^1.1.3 + es-abstract: ^1.17.5 + checksum: 95dfc514ed7f328d80a066dabbfbbb1615c3e51490351085409db2eb7cbfed7ea29fdadaf277647fbf9f4a1e10e6dd9e95e78c0fd2c4e6bb6723ea6e59401004 + languageName: node + linkType: hard + "string.prototype.trim@npm:^1.2.9": version: 1.2.9 resolution: "string.prototype.trim@npm:1.2.9" @@ -44241,6 +45179,15 @@ __metadata: languageName: node linkType: hard +"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": + version: 6.0.1 + resolution: "strip-ansi@npm:6.0.1" + dependencies: + ansi-regex: ^5.0.1 + checksum: f3cd25890aef3ba6e1a74e20896c21a46f482e93df4a06567cebf2b57edabb15133f1f94e57434e0a958d61186087b1008e89c94875d019910a213181a14fc8c + languageName: node + linkType: hard + "strip-ansi@npm:^3.0.0, strip-ansi@npm:^3.0.1": version: 3.0.1 resolution: "strip-ansi@npm:3.0.1" @@ -44268,21 +45215,12 @@ __metadata: languageName: node linkType: hard -"strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": - version: 6.0.1 - resolution: "strip-ansi@npm:6.0.1" - dependencies: - ansi-regex: ^5.0.1 - checksum: f3cd25890aef3ba6e1a74e20896c21a46f482e93df4a06567cebf2b57edabb15133f1f94e57434e0a958d61186087b1008e89c94875d019910a213181a14fc8c - languageName: node - linkType: hard - -"strip-ansi@npm:^7.0.1": - version: 7.0.1 - resolution: "strip-ansi@npm:7.0.1" +"strip-ansi@npm:^7.0.1, strip-ansi@npm:^7.1.0": + version: 7.1.0 + resolution: "strip-ansi@npm:7.1.0" dependencies: ansi-regex: ^6.0.1 - checksum: 257f78fa433520e7f9897722731d78599cb3fce29ff26a20a5e12ba4957463b50a01136f37c43707f4951817a75e90820174853d6ccc240997adc5df8f966039 + checksum: 859c73fcf27869c22a4e4d8c6acfe690064659e84bef9458aa6d13719d09ca88dcfd40cbf31fd0be63518ea1a643fe070b4827d353e09533a5b0b9fd4553d64d languageName: node linkType: hard @@ -44346,6 +45284,15 @@ __metadata: languageName: node linkType: hard +"strip-indent@npm:^4.0.0": + version: 4.0.0 + resolution: "strip-indent@npm:4.0.0" + dependencies: + min-indent: ^1.0.1 + checksum: 06cbcd93da721c46bc13caeb1c00af93a9b18146a1c95927672d2decab6a25ad83662772417cea9317a2507fb143253ecc23c4415b64f5828cef9b638a744598 + languageName: node + linkType: hard + "strip-json-comments@npm:3.1.1, strip-json-comments@npm:^3.1.0, strip-json-comments@npm:^3.1.1": version: 3.1.1 resolution: "strip-json-comments@npm:3.1.1" @@ -44381,7 +45328,7 @@ __metadata: languageName: node linkType: hard -"style-loader@npm:^3.3.1": +"style-loader@npm:3.3.2, style-loader@npm:^3.3.1": version: 3.3.2 resolution: "style-loader@npm:3.3.2" peerDependencies: @@ -44489,7 +45436,7 @@ __metadata: languageName: node linkType: hard -"sucrase@npm:3.34.0, sucrase@npm:^3.32.0": +"sucrase@npm:3.34.0": version: 3.34.0 resolution: "sucrase@npm:3.34.0" dependencies: @@ -44507,6 +45454,24 @@ __metadata: languageName: node linkType: hard +"sucrase@npm:^3.35.0": + version: 3.35.0 + resolution: "sucrase@npm:3.35.0" + dependencies: + "@jridgewell/gen-mapping": ^0.3.2 + commander: ^4.0.0 + glob: ^10.3.10 + lines-and-columns: ^1.1.6 + mz: ^2.7.0 + pirates: ^4.0.1 + ts-interface-checker: ^0.1.9 + bin: + sucrase: bin/sucrase + sucrase-node: bin/sucrase-node + checksum: 9fc5792a9ab8a14dcf9c47dcb704431d35c1cdff1d17d55d382a31c2e8e3063870ad32ce120a80915498486246d612e30cda44f1624d9d9a10423e1a43487ad1 + languageName: node + linkType: hard + "sudo-prompt@npm:9.1.1, sudo-prompt@npm:^9.0.0": version: 9.1.1 resolution: "sudo-prompt@npm:9.1.1" @@ -44774,35 +45739,35 @@ __metadata: linkType: hard "tailwindcss@npm:^3.0.2": - version: 3.3.5 - resolution: "tailwindcss@npm:3.3.5" + version: 3.4.16 + resolution: "tailwindcss@npm:3.4.16" dependencies: "@alloc/quick-lru": ^5.2.0 arg: ^5.0.2 - chokidar: ^3.5.3 + chokidar: ^3.6.0 didyoumean: ^1.2.2 dlv: ^1.1.3 - fast-glob: ^3.3.0 + fast-glob: ^3.3.2 glob-parent: ^6.0.2 is-glob: ^4.0.3 - jiti: ^1.19.1 - lilconfig: ^2.1.0 - micromatch: ^4.0.5 + jiti: ^1.21.6 + lilconfig: ^3.1.3 + micromatch: ^4.0.8 normalize-path: ^3.0.0 object-hash: ^3.0.0 - picocolors: ^1.0.0 - postcss: ^8.4.23 + picocolors: ^1.1.1 + postcss: ^8.4.47 postcss-import: ^15.1.0 postcss-js: ^4.0.1 - postcss-load-config: ^4.0.1 - postcss-nested: ^6.0.1 - postcss-selector-parser: ^6.0.11 - resolve: ^1.22.2 - sucrase: ^3.32.0 + postcss-load-config: ^4.0.2 + postcss-nested: ^6.2.0 + postcss-selector-parser: ^6.1.2 + resolve: ^1.22.8 + sucrase: ^3.35.0 bin: tailwind: lib/cli.js tailwindcss: lib/cli.js - checksum: e04bb3bb7f9f17e9b6db0c7ace755ef0d6d05bff36ebeb9e5006e13c018ed5566f09db30a1a34380e38fa93ebbb4ae0e28fe726879d5e9ddd8c5b52bffd26f14 + checksum: a6ec1ce07da6ea4d40a62d9b3babfc5e56da75c5efb3c6fe48317dbda6877949f011c67b4fd03cb9a680d3bd734f45dbc977ee9138f8ce59619c7c712fb1350f languageName: node linkType: hard @@ -45079,7 +46044,7 @@ __metadata: languageName: node linkType: hard -"terser-webpack-plugin@npm:^5.2.5, terser-webpack-plugin@npm:^5.3.10": +"terser-webpack-plugin@npm:^5.2.5, terser-webpack-plugin@npm:^5.3.1, terser-webpack-plugin@npm:^5.3.10": version: 5.3.10 resolution: "terser-webpack-plugin@npm:5.3.10" dependencies: @@ -45116,8 +46081,8 @@ __metadata: linkType: hard "terser@npm:^5.0.0, terser@npm:^5.10.0, terser@npm:^5.15.0, terser@npm:^5.16.8, terser@npm:^5.26.0": - version: 5.30.3 - resolution: "terser@npm:5.30.3" + version: 5.37.0 + resolution: "terser@npm:5.37.0" dependencies: "@jridgewell/source-map": ^0.3.3 acorn: ^8.8.2 @@ -45125,7 +46090,7 @@ __metadata: source-map-support: ~0.5.20 bin: terser: bin/terser - checksum: 8c680ed32a948f806fade0969c52aab94b6de174e4a78610f5d3abf9993b161eb19b88b2ceadff09b153858727c02deb6709635e4bfbd519f67d54e0394e2983 + checksum: 70c06a8ce1288ff4370a7e481beb6fc8b22fc4995371479f49df1552aa9cf8e794ace66e1da6e87057eda1745644311213f5043bda9a06cf55421eff68b3ac06 languageName: node linkType: hard @@ -45306,7 +46271,7 @@ __metadata: languageName: node linkType: hard -"tiny-invariant@npm:^1.1.0, tiny-invariant@npm:^1.3.3": +"tiny-invariant@npm:^1.1.0, tiny-invariant@npm:^1.3.1, tiny-invariant@npm:^1.3.3": version: 1.3.3 resolution: "tiny-invariant@npm:1.3.3" checksum: 5e185c8cc2266967984ce3b352a4e57cb89dad5a8abb0dea21468a6ecaa67cd5bb47a3b7a85d08041008644af4f667fb8b6575ba38ba5fb00b3b5068306e59fe @@ -45337,6 +46302,20 @@ __metadata: languageName: node linkType: hard +"tinyrainbow@npm:^1.2.0": + version: 1.2.0 + resolution: "tinyrainbow@npm:1.2.0" + checksum: d1e2cb5400032c0092be00e4a3da5450bea8b4fad58bfb5d3c58ca37ff5c5e252f7fcfb9af247914854af79c46014add9d1042fe044358c305a129ed55c8be35 + languageName: node + linkType: hard + +"tinyspy@npm:^3.0.0": + version: 3.0.2 + resolution: "tinyspy@npm:3.0.2" + checksum: 5db671b2ff5cd309de650c8c4761ca945459d7204afb1776db9a04fb4efa28a75f08517a8620c01ee32a577748802231ad92f7d5b194dc003ee7f987a2a06337 + languageName: node + linkType: hard + "title-case@npm:^3.0.3": version: 3.0.3 resolution: "title-case@npm:3.0.3" @@ -45435,14 +46414,14 @@ __metadata: linkType: hard "tough-cookie@npm:^4.0.0, tough-cookie@npm:^4.1.2, tough-cookie@npm:^4.1.3": - version: 4.1.3 - resolution: "tough-cookie@npm:4.1.3" + version: 4.1.4 + resolution: "tough-cookie@npm:4.1.4" dependencies: psl: ^1.1.33 punycode: ^2.1.1 universalify: ^0.2.0 url-parse: ^1.5.3 - checksum: c9226afff36492a52118432611af083d1d8493a53ff41ec4ea48e5b583aec744b989e4280bcf476c910ec1525a89a4a0f1cae81c08b18fb2ec3a9b3a72b91dcc + checksum: 5815059f014c31179a303c673f753f7899a6fce94ac93712c88ea5f3c26e0c042b5f0c7a599a00f8e0feeca4615dba75c3dffc54f3c1a489978aa8205e09307c languageName: node linkType: hard @@ -45556,7 +46535,7 @@ __metadata: languageName: node linkType: hard -"ts-api-utils@npm:^1.0.1, ts-api-utils@npm:^1.3.0": +"ts-api-utils@npm:^1.0.1": version: 1.4.0 resolution: "ts-api-utils@npm:1.4.0" peerDependencies: @@ -45641,6 +46620,22 @@ __metadata: languageName: node linkType: hard +"ts-loader@npm:9.5.1": + version: 9.5.1 + resolution: "ts-loader@npm:9.5.1" + dependencies: + chalk: ^4.1.0 + enhanced-resolve: ^5.0.0 + micromatch: ^4.0.0 + semver: ^7.3.4 + source-map: ^0.7.4 + peerDependencies: + typescript: "*" + webpack: ^5.0.0 + checksum: 7cf396e656d905388ea2a9b5e82f16d3c955fda8d3df2fbf219f4bee16ff50a3c995c44ae3e584634e9443f056cec70bb3151add3917ffb4588ecd7394bac0ec + languageName: node + linkType: hard + "ts-log@npm:^2.2.3": version: 2.2.5 resolution: "ts-log@npm:2.2.5" @@ -45703,6 +46698,16 @@ __metadata: languageName: node linkType: hard +"ts-pnp@npm:^1.1.6": + version: 1.2.0 + resolution: "ts-pnp@npm:1.2.0" + peerDependenciesMeta: + typescript: + optional: true + checksum: c2a698b85d521298fe6f2435fbf2d3dc5834b423ea25abd321805ead3f399dbeedce7ca09492d7eb005b9d2c009c6b9587055bc3ab273dc6b9e40eefd7edb5b2 + languageName: node + linkType: hard + "tsafe@npm:1.6.4": version: 1.6.4 resolution: "tsafe@npm:1.6.4" @@ -45722,6 +46727,17 @@ __metadata: languageName: node linkType: hard +"tsconfig-paths@npm:^4.2.0": + version: 4.2.0 + resolution: "tsconfig-paths@npm:4.2.0" + dependencies: + json5: ^2.2.2 + minimist: ^1.2.6 + strip-bom: ^3.0.0 + checksum: 28c5f7bbbcabc9dabd4117e8fdc61483f6872a1c6b02a4b1c4d68c5b79d06896c3cc9547610c4c3ba64658531caa2de13ead1ea1bf321c7b53e969c4752b98c7 + languageName: node + linkType: hard + "tsconfig@workspace:config/tsconfig": version: 0.0.0-use.local resolution: "tsconfig@workspace:config/tsconfig" @@ -45884,6 +46900,13 @@ __metadata: languageName: node linkType: hard +"tween-functions@npm:^1.2.0": + version: 1.2.0 + resolution: "tween-functions@npm:1.2.0" + checksum: 880708d680eff5c347ddcb9f922ad121703a91c78ce308ed309073e73a794b633eb0b80589a839365803f150515ad34c9646809ae8a0e90f09e62686eefb1ab6 + languageName: node + linkType: hard + "tweetnacl-util@npm:^0.15.1": version: 0.15.1 resolution: "tweetnacl-util@npm:0.15.1" @@ -46228,6 +47251,7 @@ __metadata: "@react-native-masked-view/masked-view": 0.2.9 "@shopify/flash-list": 1.6.3 "@shopify/react-native-skia": 1.4.2 + "@storybook/react": 8.4.2 "@tamagui/animations-moti": 1.114.4 "@tamagui/animations-react-native": 1.114.4 "@tamagui/build": 1.114.4 @@ -46347,10 +47371,10 @@ __metadata: languageName: node linkType: hard -"undici-types@npm:~6.19.2": - version: 6.19.8 - resolution: "undici-types@npm:6.19.8" - checksum: de51f1b447d22571cf155dfe14ff6d12c5bdaec237c765085b439c38ca8518fc360e88c70f99469162bf2e14188a7b0bcb06e1ed2dc031042b984b0bb9544017 +"undici-types@npm:~6.20.0": + version: 6.20.0 + resolution: "undici-types@npm:6.20.0" + checksum: b7bc50f012dc6afbcce56c9fd62d7e86b20a62ff21f12b7b5cbf1973b9578d90f22a9c7fe50e638e96905d33893bf2f9f16d98929c4673c2480de05c6c96ea8b languageName: node linkType: hard @@ -46614,7 +47638,7 @@ __metadata: "@uniswap/eslint-config": "workspace:^" "@uniswap/permit2-sdk": 1.3.0 "@uniswap/router-sdk": 1.15.0 - "@uniswap/sdk-core": 6.0.0 + "@uniswap/sdk-core": 6.1.0 "@uniswap/uniswapx-sdk": 2.1.0-beta.18 "@uniswap/v2-sdk": 4.7.0 "@uniswap/v3-sdk": 3.19.0 @@ -46770,6 +47794,16 @@ __metadata: languageName: node linkType: hard +"unplugin@npm:^1.3.1": + version: 1.16.0 + resolution: "unplugin@npm:1.16.0" + dependencies: + acorn: ^8.14.0 + webpack-virtual-modules: ^0.6.2 + checksum: 84bff88dd8fd6ba88bd21dad1b170fea2a91f7ff8ddcfadf826297cf77dfe305f3428f1612c0637f30d7ac10d668491f15fdf8f378dd56def370fdbc16edd85e + languageName: node + linkType: hard + "unquote@npm:~1.1.1": version: 1.1.1 resolution: "unquote@npm:1.1.1" @@ -47116,12 +48150,14 @@ __metadata: linkType: hard "util.promisify@npm:~1.0.0": - version: 1.0.0 - resolution: "util.promisify@npm:1.0.0" + version: 1.0.1 + resolution: "util.promisify@npm:1.0.1" dependencies: - define-properties: ^1.1.2 - object.getownpropertydescriptors: ^2.0.3 - checksum: 482e857d676adee506c5c3a10212fd6a06a51d827a9b6d5396a8e593db53b4bb7064f77c5071357d8cd76072542de5cc1c08bc6d7c10cf43fa22dc3bc67556f1 + define-properties: ^1.1.3 + es-abstract: ^1.17.2 + has-symbols: ^1.0.1 + object.getownpropertydescriptors: ^2.1.0 + checksum: d823c75b3fc66510018596f128a6592c98991df38bc0464a633bdf9134e2de0a1a33199c5c21cc261048a3982d7a19e032ecff8835b3c587f843deba96063e37 languageName: node linkType: hard @@ -47175,7 +48211,7 @@ __metadata: "@uniswap/analytics": 1.7.0 "@uniswap/analytics-events": 2.40.0 "@uniswap/eslint-config": "workspace:^" - "@uniswap/sdk-core": 6.0.0 + "@uniswap/sdk-core": 6.1.0 aws-appsync-auth-link: 3.0.7 aws-appsync-subscription-link: 3.1.3 dayjs: 1.11.7 @@ -47725,7 +48761,7 @@ __metadata: "@uniswap/eslint-config": "workspace:^" "@uniswap/permit2-sdk": 1.3.0 "@uniswap/router-sdk": 1.15.0 - "@uniswap/sdk-core": 6.0.0 + "@uniswap/sdk-core": 6.1.0 "@uniswap/uniswapx-sdk": 2.1.0-beta.18 "@uniswap/universal-router-sdk": 4.7.0 "@uniswap/v3-sdk": 3.19.0 @@ -47790,13 +48826,13 @@ __metadata: languageName: node linkType: hard -"watchpack@npm:^2.4.0": - version: 2.4.0 - resolution: "watchpack@npm:2.4.0" +"watchpack@npm:^2.4.0, watchpack@npm:^2.4.1": + version: 2.4.2 + resolution: "watchpack@npm:2.4.2" dependencies: glob-to-regexp: ^0.4.1 graceful-fs: ^4.1.2 - checksum: 23d4bc58634dbe13b86093e01c6a68d8096028b664ab7139d58f0c37d962d549a940e98f2f201cecdabd6f9c340338dc73ef8bf094a2249ef582f35183d1a131 + checksum: 92d9d52ce3d16fd83ed6994d1dd66a4d146998882f4c362d37adfea9ab77748a5b4d1e0c65fa104797928b2d40f635efa8f9b925a6265428a69f1e1852ca3441 languageName: node linkType: hard @@ -47983,9 +49019,9 @@ __metadata: languageName: node linkType: hard -"webpack-dev-middleware@npm:^5.3.1": - version: 5.3.3 - resolution: "webpack-dev-middleware@npm:5.3.3" +"webpack-dev-middleware@npm:^5.3.1, webpack-dev-middleware@npm:^5.3.4": + version: 5.3.4 + resolution: "webpack-dev-middleware@npm:5.3.4" dependencies: colorette: ^2.0.10 memfs: ^3.4.3 @@ -47994,11 +49030,29 @@ __metadata: schema-utils: ^4.0.0 peerDependencies: webpack: ^4.0.0 || ^5.0.0 - checksum: dd332cc6da61222c43d25e5a2155e23147b777ff32fdf1f1a0a8777020c072fbcef7756360ce2a13939c3f534c06b4992a4d659318c4a7fe2c0530b52a8a6621 + checksum: 90cf3e27d0714c1a745454a1794f491b7076434939340605b9ee8718ba2b85385b120939754e9fdbd6569811e749dee53eec319e0d600e70e0b0baffd8e3fb13 + languageName: node + linkType: hard + +"webpack-dev-middleware@npm:^6.1.2": + version: 6.1.3 + resolution: "webpack-dev-middleware@npm:6.1.3" + dependencies: + colorette: ^2.0.10 + memfs: ^3.4.12 + mime-types: ^2.1.31 + range-parser: ^1.2.1 + schema-utils: ^4.0.0 + peerDependencies: + webpack: ^5.0.0 + peerDependenciesMeta: + webpack: + optional: true + checksum: ddedaa913cc39d7ac7f971d902f181ecc5c4ab0b91f9eda5923f0ea513ecf458f71046f2ed423cb4fc657c2177fe279186453e395bd1051f0949e265c3124665 languageName: node linkType: hard -"webpack-dev-server@npm:4.15.1, webpack-dev-server@npm:^4.6.0": +"webpack-dev-server@npm:4.15.1": version: 4.15.1 resolution: "webpack-dev-server@npm:4.15.1" dependencies: @@ -48045,6 +49099,64 @@ __metadata: languageName: node linkType: hard +"webpack-dev-server@npm:^4.6.0": + version: 4.15.2 + resolution: "webpack-dev-server@npm:4.15.2" + dependencies: + "@types/bonjour": ^3.5.9 + "@types/connect-history-api-fallback": ^1.3.5 + "@types/express": ^4.17.13 + "@types/serve-index": ^1.9.1 + "@types/serve-static": ^1.13.10 + "@types/sockjs": ^0.3.33 + "@types/ws": ^8.5.5 + ansi-html-community: ^0.0.8 + bonjour-service: ^1.0.11 + chokidar: ^3.5.3 + colorette: ^2.0.10 + compression: ^1.7.4 + connect-history-api-fallback: ^2.0.0 + default-gateway: ^6.0.3 + express: ^4.17.3 + graceful-fs: ^4.2.6 + html-entities: ^2.3.2 + http-proxy-middleware: ^2.0.3 + ipaddr.js: ^2.0.1 + launch-editor: ^2.6.0 + open: ^8.0.9 + p-retry: ^4.5.0 + rimraf: ^3.0.2 + schema-utils: ^4.0.0 + selfsigned: ^2.1.1 + serve-index: ^1.9.1 + sockjs: ^0.3.24 + spdy: ^4.0.2 + webpack-dev-middleware: ^5.3.4 + ws: ^8.13.0 + peerDependencies: + webpack: ^4.37.0 || ^5.0.0 + peerDependenciesMeta: + webpack: + optional: true + webpack-cli: + optional: true + bin: + webpack-dev-server: bin/webpack-dev-server.js + checksum: 123507129cb4d55fdc5fabdd177574f31133605748372bb11353307b7a583ef25c6fd27b6addf56bf070ba44c88d5da861771c2ec55f52405082ec9efd01f039 + languageName: node + linkType: hard + +"webpack-hot-middleware@npm:^2.25.1": + version: 2.26.1 + resolution: "webpack-hot-middleware@npm:2.26.1" + dependencies: + ansi-html-community: 0.0.8 + html-entities: ^2.1.0 + strip-ansi: ^6.0.0 + checksum: 78513d8d5770c59c3039ce094c49b2e2772b3f1d4ec5c124a7aabe6124a0e08429993b81129649087dc300f496822257e39135bf8b891b51aea197c1b554072a + languageName: node + linkType: hard + "webpack-manifest-plugin@npm:^4.0.2": version: 4.1.1 resolution: "webpack-manifest-plugin@npm:4.1.1" @@ -48113,7 +49225,50 @@ __metadata: languageName: node linkType: hard -"webpack@npm:5.90.0, webpack@npm:^5.64.4": +"webpack-virtual-modules@npm:^0.6.0, webpack-virtual-modules@npm:^0.6.2": + version: 0.6.2 + resolution: "webpack-virtual-modules@npm:0.6.2" + checksum: 7e8e1d63f35864c815420cc2f27da8561a1e028255040698a352717de0ba46d3b3faf16f06c1a1965217054c4c2894eb9af53a85451870e919b5707ce9c5822d + languageName: node + linkType: hard + +"webpack@npm:5, webpack@npm:^5.64.4": + version: 5.97.1 + resolution: "webpack@npm:5.97.1" + dependencies: + "@types/eslint-scope": ^3.7.7 + "@types/estree": ^1.0.6 + "@webassemblyjs/ast": ^1.14.1 + "@webassemblyjs/wasm-edit": ^1.14.1 + "@webassemblyjs/wasm-parser": ^1.14.1 + acorn: ^8.14.0 + browserslist: ^4.24.0 + chrome-trace-event: ^1.0.2 + enhanced-resolve: ^5.17.1 + es-module-lexer: ^1.2.1 + eslint-scope: 5.1.1 + events: ^3.2.0 + glob-to-regexp: ^0.4.1 + graceful-fs: ^4.2.11 + json-parse-even-better-errors: ^2.3.1 + loader-runner: ^4.2.0 + mime-types: ^2.1.27 + neo-async: ^2.6.2 + schema-utils: ^3.2.0 + tapable: ^2.1.1 + terser-webpack-plugin: ^5.3.10 + watchpack: ^2.4.1 + webpack-sources: ^3.2.3 + peerDependenciesMeta: + webpack-cli: + optional: true + bin: + webpack: bin/webpack.js + checksum: 649065e2258b495ae41a4088be804b4be2ec07d280aa514ebef43da79caf96fa973d26a08826c3902b5676a098d9b37c589f16be7b4da17b68b08b6c76441196 + languageName: node + linkType: hard + +"webpack@npm:5.90.0": version: 5.90.0 resolution: "webpack@npm:5.90.0" dependencies: @@ -48194,9 +49349,9 @@ __metadata: linkType: hard "whatwg-fetch@npm:^3.0.0, whatwg-fetch@npm:^3.6.2": - version: 3.6.19 - resolution: "whatwg-fetch@npm:3.6.19" - checksum: 2896bc9ca867ea514392c73e2a272f65d5c4916248fe0837a9df5b1b92f247047bc76cf7c29c28a01ac6c5fb4314021d2718958c8a08292a96d56f72b2f56806 + version: 3.6.20 + resolution: "whatwg-fetch@npm:3.6.20" + checksum: c58851ea2c4efe5c2235f13450f426824cf0253c1d45da28f45900290ae602a20aff2ab43346f16ec58917d5562e159cd691efa368354b2e82918c2146a519c5 languageName: node linkType: hard @@ -48405,9 +49560,9 @@ __metadata: linkType: hard "word-wrap@npm:~1.2.3": - version: 1.2.3 - resolution: "word-wrap@npm:1.2.3" - checksum: 30b48f91fcf12106ed3186ae4fa86a6a1842416df425be7b60485de14bec665a54a68e4b5156647dec3a70f25e84d270ca8bc8cd23182ed095f5c7206a938c1f + version: 1.2.5 + resolution: "word-wrap@npm:1.2.5" + checksum: f93ba3586fc181f94afdaff3a6fef27920b4b6d9eaefed0f428f8e07adea2a7f54a5f2830ce59406c8416f033f86902b91eb824072354645eea687dff3691ccb languageName: node linkType: hard @@ -48685,25 +49840,25 @@ __metadata: languageName: node linkType: hard -"wrap-ansi@npm:^6.0.1, wrap-ansi@npm:^6.2.0": - version: 6.2.0 - resolution: "wrap-ansi@npm:6.2.0" +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": + version: 7.0.0 + resolution: "wrap-ansi@npm:7.0.0" dependencies: ansi-styles: ^4.0.0 string-width: ^4.1.0 strip-ansi: ^6.0.0 - checksum: 6cd96a410161ff617b63581a08376f0cb9162375adeb7956e10c8cd397821f7eb2a6de24eb22a0b28401300bf228c86e50617cd568209b5f6775b93c97d2fe3a + checksum: a790b846fd4505de962ba728a21aaeda189b8ee1c7568ca5e817d85930e06ef8d1689d49dbf0e881e8ef84436af3a88bc49115c2e2788d841ff1b8b5b51a608b languageName: node linkType: hard -"wrap-ansi@npm:^7.0.0": - version: 7.0.0 - resolution: "wrap-ansi@npm:7.0.0" +"wrap-ansi@npm:^6.0.1, wrap-ansi@npm:^6.2.0": + version: 6.2.0 + resolution: "wrap-ansi@npm:6.2.0" dependencies: ansi-styles: ^4.0.0 string-width: ^4.1.0 strip-ansi: ^6.0.0 - checksum: a790b846fd4505de962ba728a21aaeda189b8ee1c7568ca5e817d85930e06ef8d1689d49dbf0e881e8ef84436af3a88bc49115c2e2788d841ff1b8b5b51a608b + checksum: 6cd96a410161ff617b63581a08376f0cb9162375adeb7956e10c8cd397821f7eb2a6de24eb22a0b28401300bf228c86e50617cd568209b5f6775b93c97d2fe3a languageName: node linkType: hard