ci(release): publish latest release

parent c0bbcf59
IPFS hash of the deployment: IPFS hash of the deployment:
- CIDv0: `QmbEmY4ebbPrQirzx9PNZGKqyjK7pgUMVce2F2tMtJHbJ5` - CIDv0: `QmRTQkA8KswGiGLBonZxttz4C9fJSnbD9QnKis37qVEJ2j`
- CIDv1: `bafybeif7uyvbcyhd5ib6xkikxoyvm4voodg4pgagjckny4m52o7qtclpsy` - CIDv1: `bafybeibojzlcvbuydj5zkb562ipm3tcaa74sn4ub72dnwtse4diqma6gca`
The latest release is always mirrored at [app.uniswap.org](https://app.uniswap.org). The latest release is always mirrored at [app.uniswap.org](https://app.uniswap.org).
...@@ -10,51 +10,48 @@ You can also access the Uniswap Interface from an IPFS gateway. ...@@ -10,51 +10,48 @@ You can also access the Uniswap Interface from an IPFS gateway.
Your Uniswap settings are never remembered across different URLs. Your Uniswap settings are never remembered across different URLs.
IPFS gateways: IPFS gateways:
- https://bafybeif7uyvbcyhd5ib6xkikxoyvm4voodg4pgagjckny4m52o7qtclpsy.ipfs.dweb.link/ - https://bafybeibojzlcvbuydj5zkb562ipm3tcaa74sn4ub72dnwtse4diqma6gca.ipfs.dweb.link/
- https://bafybeif7uyvbcyhd5ib6xkikxoyvm4voodg4pgagjckny4m52o7qtclpsy.ipfs.cf-ipfs.com/ - https://bafybeibojzlcvbuydj5zkb562ipm3tcaa74sn4ub72dnwtse4diqma6gca.ipfs.cf-ipfs.com/
- [ipfs://QmbEmY4ebbPrQirzx9PNZGKqyjK7pgUMVce2F2tMtJHbJ5/](ipfs://QmbEmY4ebbPrQirzx9PNZGKqyjK7pgUMVce2F2tMtJHbJ5/) - [ipfs://QmRTQkA8KswGiGLBonZxttz4C9fJSnbD9QnKis37qVEJ2j/](ipfs://QmRTQkA8KswGiGLBonZxttz4C9fJSnbD9QnKis37qVEJ2j/)
## 5.24.0 (2024-04-17) ## 5.25.0 (2024-04-22)
### Features ### Features
* **web:** [wagmi] Add viem to ethers adapters (#7237) 276faae * **web:** add check:bundle-size script and ci check for bundle size not growing (#7655) 0a4bce7
* **web:** deprecate token logo lookups (#6921) 0ade412 * **web:** Add feature flag for v2 data on Explore (#7705) 1679530
* **web:** deprecate+delete token safety lookups (#7132) b4642e9 * **web:** combine all DoubleCurrencyLogo implementations (#7369) cda9384
* **web:** update signatures from subscription (#7389) f867870 * **web:** fix unicon v2 and remove jazzicons (#7586) 27caec6
* **web:** multiple routing preference (#7585) c6bfd6c
* **web:** multiple routing preferences styling (#7627) 58a55de
* **web:** remove all token-lists except avax fallbacks (#7422) 377fe4b
* **web:** remove remaining usage of token lists (#7446) 9895aa7
* **web:** subscription-based activity feed (#7266) 327da33
* **web:** update transactions from subscription (#7471) 49484c8
### Bug Fixes ### Bug Fixes
* **web:** allow TrustWallet nodes in CSP (#7515) 0a5b28d * **web:** add new chains to richlinkpreviews chainlogo (#7521) a21f010
* **web:** change background color of LP warning banner (#7491) f543ab0 * **web:** allow TrustWallet nodes in CSP (#7513) aed2bd4
* **web:** change warning icon color; add learn more link (#7483) 352be3b * **web:** deflake some cypress tests (#7575) 4a7daef
* **web:** checkbox color on open-limits drawer (#7410) 05dfaed * **web:** disable breaking tests and rename cypress passing test to be clearer in github branch protection rules (#7496) 0f88608
* **web:** dismiss chart tooltip when clicking outside of chart (#7285) 3d97a14 * **web:** Don't try to parse non-numbers (#7587) 5da785f
* **web:** ellipsis on unitag text in side drawer (#7386) 471661c * **web:** fix token cacheing in explore tabs, navbar search (#7543) aaaaaa1
* **web:** fix cypress tests (#7347) e54ceb9 * **web:** fix token safety test on TDP (#7506) 4635506
* **web:** fix icon cutoff (#7583) a01e106 * **web:** fix uk disclaimer e2e test (#7507) 1a8dbef
* **web:** fix translations with JSX rendering as [object Object] (#7336) 67df76c * **web:** fix uniswapx e2e tests (#7505) 880c131
* **web:** fix uniswapx e2e tests (#7458) c6de35e * **web:** fix unitag e2e test (#7504) 8a946d5
* **web:** fix x-chain token logos (#7374) 4367e3a * **web:** limits pending cancel state (#7654) 74a8767
* **web:** functions pass-through (#7338) ace3062 * **web:** parse native MATIC correctly (#7516) a7d7957
* **web:** make sure SimpleToken hits the cache in all cases (#7488) 1be2954 * **web:** pass gas params to provider (#7464) 3ede664
* **web:** parse matic correctly from gql response (#7519) 800eae5 * **web:** Properly compare natives for L2 PDP Tx Table (#7520) 4a1bb26
* **web:** remove assets repo fallback for all tokens (#7476) 8e2142c * **web:** remove 'review swap' title from success state (#7346) e16d7f3
* **web:** Send crashing on useENSAvatar while disconnected (#7595) 131c6a3 * **web:** remove sentence-casing for rich link previews images (#7344) dff07a9
* **web:** set usePoolData errorPolicy to all (#7466) 55e3e8a * **web:** Send crashing on useENSAvatar while disconnected (#7595) 56ba8b4
* **web:** SimpleTokenDetails fragment to be used in all queries (#7549) 678e624 * **web:** switch currency when input equals output (#7570) 1f2fd97
* **web:** switch currency when input equals output (staging) 20277d2 * **web:** use cached results for common bases (#7649) ea1866d
* **web:** TokenBalanceProvider account change (#7432) 516b781 * **web:** warn user if fee is greater than native balance (#7556) 100fce9
* **web:** use accent warning soft for outage banner icon wrapper (#7428) cda7ea9
* **web:** use cache-first policy for TopTokens query (#7484) 25d0950
### Code Refactoring
* **web:** isolate the subscription updater (#7387) 6caabbd
* **web:** split out parseRemote signature (#7388) 223e766
* **web:** use a single codepath for functions response transform (#7363) 60471a8
web/5.24.0 web/5.25.0
\ No newline at end of file \ No newline at end of file
...@@ -11,7 +11,7 @@ import Apollo ...@@ -11,7 +11,7 @@ import Apollo
public class Network { public class Network {
public static let shared = Network() public static let shared = Network()
private let UNISWAP_API_URL = Env.UNISWAP_API_BASE_URL + "/v1/graphql" private let UNISWAP_API_URL = "https://ios.wallet.gateway.uniswap.org/v1/graphql"
public lazy var apollo: ApolloClient = { public lazy var apollo: ApolloClient = {
let cache = InMemoryNormalizedCache() let cache = InMemoryNormalizedCache()
......
...@@ -83,8 +83,8 @@ ...@@ -83,8 +83,8 @@
"@uniswap/analytics": "1.7.0", "@uniswap/analytics": "1.7.0",
"@uniswap/analytics-events": "2.32.0", "@uniswap/analytics-events": "2.32.0",
"@uniswap/ethers-rs-mobile": "0.0.5", "@uniswap/ethers-rs-mobile": "0.0.5",
"@uniswap/sdk-core": "4.2.0", "@uniswap/sdk-core": "4.2.1-beta.1",
"@uniswap/v3-sdk": "3.11.0", "@uniswap/v3-sdk": "3.11.1-beta.2",
"@walletconnect/core": "2.11.2", "@walletconnect/core": "2.11.2",
"@walletconnect/react-native-compat": "2.11.2", "@walletconnect/react-native-compat": "2.11.2",
"@walletconnect/utils": "2.11.2", "@walletconnect/utils": "2.11.2",
...@@ -163,14 +163,14 @@ ...@@ -163,14 +163,14 @@
"@babel/runtime": "7.18.9", "@babel/runtime": "7.18.9",
"@faker-js/faker": "7.6.0", "@faker-js/faker": "7.6.0",
"@storybook/react": "7.0.2", "@storybook/react": "7.0.2",
"@tamagui/babel-plugin": "1.94.3", "@tamagui/babel-plugin": "1.94.5",
"@testing-library/react-hooks": "7.0.2", "@testing-library/react-hooks": "7.0.2",
"@testing-library/react-native": "11.5.0", "@testing-library/react-native": "11.5.0",
"@types/react-native": "0.71.3", "@types/react-native": "0.71.3",
"@types/redux-mock-store": "1.0.6", "@types/redux-mock-store": "1.0.6",
"@uniswap/eslint-config": "workspace:^", "@uniswap/eslint-config": "workspace:^",
"@walletconnect/types": "2.11.2", "@walletconnect/types": "2.11.2",
"@welldone-software/why-did-you-render": "7.0.1", "@welldone-software/why-did-you-render": "8.0.1",
"babel-loader": "8.2.3", "babel-loader": "8.2.3",
"babel-plugin-react-native-web": "0.17.5", "babel-plugin-react-native-web": "0.17.5",
"babel-plugin-react-require": "4.0.0", "babel-plugin-react-require": "4.0.0",
......
...@@ -3,7 +3,7 @@ import os ...@@ -3,7 +3,7 @@ import os
ENV_DEFAULTS_FILE = '../../.env.defaults' ENV_DEFAULTS_FILE = '../../.env.defaults'
ENV_DEFAULTS_LOCAL_FILE = '../../.env.defaults.local' ENV_DEFAULTS_LOCAL_FILE = '../../.env.defaults.local'
SWIFT_FILE_PATH = 'ios/WidgetsCore/Env.swift' SWIFT_FILE_PATH = 'ios/WidgetsCore/Env.swift'
SWIFT_ENV_VARIABLES = ['UNISWAP_API_BASE_URL','UNISWAP_API_KEY'] SWIFT_ENV_VARIABLES = ['UNISWAP_API_KEY']
def to_swift_constant_line(key, value): def to_swift_constant_line(key, value):
return f' static let {key.upper()} = "{value}"' return f' static let {key.upper()} = "{value}"'
......
...@@ -49,10 +49,10 @@ import { StatsigProvider } from 'statsig-react-native' ...@@ -49,10 +49,10 @@ import { StatsigProvider } from 'statsig-react-native'
import { flexStyles, useIsDarkMode } from 'ui/src' import { flexStyles, useIsDarkMode } from 'ui/src'
import { config } from 'uniswap/src/config' import { config } from 'uniswap/src/config'
import { uniswapUrls } from 'uniswap/src/constants/urls' import { uniswapUrls } from 'uniswap/src/constants/urls'
import { DUMMY_STATSIG_SDK_KEY } from 'uniswap/src/features/statsig/constants' import { DUMMY_STATSIG_SDK_KEY } from 'uniswap/src/features/gating/constants'
import { WALLET_EXPERIMENTS } from 'uniswap/src/features/statsig/experiments' import { WALLET_EXPERIMENTS } from 'uniswap/src/features/gating/experiments'
import { WALLET_FEATURE_FLAG_NAMES } from 'uniswap/src/features/statsig/flags' import { WALLET_FEATURE_FLAG_NAMES } from 'uniswap/src/features/gating/flags'
import { Statsig } from 'uniswap/src/features/statsig/sdk/statsig' import { Statsig } from 'uniswap/src/features/gating/sdk/statsig'
import { UnitagUpdaterContextProvider } from 'uniswap/src/features/unitags/context' import { UnitagUpdaterContextProvider } from 'uniswap/src/features/unitags/context'
import i18n from 'uniswap/src/i18n/i18n' import i18n from 'uniswap/src/i18n/i18n'
import { CurrencyId } from 'uniswap/src/types/currency' import { CurrencyId } from 'uniswap/src/types/currency'
......
...@@ -6,8 +6,8 @@ import { useAppStackNavigation } from 'src/app/navigation/types' ...@@ -6,8 +6,8 @@ import { useAppStackNavigation } from 'src/app/navigation/types'
import { closeModal, openModal } from 'src/features/modals/modalSlice' import { closeModal, openModal } from 'src/features/modals/modalSlice'
import { HomeScreenTabIndex } from 'src/screens/HomeScreenTabIndex' import { HomeScreenTabIndex } from 'src/screens/HomeScreenTabIndex'
import { Screens } from 'src/screens/Screens' import { Screens } from 'src/screens/Screens'
import { FeatureFlags } from 'uniswap/src/features/statsig/flags' import { FeatureFlags } from 'uniswap/src/features/gating/flags'
import { useFeatureFlag } from 'uniswap/src/features/statsig/hooks' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks'
import { logger } from 'utilities/src/logger/logger' import { logger } from 'utilities/src/logger/logger'
import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants' import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants'
import { import {
......
...@@ -22,8 +22,6 @@ import { ...@@ -22,8 +22,6 @@ import {
useSporeColors, useSporeColors,
} from 'ui/src' } from 'ui/src'
import { spacing } from 'ui/src/theme' import { spacing } from 'ui/src/theme'
import { FeatureFlags } from 'uniswap/src/features/statsig/flags'
import { useFeatureFlag } from 'uniswap/src/features/statsig/hooks'
import { isAndroid } from 'uniswap/src/utils/platform' import { isAndroid } from 'uniswap/src/utils/platform'
import { AddressDisplay } from 'wallet/src/components/accounts/AddressDisplay' import { AddressDisplay } from 'wallet/src/components/accounts/AddressDisplay'
import { ActionSheetModal, MenuItemProp } from 'wallet/src/components/modals/ActionSheetModal' import { ActionSheetModal, MenuItemProp } from 'wallet/src/components/modals/ActionSheetModal'
...@@ -76,7 +74,6 @@ export function AccountSwitcher({ onClose }: { onClose: () => void }): JSX.Eleme ...@@ -76,7 +74,6 @@ export function AccountSwitcher({ onClose }: { onClose: () => void }): JSX.Eleme
const dispatch = useAppDispatch() const dispatch = useAppDispatch()
const hasImportedSeedPhrase = useNativeAccountExists() const hasImportedSeedPhrase = useNativeAccountExists()
const modalState = useAppSelector(selectModalState(ModalName.AccountSwitcher)) const modalState = useAppSelector(selectModalState(ModalName.AccountSwitcher))
const unitagsFeatureFlagEnabled = useFeatureFlag(FeatureFlags.Unitags)
const onCompleteOnboarding = useCompleteOnboardingCallback({ const onCompleteOnboarding = useCompleteOnboardingCallback({
entryPoint: OnboardingEntryPoint.Sidebar, entryPoint: OnboardingEntryPoint.Sidebar,
importType: hasImportedSeedPhrase ? ImportType.CreateAdditional : ImportType.CreateNew, importType: hasImportedSeedPhrase ? ImportType.CreateAdditional : ImportType.CreateNew,
...@@ -132,7 +129,6 @@ export function AccountSwitcher({ onClose }: { onClose: () => void }): JSX.Eleme ...@@ -132,7 +129,6 @@ export function AccountSwitcher({ onClose }: { onClose: () => void }): JSX.Eleme
dispatch(pendingAccountActions.trigger(PendingAccountActions.ActivateOneAndDelete)) dispatch(pendingAccountActions.trigger(PendingAccountActions.ActivateOneAndDelete))
dispatch(createAccountActions.trigger()) dispatch(createAccountActions.trigger())
if (unitagsFeatureFlagEnabled) {
if (hasImportedSeedPhrase) { if (hasImportedSeedPhrase) {
setCreatedAdditionalAccount(true) setCreatedAdditionalAccount(true)
} else { } else {
...@@ -145,15 +141,6 @@ export function AccountSwitcher({ onClose }: { onClose: () => void }): JSX.Eleme ...@@ -145,15 +141,6 @@ export function AccountSwitcher({ onClose }: { onClose: () => void }): JSX.Eleme
}, },
}) })
} }
} else {
navigate(Screens.OnboardingStack, {
screen: OnboardingScreens.EditName,
params: {
entryPoint: OnboardingEntryPoint.Sidebar,
importType: hasImportedSeedPhrase ? ImportType.CreateAdditional : ImportType.CreateNew,
},
})
}
setShowAddWalletModal(false) setShowAddWalletModal(false)
onClose() onClose()
...@@ -267,7 +254,7 @@ export function AccountSwitcher({ onClose }: { onClose: () => void }): JSX.Eleme ...@@ -267,7 +254,7 @@ export function AccountSwitcher({ onClose }: { onClose: () => void }): JSX.Eleme
} }
return options return options
}, [activeAccountAddress, dispatch, hasImportedSeedPhrase, onClose, t, unitagsFeatureFlagEnabled]) }, [activeAccountAddress, dispatch, hasImportedSeedPhrase, onClose, t])
const accountsWithoutActive = accounts.filter((a) => a.address !== activeAccountAddress) const accountsWithoutActive = accounts.filter((a) => a.address !== activeAccountAddress)
......
...@@ -21,17 +21,17 @@ import { ...@@ -21,17 +21,17 @@ import {
Experiments, Experiments,
WALLET_EXPERIMENTS, WALLET_EXPERIMENTS,
getExperimentDefinition, getExperimentDefinition,
} from 'uniswap/src/features/statsig/experiments' } from 'uniswap/src/features/gating/experiments'
import { import {
FeatureFlags, FeatureFlags,
WALLET_FEATURE_FLAG_NAMES, WALLET_FEATURE_FLAG_NAMES,
getFeatureFlagName, getFeatureFlagName,
} from 'uniswap/src/features/statsig/flags' } from 'uniswap/src/features/gating/flags'
import { import {
useExperimentValueWithExposureLoggingDisabled, useExperimentValueWithExposureLoggingDisabled,
useFeatureFlagWithExposureLoggingDisabled, useFeatureFlagWithExposureLoggingDisabled,
} from 'uniswap/src/features/statsig/hooks' } from 'uniswap/src/features/gating/hooks'
import { Statsig } from 'uniswap/src/features/statsig/sdk/statsig' import { Statsig } from 'uniswap/src/features/gating/sdk/statsig'
import { Switch } from 'wallet/src/components/buttons/Switch' import { Switch } from 'wallet/src/components/buttons/Switch'
import { TextInput } from 'wallet/src/components/input/TextInput' import { TextInput } from 'wallet/src/components/input/TextInput'
import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal' import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal'
......
...@@ -5,8 +5,8 @@ import { selectModalState } from 'src/features/modals/selectModalState' ...@@ -5,8 +5,8 @@ import { selectModalState } from 'src/features/modals/selectModalState'
import { TransferFlow } from 'src/features/transactions/transfer/TransferFlow' import { TransferFlow } from 'src/features/transactions/transfer/TransferFlow'
import { TransferFlow as TransferFlowRewrite } from 'src/features/transactions/transfer/transferRewrite/TransferFlow' import { TransferFlow as TransferFlowRewrite } from 'src/features/transactions/transfer/transferRewrite/TransferFlow'
import { useSporeColors } from 'ui/src' import { useSporeColors } from 'ui/src'
import { FeatureFlags } from 'uniswap/src/features/statsig/flags' import { FeatureFlags } from 'uniswap/src/features/gating/flags'
import { useFeatureFlag } from 'uniswap/src/features/statsig/hooks' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks'
import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal' import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal'
import { ModalName } from 'wallet/src/telemetry/constants' import { ModalName } from 'wallet/src/telemetry/constants'
......
...@@ -41,7 +41,6 @@ import { BackupScreen } from 'src/screens/Onboarding/BackupScreen' ...@@ -41,7 +41,6 @@ import { BackupScreen } from 'src/screens/Onboarding/BackupScreen'
import { CloudBackupPasswordConfirmScreen } from 'src/screens/Onboarding/CloudBackupPasswordConfirmScreen' import { CloudBackupPasswordConfirmScreen } from 'src/screens/Onboarding/CloudBackupPasswordConfirmScreen'
import { CloudBackupPasswordCreateScreen } from 'src/screens/Onboarding/CloudBackupPasswordCreateScreen' import { CloudBackupPasswordCreateScreen } from 'src/screens/Onboarding/CloudBackupPasswordCreateScreen'
import { CloudBackupProcessingScreen } from 'src/screens/Onboarding/CloudBackupProcessingScreen' import { CloudBackupProcessingScreen } from 'src/screens/Onboarding/CloudBackupProcessingScreen'
import { EditNameScreen } from 'src/screens/Onboarding/EditNameScreen'
import { LandingScreen } from 'src/screens/Onboarding/LandingScreen' import { LandingScreen } from 'src/screens/Onboarding/LandingScreen'
import { ManualBackupScreen } from 'src/screens/Onboarding/ManualBackupScreen' import { ManualBackupScreen } from 'src/screens/Onboarding/ManualBackupScreen'
import { NotificationsSetupScreen } from 'src/screens/Onboarding/NotificationsSetupScreen' import { NotificationsSetupScreen } from 'src/screens/Onboarding/NotificationsSetupScreen'
...@@ -64,8 +63,8 @@ import { TokenDetailsScreen } from 'src/screens/TokenDetailsScreen' ...@@ -64,8 +63,8 @@ import { TokenDetailsScreen } from 'src/screens/TokenDetailsScreen'
import { WebViewScreen } from 'src/screens/WebViewScreen' import { WebViewScreen } from 'src/screens/WebViewScreen'
import { Icons, useDeviceInsets, useSporeColors } from 'ui/src' import { Icons, useDeviceInsets, useSporeColors } from 'ui/src'
import { spacing } from 'ui/src/theme' import { spacing } from 'ui/src/theme'
import { FeatureFlags } from 'uniswap/src/features/statsig/flags' import { FeatureFlags } from 'uniswap/src/features/gating/flags'
import { useFeatureFlag } from 'uniswap/src/features/statsig/hooks' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks'
import { OnboardingEntryPoint } from 'wallet/src/features/onboarding/types' import { OnboardingEntryPoint } from 'wallet/src/features/onboarding/types'
import { useActiveAccountWithThrow } from 'wallet/src/features/wallet/hooks' import { useActiveAccountWithThrow } from 'wallet/src/features/wallet/hooks'
import { selectFinishedOnboarding } from 'wallet/src/features/wallet/selectors' import { selectFinishedOnboarding } from 'wallet/src/features/wallet/selectors'
...@@ -249,7 +248,6 @@ export function OnboardingStackNavigator(): JSX.Element { ...@@ -249,7 +248,6 @@ export function OnboardingStackNavigator(): JSX.Element {
name={UnitagScreens.ChooseProfilePicture} name={UnitagScreens.ChooseProfilePicture}
options={{ ...TransitionPresets.ModalFadeTransition }} options={{ ...TransitionPresets.ModalFadeTransition }}
/> />
<OnboardingStack.Screen component={EditNameScreen} name={OnboardingScreens.EditName} />
<OnboardingStack.Screen component={BackupScreen} name={OnboardingScreens.Backup} /> <OnboardingStack.Screen component={BackupScreen} name={OnboardingScreens.Backup} />
<OnboardingStack.Screen <OnboardingStack.Screen
component={NotificationsSetupScreen} component={NotificationsSetupScreen}
......
...@@ -92,7 +92,6 @@ export type OnboardingStackParamList = { ...@@ -92,7 +92,6 @@ export type OnboardingStackParamList = {
[OnboardingScreens.BackupCloudProcessing]: CloudBackupFormParams & OnboardingStackBaseParams [OnboardingScreens.BackupCloudProcessing]: CloudBackupFormParams & OnboardingStackBaseParams
[OnboardingScreens.Backup]: OnboardingStackBaseParams [OnboardingScreens.Backup]: OnboardingStackBaseParams
[OnboardingScreens.Landing]: OnboardingStackBaseParams [OnboardingScreens.Landing]: OnboardingStackBaseParams
[OnboardingScreens.EditName]: OnboardingStackBaseParams
[OnboardingScreens.Notifications]: OnboardingStackBaseParams [OnboardingScreens.Notifications]: OnboardingStackBaseParams
[OnboardingScreens.WelcomeWallet]: OnboardingStackBaseParams [OnboardingScreens.WelcomeWallet]: OnboardingStackBaseParams
[OnboardingScreens.Security]: OnboardingStackBaseParams [OnboardingScreens.Security]: OnboardingStackBaseParams
......
...@@ -10,7 +10,7 @@ import { logger } from 'utilities/src/logger/logger' ...@@ -10,7 +10,7 @@ import { logger } from 'utilities/src/logger/logger'
import { fiatOnRampAggregatorApi, fiatOnRampApi } from 'wallet/src/features/fiatOnRamp/api' import { fiatOnRampAggregatorApi, fiatOnRampApi } from 'wallet/src/features/fiatOnRamp/api'
import { importAccountSagaName } from 'wallet/src/features/wallet/import/importAccountSaga' import { importAccountSagaName } from 'wallet/src/features/wallet/import/importAccountSaga'
import { createStore } from 'wallet/src/state' import { createStore } from 'wallet/src/state'
import { RootReducerNames } from 'wallet/src/state/reducer' import { RootReducerNames, sharedPersistedStateWhitelist } from 'wallet/src/state/reducer'
import { MobileState, ReducerNames, mobileReducer } from './reducer' import { MobileState, ReducerNames, mobileReducer } from './reducer'
import { mobileSaga } from './saga' import { mobileSaga } from './saga'
...@@ -54,21 +54,12 @@ const rtkQueryErrorLogger: Middleware = () => (next) => (action: PayloadAction<u ...@@ -54,21 +54,12 @@ const rtkQueryErrorLogger: Middleware = () => (next) => (action: PayloadAction<u
} }
const whitelist: Array<ReducerNames | RootReducerNames> = [ const whitelist: Array<ReducerNames | RootReducerNames> = [
'appearanceSettings', ...sharedPersistedStateWhitelist,
'behaviorHistory',
'biometricSettings', 'biometricSettings',
'favorites',
'notifications',
'passwordLockout', 'passwordLockout',
'searchHistory',
'telemetry', 'telemetry',
'tokens',
'transactions',
'tweaks', 'tweaks',
'wallet',
'cloudBackup', 'cloudBackup',
'languageSettings',
'fiatCurrencySettings',
] ]
export const persistConfig = { export const persistConfig = {
......
import React from 'react' import React from 'react'
import { Flex, Separator, Text, Unicon, UniconV2, useSporeColors } from 'ui/src' import { Flex, Separator, Text, Unicon, UniconV2, useSporeColors } from 'ui/src'
import Check from 'ui/src/assets/icons/check.svg' import Check from 'ui/src/assets/icons/check.svg'
import { FeatureFlags } from 'uniswap/src/features/statsig/flags' import { FeatureFlags } from 'uniswap/src/features/gating/flags'
import { useFeatureFlag } from 'uniswap/src/features/statsig/hooks' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks'
import { DisplayNameText } from 'wallet/src/components/accounts/DisplayNameText' import { DisplayNameText } from 'wallet/src/components/accounts/DisplayNameText'
import { Account } from 'wallet/src/features/wallet/accounts/types' import { Account } from 'wallet/src/features/wallet/accounts/types'
import { useDisplayName } from 'wallet/src/features/wallet/hooks' import { useDisplayName } from 'wallet/src/features/wallet/hooks'
......
...@@ -25,8 +25,8 @@ import { Flex, HapticFeedback, Text, TouchableArea, useIsDarkMode, useSporeColor ...@@ -25,8 +25,8 @@ import { Flex, HapticFeedback, Text, TouchableArea, useIsDarkMode, useSporeColor
import Scan from 'ui/src/assets/icons/receive.svg' import Scan from 'ui/src/assets/icons/receive.svg'
import ScanQRIcon from 'ui/src/assets/icons/scan.svg' import ScanQRIcon from 'ui/src/assets/icons/scan.svg'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { FeatureFlags } from 'uniswap/src/features/statsig/flags' import { FeatureFlags } from 'uniswap/src/features/gating/flags'
import { useFeatureFlag } from 'uniswap/src/features/statsig/hooks' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks'
import { logger } from 'utilities/src/logger/logger' import { logger } from 'utilities/src/logger/logger'
import { WalletQRCode } from 'wallet/src/components/QRCodeScanner/WalletQRCode' import { WalletQRCode } from 'wallet/src/components/QRCodeScanner/WalletQRCode'
import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants' import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants'
......
...@@ -6,8 +6,8 @@ import { ...@@ -6,8 +6,8 @@ import {
UNISWAP_URL_SCHEME_WALLETCONNECT_AS_PARAM, UNISWAP_URL_SCHEME_WALLETCONNECT_AS_PARAM,
UNISWAP_WALLETCONNECT_URL, UNISWAP_WALLETCONNECT_URL,
} from 'src/features/deepLinking/constants' } from 'src/features/deepLinking/constants'
import { DynamicConfigs } from 'uniswap/src/features/statsig/configs' import { DynamicConfigs } from 'uniswap/src/features/gating/configs'
import { useDynamicConfig } from 'uniswap/src/features/statsig/hooks' import { useDynamicConfig } from 'uniswap/src/features/gating/hooks'
import { logger } from 'utilities/src/logger/logger' import { logger } from 'utilities/src/logger/logger'
import { RPCType } from 'wallet/src/constants/chains' import { RPCType } from 'wallet/src/constants/chains'
import { AssetType } from 'wallet/src/entities/assets' import { AssetType } from 'wallet/src/entities/assets'
......
...@@ -5,8 +5,8 @@ import { openModal } from 'src/features/modals/modalSlice' ...@@ -5,8 +5,8 @@ import { openModal } from 'src/features/modals/modalSlice'
import { setUserProperty } from 'src/features/telemetry' import { setUserProperty } from 'src/features/telemetry'
import { UserPropertyName } from 'src/features/telemetry/constants' import { UserPropertyName } from 'src/features/telemetry/constants'
import { Screens } from 'src/screens/Screens' import { Screens } from 'src/screens/Screens'
import { isDevBuild } from 'src/utils/version'
import { Flex, HapticFeedback, Icons, ImpactFeedbackStyle, Text, TouchableArea } from 'ui/src' import { Flex, HapticFeedback, Icons, ImpactFeedbackStyle, Text, TouchableArea } from 'ui/src'
import { isDevEnv } from 'uniswap/src/utils/env'
import { AccountIcon } from 'wallet/src/components/accounts/AccountIcon' import { AccountIcon } from 'wallet/src/components/accounts/AccountIcon'
import { AnimatedUnitagDisplayName } from 'wallet/src/components/accounts/AnimatedUnitagDisplayName' import { AnimatedUnitagDisplayName } from 'wallet/src/components/accounts/AnimatedUnitagDisplayName'
import { pushNotification } from 'wallet/src/features/notifications/slice' import { pushNotification } from 'wallet/src/features/notifications/slice'
...@@ -87,7 +87,7 @@ export function AccountHeader(): JSX.Element { ...@@ -87,7 +87,7 @@ export function AccountHeader(): JSX.Element {
hitSlop={20} hitSlop={20}
testID={ElementName.Manage} testID={ElementName.Manage}
onLongPress={async (): Promise<void> => { onLongPress={async (): Promise<void> => {
if (isDevBuild()) { if (isDevEnv()) {
await HapticFeedback.selection() await HapticFeedback.selection()
dispatch(openModal({ name: ModalName.Experiments })) dispatch(openModal({ name: ModalName.Experiments }))
} }
......
...@@ -3,8 +3,8 @@ import configureMockStore from 'redux-mock-store' ...@@ -3,8 +3,8 @@ import configureMockStore from 'redux-mock-store'
import { Screens } from 'src/screens/Screens' import { Screens } from 'src/screens/Screens'
import { preloadedMobileState } from 'src/test/fixtures' import { preloadedMobileState } from 'src/test/fixtures'
import { fireEvent, render } from 'src/test/test-utils' import { fireEvent, render } from 'src/test/test-utils'
import * as unitagHooks from 'uniswap/src/features/unitags/hooks'
import * as ensHooks from 'wallet/src/features/ens/api' import * as ensHooks from 'wallet/src/features/ens/api'
import * as unitagHooks from 'wallet/src/features/unitags/hooks'
import { import {
ON_PRESS_EVENT_PAYLOAD, ON_PRESS_EVENT_PAYLOAD,
SAMPLE_SEED_ADDRESS_1, SAMPLE_SEED_ADDRESS_1,
......
import React, { useMemo } from 'react' import React from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { FlatList } from 'react-native' import { FlatList } from 'react-native'
import { FadeIn, FadeOut } from 'react-native-reanimated' import { FadeIn, FadeOut } from 'react-native-reanimated'
...@@ -10,14 +10,8 @@ import { SectionHeaderText } from 'src/components/explore/search/SearchSectionHe ...@@ -10,14 +10,8 @@ import { SectionHeaderText } from 'src/components/explore/search/SearchSectionHe
import { AnimatedFlex, Flex, Icons, Text, TouchableArea, useSporeColors } from 'ui/src' import { AnimatedFlex, Flex, Icons, Text, TouchableArea, useSporeColors } from 'ui/src'
import ClockIcon from 'ui/src/assets/icons/clock.svg' import ClockIcon from 'ui/src/assets/icons/clock.svg'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { FeatureFlags } from 'uniswap/src/features/statsig/flags'
import { useFeatureFlag } from 'uniswap/src/features/statsig/hooks'
import { clearSearchHistory } from 'wallet/src/features/search/searchHistorySlice' import { clearSearchHistory } from 'wallet/src/features/search/searchHistorySlice'
import { import { SearchResultType, WalletSearchResult } from 'wallet/src/features/search/SearchResult'
SearchResult,
SearchResultType,
WalletSearchResult,
} from 'wallet/src/features/search/SearchResult'
import { selectSearchHistory } from 'wallet/src/features/search/selectSearchHistory' import { selectSearchHistory } from 'wallet/src/features/search/selectSearchHistory'
const TrendUpIcon = <Icons.TrendUp color="$neutral2" size="$icon.24" /> const TrendUpIcon = <Icons.TrendUp color="$neutral2" size="$icon.24" />
...@@ -39,28 +33,11 @@ export function SearchEmptySection(): JSX.Element { ...@@ -39,28 +33,11 @@ export function SearchEmptySection(): JSX.Element {
const { t } = useTranslation() const { t } = useTranslation()
const dispatch = useAppDispatch() const dispatch = useAppDispatch()
const searchHistory = useAppSelector(selectSearchHistory) const searchHistory = useAppSelector(selectSearchHistory)
const unitagFeatureFlagEnabled = useFeatureFlag(FeatureFlags.Unitags)
const onPressClearSearchHistory = (): void => { const onPressClearSearchHistory = (): void => {
dispatch(clearSearchHistory()) dispatch(clearSearchHistory())
} }
const modifiedHistory: SearchResult[] = useMemo(
() =>
searchHistory.map((historyItem: SearchResult) => {
if (!unitagFeatureFlagEnabled && historyItem.type === SearchResultType.Unitag) {
return {
type: SearchResultType.WalletByAddress,
address: historyItem.address,
searchId: historyItem.searchId,
}
} else {
return historyItem
}
}),
[searchHistory, unitagFeatureFlagEnabled]
)
// Show search history (if applicable), trending tokens, and wallets // Show search history (if applicable), trending tokens, and wallets
return ( return (
<AnimatedFlex entering={FadeIn} exiting={FadeOut} gap="$spacing12" pb="$spacing36"> <AnimatedFlex entering={FadeIn} exiting={FadeOut} gap="$spacing12" pb="$spacing36">
...@@ -85,7 +62,7 @@ export function SearchEmptySection(): JSX.Element { ...@@ -85,7 +62,7 @@ export function SearchEmptySection(): JSX.Element {
</TouchableArea> </TouchableArea>
</Flex> </Flex>
} }
data={modifiedHistory} data={searchHistory}
renderItem={(props): JSX.Element | null => renderItem={(props): JSX.Element | null =>
renderSearchItem({ ...props, searchContext: { isHistory: true } }) renderSearchItem({ ...props, searchContext: { isHistory: true } })
} }
......
import { useMemo } from 'react' import { useMemo } from 'react'
import { useUnitagByAddress, useUnitagByName } from 'uniswap/src/features/unitags/hooks'
import { ChainId } from 'wallet/src/constants/chains' import { ChainId } from 'wallet/src/constants/chains'
import { useENS } from 'wallet/src/features/ens/useENS' import { useENS } from 'wallet/src/features/ens/useENS'
import { SearchResultType, WalletSearchResult } from 'wallet/src/features/search/SearchResult' import { SearchResultType, WalletSearchResult } from 'wallet/src/features/search/SearchResult'
import { useIsSmartContractAddress } from 'wallet/src/features/transactions/transfer/hooks/useIsSmartContractAddress' import { useIsSmartContractAddress } from 'wallet/src/features/transactions/transfer/hooks/useIsSmartContractAddress'
import { useUnitagByAddress, useUnitagByName } from 'wallet/src/features/unitags/hooks'
import { getValidAddress } from 'wallet/src/utils/addresses' import { getValidAddress } from 'wallet/src/utils/addresses'
// eslint-disable-next-line complexity // eslint-disable-next-line complexity
......
...@@ -6,7 +6,7 @@ import { Flex, Text, TouchableArea, useIsDarkMode } from 'ui/src' ...@@ -6,7 +6,7 @@ import { Flex, Text, TouchableArea, useIsDarkMode } from 'ui/src'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { concatStrings } from 'utilities/src/primitives/string' import { concatStrings } from 'utilities/src/primitives/string'
import { FORServiceProvider } from 'wallet/src/features/fiatOnRamp/types' import { FORServiceProvider } from 'wallet/src/features/fiatOnRamp/types'
import { getServiceProviderLogo } from 'wallet/src/features/fiatOnRamp/utils' import { getOptionalServiceProviderLogo } from 'wallet/src/features/fiatOnRamp/utils'
import { ImageUri } from 'wallet/src/features/images/ImageUri' import { ImageUri } from 'wallet/src/features/images/ImageUri'
function LogoLoader(): JSX.Element { function LogoLoader(): JSX.Element {
...@@ -24,7 +24,7 @@ export function FORQuoteItem({ ...@@ -24,7 +24,7 @@ export function FORQuoteItem({
}): JSX.Element | null { }): JSX.Element | null {
const { t } = useTranslation() const { t } = useTranslation()
const isDarkMode = useIsDarkMode() const isDarkMode = useIsDarkMode()
const logoUrl = getServiceProviderLogo(serviceProvider?.logos, isDarkMode) const logoUrl = getOptionalServiceProviderLogo(serviceProvider?.logos, isDarkMode)
if (!serviceProvider) { if (!serviceProvider) {
return null return null
......
...@@ -5,8 +5,8 @@ import { SeedPhraseDisplay } from 'src/components/mnemonic/SeedPhraseDisplay' ...@@ -5,8 +5,8 @@ import { SeedPhraseDisplay } from 'src/components/mnemonic/SeedPhraseDisplay'
import { APP_STORE_LINK } from 'src/constants/urls' import { APP_STORE_LINK } from 'src/constants/urls'
import { UpgradeStatus } from 'src/features/forceUpgrade/types' import { UpgradeStatus } from 'src/features/forceUpgrade/types'
import { Flex, Text, TouchableArea, useSporeColors } from 'ui/src' import { Flex, Text, TouchableArea, useSporeColors } from 'ui/src'
import { DynamicConfigs } from 'uniswap/src/features/statsig/configs' import { DynamicConfigs } from 'uniswap/src/features/gating/configs'
import { useDynamicConfig } from 'uniswap/src/features/statsig/hooks' import { useDynamicConfig } from 'uniswap/src/features/gating/hooks'
import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal' import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal'
import { WarningModal } from 'wallet/src/components/modals/WarningModal/WarningModal' import { WarningModal } from 'wallet/src/components/modals/WarningModal/WarningModal'
import { WarningSeverity } from 'wallet/src/features/transactions/WarningModal/types' import { WarningSeverity } from 'wallet/src/features/transactions/WarningModal/types'
......
...@@ -2,13 +2,13 @@ import { FlashList } from '@shopify/flash-list' ...@@ -2,13 +2,13 @@ import { FlashList } from '@shopify/flash-list'
import React, { forwardRef, memo, useCallback, useMemo } from 'react' import React, { forwardRef, memo, useCallback, useMemo } from 'react'
import { RefreshControl } from 'react-native' import { RefreshControl } from 'react-native'
import { useAppStackNavigation } from 'src/app/navigation/types' import { useAppStackNavigation } from 'src/app/navigation/types'
import { NftView } from 'src/components/NFT/NftView'
import { useAdaptiveFooter } from 'src/components/home/hooks' import { useAdaptiveFooter } from 'src/components/home/hooks'
import { TAB_BAR_HEIGHT, TabProps } from 'src/components/layout/TabHelpers' import { TAB_BAR_HEIGHT, TabProps } from 'src/components/layout/TabHelpers'
import { Screens } from 'src/screens/Screens' import { Screens } from 'src/screens/Screens'
import { Flex, useDeviceInsets, useSporeColors } from 'ui/src' import { Flex, useDeviceInsets, useSporeColors } from 'ui/src'
import { GQLQueries } from 'uniswap/src/data/graphql/uniswap-data-api/queries' import { GQLQueries } from 'uniswap/src/data/graphql/uniswap-data-api/queries'
import { isAndroid } from 'uniswap/src/utils/platform' import { isAndroid } from 'uniswap/src/utils/platform'
import { NftView } from 'wallet/src/components/nfts/NftView'
import { NftsList } from 'wallet/src/components/nfts/NftsList' import { NftsList } from 'wallet/src/components/nfts/NftsList'
import { NFTItem } from 'wallet/src/features/nfts/types' import { NFTItem } from 'wallet/src/features/nfts/types'
......
...@@ -6,8 +6,8 @@ import { openModal } from 'src/features/modals/modalSlice' ...@@ -6,8 +6,8 @@ import { openModal } from 'src/features/modals/modalSlice'
import { Flex, Icons, Text, TouchableArea } from 'ui/src' import { Flex, Icons, Text, TouchableArea } from 'ui/src'
import PaperStackIcon from 'ui/src/assets/icons/paper-stack.svg' import PaperStackIcon from 'ui/src/assets/icons/paper-stack.svg'
import { iconSizes, colors as rawColors } from 'ui/src/theme' import { iconSizes, colors as rawColors } from 'ui/src/theme'
import { FeatureFlags } from 'uniswap/src/features/statsig/flags' import { FeatureFlags } from 'uniswap/src/features/gating/flags'
import { useFeatureFlag } from 'uniswap/src/features/statsig/hooks' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks'
import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants' import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants'
import { AccountType } from 'wallet/src/features/wallet/accounts/types' import { AccountType } from 'wallet/src/features/wallet/accounts/types'
import { useActiveAccount } from 'wallet/src/features/wallet/hooks' import { useActiveAccount } from 'wallet/src/features/wallet/hooks'
......
import { NftView } from 'src/components/NFT/NftView'
import { useDeviceInsets, useSporeColors } from 'ui/src' import { useDeviceInsets, useSporeColors } from 'ui/src'
import { spacing } from 'ui/src/theme' import { spacing } from 'ui/src/theme'
import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal' import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal'
import { NftView } from 'wallet/src/components/nfts/NftView'
import { NftsList } from 'wallet/src/components/nfts/NftsList' import { NftsList } from 'wallet/src/components/nfts/NftsList'
import { NFTItem } from 'wallet/src/features/nfts/types' import { NFTItem } from 'wallet/src/features/nfts/types'
import { ModalName } from 'wallet/src/telemetry/constants' import { ModalName } from 'wallet/src/telemetry/constants'
......
...@@ -7,9 +7,6 @@ import { initAndPersistCache } from 'src/data/cache' ...@@ -7,9 +7,6 @@ import { initAndPersistCache } from 'src/data/cache'
import { sendMobileAnalyticsEvent } from 'src/features/telemetry' import { sendMobileAnalyticsEvent } from 'src/features/telemetry'
import { MobileEventName } from 'src/features/telemetry/constants' import { MobileEventName } from 'src/features/telemetry/constants'
import { selectCustomEndpoint } from 'src/features/tweaks/selectors' import { selectCustomEndpoint } from 'src/features/tweaks/selectors'
import { uniswapUrls } from 'uniswap/src/constants/urls'
import { FeatureFlags } from 'uniswap/src/features/statsig/flags'
import { useFeatureFlag } from 'uniswap/src/features/statsig/hooks'
import { isNonJestDev } from 'utilities/src/environment' import { isNonJestDev } from 'utilities/src/environment'
import { logger } from 'utilities/src/logger/logger' import { logger } from 'utilities/src/logger/logger'
import { useAsyncData } from 'utilities/src/react/hooks' import { useAsyncData } from 'utilities/src/react/hooks'
...@@ -72,7 +69,6 @@ if (isNonJestDev) { ...@@ -72,7 +69,6 @@ if (isNonJestDev) {
export const usePersistedApolloClient = (): ApolloClient<NormalizedCacheObject> | undefined => { export const usePersistedApolloClient = (): ApolloClient<NormalizedCacheObject> | undefined => {
const [client, setClient] = useState<ApolloClient<NormalizedCacheObject>>() const [client, setClient] = useState<ApolloClient<NormalizedCacheObject>>()
const customEndpoint = useAppSelector(selectCustomEndpoint) const customEndpoint = useAppSelector(selectCustomEndpoint)
const cloudflareGatewayEnabled = useFeatureFlag(FeatureFlags.GatewayDNSUpdateMobile)
const apolloLink = customEndpoint const apolloLink = customEndpoint
? getCustomGraphqlHttpLink(customEndpoint) ? getCustomGraphqlHttpLink(customEndpoint)
...@@ -90,9 +86,7 @@ export const usePersistedApolloClient = (): ApolloClient<NormalizedCacheObject> ...@@ -90,9 +86,7 @@ export const usePersistedApolloClient = (): ApolloClient<NormalizedCacheObject>
) )
} }
const restLink = cloudflareGatewayEnabled const restLink = getRestLink()
? getRestLink(uniswapUrls.apiBaseUrlCloudflare)
: getRestLink()
const newClient = new ApolloClient({ const newClient = new ApolloClient({
assumeImmutableResults: true, assumeImmutableResults: true,
......
import appsFlyer from 'react-native-appsflyer' import appsFlyer from 'react-native-appsflyer'
import { isBetaBuild, isDevBuild } from 'src/utils/version'
import { config } from 'uniswap/src/config' import { config } from 'uniswap/src/config'
import { isBetaEnv, isDevEnv } from 'uniswap/src/utils/env'
import { logger } from 'utilities/src/logger/logger' import { logger } from 'utilities/src/logger/logger'
export function initAppsFlyer(): void { export function initAppsFlyer(): void {
appsFlyer.initSdk( appsFlyer.initSdk(
{ {
devKey: config.appsflyerApiKey, devKey: config.appsflyerApiKey,
isDebug: isDevBuild() || isBetaBuild(), isDebug: isDevEnv() || isBetaEnv(),
appId: config.appsflyerAppId, appId: config.appsflyerAppId,
onInstallConversionDataListener: false, onInstallConversionDataListener: false,
onDeepLinkListener: false, onDeepLinkListener: false,
......
...@@ -15,7 +15,7 @@ import { sendMobileAnalyticsEvent } from 'src/features/telemetry' ...@@ -15,7 +15,7 @@ import { sendMobileAnalyticsEvent } from 'src/features/telemetry'
import { MobileEventName } from 'src/features/telemetry/constants' import { MobileEventName } from 'src/features/telemetry/constants'
import { waitForWcWeb3WalletIsReady } from 'src/features/walletConnect/saga' import { waitForWcWeb3WalletIsReady } from 'src/features/walletConnect/saga'
import { Screens } from 'src/screens/Screens' import { Screens } from 'src/screens/Screens'
import { UNISWAP_APP_HOSTNAME } from 'uniswap/src/constants/urls' import { UNISWAP_WEB_URL } from 'uniswap/src/constants/urls'
import { setAccountAsActive } from 'wallet/src/features/wallet/slice' import { setAccountAsActive } from 'wallet/src/features/wallet/slice'
import { ModalName } from 'wallet/src/telemetry/constants' import { ModalName } from 'wallet/src/telemetry/constants'
import { import {
...@@ -164,8 +164,8 @@ describe(handleDeepLink, () => { ...@@ -164,8 +164,8 @@ describe(handleDeepLink, () => {
it('Handles Share NFT Item Universal Link', async () => { it('Handles Share NFT Item Universal Link', async () => {
const path = `nfts/asset/${SAMPLE_SEED_ADDRESS_1}/123` const path = `nfts/asset/${SAMPLE_SEED_ADDRESS_1}/123`
const pathUrl = `https://${UNISWAP_APP_HOSTNAME}/${path}` const pathUrl = `${UNISWAP_WEB_URL}/${path}`
const hashedUrl = `https://${UNISWAP_APP_HOSTNAME}/#/${path}` const hashedUrl = `${UNISWAP_WEB_URL}/#/${path}`
const expectedModal: OpenModalParams = { const expectedModal: OpenModalParams = {
name: ModalName.Explore, name: ModalName.Explore,
initialState: { initialState: {
...@@ -207,8 +207,8 @@ describe(handleDeepLink, () => { ...@@ -207,8 +207,8 @@ describe(handleDeepLink, () => {
it('Handles Share NFT Collection Universal Link', async () => { it('Handles Share NFT Collection Universal Link', async () => {
const path = `nfts/collection/${SAMPLE_SEED_ADDRESS_1}` const path = `nfts/collection/${SAMPLE_SEED_ADDRESS_1}`
const pathUrl = `https://${UNISWAP_APP_HOSTNAME}/${path}` const pathUrl = `${UNISWAP_WEB_URL}/${path}`
const hashedUrl = `https://${UNISWAP_APP_HOSTNAME}/#/${path}` const hashedUrl = `${UNISWAP_WEB_URL}/#/${path}`
const expectedModal: OpenModalParams = { const expectedModal: OpenModalParams = {
name: ModalName.Explore, name: ModalName.Explore,
initialState: { initialState: {
...@@ -248,8 +248,8 @@ describe(handleDeepLink, () => { ...@@ -248,8 +248,8 @@ describe(handleDeepLink, () => {
it('Handles Share Token Item Universal Link', async () => { it('Handles Share Token Item Universal Link', async () => {
const path = `tokens/ethereum/${SAMPLE_SEED_ADDRESS_1}` const path = `tokens/ethereum/${SAMPLE_SEED_ADDRESS_1}`
const pathUrl = `https://${UNISWAP_APP_HOSTNAME}/${path}` const pathUrl = `${UNISWAP_WEB_URL}/${path}`
const hashedUrl = `https://${UNISWAP_APP_HOSTNAME}/#/${path}` const hashedUrl = `${UNISWAP_WEB_URL}/#/${path}`
const expectedModal: OpenModalParams = { const expectedModal: OpenModalParams = {
name: ModalName.Explore, name: ModalName.Explore,
initialState: { initialState: {
...@@ -289,7 +289,7 @@ describe(handleDeepLink, () => { ...@@ -289,7 +289,7 @@ describe(handleDeepLink, () => {
it('Handles Share currently active Account Address Universal Link', () => { it('Handles Share currently active Account Address Universal Link', () => {
const hash = `#/address/${account.address}` const hash = `#/address/${account.address}`
const url = `https://${UNISWAP_APP_HOSTNAME}/${hash}` const url = `${UNISWAP_WEB_URL}/${hash}`
return expectSaga(handleDeepLink, { return expectSaga(handleDeepLink, {
payload: { payload: {
url, url,
...@@ -305,7 +305,7 @@ describe(handleDeepLink, () => { ...@@ -305,7 +305,7 @@ describe(handleDeepLink, () => {
it('Handles Share already added Account Address Universal Link', () => { it('Handles Share already added Account Address Universal Link', () => {
const hash = `#/address/${SAMPLE_SEED_ADDRESS_2}` const hash = `#/address/${SAMPLE_SEED_ADDRESS_2}`
const url = `https://${UNISWAP_APP_HOSTNAME}/${hash}` const url = `${UNISWAP_WEB_URL}/${hash}`
return expectSaga(handleDeepLink, { return expectSaga(handleDeepLink, {
payload: { payload: {
url, url,
...@@ -330,8 +330,8 @@ describe(handleDeepLink, () => { ...@@ -330,8 +330,8 @@ describe(handleDeepLink, () => {
it('Handles Share external Account Address Universal Link', async () => { it('Handles Share external Account Address Universal Link', async () => {
const path = `address/${SAMPLE_SEED_ADDRESS_2}` const path = `address/${SAMPLE_SEED_ADDRESS_2}`
const pathUrl = `https://${UNISWAP_APP_HOSTNAME}/${path}` const pathUrl = `${UNISWAP_WEB_URL}/${path}`
const hashedUrl = `https://${UNISWAP_APP_HOSTNAME}/#/${path}` const hashedUrl = `${UNISWAP_WEB_URL}/#/${path}`
const expectedModal: OpenModalParams = { const expectedModal: OpenModalParams = {
name: ModalName.Explore, name: ModalName.Explore,
initialState: { initialState: {
......
...@@ -26,8 +26,8 @@ import { WidgetType } from 'src/features/widgets/widgets' ...@@ -26,8 +26,8 @@ import { WidgetType } from 'src/features/widgets/widgets'
import { Screens } from 'src/screens/Screens' import { Screens } from 'src/screens/Screens'
import { Statsig } from 'statsig-react-native' import { Statsig } from 'statsig-react-native'
import { call, put, takeLatest } from 'typed-redux-saga' import { call, put, takeLatest } from 'typed-redux-saga'
import { UNISWAP_APP_HOSTNAME } from 'uniswap/src/constants/urls' import { UNISWAP_WEB_HOSTNAME } from 'uniswap/src/constants/urls'
import { FeatureFlags, getFeatureFlagName } from 'uniswap/src/features/statsig/flags' import { FeatureFlags, getFeatureFlagName } from 'uniswap/src/features/gating/flags'
import i18n from 'uniswap/src/i18n/i18n' import i18n from 'uniswap/src/i18n/i18n'
import { logger } from 'utilities/src/logger/logger' import { logger } from 'utilities/src/logger/logger'
import { selectExtensionOnboardingState } from 'wallet/src/features/behaviorHistory/selectors' import { selectExtensionOnboardingState } from 'wallet/src/features/behaviorHistory/selectors'
...@@ -217,7 +217,7 @@ export function* handleDeepLink(action: ReturnType<typeof openDeepLink>) { ...@@ -217,7 +217,7 @@ export function* handleDeepLink(action: ReturnType<typeof openDeepLink>) {
if (!activeAccount) { if (!activeAccount) {
// For app.uniswap.org links it should open a browser with the link // For app.uniswap.org links it should open a browser with the link
// instead of handling it inside the app // instead of handling it inside the app
if (url.hostname === UNISWAP_APP_HOSTNAME) { if (url.hostname === UNISWAP_WEB_HOSTNAME) {
yield* call(openUri, action.payload.url, /* openExternalBrowser */ true) yield* call(openUri, action.payload.url, /* openExternalBrowser */ true)
} }
// Skip handling any other deep links // Skip handling any other deep links
...@@ -315,8 +315,8 @@ export function* handleDeepLink(action: ReturnType<typeof openDeepLink>) { ...@@ -315,8 +315,8 @@ export function* handleDeepLink(action: ReturnType<typeof openDeepLink>) {
} }
} }
if (url.hostname === UNISWAP_APP_HOSTNAME) { if (url.hostname === UNISWAP_WEB_HOSTNAME) {
const urlParts = url.href.split(`${UNISWAP_APP_HOSTNAME}/`) const urlParts = url.href.split(`${UNISWAP_WEB_HOSTNAME}/`)
const urlPath = urlParts.length >= 1 ? (urlParts[1] as string) : '' const urlPath = urlParts.length >= 1 ? (urlParts[1] as string) : ''
yield* call(handleUniswapAppDeepLink, urlPath, action.payload.url, LinkSource.Share) yield* call(handleUniswapAppDeepLink, urlPath, action.payload.url, LinkSource.Share)
return return
......
...@@ -8,11 +8,11 @@ import { disableOnPress } from 'src/utils/disableOnPress' ...@@ -8,11 +8,11 @@ import { disableOnPress } from 'src/utils/disableOnPress'
import { Flex, HapticFeedback, TouchableArea } from 'ui/src' import { Flex, HapticFeedback, TouchableArea } from 'ui/src'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { uniswapUrls } from 'uniswap/src/constants/urls' import { uniswapUrls } from 'uniswap/src/constants/urls'
import { useUnitagByAddress } from 'uniswap/src/features/unitags/hooks'
import { logger } from 'utilities/src/logger/logger' import { logger } from 'utilities/src/logger/logger'
import { CHAIN_INFO, ChainId } from 'wallet/src/constants/chains' import { CHAIN_INFO, ChainId } from 'wallet/src/constants/chains'
import { pushNotification } from 'wallet/src/features/notifications/slice' import { pushNotification } from 'wallet/src/features/notifications/slice'
import { AppNotificationType, CopyNotificationType } from 'wallet/src/features/notifications/types' import { AppNotificationType, CopyNotificationType } from 'wallet/src/features/notifications/types'
import { useUnitagByAddress } from 'wallet/src/features/unitags/hooks'
import { sendWalletAnalyticsEvent } from 'wallet/src/telemetry' import { sendWalletAnalyticsEvent } from 'wallet/src/telemetry'
import { ShareableEntity, WalletEventName } from 'wallet/src/telemetry/constants' import { ShareableEntity, WalletEventName } from 'wallet/src/telemetry/constants'
import { setClipboard } from 'wallet/src/utils/clipboard' import { setClipboard } from 'wallet/src/utils/clipboard'
......
...@@ -27,8 +27,8 @@ import { ...@@ -27,8 +27,8 @@ import {
} from 'ui/src' } from 'ui/src'
import { ENS_LOGO } from 'ui/src/assets' import { ENS_LOGO } from 'ui/src/assets'
import { iconSizes, imageSizes } from 'ui/src/theme' import { iconSizes, imageSizes } from 'ui/src/theme'
import { FeatureFlags } from 'uniswap/src/features/statsig/flags' import { FeatureFlags } from 'uniswap/src/features/gating/flags'
import { useFeatureFlag } from 'uniswap/src/features/statsig/hooks' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks'
import { AddressDisplay } from 'wallet/src/components/accounts/AddressDisplay' import { AddressDisplay } from 'wallet/src/components/accounts/AddressDisplay'
import { useENSDescription, useENSName, useENSTwitterUsername } from 'wallet/src/features/ens/api' import { useENSDescription, useENSName, useENSTwitterUsername } from 'wallet/src/features/ens/api'
import { selectWatchedAddressSet } from 'wallet/src/features/favorites/selectors' import { selectWatchedAddressSet } from 'wallet/src/features/favorites/selectors'
......
import { FORTransferInstitution } from 'wallet/src/features/fiatOnRamp/types' import { FORServiceProvider } from 'wallet/src/features/fiatOnRamp/types'
export interface ExchangeTransferModalState { export interface ExchangeTransferModalState {
serviceProvider: FORTransferInstitution serviceProvider: FORServiceProvider
} }
import { BottomSheetFlatList } from '@gorhom/bottom-sheet'
import React, { useCallback } from 'react' import React, { useCallback } from 'react'
import { ListRenderItemInfo } from 'react-native' import { FlatList, ListRenderItemInfo } from 'react-native'
import { getCountry } from 'react-native-localize'
import { FadeIn, FadeOut } from 'react-native-reanimated' import { FadeIn, FadeOut } from 'react-native-reanimated'
import { useAppDispatch } from 'src/app/hooks' import { useAppDispatch } from 'src/app/hooks'
import { openModal } from 'src/features/modals/modalSlice' import { openModal } from 'src/features/modals/modalSlice'
import { AnimatedFlex, Flex, ImpactFeedbackStyle, Loader, Text, TouchableArea } from 'ui/src' import { AnimatedFlex, Flex, ImpactFeedbackStyle, Text, TouchableArea, useIsDarkMode } from 'ui/src'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { useFiatOnRampAggregatorTransferInstitutionsQuery } from 'wallet/src/features/fiatOnRamp/api' import { FORServiceProvider } from 'wallet/src/features/fiatOnRamp/types'
import { FORTransferInstitution } from 'wallet/src/features/fiatOnRamp/types' import { getServiceProviderLogo } from 'wallet/src/features/fiatOnRamp/utils'
import { RemoteImage } from 'wallet/src/features/images/RemoteImage' import { RemoteImage } from 'wallet/src/features/images/RemoteImage'
import { ModalName } from 'wallet/src/telemetry/constants' import { ModalName } from 'wallet/src/telemetry/constants'
function key(item: FORTransferInstitution): string { function key(item: FORServiceProvider): string {
return item.id as string return item.serviceProvider
} }
const CEX_ICON_SIZE = iconSizes.icon36 const CEX_ICON_SIZE = iconSizes.icon36
const CEX_ICON_BORDER_RADIUS = 12 const CEX_ICON_BORDER_RADIUS = 12
function CEXItemWrapper({ function CEXItemWrapper({
institution, serviceProvider,
onSelectTransferInstitution, onSelectServiceProvider,
}: { }: {
institution: FORTransferInstitution serviceProvider: FORServiceProvider
onSelectTransferInstitution: (transferInstitution: FORTransferInstitution) => void onSelectServiceProvider: (serviceProvider: FORServiceProvider) => void
}): JSX.Element | null { }): JSX.Element | null {
const onPress = (): void => onSelectTransferInstitution(institution) const onPress = (): void => onSelectServiceProvider(serviceProvider)
const isDarkMode = useIsDarkMode()
const logoUrl = getServiceProviderLogo(serviceProvider.logos, isDarkMode)
return ( return (
<TouchableArea hapticFeedback hapticStyle={ImpactFeedbackStyle.Light} onPress={onPress}> <TouchableArea hapticFeedback hapticStyle={ImpactFeedbackStyle.Light} onPress={onPress}>
...@@ -46,11 +47,11 @@ function CEXItemWrapper({ ...@@ -46,11 +47,11 @@ function CEXItemWrapper({
borderRadius={CEX_ICON_BORDER_RADIUS} borderRadius={CEX_ICON_BORDER_RADIUS}
height={CEX_ICON_SIZE} height={CEX_ICON_SIZE}
resizeMode="cover" resizeMode="cover"
uri={institution.icon} uri={logoUrl}
width={CEX_ICON_SIZE} width={CEX_ICON_SIZE}
/> />
<Text flexShrink={1} variant="body2"> <Text flexShrink={1} variant="body2">
{institution.name} {serviceProvider.name}
</Text> </Text>
</Flex> </Flex>
</Flex> </Flex>
...@@ -58,18 +59,21 @@ function CEXItemWrapper({ ...@@ -58,18 +59,21 @@ function CEXItemWrapper({
) )
} }
export function TransferInstitutionSelector({ onClose }: { onClose: () => void }): JSX.Element { export function ServiceProviderSelector({
onClose,
serviceProviders,
}: {
onClose: () => void
serviceProviders: FORServiceProvider[]
}): JSX.Element {
const dispatch = useAppDispatch() const dispatch = useAppDispatch()
const { data, isLoading } = useFiatOnRampAggregatorTransferInstitutionsQuery({
countryCode: getCountry(),
})
const onSelectTransferInstitution = useCallback( const onSelectServiceProvider = useCallback(
(transferInstitution: FORTransferInstitution) => { (serviceProvider: FORServiceProvider) => {
dispatch( dispatch(
openModal({ openModal({
name: ModalName.ExchangeTransferModal, name: ModalName.ExchangeTransferModal,
initialState: { serviceProvider: transferInstitution }, initialState: { serviceProvider },
}) })
) )
onClose() onClose()
...@@ -78,30 +82,26 @@ export function TransferInstitutionSelector({ onClose }: { onClose: () => void } ...@@ -78,30 +82,26 @@ export function TransferInstitutionSelector({ onClose }: { onClose: () => void }
) )
const renderItem = useCallback( const renderItem = useCallback(
({ item: institution }: ListRenderItemInfo<FORTransferInstitution>) => ( ({ item: serviceProvider }: ListRenderItemInfo<FORServiceProvider>) => (
<CEXItemWrapper <CEXItemWrapper
institution={institution} serviceProvider={serviceProvider}
onSelectTransferInstitution={onSelectTransferInstitution} onSelectServiceProvider={onSelectServiceProvider}
/> />
), ),
[onSelectTransferInstitution] [onSelectServiceProvider]
) )
return ( return (
<Flex grow> <Flex grow>
<AnimatedFlex grow entering={FadeIn} exiting={FadeOut}> <AnimatedFlex grow entering={FadeIn} exiting={FadeOut}>
{isLoading ? ( <FlatList
<Loader.TransferInstitution iconSize={CEX_ICON_SIZE} itemsCount={5} />
) : (
<BottomSheetFlatList
ItemSeparatorComponent={renderItemSeparator} ItemSeparatorComponent={renderItemSeparator}
bounces={true} bounces={true}
data={data?.institutions || []} data={serviceProviders}
keyExtractor={key} keyExtractor={key}
renderItem={renderItem} renderItem={renderItem}
showsVerticalScrollIndicator={false} showsVerticalScrollIndicator={false}
/> />
)}
</AnimatedFlex> </AnimatedFlex>
</Flex> </Flex>
) )
......
...@@ -48,6 +48,16 @@ const PREDEFINED_AMOUNTS = [100, 300, 1000] ...@@ -48,6 +48,16 @@ const PREDEFINED_AMOUNTS = [100, 300, 1000]
type OnChangeAmount = (amount: string) => void type OnChangeAmount = (amount: string) => void
function OnRampError({ errorText, color }: { errorText: string; color: ColorTokens }): JSX.Element {
return (
<Flex centered>
<Text color={color} variant="body3">
{errorText}
</Text>
</Flex>
)
}
interface Props { interface Props {
showNativeKeyboard: boolean showNativeKeyboard: boolean
onInputPanelLayout: (event: LayoutChangeEvent) => void onInputPanelLayout: (event: LayoutChangeEvent) => void
...@@ -67,6 +77,7 @@ interface Props { ...@@ -67,6 +77,7 @@ interface Props {
onTokenSelectorPress: () => void onTokenSelectorPress: () => void
predefinedAmountsSupported: boolean predefinedAmountsSupported: boolean
appFiatCurrencySupported: boolean appFiatCurrencySupported: boolean
notAvailableInThisRegion?: boolean
fiatCurrencyInfo: FiatCurrencyInfo fiatCurrencyInfo: FiatCurrencyInfo
} }
...@@ -89,6 +100,7 @@ export function FiatOnRampAmountSection({ ...@@ -89,6 +100,7 @@ export function FiatOnRampAmountSection({
onTokenSelectorPress, onTokenSelectorPress,
predefinedAmountsSupported, predefinedAmountsSupported,
appFiatCurrencySupported, appFiatCurrencySupported,
notAvailableInThisRegion,
fiatCurrencyInfo, fiatCurrencyInfo,
}: Props): JSX.Element { }: Props): JSX.Element {
const { t } = useTranslation() const { t } = useTranslation()
...@@ -186,7 +198,8 @@ export function FiatOnRampAmountSection({ ...@@ -186,7 +198,8 @@ export function FiatOnRampAmountSection({
{currency.currencyInfo && ( {currency.currencyInfo && (
<SelectTokenButton <SelectTokenButton
amount={quoteAmount} amount={quoteAmount}
disabled={!quoteCurrencyAmountReady} amountReady={quoteCurrencyAmountReady}
disabled={notAvailableInThisRegion}
loading={selectTokenLoading} loading={selectTokenLoading}
selectedCurrencyInfo={currency.currencyInfo} selectedCurrencyInfo={currency.currencyInfo}
onPress={onTokenSelectorPress} onPress={onTokenSelectorPress}
...@@ -199,18 +212,17 @@ export function FiatOnRampAmountSection({ ...@@ -199,18 +212,17 @@ export function FiatOnRampAmountSection({
key={amount} key={amount}
amount={amount} amount={amount}
currentAmount={value} currentAmount={value}
disabled={notAvailableInThisRegion}
fiatCurrencyInfo={fiatCurrencyInfo} fiatCurrencyInfo={fiatCurrencyInfo}
onPress={onChoosePredifendAmount} onPress={onChoosePredifendAmount}
/> />
))} ))}
</Flex> </Flex>
) : null} ) : null}
{!appFiatCurrencySupported ? ( {notAvailableInThisRegion ? (
<Flex centered> <OnRampError color="$neutral2" errorText={t('fiatOnRamp.error.unavailable')} />
<Text color="$neutral3" variant="body3"> ) : !appFiatCurrencySupported ? (
{t('fiatOnRamp.error.usd')} <OnRampError color="$neutral3" errorText={t('fiatOnRamp.error.usd')} />
</Text>
</Flex>
) : null} ) : null}
</Flex> </Flex>
</Flex> </Flex>
...@@ -221,6 +233,7 @@ interface SelectTokenButtonProps { ...@@ -221,6 +233,7 @@ interface SelectTokenButtonProps {
onPress: () => void onPress: () => void
selectedCurrencyInfo: CurrencyInfo selectedCurrencyInfo: CurrencyInfo
amount: number amount: number
amountReady?: boolean
disabled?: boolean disabled?: boolean
loading?: boolean loading?: boolean
} }
...@@ -229,6 +242,7 @@ function SelectTokenButton({ ...@@ -229,6 +242,7 @@ function SelectTokenButton({
selectedCurrencyInfo, selectedCurrencyInfo,
onPress, onPress,
amount, amount,
amountReady,
disabled, disabled,
loading, loading,
}: SelectTokenButtonProps): JSX.Element { }: SelectTokenButtonProps): JSX.Element {
...@@ -236,12 +250,13 @@ function SelectTokenButton({ ...@@ -236,12 +250,13 @@ function SelectTokenButton({
amount.toString(), amount.toString(),
selectedCurrencyInfo.currency selectedCurrencyInfo.currency
) )
const textColor = disabled || loading ? '$neutral3' : '$neutral2' const textColor = !amountReady || disabled || loading ? '$neutral3' : '$neutral2'
return ( return (
<TouchableArea <TouchableArea
hapticFeedback hapticFeedback
borderRadius="$roundedFull" borderRadius="$roundedFull"
disabled={disabled}
testID={ElementName.TokenSelectorToggle} testID={ElementName.TokenSelectorToggle}
onPress={onPress}> onPress={onPress}>
<Flex centered row flexDirection="row" gap="$none" p="$spacing4"> <Flex centered row flexDirection="row" gap="$none" p="$spacing4">
...@@ -272,11 +287,13 @@ function PredefinedAmount({ ...@@ -272,11 +287,13 @@ function PredefinedAmount({
onPress, onPress,
currentAmount, currentAmount,
fiatCurrencyInfo, fiatCurrencyInfo,
disabled,
}: { }: {
amount: number amount: number
currentAmount: string currentAmount: string
onPress: (amount: string) => void onPress: (amount: string) => void
fiatCurrencyInfo: FiatCurrencyInfo fiatCurrencyInfo: FiatCurrencyInfo
disabled?: boolean
}): JSX.Element { }): JSX.Element {
const colors = useSporeColors() const colors = useSporeColors()
const { addFiatSymbolToNumber } = useLocalizationContext() const { addFiatSymbolToNumber } = useLocalizationContext()
...@@ -290,14 +307,15 @@ function PredefinedAmount({ ...@@ -290,14 +307,15 @@ function PredefinedAmount({
return ( return (
<TouchableOpacity <TouchableOpacity
disabled={disabled}
onPress={async (): Promise<void> => { onPress={async (): Promise<void> => {
await HapticFeedback.impact() await HapticFeedback.impact()
onPress(amount.toString()) onPress(amount.toString())
}}> }}>
<Pill <Pill
backgroundColor={highlighted ? '$surface2' : '$surface1'} backgroundColor={!disabled && highlighted ? '$surface2' : '$surface1'}
customBorderColor={colors.surface3.val} customBorderColor={disabled ? colors.surface2.val : colors.surface3.val}
foregroundColor={colors[highlighted ? 'neutral1' : 'neutral2'].val} foregroundColor={colors[disabled ? 'neutral3' : highlighted ? 'neutral1' : 'neutral2'].val}
label={formattedAmount} label={formattedAmount}
px="$spacing16" px="$spacing16"
textVariant="buttonLabel3" textVariant="buttonLabel3"
......
...@@ -2,6 +2,10 @@ import React from 'react' ...@@ -2,6 +2,10 @@ import React from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Image, ImageBackground, StyleSheet } from 'react-native' import { Image, ImageBackground, StyleSheet } from 'react-native'
import { FadeIn, FadeOut } from 'react-native-reanimated' import { FadeIn, FadeOut } from 'react-native-reanimated'
import {
SERVICE_PROVIDER_ICON_BORDER_RADIUS,
ServiceProviderLogoStyles,
} from 'src/features/fiatOnRamp/constants'
import { AnimatedFlex, Flex, Text, useDeviceInsets, useIsDarkMode } from 'ui/src' import { AnimatedFlex, Flex, Text, useDeviceInsets, useIsDarkMode } from 'ui/src'
import { import {
FOR_CONNECTING_BACKGROUND_DARK, FOR_CONNECTING_BACKGROUND_DARK,
...@@ -10,9 +14,6 @@ import { ...@@ -10,9 +14,6 @@ import {
} from 'ui/src/assets' } from 'ui/src/assets'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
export const SERVICE_PROVIDER_ICON_SIZE = 90
export const SERVICE_PROVIDER_ICON_BORDER_RADIUS = 20
export function FiatOnRampConnectingView({ export function FiatOnRampConnectingView({
amount, amount,
quoteCurrencyCode, quoteCurrencyCode,
...@@ -75,7 +76,7 @@ const styles = StyleSheet.create({ ...@@ -75,7 +76,7 @@ const styles = StyleSheet.create({
uniswapLogoWrapper: { uniswapLogoWrapper: {
backgroundColor: '#FFEFF8', // #FFD8EF with 40% opacity on a white background backgroundColor: '#FFEFF8', // #FFD8EF with 40% opacity on a white background
borderRadius: SERVICE_PROVIDER_ICON_BORDER_RADIUS, borderRadius: SERVICE_PROVIDER_ICON_BORDER_RADIUS,
height: SERVICE_PROVIDER_ICON_SIZE, height: ServiceProviderLogoStyles.icon.height,
width: SERVICE_PROVIDER_ICON_SIZE, width: ServiceProviderLogoStyles.icon.width,
}, },
}) })
...@@ -5,10 +5,8 @@ import { FadeIn, FadeOut, FadeOutDown } from 'react-native-reanimated' ...@@ -5,10 +5,8 @@ import { FadeIn, FadeOut, FadeOutDown } from 'react-native-reanimated'
import { useAppDispatch, useShouldShowNativeKeyboard } from 'src/app/hooks' import { useAppDispatch, useShouldShowNativeKeyboard } from 'src/app/hooks'
import { FiatOnRampCtaButton } from 'src/components/fiatOnRamp/CtaButton' import { FiatOnRampCtaButton } from 'src/components/fiatOnRamp/CtaButton'
import { FiatOnRampAmountSection } from 'src/features/fiatOnRamp/FiatOnRampAmountSection' import { FiatOnRampAmountSection } from 'src/features/fiatOnRamp/FiatOnRampAmountSection'
import { import { FiatOnRampConnectingView } from 'src/features/fiatOnRamp/FiatOnRampConnecting'
FiatOnRampConnectingView, import { ServiceProviderLogoStyles } from 'src/features/fiatOnRamp/constants'
SERVICE_PROVIDER_ICON_SIZE,
} from 'src/features/fiatOnRamp/FiatOnRampConnecting'
import { useMoonpayFiatOnRamp, useMoonpaySupportedTokens } from 'src/features/fiatOnRamp/hooks' import { useMoonpayFiatOnRamp, useMoonpaySupportedTokens } from 'src/features/fiatOnRamp/hooks'
import { FiatOnRampCurrency } from 'src/features/fiatOnRamp/types' import { FiatOnRampCurrency } from 'src/features/fiatOnRamp/types'
import { closeModal } from 'src/features/modals/modalSlice' import { closeModal } from 'src/features/modals/modalSlice'
...@@ -292,11 +290,14 @@ function FiatOnRampContent({ onClose }: { onClose: () => void }): JSX.Element { ...@@ -292,11 +290,14 @@ function FiatOnRampContent({ onClose }: { onClose: () => void }): JSX.Element {
<Flex <Flex
alignItems="center" alignItems="center"
borderRadius="$rounded20" borderRadius="$rounded20"
height={SERVICE_PROVIDER_ICON_SIZE} height={ServiceProviderLogoStyles.icon.height}
justifyContent="center" justifyContent="center"
style={styles.moonpayLogoWrapper} style={styles.moonpayLogoWrapper}
width={SERVICE_PROVIDER_ICON_SIZE}> width={ServiceProviderLogoStyles.icon.width}>
<MoonpayLogo height={SERVICE_PROVIDER_ICON_SIZE} width={SERVICE_PROVIDER_ICON_SIZE} /> <MoonpayLogo
height={ServiceProviderLogoStyles.icon.height}
width={ServiceProviderLogoStyles.icon.width}
/>
</Flex> </Flex>
} }
serviceProviderName="MoonPay" serviceProviderName="MoonPay"
......
...@@ -15,7 +15,7 @@ import { ...@@ -15,7 +15,7 @@ import {
useFiatOnRampAggregatorCryptoQuoteQuery, useFiatOnRampAggregatorCryptoQuoteQuery,
useFiatOnRampAggregatorSupportedFiatCurrenciesQuery, useFiatOnRampAggregatorSupportedFiatCurrenciesQuery,
} from 'wallet/src/features/fiatOnRamp/api' } from 'wallet/src/features/fiatOnRamp/api'
import { FORQuote } from 'wallet/src/features/fiatOnRamp/types' import { FORQuote, FORSupportedFiatCurrency } from 'wallet/src/features/fiatOnRamp/types'
import { import {
isFiatOnRampApiError, isFiatOnRampApiError,
isInvalidRequestAmountTooHigh, isInvalidRequestAmountTooHigh,
...@@ -27,6 +27,7 @@ import { useActiveAccountAddress } from 'wallet/src/features/wallet/hooks' ...@@ -27,6 +27,7 @@ import { useActiveAccountAddress } from 'wallet/src/features/wallet/hooks'
export function useMeldFiatCurrencySupportInfo(countryCode: string): { export function useMeldFiatCurrencySupportInfo(countryCode: string): {
appFiatCurrencySupportedInMeld: boolean appFiatCurrencySupportedInMeld: boolean
meldSupportedFiatCurrency: FiatCurrencyInfo meldSupportedFiatCurrency: FiatCurrencyInfo
supportedFiatCurrencies: FORSupportedFiatCurrency[] | undefined
} { } {
// Not all the currencies are supported by Meld, so we need to fallback to USD if the currency is not supported // Not all the currencies are supported by Meld, so we need to fallback to USD if the currency is not supported
const appFiatCurrencyInfo = useAppFiatCurrencyInfo() const appFiatCurrencyInfo = useAppFiatCurrencyInfo()
...@@ -49,6 +50,7 @@ export function useMeldFiatCurrencySupportInfo(countryCode: string): { ...@@ -49,6 +50,7 @@ export function useMeldFiatCurrencySupportInfo(countryCode: string): {
return { return {
appFiatCurrencySupportedInMeld: appFiatCurrencySupported, appFiatCurrencySupportedInMeld: appFiatCurrencySupported,
meldSupportedFiatCurrency, meldSupportedFiatCurrency,
supportedFiatCurrencies: supportedFiatCurrencies?.fiatCurrencies,
} }
} }
......
import { StyleSheet } from 'react-native'
export const FOR_MODAL_SNAP_POINTS = ['70%', '100%'] export const FOR_MODAL_SNAP_POINTS = ['70%', '100%']
export const SERVICE_PROVIDER_ICON_SIZE = 90
export const SERVICE_PROVIDER_ICON_BORDER_RADIUS = 20
export const ServiceProviderLogoStyles = StyleSheet.create({
icon: {
height: SERVICE_PROVIDER_ICON_SIZE,
width: SERVICE_PROVIDER_ICON_SIZE,
},
})
...@@ -8,7 +8,6 @@ import { FiatOnRampCurrency } from 'src/features/fiatOnRamp/types' ...@@ -8,7 +8,6 @@ import { FiatOnRampCurrency } from 'src/features/fiatOnRamp/types'
import { ColorTokens, useSporeColors } from 'ui/src' import { ColorTokens, useSporeColors } from 'ui/src'
import { uniswapUrls } from 'uniswap/src/constants/urls' import { uniswapUrls } from 'uniswap/src/constants/urls'
import { CurrencyInfo } from 'uniswap/src/features/dataApi/types' import { CurrencyInfo } from 'uniswap/src/features/dataApi/types'
import { isAndroid } from 'uniswap/src/utils/platform'
import { logger } from 'utilities/src/logger/logger' import { logger } from 'utilities/src/logger/logger'
import { useDebounce } from 'utilities/src/time/timing' import { useDebounce } from 'utilities/src/time/timing'
import { import {
...@@ -194,9 +193,7 @@ export function useMoonpayFiatOnRamp({ ...@@ -194,9 +193,7 @@ export function useMoonpayFiatOnRamp({
amount: baseCurrencyAmount, amount: baseCurrencyAmount,
currencyCode: quoteCurrencyCode, currencyCode: quoteCurrencyCode,
baseCurrencyCode, baseCurrencyCode,
redirectUrl: `${ redirectUrl: `${uniswapUrls.redirectUrlBase}/?screen=transaction&fiatOnRamp=true&userAddress=${activeAccountAddress}`,
isAndroid ? uniswapUrls.appUrl : uniswapUrls.appBaseUrl
}/?screen=transaction&fiatOnRamp=true&userAddress=${activeAccountAddress}`,
} }
: skipToken : skipToken
) )
......
import type { ReactNativeFirebase } from '@react-native-firebase/app' import type { ReactNativeFirebase } from '@react-native-firebase/app'
import '@react-native-firebase/auth' import '@react-native-firebase/auth'
import firestore, { FirebaseFirestoreTypes } from '@react-native-firebase/firestore' import firestore, { FirebaseFirestoreTypes } from '@react-native-firebase/firestore'
import { isBetaBuild, isDevBuild } from 'src/utils/version' import { isBetaEnv, isDevEnv } from 'uniswap/src/utils/env'
const ADDRESS_DATA_COLLECTION = 'address_data' const ADDRESS_DATA_COLLECTION = 'address_data'
const DEV_ADDRESS_DATA_COLLECTION = 'dev_address_data' const DEV_ADDRESS_DATA_COLLECTION = 'dev_address_data'
...@@ -39,10 +39,10 @@ export const getFirestoreMetadataRef = ( ...@@ -39,10 +39,10 @@ export const getFirestoreMetadataRef = (
.doc('data') .doc('data')
export function getAddressDataCollectionFromBundleId(): string { export function getAddressDataCollectionFromBundleId(): string {
if (isDevBuild()) { if (isDevEnv()) {
return DEV_ADDRESS_DATA_COLLECTION return DEV_ADDRESS_DATA_COLLECTION
} }
if (isBetaBuild()) { if (isBetaEnv()) {
return BETA_ADDRESS_DATA_COLLECTION return BETA_ADDRESS_DATA_COLLECTION
} }
return ADDRESS_DATA_COLLECTION return ADDRESS_DATA_COLLECTION
......
...@@ -2,9 +2,10 @@ import { ExploreModalState } from 'src/app/modals/ExploreModalState' ...@@ -2,9 +2,10 @@ import { ExploreModalState } from 'src/app/modals/ExploreModalState'
import { RemoveWalletModalState } from 'src/components/RemoveWallet/RemoveWalletModalState' import { RemoveWalletModalState } from 'src/components/RemoveWallet/RemoveWalletModalState'
import { ExtensionWaitlistModalState } from 'src/features/scantastic/ExtensionWaitlistModalState' import { ExtensionWaitlistModalState } from 'src/features/scantastic/ExtensionWaitlistModalState'
import { ScantasticModalState } from 'src/features/scantastic/ScantasticModalState' import { ScantasticModalState } from 'src/features/scantastic/ScantasticModalState'
import { ReceiveCryptoModalState } from 'src/screens/ReceiveCryptoModalState'
import { Screens } from 'src/screens/Screens' import { Screens } from 'src/screens/Screens'
import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants' import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants'
import { FORTransferInstitution } from 'wallet/src/features/fiatOnRamp/types' import { FORServiceProvider } from 'wallet/src/features/fiatOnRamp/types'
import { TransactionState } from 'wallet/src/features/transactions/transactionState/types' import { TransactionState } from 'wallet/src/features/transactions/transactionState/types'
import { ModalName } from 'wallet/src/telemetry/constants' import { ModalName } from 'wallet/src/telemetry/constants'
...@@ -16,14 +17,14 @@ export interface AppModalState<T> { ...@@ -16,14 +17,14 @@ export interface AppModalState<T> {
export interface ModalsState { export interface ModalsState {
[ModalName.AccountSwitcher]: AppModalState<undefined> [ModalName.AccountSwitcher]: AppModalState<undefined>
[ModalName.ExchangeTransferModal]: AppModalState<{ [ModalName.ExchangeTransferModal]: AppModalState<{
serviceProvider: FORTransferInstitution serviceProvider: FORServiceProvider
}> }>
[ModalName.Experiments]: AppModalState<undefined> [ModalName.Experiments]: AppModalState<undefined>
[ModalName.Explore]: AppModalState<ExploreModalState> [ModalName.Explore]: AppModalState<ExploreModalState>
[ModalName.FiatCurrencySelector]: AppModalState<undefined> [ModalName.FiatCurrencySelector]: AppModalState<undefined>
[ModalName.FiatOnRamp]: AppModalState<undefined> [ModalName.FiatOnRamp]: AppModalState<undefined>
[ModalName.FiatOnRampAggregator]: AppModalState<undefined> [ModalName.FiatOnRampAggregator]: AppModalState<undefined>
[ModalName.ReceiveCryptoModal]: AppModalState<undefined> [ModalName.ReceiveCryptoModal]: AppModalState<ReceiveCryptoModalState>
[ModalName.LanguageSelector]: AppModalState<undefined> [ModalName.LanguageSelector]: AppModalState<undefined>
[ModalName.RemoveWallet]: AppModalState<RemoveWalletModalState> [ModalName.RemoveWallet]: AppModalState<RemoveWalletModalState>
[ModalName.RestoreWallet]: AppModalState<undefined> [ModalName.RestoreWallet]: AppModalState<undefined>
......
...@@ -4,6 +4,7 @@ import { RemoveWalletModalState } from 'src/components/RemoveWallet/RemoveWallet ...@@ -4,6 +4,7 @@ import { RemoveWalletModalState } from 'src/components/RemoveWallet/RemoveWallet
import { ExchangeTransferModalState } from 'src/features/fiatOnRamp/ExchangeTransferModalState' import { ExchangeTransferModalState } from 'src/features/fiatOnRamp/ExchangeTransferModalState'
import { ExtensionWaitlistModalState } from 'src/features/scantastic/ExtensionWaitlistModalState' import { ExtensionWaitlistModalState } from 'src/features/scantastic/ExtensionWaitlistModalState'
import { ScantasticModalState } from 'src/features/scantastic/ScantasticModalState' import { ScantasticModalState } from 'src/features/scantastic/ScantasticModalState'
import { ReceiveCryptoModalState } from 'src/screens/ReceiveCryptoModalState'
import { Screens } from 'src/screens/Screens' import { Screens } from 'src/screens/Screens'
import { getKeys } from 'utilities/src/primitives/objects' import { getKeys } from 'utilities/src/primitives/objects'
import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants' import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants'
...@@ -47,7 +48,7 @@ type FiatOnRampAggregatorModalParams = { ...@@ -47,7 +48,7 @@ type FiatOnRampAggregatorModalParams = {
type ReceiveCryptoModalParams = { type ReceiveCryptoModalParams = {
name: typeof ModalName.ReceiveCryptoModal name: typeof ModalName.ReceiveCryptoModal
initialState?: undefined initialState: ReceiveCryptoModalState
} }
type LanguageSelectorModalParams = { type LanguageSelectorModalParams = {
...@@ -123,7 +124,7 @@ export const initialModalsState: ModalsState = { ...@@ -123,7 +124,7 @@ export const initialModalsState: ModalsState = {
}, },
[ModalName.ReceiveCryptoModal]: { [ModalName.ReceiveCryptoModal]: {
isOpen: false, isOpen: false,
initialState: undefined, initialState: [],
}, },
[ModalName.WalletConnectScan]: { [ModalName.WalletConnectScan]: {
isOpen: false, isOpen: false,
......
...@@ -4,8 +4,8 @@ import { OnboardingStackBaseParams, useOnboardingStackNavigation } from 'src/app ...@@ -4,8 +4,8 @@ import { OnboardingStackBaseParams, useOnboardingStackNavigation } from 'src/app
import { sendMobileAnalyticsEvent } from 'src/features/telemetry' import { sendMobileAnalyticsEvent } from 'src/features/telemetry'
import { MobileEventName } from 'src/features/telemetry/constants' import { MobileEventName } from 'src/features/telemetry/constants'
import { Screens } from 'src/screens/Screens' import { Screens } from 'src/screens/Screens'
import { FeatureFlags } from 'uniswap/src/features/statsig/flags' import { FeatureFlags } from 'uniswap/src/features/gating/flags'
import { useFeatureFlag } from 'uniswap/src/features/statsig/hooks' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks'
import { useTrace } from 'utilities/src/telemetry/trace/TraceContext' import { useTrace } from 'utilities/src/telemetry/trace/TraceContext'
import { import {
setHasSkippedUnitagPrompt, setHasSkippedUnitagPrompt,
...@@ -43,7 +43,6 @@ export function useCompleteOnboardingCallback({ ...@@ -43,7 +43,6 @@ export function useCompleteOnboardingCallback({
const parentTrace = useTrace() const parentTrace = useTrace()
const navigation = useOnboardingStackNavigation() const navigation = useOnboardingStackNavigation()
const unitagsFeatureFlagEnabled = useFeatureFlag(FeatureFlags.Unitags)
const claimUnitag = useClaimUnitag() const claimUnitag = useClaimUnitag()
const uniconsV2Enabled = useFeatureFlag(FeatureFlags.UniconsV2) const uniconsV2Enabled = useFeatureFlag(FeatureFlags.UniconsV2)
...@@ -90,10 +89,8 @@ export function useCompleteOnboardingCallback({ ...@@ -90,10 +89,8 @@ export function useCompleteOnboardingCallback({
// Remove pending flag from all new accounts. // Remove pending flag from all new accounts.
dispatch(pendingAccountActions.trigger(PendingAccountActions.Activate)) dispatch(pendingAccountActions.trigger(PendingAccountActions.Activate))
// Dismiss unitags prompt if: // Dismiss unitags prompt if the onboarding method prompts for unitags (create new)
// - the feature was enabled if (importType === ImportType.CreateNew) {
// - the onboarding method prompts for unitags (create new)
if (unitagsFeatureFlagEnabled && importType === ImportType.CreateNew) {
dispatch(setHasSkippedUnitagPrompt(true)) dispatch(setHasSkippedUnitagPrompt(true))
} }
......
...@@ -121,7 +121,7 @@ export function ScantasticModal(): JSX.Element | null { ...@@ -121,7 +121,7 @@ export function ScantasticModal(): JSX.Element | null {
try { try {
// submit encrypted blob // submit encrypted blob
const response = await fetch(`${uniswapUrls.apiBaseExtensionUrl}/scantastic/blob`, { const response = await fetch(`${uniswapUrls.scantasticApiUrl}/blob`, {
method: 'POST', method: 'POST',
headers: { headers: {
Accept: 'application/json', Accept: 'application/json',
...@@ -176,16 +176,13 @@ export function ScantasticModal(): JSX.Element | null { ...@@ -176,16 +176,13 @@ export function ScantasticModal(): JSX.Element | null {
return return
} }
try { try {
const response = await fetch( const response = await fetch(`${uniswapUrls.scantasticApiUrl}/otp-state/${uuid}`, {
`${uniswapUrls.apiBaseExtensionUrl}/scantastic/otp-state/${uuid}`,
{
method: 'POST', method: 'POST',
headers: { headers: {
Accept: 'application/json', Accept: 'application/json',
Origin: 'https://uniswap.org', Origin: 'https://uniswap.org',
}, },
} })
)
if (!response.ok) { if (!response.ok) {
throw new Error(`Failed to check OTP state: ${await response.text()}`) throw new Error(`Failed to check OTP state: ${await response.text()}`)
} }
......
...@@ -16,7 +16,7 @@ export function* telemetrySaga() { ...@@ -16,7 +16,7 @@ export function* telemetrySaga() {
new ApplicationTransport( new ApplicationTransport(
uniswapUrls.amplitudeProxyUrl, uniswapUrls.amplitudeProxyUrl,
OriginApplication.MOBILE, OriginApplication.MOBILE,
uniswapUrls.apiBaseUrl, uniswapUrls.apiOrigin,
DeviceInfo.getBundleId() DeviceInfo.getBundleId()
), ),
allowAnalytics allowAnalytics
......
...@@ -28,9 +28,10 @@ import { ...@@ -28,9 +28,10 @@ import {
} from 'ui/src' } from 'ui/src'
import { borderRadii, fonts, iconSizes, imageSizes, spacing } from 'ui/src/theme' import { borderRadii, fonts, iconSizes, imageSizes, spacing } from 'ui/src/theme'
import { useExtractedColors } from 'ui/src/utils/colors' import { useExtractedColors } from 'ui/src/utils/colors'
import { FeatureFlags } from 'uniswap/src/features/statsig/flags' import { FeatureFlags } from 'uniswap/src/features/gating/flags'
import { useFeatureFlag } from 'uniswap/src/features/statsig/hooks' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks'
import { useUnitagUpdater } from 'uniswap/src/features/unitags/context' import { useUnitagUpdater } from 'uniswap/src/features/unitags/context'
import { useUnitagByAddress } from 'uniswap/src/features/unitags/hooks'
import { ProfileMetadata } from 'uniswap/src/features/unitags/types' import { ProfileMetadata } from 'uniswap/src/features/unitags/types'
import { isIOS } from 'uniswap/src/utils/platform' import { isIOS } from 'uniswap/src/utils/platform'
import { logger } from 'utilities/src/logger/logger' import { logger } from 'utilities/src/logger/logger'
...@@ -43,10 +44,7 @@ import { pushNotification } from 'wallet/src/features/notifications/slice' ...@@ -43,10 +44,7 @@ import { pushNotification } from 'wallet/src/features/notifications/slice'
import { AppNotificationType } from 'wallet/src/features/notifications/types' import { AppNotificationType } from 'wallet/src/features/notifications/types'
import { updateUnitagMetadata } from 'wallet/src/features/unitags/api' import { updateUnitagMetadata } from 'wallet/src/features/unitags/api'
import { tryUploadAvatar } from 'wallet/src/features/unitags/avatars' import { tryUploadAvatar } from 'wallet/src/features/unitags/avatars'
import { import { useAvatarUploadCredsWithRefresh } from 'wallet/src/features/unitags/hooks'
useAvatarUploadCredsWithRefresh,
useUnitagByAddress,
} from 'wallet/src/features/unitags/hooks'
import { useWalletSigners } from 'wallet/src/features/wallet/context' import { useWalletSigners } from 'wallet/src/features/wallet/context'
import { useAccount } from 'wallet/src/features/wallet/hooks' import { useAccount } from 'wallet/src/features/wallet/hooks'
import { DisplayNameType } from 'wallet/src/features/wallet/types' import { DisplayNameType } from 'wallet/src/features/wallet/types'
......
...@@ -2,8 +2,8 @@ import { useCallback, useEffect, useState } from 'react' ...@@ -2,8 +2,8 @@ import { useCallback, useEffect, useState } from 'react'
import { useAppSelector } from 'src/app/hooks' import { useAppSelector } from 'src/app/hooks'
import { openModal } from 'src/features/modals/modalSlice' import { openModal } from 'src/features/modals/modalSlice'
import { selectModalState } from 'src/features/modals/selectModalState' import { selectModalState } from 'src/features/modals/selectModalState'
import { FeatureFlags } from 'uniswap/src/features/statsig/flags' import { FeatureFlags } from 'uniswap/src/features/gating/flags'
import { useFeatureFlag } from 'uniswap/src/features/statsig/hooks' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks'
import { logger } from 'utilities/src/logger/logger' import { logger } from 'utilities/src/logger/logger'
import { Keyring } from 'wallet/src/features/wallet/Keyring/Keyring' import { Keyring } from 'wallet/src/features/wallet/Keyring/Keyring'
import { useNativeAccountExists } from 'wallet/src/features/wallet/hooks' import { useNativeAccountExists } from 'wallet/src/features/wallet/hooks'
......
...@@ -3,20 +3,18 @@ import { useTranslation } from 'react-i18next' ...@@ -3,20 +3,18 @@ import { useTranslation } from 'react-i18next'
import { getCountry } from 'react-native-localize' import { getCountry } from 'react-native-localize'
import { useAppDispatch } from 'src/app/hooks' import { useAppDispatch } from 'src/app/hooks'
import { Screen } from 'src/components/layout/Screen' import { Screen } from 'src/components/layout/Screen'
import { import { FiatOnRampConnectingView } from 'src/features/fiatOnRamp/FiatOnRampConnecting'
FiatOnRampConnectingView, import { ServiceProviderLogoStyles } from 'src/features/fiatOnRamp/constants'
SERVICE_PROVIDER_ICON_BORDER_RADIUS,
SERVICE_PROVIDER_ICON_SIZE,
} from 'src/features/fiatOnRamp/FiatOnRampConnecting'
import { useFiatOnRampTransactionCreator } from 'src/features/fiatOnRamp/hooks' import { useFiatOnRampTransactionCreator } from 'src/features/fiatOnRamp/hooks'
import { Flex, useIsDarkMode } from 'ui/src'
import { uniswapUrls } from 'uniswap/src/constants/urls' import { uniswapUrls } from 'uniswap/src/constants/urls'
import { isAndroid } from 'uniswap/src/utils/platform'
import { ONE_SECOND_MS } from 'utilities/src/time/time' import { ONE_SECOND_MS } from 'utilities/src/time/time'
import { useTimeout } from 'utilities/src/time/timing' import { useTimeout } from 'utilities/src/time/timing'
import { ChainId } from 'wallet/src/constants/chains' import { ChainId } from 'wallet/src/constants/chains'
import { useFiatOnRampAggregatorTransferWidgetQuery } from 'wallet/src/features/fiatOnRamp/api' import { useFiatOnRampAggregatorTransferWidgetQuery } from 'wallet/src/features/fiatOnRamp/api'
import { FORTransferInstitution } from 'wallet/src/features/fiatOnRamp/types' import { FORServiceProvider } from 'wallet/src/features/fiatOnRamp/types'
import { RemoteImage } from 'wallet/src/features/images/RemoteImage' import { getServiceProviderLogo } from 'wallet/src/features/fiatOnRamp/utils'
import { ImageUri } from 'wallet/src/features/images/ImageUri'
import { pushNotification } from 'wallet/src/features/notifications/slice' import { pushNotification } from 'wallet/src/features/notifications/slice'
import { AppNotificationType } from 'wallet/src/features/notifications/types' import { AppNotificationType } from 'wallet/src/features/notifications/types'
import { useActiveAccountAddressWithThrow } from 'wallet/src/features/wallet/hooks' import { useActiveAccountAddressWithThrow } from 'wallet/src/features/wallet/hooks'
...@@ -27,14 +25,11 @@ import { openUri } from 'wallet/src/utils/linking' ...@@ -27,14 +25,11 @@ import { openUri } from 'wallet/src/utils/linking'
// Design decision // Design decision
const CONNECTING_TIMEOUT = 2 * ONE_SECOND_MS const CONNECTING_TIMEOUT = 2 * ONE_SECOND_MS
const DEFAULT_TRANSFER_AMOUNT = 1
const DEFAULT_TRANSFER_CURRENCY = 'ETH'
export function ExchangeTransferConnecting({ export function ExchangeTransferConnecting({
serviceProvider, serviceProvider,
onClose, onClose,
}: { }: {
serviceProvider: FORTransferInstitution serviceProvider: FORServiceProvider
onClose: () => void onClose: () => void
}): JSX.Element { }): JSX.Element {
const { t } = useTranslation() const { t } = useTranslation()
...@@ -43,8 +38,8 @@ export function ExchangeTransferConnecting({ ...@@ -43,8 +38,8 @@ export function ExchangeTransferConnecting({
const [timeoutElapsed, setTimeoutElapsed] = useState(false) const [timeoutElapsed, setTimeoutElapsed] = useState(false)
const initialTypeInfo = useMemo( const initialTypeInfo = useMemo(
() => ({ institutionLogoUrl: serviceProvider.icon }), () => ({ serviceProviderLogo: serviceProvider.logos }),
[serviceProvider.icon] [serviceProvider.logos]
) )
const { externalTransactionId, dispatchAddTransaction } = useFiatOnRampTransactionCreator( const { externalTransactionId, dispatchAddTransaction } = useFiatOnRampTransactionCreator(
...@@ -72,15 +67,11 @@ export function ExchangeTransferConnecting({ ...@@ -72,15 +67,11 @@ export function ExchangeTransferConnecting({
isLoading: widgetLoading, isLoading: widgetLoading,
error: widgetError, error: widgetError,
} = useFiatOnRampAggregatorTransferWidgetQuery({ } = useFiatOnRampAggregatorTransferWidgetQuery({
sourceAmount: DEFAULT_TRANSFER_AMOUNT,
sourceCurrencyCode: DEFAULT_TRANSFER_CURRENCY,
countryCode: getCountry(), countryCode: getCountry(),
institutionId: serviceProvider.id, serviceProvider: serviceProvider.serviceProvider,
walletAddress: activeAccountAddress, walletAddress: activeAccountAddress,
externalSessionId: externalTransactionId, externalSessionId: externalTransactionId,
redirectURL: `${ redirectUrl: `${uniswapUrls.redirectUrlBase}/?screen=transaction&fiatOnRamp=true&userAddress=${activeAccountAddress}`,
isAndroid ? uniswapUrls.appUrl : uniswapUrls.appBaseUrl
}/?screen=transaction&fiatOnRamp=true&userAddress=${activeAccountAddress}`,
}) })
useEffect(() => { useEffect(() => {
...@@ -113,16 +104,20 @@ export function ExchangeTransferConnecting({ ...@@ -113,16 +104,20 @@ export function ExchangeTransferConnecting({
serviceProvider?.name, serviceProvider?.name,
]) ])
const isDarkMode = useIsDarkMode()
const logoUrl = getServiceProviderLogo(serviceProvider.logos, isDarkMode)
return ( return (
<Screen> <Screen>
<FiatOnRampConnectingView <FiatOnRampConnectingView
serviceProviderLogo={ serviceProviderLogo={
<RemoteImage <Flex
borderRadius={SERVICE_PROVIDER_ICON_BORDER_RADIUS} alignItems="center"
height={SERVICE_PROVIDER_ICON_SIZE} height={ServiceProviderLogoStyles.icon.height}
uri={serviceProvider.icon} justifyContent="center"
width={SERVICE_PROVIDER_ICON_SIZE} width={ServiceProviderLogoStyles.icon.width}>
/> <ImageUri imageStyle={ServiceProviderLogoStyles.icon} uri={logoUrl} />
</Flex>
} }
serviceProviderName={serviceProvider.name} serviceProviderName={serviceProvider.name}
/> />
......
...@@ -2,15 +2,12 @@ import { NativeStackScreenProps } from '@react-navigation/native-stack' ...@@ -2,15 +2,12 @@ import { NativeStackScreenProps } from '@react-navigation/native-stack'
import { skipToken } from '@reduxjs/toolkit/query/react' import { skipToken } from '@reduxjs/toolkit/query/react'
import React, { useCallback, useEffect, useMemo, useState } from 'react' import React, { useCallback, useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { StyleSheet } from 'react-native'
import { useAppDispatch } from 'src/app/hooks' import { useAppDispatch } from 'src/app/hooks'
import { FiatOnRampStackParamList } from 'src/app/navigation/types' import { FiatOnRampStackParamList } from 'src/app/navigation/types'
import { Screen } from 'src/components/layout/Screen' import { Screen } from 'src/components/layout/Screen'
import { import { FiatOnRampConnectingView } from 'src/features/fiatOnRamp/FiatOnRampConnecting'
FiatOnRampConnectingView,
SERVICE_PROVIDER_ICON_SIZE,
} from 'src/features/fiatOnRamp/FiatOnRampConnecting'
import { useFiatOnRampContext } from 'src/features/fiatOnRamp/FiatOnRampContext' import { useFiatOnRampContext } from 'src/features/fiatOnRamp/FiatOnRampContext'
import { ServiceProviderLogoStyles } from 'src/features/fiatOnRamp/constants'
import { useFiatOnRampTransactionCreator } from 'src/features/fiatOnRamp/hooks' import { useFiatOnRampTransactionCreator } from 'src/features/fiatOnRamp/hooks'
import { getServiceProviderForQuote } from 'src/features/fiatOnRamp/utils' import { getServiceProviderForQuote } from 'src/features/fiatOnRamp/utils'
import { closeModal } from 'src/features/modals/modalSlice' import { closeModal } from 'src/features/modals/modalSlice'
...@@ -18,12 +15,11 @@ import { FiatOnRampScreens } from 'src/screens/Screens' ...@@ -18,12 +15,11 @@ import { FiatOnRampScreens } from 'src/screens/Screens'
import { Flex, Text, useIsDarkMode } from 'ui/src' import { Flex, Text, useIsDarkMode } from 'ui/src'
import { spacing } from 'ui/src/theme' import { spacing } from 'ui/src/theme'
import { uniswapUrls } from 'uniswap/src/constants/urls' import { uniswapUrls } from 'uniswap/src/constants/urls'
import { isAndroid } from 'uniswap/src/utils/platform'
import { ONE_SECOND_MS } from 'utilities/src/time/time' import { ONE_SECOND_MS } from 'utilities/src/time/time'
import { useTimeout } from 'utilities/src/time/timing' import { useTimeout } from 'utilities/src/time/timing'
import { ChainId } from 'wallet/src/constants/chains' import { ChainId } from 'wallet/src/constants/chains'
import { useFiatOnRampAggregatorWidgetQuery } from 'wallet/src/features/fiatOnRamp/api' import { useFiatOnRampAggregatorWidgetQuery } from 'wallet/src/features/fiatOnRamp/api'
import { getServiceProviderLogo } from 'wallet/src/features/fiatOnRamp/utils' import { getOptionalServiceProviderLogo } from 'wallet/src/features/fiatOnRamp/utils'
import { ImageUri } from 'wallet/src/features/images/ImageUri' import { ImageUri } from 'wallet/src/features/images/ImageUri'
import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext' import { useLocalizationContext } from 'wallet/src/features/language/LocalizationContext'
import { pushNotification } from 'wallet/src/features/notifications/slice' import { pushNotification } from 'wallet/src/features/notifications/slice'
...@@ -93,9 +89,7 @@ export function FiatOnRampConnectingScreen({ navigation }: Props): JSX.Element | ...@@ -93,9 +89,7 @@ export function FiatOnRampConnectingScreen({ navigation }: Props): JSX.Element |
sourceCurrencyCode: baseCurrencyInfo.code, sourceCurrencyCode: baseCurrencyInfo.code,
walletAddress: activeAccountAddress, walletAddress: activeAccountAddress,
externalSessionId: externalTransactionId, externalSessionId: externalTransactionId,
redirectUrl: `${ redirectUrl: `${uniswapUrls.redirectUrlBase}/?screen=transaction&fiatOnRamp=true&userAddress=${activeAccountAddress}`,
isAndroid ? uniswapUrls.appUrl : uniswapUrls.appBaseUrl
}/?screen=transaction&fiatOnRamp=true&userAddress=${activeAccountAddress}`,
} }
: skipToken : skipToken
) )
...@@ -154,7 +148,7 @@ export function FiatOnRampConnectingScreen({ navigation }: Props): JSX.Element | ...@@ -154,7 +148,7 @@ export function FiatOnRampConnectingScreen({ navigation }: Props): JSX.Element |
]) ])
const isDarkMode = useIsDarkMode() const isDarkMode = useIsDarkMode()
const logoUrl = getServiceProviderLogo(serviceProvider?.logos, isDarkMode) const logoUrl = getOptionalServiceProviderLogo(serviceProvider?.logos, isDarkMode)
return ( return (
<Screen> <Screen>
...@@ -170,9 +164,9 @@ export function FiatOnRampConnectingScreen({ navigation }: Props): JSX.Element | ...@@ -170,9 +164,9 @@ export function FiatOnRampConnectingScreen({ navigation }: Props): JSX.Element |
serviceProviderLogo={ serviceProviderLogo={
<Flex <Flex
alignItems="center" alignItems="center"
height={SERVICE_PROVIDER_ICON_SIZE} height={ServiceProviderLogoStyles.icon.height}
justifyContent="center" justifyContent="center"
width={SERVICE_PROVIDER_ICON_SIZE}> width={ServiceProviderLogoStyles.icon.width}>
<ImageUri imageStyle={ServiceProviderLogoStyles.icon} uri={logoUrl} /> <ImageUri imageStyle={ServiceProviderLogoStyles.icon} uri={logoUrl} />
</Flex> </Flex>
} }
...@@ -192,10 +186,3 @@ export function FiatOnRampConnectingScreen({ navigation }: Props): JSX.Element | ...@@ -192,10 +186,3 @@ export function FiatOnRampConnectingScreen({ navigation }: Props): JSX.Element |
</Screen> </Screen>
) )
} }
const ServiceProviderLogoStyles = StyleSheet.create({
icon: {
height: SERVICE_PROVIDER_ICON_SIZE,
width: SERVICE_PROVIDER_ICON_SIZE,
},
})
...@@ -33,7 +33,11 @@ import { ...@@ -33,7 +33,11 @@ import {
useFiatOnRampAggregatorTransactionsQuery, useFiatOnRampAggregatorTransactionsQuery,
} from 'wallet/src/features/fiatOnRamp/api' } from 'wallet/src/features/fiatOnRamp/api'
import { FORQuote, FORServiceProvider, FORTransaction } from 'wallet/src/features/fiatOnRamp/types' import { FORQuote, FORServiceProvider, FORTransaction } from 'wallet/src/features/fiatOnRamp/types'
import { getServiceProviderLogo } from 'wallet/src/features/fiatOnRamp/utils' import {
getServiceProviderLogo,
isFiatOnRampApiError,
isNoQuotesError,
} from 'wallet/src/features/fiatOnRamp/utils'
import { pushNotification } from 'wallet/src/features/notifications/slice' import { pushNotification } from 'wallet/src/features/notifications/slice'
import { AppNotificationType } from 'wallet/src/features/notifications/types' import { AppNotificationType } from 'wallet/src/features/notifications/types'
import { sendWalletAnalyticsEvent } from 'wallet/src/telemetry' import { sendWalletAnalyticsEvent } from 'wallet/src/telemetry'
...@@ -116,7 +120,7 @@ export function FiatOnRampScreen({ navigation }: Props): JSX.Element { ...@@ -116,7 +120,7 @@ export function FiatOnRampScreen({ navigation }: Props): JSX.Element {
const { showNativeKeyboard, onDecimalPadLayout, isLayoutPending, onInputPanelLayout } = const { showNativeKeyboard, onDecimalPadLayout, isLayoutPending, onInputPanelLayout } =
useShouldShowNativeKeyboard() useShouldShowNativeKeyboard()
const { appFiatCurrencySupportedInMeld, meldSupportedFiatCurrency } = const { appFiatCurrencySupportedInMeld, meldSupportedFiatCurrency, supportedFiatCurrencies } =
useMeldFiatCurrencySupportInfo(countryCode) useMeldFiatCurrencySupportInfo(countryCode)
const debouncedAmount = useDebounce(amount, DEFAULT_DELAY * 2) const debouncedAmount = useDebounce(amount, DEFAULT_DELAY * 2)
...@@ -164,11 +168,6 @@ export function FiatOnRampScreen({ navigation }: Props): JSX.Element { ...@@ -164,11 +168,6 @@ export function FiatOnRampScreen({ navigation }: Props): JSX.Element {
limit: 1, limit: 1,
}) })
const { errorText, errorColor } = useParseFiatOnRampError(
quotesError || serviceProvidersError,
meldSupportedFiatCurrency.code
)
const prevQuotes = usePrevious(quotes) const prevQuotes = usePrevious(quotes)
useEffect(() => { useEffect(() => {
if (quotes && (!selectedQuote || prevQuotes !== quotes)) { if (quotes && (!selectedQuote || prevQuotes !== quotes)) {
...@@ -285,6 +284,16 @@ export function FiatOnRampScreen({ navigation }: Props): JSX.Element { ...@@ -285,6 +284,16 @@ export function FiatOnRampScreen({ navigation }: Props): JSX.Element {
meldSupportedFiatCurrency.code.toLowerCase() meldSupportedFiatCurrency.code.toLowerCase()
) )
const notAvailableInThisRegion =
supportedFiatCurrencies?.length === 0 ||
(isFiatOnRampApiError(quotesError) && isNoQuotesError(quotesError)) ||
quotes?.length === 0
const { errorText, errorColor } = useParseFiatOnRampError(
!notAvailableInThisRegion && (quotesError || serviceProvidersError),
meldSupportedFiatCurrency.code
)
return ( return (
<Screen edges={['top']}> <Screen edges={['top']}>
<HandleBar backgroundColor="none" /> <HandleBar backgroundColor="none" />
...@@ -312,6 +321,7 @@ export function FiatOnRampScreen({ navigation }: Props): JSX.Element { ...@@ -312,6 +321,7 @@ export function FiatOnRampScreen({ navigation }: Props): JSX.Element {
errorText={errorText} errorText={errorText}
fiatCurrencyInfo={meldSupportedFiatCurrency} fiatCurrencyInfo={meldSupportedFiatCurrency}
inputRef={inputRef} inputRef={inputRef}
notAvailableInThisRegion={notAvailableInThisRegion}
predefinedAmountsSupported={predefinedAmountsSupported} predefinedAmountsSupported={predefinedAmountsSupported}
quoteAmount={selectedQuote?.destinationAmount ?? 0} quoteAmount={selectedQuote?.destinationAmount ?? 0}
quoteCurrencyAmountReady={Boolean(amount && selectedQuote)} quoteCurrencyAmountReady={Boolean(amount && selectedQuote)}
...@@ -341,6 +351,7 @@ export function FiatOnRampScreen({ navigation }: Props): JSX.Element { ...@@ -341,6 +351,7 @@ export function FiatOnRampScreen({ navigation }: Props): JSX.Element {
{!showNativeKeyboard && ( {!showNativeKeyboard && (
<DecimalPadLegacy <DecimalPadLegacy
hasCurrencyPrefix hasCurrencyPrefix
disabled={notAvailableInThisRegion}
resetSelection={resetSelection} resetSelection={resetSelection}
selection={selection} selection={selection}
setValue={onChangeValue('textInput')} setValue={onChangeValue('textInput')}
......
...@@ -67,8 +67,8 @@ import BuyIcon from 'ui/src/assets/icons/buy.svg' ...@@ -67,8 +67,8 @@ import BuyIcon from 'ui/src/assets/icons/buy.svg'
import ScanIcon from 'ui/src/assets/icons/scan-home.svg' import ScanIcon from 'ui/src/assets/icons/scan-home.svg'
import SendIcon from 'ui/src/assets/icons/send-action.svg' import SendIcon from 'ui/src/assets/icons/send-action.svg'
import { iconSizes, spacing } from 'ui/src/theme' import { iconSizes, spacing } from 'ui/src/theme'
import { FeatureFlags } from 'uniswap/src/features/statsig/flags' import { FeatureFlags } from 'uniswap/src/features/gating/flags'
import { useFeatureFlag } from 'uniswap/src/features/statsig/hooks' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks'
import { ONE_SECOND_MS } from 'utilities/src/time/time' import { ONE_SECOND_MS } from 'utilities/src/time/time'
import { useInterval, useTimeout } from 'utilities/src/time/timing' import { useInterval, useTimeout } from 'utilities/src/time/timing'
import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants' import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants'
...@@ -76,6 +76,7 @@ import { ...@@ -76,6 +76,7 @@ import {
selectHasSkippedUnitagPrompt, selectHasSkippedUnitagPrompt,
selectHasViewedUniconV2IntroModal, selectHasViewedUniconV2IntroModal,
} from 'wallet/src/features/behaviorHistory/selectors' } from 'wallet/src/features/behaviorHistory/selectors'
import { useCexTransferProviders } from 'wallet/src/features/fiatOnRamp/api'
import { useSelectAddressHasNotifications } from 'wallet/src/features/notifications/hooks' import { useSelectAddressHasNotifications } from 'wallet/src/features/notifications/hooks'
import { setNotificationStatus } from 'wallet/src/features/notifications/slice' import { setNotificationStatus } from 'wallet/src/features/notifications/slice'
import { PortfolioBalance } from 'wallet/src/features/portfolio/PortfolioBalance' import { PortfolioBalance } from 'wallet/src/features/portfolio/PortfolioBalance'
...@@ -332,6 +333,7 @@ export function HomeScreen(props?: AppStackScreenProp<Screens.Home>): JSX.Elemen ...@@ -332,6 +333,7 @@ export function HomeScreen(props?: AppStackScreenProp<Screens.Home>): JSX.Elemen
const forAggregatorEnabled = useFeatureFlag(FeatureFlags.ForAggregator) const forAggregatorEnabled = useFeatureFlag(FeatureFlags.ForAggregator)
const cexTransferEnabled = useFeatureFlag(FeatureFlags.CexTransfers) const cexTransferEnabled = useFeatureFlag(FeatureFlags.CexTransfers)
const cexTransferProviders = useCexTransferProviders(cexTransferEnabled)
const onPressBuy = useCallback( const onPressBuy = useCallback(
() => () =>
...@@ -351,14 +353,16 @@ export function HomeScreen(props?: AppStackScreenProp<Screens.Home>): JSX.Elemen ...@@ -351,14 +353,16 @@ export function HomeScreen(props?: AppStackScreenProp<Screens.Home>): JSX.Elemen
}, [dispatch]) }, [dispatch])
const onPressSend = useCallback(() => dispatch(openModal({ name: ModalName.Send })), [dispatch]) const onPressSend = useCallback(() => dispatch(openModal({ name: ModalName.Send })), [dispatch])
const onPressReceive = useCallback(() => { const onPressReceive = useCallback(() => {
if (cexTransferEnabled) { if (cexTransferProviders.length > 0) {
dispatch(openModal({ name: ModalName.ReceiveCryptoModal })) dispatch(
openModal({ name: ModalName.ReceiveCryptoModal, initialState: cexTransferProviders })
)
} else { } else {
dispatch( dispatch(
openModal({ name: ModalName.WalletConnectScan, initialState: ScannerModalState.WalletQr }) openModal({ name: ModalName.WalletConnectScan, initialState: ScannerModalState.WalletQr })
) )
} }
}, [dispatch, cexTransferEnabled]) }, [dispatch, cexTransferProviders])
const onPressViewOnlyLabel = useCallback( const onPressViewOnlyLabel = useCallback(
() => dispatch(openModal({ name: ModalName.ViewOnlyExplainer })), () => dispatch(openModal({ name: ModalName.ViewOnlyExplainer })),
[dispatch] [dispatch]
......
...@@ -11,8 +11,8 @@ import { OnboardingScreens } from 'src/screens/Screens' ...@@ -11,8 +11,8 @@ import { OnboardingScreens } from 'src/screens/Screens'
import { useAddBackButton } from 'src/utils/useAddBackButton' import { useAddBackButton } from 'src/utils/useAddBackButton'
import { Flex, Icons, Text, TouchableArea, Unicon, UniconV2, useIsDarkMode } from 'ui/src' import { Flex, Icons, Text, TouchableArea, Unicon, UniconV2, useIsDarkMode } from 'ui/src'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { FeatureFlags } from 'uniswap/src/features/statsig/flags' import { FeatureFlags } from 'uniswap/src/features/gating/flags'
import { useFeatureFlag } from 'uniswap/src/features/statsig/hooks' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks'
import { getCloudProviderName } from 'uniswap/src/utils/cloud-backup/getCloudProviderName' import { getCloudProviderName } from 'uniswap/src/utils/cloud-backup/getCloudProviderName'
import { import {
FORMAT_DATE_TIME_SHORT, FORMAT_DATE_TIME_SHORT,
......
import { NativeStackScreenProps } from '@react-navigation/native-stack'
import React, { Dispatch, SetStateAction, useEffect, useRef, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { ActivityIndicator, TextInput as NativeTextInput, StyleSheet } from 'react-native'
import { useAppDispatch } from 'src/app/hooks'
import { OnboardingStackParamList } from 'src/app/navigation/types'
import Trace from 'src/components/Trace/Trace'
import { SafeKeyboardOnboardingScreen } from 'src/features/onboarding/SafeKeyboardOnboardingScreen'
import { OnboardingScreens } from 'src/screens/Screens'
import { useAddBackButton } from 'src/utils/useAddBackButton'
import { AnimatePresence, Button, Flex, Icons, Text } from 'ui/src'
import { fonts } from 'ui/src/theme'
import { isAndroid } from 'uniswap/src/utils/platform'
import { TextInput } from 'wallet/src/components/input/TextInput'
import { NICKNAME_MAX_LENGTH } from 'wallet/src/constants/accounts'
import { ImportType } from 'wallet/src/features/onboarding/types'
import {
EditAccountAction,
editAccountActions,
} from 'wallet/src/features/wallet/accounts/editAccountSaga'
import { AccountType } from 'wallet/src/features/wallet/accounts/types'
import {
PendingAccountActions,
pendingAccountActions,
} from 'wallet/src/features/wallet/create/pendingAccountsSaga'
import { usePendingAccounts } from 'wallet/src/features/wallet/hooks'
import { ElementName } from 'wallet/src/telemetry/constants'
import { shortenAddress } from 'wallet/src/utils/addresses'
type Props = NativeStackScreenProps<OnboardingStackParamList, OnboardingScreens.EditName>
export function EditNameScreen({ navigation, route: { params } }: Props): JSX.Element {
const dispatch = useAppDispatch()
const { t } = useTranslation()
// Reference pending accounts to avoid any lag in saga import.
const pendingAccount = Object.values(usePendingAccounts())?.[0]
useEffect(() => {
// Sets the default wallet nickname based on derivation index once the pendingAccount is set.
if (pendingAccount && pendingAccount.type !== AccountType.Readonly) {
setNewAccountName(
pendingAccount.name ||
t('onboarding.wallet.defaultName', { number: pendingAccount.derivationIndex + 1 }) ||
''
)
}
}, [pendingAccount, t])
const [newAccountName, setNewAccountName] = useState<string>('')
useAddBackButton(navigation)
useEffect(() => {
const beforeRemoveListener = (): void => {
dispatch(pendingAccountActions.trigger(PendingAccountActions.Delete))
}
navigation.addListener('beforeRemove', beforeRemoveListener)
return () => navigation.removeListener('beforeRemove', beforeRemoveListener)
}, [dispatch, navigation])
const onPressNext = (): void => {
navigation.navigate({
name:
params?.importType === ImportType.CreateNew
? OnboardingScreens.WelcomeWallet
: OnboardingScreens.Notifications,
merge: true,
params,
})
if (pendingAccount) {
dispatch(
editAccountActions.trigger({
type: EditAccountAction.Rename,
address: pendingAccount?.address,
newName: newAccountName.trim(),
})
)
}
}
return (
<SafeKeyboardOnboardingScreen
subtitle={t('onboarding.editName.subtitle')}
title={t('onboarding.editName.title')}>
{pendingAccount ? (
<CustomizationSection
accountName={newAccountName}
address={pendingAccount?.address}
setAccountName={setNewAccountName}
/>
) : (
<ActivityIndicator />
)}
<Flex justifyContent="flex-end">
<Trace logPress element={ElementName.Continue}>
<Button testID={ElementName.Continue} onPress={onPressNext}>
{t('onboarding.editName.button.create')}
</Button>
</Trace>
</Flex>
</SafeKeyboardOnboardingScreen>
)
}
function CustomizationSection({
address,
accountName,
setAccountName,
}: {
address: Address
accountName: string
setAccountName: Dispatch<SetStateAction<string>>
}): JSX.Element {
const { t } = useTranslation()
const textInputRef = useRef<NativeTextInput>(null)
// we default it to `true` to avoid flickering of a pencil icon,
// because CustomizationSection has `autoFocus=true`
const [focused, setFocused] = useState(true)
const focusInputWithKeyboard = (): void => {
textInputRef.current?.focus()
}
const walletAddress = shortenAddress(address)
return (
<Flex
centered
$short={{
gap: '$none',
}}
gap="$spacing24">
<Flex centered gap="$spacing24" height={200} px="$spacing16" width="100%">
<Flex
borderColor="$surface3"
borderRadius="$rounded16"
borderWidth={1}
py="$spacing12"
width="100%">
<Flex centered row>
<TextInput
ref={textInputRef}
autoFocus
fontSize={fonts.heading3.fontSize}
maxFontSizeMultiplier={fonts.heading3.maxFontSizeMultiplier}
maxLength={NICKNAME_MAX_LENGTH}
placeholder={t('onboarding.editName.label')}
placeholderTextColor="$neutral3"
style={isAndroid ? styles.noHorizontalPadding : {}}
testID={ElementName.WalletNameInput}
textAlign="center"
value={accountName}
onBlur={(): void => {
setFocused(false)
setAccountName(accountName.trim())
}}
onChangeText={setAccountName}
onFocus={(): void => setFocused(true)}
/>
<AnimatePresence>
{!focused && (
<Button
fadeIn
fadeOut
animation="lazy"
icon={<Icons.Pencil color="$neutral2" />}
theme="secondary"
onPress={focusInputWithKeyboard}
/>
)}
</AnimatePresence>
</Flex>
</Flex>
<Flex centered gap="$spacing4">
<Text color="$neutral3" variant="body3">
<Trans
components={{ highlight: <Text color="$neutral3" variant="buttonLabel3" /> }}
i18nKey="onboarding.editName.walletAddress"
values={{ walletAddress }}
/>
</Text>
</Flex>
</Flex>
</Flex>
)
}
const styles = StyleSheet.create({
noHorizontalPadding: {
paddingHorizontal: 0,
},
})
...@@ -10,10 +10,8 @@ import { openModal } from 'src/features/modals/modalSlice' ...@@ -10,10 +10,8 @@ import { openModal } from 'src/features/modals/modalSlice'
import { TermsOfService } from 'src/screens/Onboarding/TermsOfService' import { TermsOfService } from 'src/screens/Onboarding/TermsOfService'
import { OnboardingScreens, UnitagScreens } from 'src/screens/Screens' import { OnboardingScreens, UnitagScreens } from 'src/screens/Screens'
import { hideSplashScreen } from 'src/utils/splashScreen' import { hideSplashScreen } from 'src/utils/splashScreen'
import { isDevBuild } from 'src/utils/version'
import { Button, Flex, HapticFeedback, Text, TouchableArea, useIsDarkMode } from 'ui/src' import { Button, Flex, HapticFeedback, Text, TouchableArea, useIsDarkMode } from 'ui/src'
import { FeatureFlags } from 'uniswap/src/features/statsig/flags' import { isDevEnv } from 'uniswap/src/utils/env'
import { useFeatureFlag } from 'uniswap/src/features/statsig/hooks'
import { useTimeout } from 'utilities/src/time/timing' import { useTimeout } from 'utilities/src/time/timing'
import { ImportType, OnboardingEntryPoint } from 'wallet/src/features/onboarding/types' import { ImportType, OnboardingEntryPoint } from 'wallet/src/features/onboarding/types'
import { useCanAddressClaimUnitag } from 'wallet/src/features/unitags/hooks' import { useCanAddressClaimUnitag } from 'wallet/src/features/unitags/hooks'
...@@ -31,14 +29,12 @@ export function LandingScreen({ navigation }: Props): JSX.Element { ...@@ -31,14 +29,12 @@ export function LandingScreen({ navigation }: Props): JSX.Element {
const { t } = useTranslation() const { t } = useTranslation()
const isDarkMode = useIsDarkMode() const isDarkMode = useIsDarkMode()
const unitagsFeatureFlagEnabled = useFeatureFlag(FeatureFlags.Unitags)
const { canClaimUnitag } = useCanAddressClaimUnitag() const { canClaimUnitag } = useCanAddressClaimUnitag()
const onPressCreateWallet = useCallback((): void => { const onPressCreateWallet = useCallback((): void => {
dispatch(pendingAccountActions.trigger(PendingAccountActions.Delete)) dispatch(pendingAccountActions.trigger(PendingAccountActions.Delete))
dispatch(createAccountActions.trigger()) dispatch(createAccountActions.trigger())
if (unitagsFeatureFlagEnabled) {
if (canClaimUnitag) { if (canClaimUnitag) {
navigation.navigate(UnitagScreens.ClaimUnitag, { navigation.navigate(UnitagScreens.ClaimUnitag, {
entryPoint: OnboardingScreens.Landing, entryPoint: OnboardingScreens.Landing,
...@@ -50,14 +46,7 @@ export function LandingScreen({ navigation }: Props): JSX.Element { ...@@ -50,14 +46,7 @@ export function LandingScreen({ navigation }: Props): JSX.Element {
entryPoint: OnboardingEntryPoint.FreshInstallOrReplace, entryPoint: OnboardingEntryPoint.FreshInstallOrReplace,
}) })
} }
} else { }, [canClaimUnitag, dispatch, navigation])
// use edit nickname screen still before launch of unitags
navigation.navigate(OnboardingScreens.EditName, {
importType: ImportType.CreateNew,
entryPoint: OnboardingEntryPoint.FreshInstallOrReplace,
})
}
}, [canClaimUnitag, dispatch, navigation, unitagsFeatureFlagEnabled])
const onPressImportWallet = (): void => { const onPressImportWallet = (): void => {
navigation.navigate(OnboardingScreens.ImportMethod, { navigation.navigate(OnboardingScreens.ImportMethod, {
...@@ -101,7 +90,7 @@ export function LandingScreen({ navigation }: Props): JSX.Element { ...@@ -101,7 +90,7 @@ export function LandingScreen({ navigation }: Props): JSX.Element {
hitSlop={16} hitSlop={16}
testID={ElementName.ImportAccount} testID={ElementName.ImportAccount}
onLongPress={async (): Promise<void> => { onLongPress={async (): Promise<void> => {
if (isDevBuild()) { if (isDevEnv()) {
await HapticFeedback.selection() await HapticFeedback.selection()
dispatch(openModal({ name: ModalName.Experiments })) dispatch(openModal({ name: ModalName.Experiments }))
} }
......
...@@ -51,8 +51,8 @@ import { ONBOARDING_QR_ETCHING_VIDEO_DARK, ONBOARDING_QR_ETCHING_VIDEO_LIGHT } f ...@@ -51,8 +51,8 @@ import { ONBOARDING_QR_ETCHING_VIDEO_DARK, ONBOARDING_QR_ETCHING_VIDEO_LIGHT } f
import LockIcon from 'ui/src/assets/icons/lock.svg' import LockIcon from 'ui/src/assets/icons/lock.svg'
import { AnimatedFlex, flexStyles } from 'ui/src/components/layout' import { AnimatedFlex, flexStyles } from 'ui/src/components/layout'
import { fonts, iconSizes, opacify, spacing } from 'ui/src/theme' import { fonts, iconSizes, opacify, spacing } from 'ui/src/theme'
import { FeatureFlags } from 'uniswap/src/features/statsig/flags' import { FeatureFlags } from 'uniswap/src/features/gating/flags'
import { useFeatureFlag } from 'uniswap/src/features/statsig/hooks' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks'
import { QRCodeDisplay } from 'wallet/src/components/QRCodeScanner/QRCode' import { QRCodeDisplay } from 'wallet/src/components/QRCodeScanner/QRCode'
import { AddressDisplay } from 'wallet/src/components/accounts/AddressDisplay' import { AddressDisplay } from 'wallet/src/components/accounts/AddressDisplay'
import { Arrow } from 'wallet/src/components/icons/Arrow' import { Arrow } from 'wallet/src/components/icons/Arrow'
......
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { TransferInstitutionSelector } from 'src/features/fiatOnRamp/FiatOnRampTransferInstitutionSelector' import { useAppSelector } from 'src/app/hooks'
import { FOR_MODAL_SNAP_POINTS } from 'src/features/fiatOnRamp/constants' import { ServiceProviderSelector } from 'src/features/fiatOnRamp/ExchangeTransferServiceProviderSelector'
import { closeModal, openModal } from 'src/features/modals/modalSlice' import { closeModal, openModal } from 'src/features/modals/modalSlice'
import { selectModalState } from 'src/features/modals/selectModalState'
import { import {
Flex, Flex,
HapticFeedback, HapticFeedback,
...@@ -106,6 +107,7 @@ export function ReceiveCryptoModal(): JSX.Element { ...@@ -106,6 +107,7 @@ export function ReceiveCryptoModal(): JSX.Element {
const colors = useSporeColors() const colors = useSporeColors()
const dispatch = useAppDispatch() const dispatch = useAppDispatch()
const { t } = useTranslation() const { t } = useTranslation()
const { initialState } = useAppSelector(selectModalState(ModalName.ReceiveCryptoModal))
const onClose = (): void => { const onClose = (): void => {
dispatch(closeModal({ name: ModalName.ReceiveCryptoModal })) dispatch(closeModal({ name: ModalName.ReceiveCryptoModal }))
...@@ -114,14 +116,12 @@ export function ReceiveCryptoModal(): JSX.Element { ...@@ -114,14 +116,12 @@ export function ReceiveCryptoModal(): JSX.Element {
return ( return (
<BottomSheetModal <BottomSheetModal
extendOnKeyboardVisible extendOnKeyboardVisible
fullScreen
hideKeyboardOnDismiss hideKeyboardOnDismiss
hideKeyboardOnSwipeDown hideKeyboardOnSwipeDown
backgroundColor={colors.surface1.get()} backgroundColor={colors.surface1.get()}
name={ModalName.ReceiveCryptoModal} name={ModalName.ReceiveCryptoModal}
snapPoints={FOR_MODAL_SNAP_POINTS}
onClose={onClose}> onClose={onClose}>
<Flex grow gap="$spacing12" px="$spacing16"> <Flex grow gap="$spacing12" mb="$spacing16" px="$spacing16">
<Flex gap="$spacing4" p="$spacing8"> <Flex gap="$spacing4" p="$spacing8">
<Text color="$neutral1" mt="$spacing2" textAlign="center" variant="subheading1"> <Text color="$neutral1" mt="$spacing2" textAlign="center" variant="subheading1">
{t('home.upsell.receive.title')} {t('home.upsell.receive.title')}
...@@ -138,7 +138,7 @@ export function ReceiveCryptoModal(): JSX.Element { ...@@ -138,7 +138,7 @@ export function ReceiveCryptoModal(): JSX.Element {
</Text> </Text>
<Separator /> <Separator />
</Flex> </Flex>
<TransferInstitutionSelector onClose={onClose} /> <ServiceProviderSelector serviceProviders={initialState || []} onClose={onClose} />
</Flex> </Flex>
</BottomSheetModal> </BottomSheetModal>
) )
......
import { FORServiceProvider } from 'wallet/src/features/fiatOnRamp/types'
export type ReceiveCryptoModalState = FORServiceProvider[]
...@@ -34,7 +34,6 @@ export enum OnboardingScreens { ...@@ -34,7 +34,6 @@ export enum OnboardingScreens {
BackupCloudProcessing = 'OnboardingBackupCloudProcessing', BackupCloudProcessing = 'OnboardingBackupCloudProcessing',
BackupManual = 'OnboardingBackupManual', BackupManual = 'OnboardingBackupManual',
Landing = 'OnboardingLanding', Landing = 'OnboardingLanding',
EditName = 'EditName',
Notifications = 'OnboardingNotifications', Notifications = 'OnboardingNotifications',
WelcomeWallet = 'WelcomeWallet', WelcomeWallet = 'WelcomeWallet',
Security = 'OnboardingSecurity', Security = 'OnboardingSecurity',
......
...@@ -47,8 +47,8 @@ import MessageQuestion from 'ui/src/assets/icons/message-question.svg' ...@@ -47,8 +47,8 @@ import MessageQuestion from 'ui/src/assets/icons/message-question.svg'
import UniswapIcon from 'ui/src/assets/icons/uniswap-logo.svg' import UniswapIcon from 'ui/src/assets/icons/uniswap-logo.svg'
import { iconSizes, spacing } from 'ui/src/theme' import { iconSizes, spacing } from 'ui/src/theme'
import { uniswapUrls } from 'uniswap/src/constants/urls' import { uniswapUrls } from 'uniswap/src/constants/urls'
import { FeatureFlags } from 'uniswap/src/features/statsig/flags' import { FeatureFlags } from 'uniswap/src/features/gating/flags'
import { useFeatureFlag } from 'uniswap/src/features/statsig/hooks' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks'
import { getCloudProviderName } from 'uniswap/src/utils/cloud-backup/getCloudProviderName' import { getCloudProviderName } from 'uniswap/src/utils/cloud-backup/getCloudProviderName'
import { isAndroid } from 'uniswap/src/utils/platform' import { isAndroid } from 'uniswap/src/utils/platform'
import { ONE_SECOND_MS } from 'utilities/src/time/time' import { ONE_SECOND_MS } from 'utilities/src/time/time'
......
...@@ -34,13 +34,11 @@ import NotificationIcon from 'ui/src/assets/icons/bell.svg' ...@@ -34,13 +34,11 @@ import NotificationIcon from 'ui/src/assets/icons/bell.svg'
import GlobalIcon from 'ui/src/assets/icons/global.svg' import GlobalIcon from 'ui/src/assets/icons/global.svg'
import TextEditIcon from 'ui/src/assets/icons/textEdit.svg' import TextEditIcon from 'ui/src/assets/icons/textEdit.svg'
import { iconSizes, spacing } from 'ui/src/theme' import { iconSizes, spacing } from 'ui/src/theme'
import { FeatureFlags } from 'uniswap/src/features/statsig/flags' import { useUnitagByAddress } from 'uniswap/src/features/unitags/hooks'
import { useFeatureFlag } from 'uniswap/src/features/statsig/hooks'
import { AddressDisplay } from 'wallet/src/components/accounts/AddressDisplay' import { AddressDisplay } from 'wallet/src/components/accounts/AddressDisplay'
import { Switch } from 'wallet/src/components/buttons/Switch' import { Switch } from 'wallet/src/components/buttons/Switch'
import { ChainId } from 'wallet/src/constants/chains' import { ChainId } from 'wallet/src/constants/chains'
import { useENS } from 'wallet/src/features/ens/useENS' import { useENS } from 'wallet/src/features/ens/useENS'
import { useUnitagByAddress } from 'wallet/src/features/unitags/hooks'
import { import {
EditAccountAction, EditAccountAction,
editAccountActions, editAccountActions,
...@@ -74,9 +72,8 @@ export function SettingsWallet({ ...@@ -74,9 +72,8 @@ export function SettingsWallet({
const [notificationSwitchEnabled, setNotificationSwitchEnabled] = useState<boolean>( const [notificationSwitchEnabled, setNotificationSwitchEnabled] = useState<boolean>(
notificationsEnabledOnFirebase notificationsEnabledOnFirebase
) )
const unitagsFeatureFlagEnabled = useFeatureFlag(FeatureFlags.Unitags)
const showEditProfile = unitagsFeatureFlagEnabled && !readonly const showEditProfile = !readonly
useEffect(() => { useEffect(() => {
// If the user deletes the account while on this screen, go back // If the user deletes the account while on this screen, go back
......
...@@ -14,8 +14,6 @@ import { Screen } from 'src/components/layout/Screen' ...@@ -14,8 +14,6 @@ import { Screen } from 'src/components/layout/Screen'
import { UnitagBanner } from 'src/components/unitags/UnitagBanner' import { UnitagBanner } from 'src/components/unitags/UnitagBanner'
import { Button, Flex, Icons, Text } from 'ui/src' import { Button, Flex, Icons, Text } from 'ui/src'
import { fonts } from 'ui/src/theme' import { fonts } from 'ui/src/theme'
import { FeatureFlags } from 'uniswap/src/features/statsig/flags'
import { useFeatureFlag } from 'uniswap/src/features/statsig/hooks'
import { isIOS } from 'uniswap/src/utils/platform' import { isIOS } from 'uniswap/src/utils/platform'
import { TextInput } from 'wallet/src/components/input/TextInput' import { TextInput } from 'wallet/src/components/input/TextInput'
import { NICKNAME_MAX_LENGTH } from 'wallet/src/constants/accounts' import { NICKNAME_MAX_LENGTH } from 'wallet/src/constants/accounts'
...@@ -42,12 +40,8 @@ export function SettingsWalletEdit({ ...@@ -42,12 +40,8 @@ export function SettingsWalletEdit({
const displayName = useDisplayName(address) const displayName = useDisplayName(address)
const [nickname, setNickname] = useState(displayName?.name) const [nickname, setNickname] = useState(displayName?.name)
const [showEditButton, setShowEditButton] = useState(true) const [showEditButton, setShowEditButton] = useState(true)
const unitagsFeatureFlagEnabled = useFeatureFlag(FeatureFlags.Unitags)
const { canClaimUnitag } = useCanAddressClaimUnitag(address) const { canClaimUnitag } = useCanAddressClaimUnitag(address)
const showUnitagBanner = const showUnitagBanner = activeAccount?.type === AccountType.SignerMnemonic && canClaimUnitag
unitagsFeatureFlagEnabled &&
activeAccount?.type === AccountType.SignerMnemonic &&
canClaimUnitag
const accountNameIsEditable = const accountNameIsEditable =
displayName?.type === DisplayNameType.Local || displayName?.type === DisplayNameType.Address displayName?.type === DisplayNameType.Local || displayName?.type === DisplayNameType.Address
......
import DeviceInfo from 'react-native-device-info' import DeviceInfo from 'react-native-device-info'
import { isBetaEnv, isDevEnv } from 'uniswap/src/utils/env'
import { StatsigEnvironmentTier } from 'wallet/src/version' import { StatsigEnvironmentTier } from 'wallet/src/version'
/** /**
...@@ -24,44 +25,37 @@ export enum BuildVariant { ...@@ -24,44 +25,37 @@ export enum BuildVariant {
} }
export function getBuildVariant(): BuildVariant { export function getBuildVariant(): BuildVariant {
if (isDevBuild()) { if (isDevEnv()) {
return BuildVariant.Development return BuildVariant.Development
} else if (isBetaBuild()) { } else if (isBetaEnv()) {
return BuildVariant.Beta return BuildVariant.Beta
} else { } else {
return BuildVariant.Production return BuildVariant.Production
} }
} }
export function isDevBuild(): boolean {
return DeviceInfo.getBundleId().endsWith('.dev')
}
export function isBetaBuild(): boolean {
return DeviceInfo.getBundleId().endsWith('.beta')
}
export function getStatsigEnvironmentTier(): StatsigEnvironmentTier { export function getStatsigEnvironmentTier(): StatsigEnvironmentTier {
if (isDevBuild()) { if (isDevEnv()) {
return StatsigEnvironmentTier.DEV return StatsigEnvironmentTier.DEV
} }
if (isBetaBuild()) { if (isBetaEnv()) {
return StatsigEnvironmentTier.BETA return StatsigEnvironmentTier.BETA
} }
return StatsigEnvironmentTier.PROD return StatsigEnvironmentTier.PROD
} }
export function getSentryEnvironment(): SentryEnvironment { export function getSentryEnvironment(): SentryEnvironment {
if (isDevBuild()) { if (isDevEnv()) {
return SentryEnvironment.DEV return SentryEnvironment.DEV
} }
if (isBetaBuild()) { if (isBetaEnv()) {
return SentryEnvironment.BETA return SentryEnvironment.BETA
} }
return SentryEnvironment.PROD return SentryEnvironment.PROD
} }
export function getSentryTracesSamplingRate(): number { export function getSentryTracesSamplingRate(): number {
if (isDevBuild() || isBetaBuild()) { if (isDevEnv() || isBetaEnv()) {
return 1 return 1
} }
return 0.2 return 0.2
......
...@@ -13,6 +13,8 @@ ignores: [ ...@@ -13,6 +13,8 @@ ignores: [
"process", "process",
"madge", "madge",
# Dependencies that depcheck thinks are missing but are actually present or never used # Dependencies that depcheck thinks are missing but are actually present or never used
## package.json scripts
"esbuild-register",
## GraphQL ## GraphQL
"@graphql-codegen/*", "@graphql-codegen/*",
"get-graphql-schema", "get-graphql-schema",
......
...@@ -17,6 +17,5 @@ REACT_APP_TEMP_API_URL="https://temp.gateway.uniswap.org/v1" ...@@ -17,6 +17,5 @@ REACT_APP_TEMP_API_URL="https://temp.gateway.uniswap.org/v1"
REACT_APP_UNISWAP_API_URL="https://interface.gateway.uniswap.org/v2" REACT_APP_UNISWAP_API_URL="https://interface.gateway.uniswap.org/v2"
REACT_APP_UNISWAP_BASE_API_URL="https://interface.gateway.uniswap.org" REACT_APP_UNISWAP_BASE_API_URL="https://interface.gateway.uniswap.org"
REACT_APP_UNISWAP_GATEWAY_DNS="https://interface.gateway.uniswap.org/v2" REACT_APP_UNISWAP_GATEWAY_DNS="https://interface.gateway.uniswap.org/v2"
REACT_APP_UNITAGS_API_URL="https://gateway.uniswap.org/v2/unitags"
REACT_APP_WALLET_CONNECT_PROJECT_ID="c6c9bacd35afa3eb9e6cccf6d8464395" REACT_APP_WALLET_CONNECT_PROJECT_ID="c6c9bacd35afa3eb9e6cccf6d8464395"
REACT_APP_IS_UNISWAP_INTERFACE=true REACT_APP_IS_UNISWAP_INTERFACE=true
...@@ -46,6 +46,11 @@ module.exports = { ...@@ -46,6 +46,11 @@ module.exports = {
importNames: ['usePortfolioBalancesQuery', 'usePortfolioBalancesWebLazyQuery'], importNames: ['usePortfolioBalancesQuery', 'usePortfolioBalancesWebLazyQuery'],
message: 'Import cached/subscription-based balance hooks from `TokenBalancesProvider.tsx` instead.', message: 'Import cached/subscription-based balance hooks from `TokenBalancesProvider.tsx` instead.',
}, },
{
name: 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks',
importNames: ['useActivityWebQuery'],
message: 'Import cached/subscription-based activity hooks from `AssetActivityProvider` instead.',
},
{ {
name: '@uniswap/smart-order-router', name: '@uniswap/smart-order-router',
message: 'Only import types, unless you are in the client-side SOR, to preserve lazy-loading.', message: 'Only import types, unless you are in the client-side SOR, to preserve lazy-loading.',
......
...@@ -13,12 +13,6 @@ yarn ...@@ -13,12 +13,6 @@ yarn
yarn web start yarn web start
``` ```
## Unsupported tokens
Check out `useUnsupportedTokenList()` in [src/state/lists/hooks.ts](./src/state/lists/hooks.ts) for blocking tokens in your instance of the interface.
You can block an entire list of tokens by passing in a tokenlist like [here](./src/constants/lists.ts)
## Accessing Uniswap V2 ## Accessing Uniswap V2
The Uniswap Interface supports swapping, adding liquidity, removing liquidity and migrating liquidity for Uniswap protocol V2. The Uniswap Interface supports swapping, adding liquidity, removing liquidity and migrating liquidity for Uniswap protocol V2.
......
...@@ -8,6 +8,7 @@ const path = require('path') ...@@ -8,6 +8,7 @@ const path = require('path')
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin') const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin')
const { IgnorePlugin, ProvidePlugin } = require('webpack') const { IgnorePlugin, ProvidePlugin } = require('webpack')
const { RetryChunkLoadPlugin } = require('webpack-retry-chunk-load-plugin') const { RetryChunkLoadPlugin } = require('webpack-retry-chunk-load-plugin')
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
const commitHash = execSync('git rev-parse HEAD').toString().trim() const commitHash = execSync('git rev-parse HEAD').toString().trim()
const isProduction = process.env.NODE_ENV === 'production' const isProduction = process.env.NODE_ENV === 'production'
...@@ -92,6 +93,15 @@ module.exports = { ...@@ -92,6 +93,15 @@ module.exports = {
}), }),
], ],
configure: (webpackConfig) => { configure: (webpackConfig) => {
if (isProduction || process.env.UNISWAP_ANALYZE_BUNDLE_SIZE) {
// do bundle analysis
webpackConfig.plugins.push(
new BundleAnalyzerPlugin({
analyzerMode: 'json',
})
)
}
// Configure webpack plugins: // Configure webpack plugins:
webpackConfig.plugins = webpackConfig.plugins webpackConfig.plugins = webpackConfig.plugins
.map((plugin) => { .map((plugin) => {
......
...@@ -2,6 +2,7 @@ import { getTestSelector } from '../utils' ...@@ -2,6 +2,7 @@ import { getTestSelector } from '../utils'
describe('Buy Crypto Modal', () => { describe('Buy Crypto Modal', () => {
it('should open and close', () => { it('should open and close', () => {
cy.intercept('https://api.moonpay.com/v4/ip_address?apiKey=*', { fixture: 'moonpay/ip_address_valid.json' })
cy.visit('/') cy.visit('/')
// Open the fiat onramp modal // Open the fiat onramp modal
...@@ -14,6 +15,7 @@ describe('Buy Crypto Modal', () => { ...@@ -14,6 +15,7 @@ describe('Buy Crypto Modal', () => {
}) })
it('should open and close, mobile viewport', () => { it('should open and close, mobile viewport', () => {
cy.intercept('https://api.moonpay.com/v4/ip_address?apiKey=*', { fixture: 'moonpay/ip_address_valid.json' })
cy.viewport('iphone-6') cy.viewport('iphone-6')
cy.visit('/') cy.visit('/')
...@@ -25,4 +27,13 @@ describe('Buy Crypto Modal', () => { ...@@ -25,4 +27,13 @@ describe('Buy Crypto Modal', () => {
cy.get('body').click(10, 10) cy.get('body').click(10, 10)
cy.get(getTestSelector('fiat-onramp-modal')).should('not.exist') cy.get(getTestSelector('fiat-onramp-modal')).should('not.exist')
}) })
it("should not open if the user's region is not supported", () => {
cy.intercept('https://api.moonpay.com/v4/ip_address?apiKey=*', { fixture: 'moonpay/ip_address_invalid.json' })
cy.visit('/')
// Try to open the fiat onramp modal
cy.get(getTestSelector('buy-fiat-button')).click()
cy.get(getTestSelector('fiat-onramp-modal')).should('not.exist')
})
}) })
...@@ -72,7 +72,7 @@ describe('Landing Page', () => { ...@@ -72,7 +72,7 @@ describe('Landing Page', () => {
}) })
it('renders uk compliance banner in uk', () => { it('renders uk compliance banner in uk', () => {
cy.intercept('https://interface.gateway.uniswap.org/v1/amplitude-proxy', (req) => { cy.intercept(/(?:interface|beta).gateway.uniswap.org\/v1\/amplitude-proxy/, (req) => {
const requestBody = JSON.stringify(req.body) const requestBody = JSON.stringify(req.body)
const byteSize = new Blob([requestBody]).size const byteSize = new Blob([requestBody]).size
req.alias = 'amplitude' req.alias = 'amplitude'
...@@ -89,7 +89,8 @@ describe('Landing Page', () => { ...@@ -89,7 +89,8 @@ describe('Landing Page', () => {
) )
}) })
cy.visit('/swap') cy.visit('/swap')
cy.contains('UK disclaimer') cy.contains('Read more').click()
cy.contains('Disclaimer for UK residents')
}) })
it('shows a nav button to download the app when feature is enabled', () => { it('shows a nav button to download the app when feature is enabled', () => {
......
...@@ -64,17 +64,16 @@ describe('Swap errors', () => { ...@@ -64,17 +64,16 @@ describe('Swap errors', () => {
}) })
it('slippage failure', () => { it('slippage failure', () => {
cy.visit(`/swap?inputCurrency=${USDC_MAINNET.address}&outputCurrency=${DAI.address}`)
cy.hardhat({ automine: false }).then(async (hardhat) => { cy.hardhat({ automine: false }).then(async (hardhat) => {
await hardhat.fund(hardhat.wallet, CurrencyAmount.fromRawAmount(USDC_MAINNET, 500e6)) await hardhat.fund(hardhat.wallet, CurrencyAmount.fromRawAmount(USDC_MAINNET, 500e6))
await hardhat.mine() await hardhat.mine()
await Promise.all([ await hardhat.approval.setTokenAllowanceForPermit2({ owner: hardhat.wallet, token: USDC_MAINNET })
hardhat.approval.setTokenAllowanceForPermit2({ owner: hardhat.wallet, token: USDC_MAINNET }), await hardhat.approval.setPermit2Allowance({ owner: hardhat.wallet, token: USDC_MAINNET })
hardhat.approval.setPermit2Allowance({ owner: hardhat.wallet, token: USDC_MAINNET }),
])
await hardhat.mine() await hardhat.mine()
}) })
cy.visit(`/swap?inputCurrency=${USDC_MAINNET.address}&outputCurrency=${DAI.address}`)
getBalance(DAI).then((initialBalance) => { getBalance(DAI).then((initialBalance) => {
// Gas estimation fails for this transaction (that would normally fail), so we stub it. // Gas estimation fails for this transaction (that would normally fail), so we stub it.
cy.hardhat().then((hardhat) => { cy.hardhat().then((hardhat) => {
......
import { CurrencyAmount } from '@uniswap/sdk-core' import { CurrencyAmount } from '@uniswap/sdk-core'
import { URADutchOrderQuoteResponse } from 'state/routing/types' import { URAQuoteResponse } from 'state/routing/types'
import { USDC_MAINNET } from '../../../src/constants/tokens' import { USDC_MAINNET } from '../../../src/constants/tokens'
import { getBalance, getTestSelector } from '../../utils' import { getBalance, getTestSelector } from '../../utils'
...@@ -120,7 +120,7 @@ describe('Swap with fees', () => { ...@@ -120,7 +120,7 @@ describe('Swap with fees', () => {
it('displays UniswapX fee in UI', () => { it('displays UniswapX fee in UI', () => {
cy.visit('/swap') cy.visit('/swap')
cy.fixture('uniswapx/feeQuote.json').then((fixture: URADutchOrderQuoteResponse) => { cy.fixture('uniswapx/feeQuote.json').then((fixture: URAQuoteResponse) => {
// Intercept the trade quote // Intercept the trade quote
cy.intercept({ url: 'https://interface.gateway.uniswap.org/v2/quote' }, (req) => { cy.intercept({ url: 'https://interface.gateway.uniswap.org/v2/quote' }, (req) => {
// Avoid intercepting stablecoin pricing fetches // Avoid intercepting stablecoin pricing fetches
......
...@@ -54,9 +54,12 @@ describe('Swap', () => { ...@@ -54,9 +54,12 @@ describe('Swap', () => {
it('swaps ETH for USDC', () => { it('swaps ETH for USDC', () => {
cy.interceptGraphqlOperation('Activity', 'mini-portfolio/empty_activity.json') cy.interceptGraphqlOperation('Activity', 'mini-portfolio/empty_activity.json')
cy.interceptQuoteRequest('swap_eth_usdc_classic.json')
cy.visit('/swap') cy.visit('/swap')
cy.hardhat({ automine: false }) cy.hardhat({ automine: false })
getBalance(USDC_MAINNET).then((initialBalance) => { getBalance(USDC_MAINNET).then((initialBalance) => {
cy.get(`#swap-currency-input .token-symbol-container`).should('contain.text', 'ETH')
// Select USDC // Select USDC
cy.get('#swap-currency-output .open-currency-select-button').click() cy.get('#swap-currency-output .open-currency-select-button').click()
cy.get(getTestSelector('token-search-input')).type(USDC_MAINNET.address) cy.get(getTestSelector('token-search-input')).type(USDC_MAINNET.address)
......
...@@ -383,13 +383,17 @@ describe('UniswapX activity history', () => { ...@@ -383,13 +383,17 @@ describe('UniswapX activity history', () => {
cy.get('#swap-currency-input .token-amount-input').type('300') cy.get('#swap-currency-input .token-amount-input').type('300')
const gqlSpy = cy.spy().as('gqlSpy') const gqlSpy = cy.spy().as('gqlSpy')
cy.intercept(/graphql/, (req) => { cy.intercept(/(?:interface|beta).gateway.uniswap.org\/v1\/graphql/, (req) => {
if (req.body.operationName === 'PortfolioBalancesWeb') {
// Spy on request frequency // Spy on request frequency
req.on('response', gqlSpy) req.on('response', gqlSpy)
// Reply with a fixture to speed up test // Reply with a fixture to speed up test
req.reply({ req.reply({
fixture: 'mini-portfolio/tokens.json', fixture: 'mini-portfolio/tokens.json',
}) })
} else {
req.continue()
}
}) })
// Expect balances to fetch upon opening mini portfolio // Expect balances to fetch upon opening mini portfolio
...@@ -400,13 +404,10 @@ describe('UniswapX activity history', () => { ...@@ -400,13 +404,10 @@ describe('UniswapX activity history', () => {
cy.get('#swap-button').click() cy.get('#swap-button').click()
cy.contains('Confirm swap').click() cy.contains('Confirm swap').click()
// Expect balances to refetch after approval
cy.get('@gqlSpy').should('have.been.calledTwice')
// Return filled order status from uniswapx api // Return filled order status from uniswapx api
cy.intercept(OrderStatusEndpoint, { fixture: 'uniswapx/filledStatusResponse.json' }) cy.intercept(OrderStatusEndpoint, { fixture: 'uniswapx/filledStatusResponse.json' })
// Expect balances to refetch after swap // Expect balances to refetch after swap
cy.get('@gqlSpy').should('have.been.calledThrice') cy.get('@gqlSpy').should('have.been.calledTwice')
}) })
}) })
import { ChainId, WETH9 } from '@uniswap/sdk-core' import { ChainId, WETH9 } from '@uniswap/sdk-core'
import { FeatureFlags } from 'uniswap/src/features/gating/flags'
import { shortenAddress } from 'utilities/src/addresses' import { shortenAddress } from 'utilities/src/addresses'
import { ARB, UNI } from '../../src/constants/tokens' import { ARB, UNI } from '../../src/constants/tokens'
import { getTestSelector } from '../utils' import { getTestSelector } from '../utils'
...@@ -51,8 +52,12 @@ describe('Token details', () => { ...@@ -51,8 +52,12 @@ describe('Token details', () => {
}) })
it('token with warning and low trading volume should have all information populated', () => { it('token with warning and low trading volume should have all information populated', () => {
cy.interceptGraphqlOperation('SimpleToken', 'simple_token_warning.json')
// Null token created for this test, 0 trading volume and has warning modal // Null token created for this test, 0 trading volume and has warning modal
cy.visit('/explore/tokens/ethereum/0x1eFBB78C8b917f67986BcE54cE575069c0143681') cy.visit('/explore/tokens/ethereum/0x1eFBB78C8b917f67986BcE54cE575069c0143681', {
featureFlags: [{ flag: FeatureFlags.GqlTokenLists, value: true }],
})
// Should have missing price view when price unavailable (expected for this token) // Should have missing price view when price unavailable (expected for this token)
cy.get('[data-cy="chart-error-view"]').should('exist') cy.get('[data-cy="chart-error-view"]').should('exist')
......
import { FeatureFlags } from 'uniswap/src/features/statsig/flags' import { FeatureFlags } from 'uniswap/src/features/gating/flags'
import { getTestSelector } from '../utils' import { getTestSelector } from '../utils'
describe('Wallet Dropdown', () => { describe('Wallet Dropdown', () => {
......
{
"alpha2": "US",
"alpha3": "USA",
"country": "United States of America",
"ipAddress": "142.154.213.230",
"isAllowed": true,
"isBuyAllowed": false,
"isNftAllowed": true,
"isSellAllowed": false,
"isBalanceLedgerWithdrawAllowed": true,
"isLowLimitEnabled": false,
"state": "NY"
}
{
"alpha2": "US",
"alpha3": "USA",
"country": "United States of America",
"ipAddress": "142.154.213.230",
"isAllowed": true,
"isBuyAllowed": true,
"isNftAllowed": true,
"isSellAllowed": true,
"isBalanceLedgerWithdrawAllowed": true,
"isLowLimitEnabled": true,
"state": "NY"
}
{
"data": {
"token": {
"id": "VG9rZW46RVRIRVJFVU1fbnVsbA==",
"address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"chain": "ETHEREUM",
"symbol": "USDC",
"name": "USD Coin",
"decimals": 6,
"standard": "ERC20",
"project": {
"id": "VG9rZW5Qcm9qZWN0OkVUSEVSRVVNX251bGxfRXRoZXJldW0=",
"name": "Circle: USDC",
"logo": {
"id": "SW1hZ2U6aHR0cHM6Ly90b2tlbi1pY29ucy5zMy5hbWF6b25hd3MuY29tL2V0aC5wbmc=",
"url": "https://etherscan.io/token/images/centre-usdc_28.png",
"__typename": "Image"
},
"safetyLevel": "VERIFIED",
"logoUrl": "https://etherscan.io/token/images/centre-usdc_28.png",
"isSpam": false,
"__typename": "TokenProject"
},
"__typename": "Token"
}
}
}
{
"data": {
"token": {
"id": "test-0x1eFBB78C8b917f67986BcE54cE575069c0143681",
"address": "0x1eFBB78C8b917f67986BcE54cE575069c0143681",
"chain": "ETHEREUM",
"symbol": "test",
"name": "test token",
"decimals": 18,
"project": {
"id": "VG9rZW5Qcm9qZWN0OkVUSEVSRVVNXzB4NmIxNzU0NzRlODkwOTRjNDRkYTk4Yjk1NGVlZGVhYzQ5NTI3MWQwZl9EYWk=",
"name": "Dai",
"logo": {
"id": "SW1hZ2U6aHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL1VuaXN3YXAvYXNzZXRzL21hc3Rlci9ibG9ja2NoYWlucy9ldGhlcmV1bS9hc3NldHMvMHg2QjE3NTQ3NEU4OTA5NEM0NERhOThiOTU0RWVkZUFDNDk1MjcxZDBGL2xvZ28ucG5n",
"url": "https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/ethereum/assets/0x1eFBB78C8b917f67986BcE54cE575069c0143681/logo.png",
"__typename": "Image"
},
"safetyLevel": "STRONG_WARNING",
"logoUrl": "https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/ethereum/assets/0x1eFBB78C8b917f67986BcE54cE575069c0143681/logo.png",
"isSpam": false,
"__typename": "TokenProject"
},
"__typename": "Token"
}
}
}
{
"routing": "CLASSIC",
"quote": {
"methodParameters": {
"calldata": "0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000661ebbb400000000000000000000000000000000000000000000000000000000000000050b0905040c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000012c5b11105b570000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000f4c0400000000000000000000000000000000000000000000000000012c5b11105b5700000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000060000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000027213e28d7fda5c57fe9e5dd923818dbccf71c4700000000000000000000000000000000000000000000000000000000000009c40000000000000000000000000000000000000000000000000000000000000060000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb922660000000000000000000000000000000000000000000000000000000000000000",
"value": "0x012c5b11105b57",
"to": "0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD"
},
"amount": "1000000",
"amountDecimals": "1",
"quote": "327782153215338",
"quoteDecimals": "0.000327782153215338",
"quoteGasAdjusted": "3754905339323778",
"quoteGasAdjustedDecimals": "0.003754905339323778",
"quoteGasAndPortionAdjusted": "3754905339323778",
"quoteGasAndPortionAdjustedDecimals": "0.003754905339323778",
"gasUseEstimateQuote": "3427123186108440",
"gasUseEstimateQuoteDecimals": "0.00342712318610844",
"gasUseEstimate": "264285",
"gasUseEstimateUSD": "10.481019768575804317",
"simulationStatus": "SUCCESS",
"simulationError": false,
"gasPriceWei": "12967528184",
"route": [
[
{
"type": "v2-pool",
"address": "0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc",
"tokenIn": {
"chainId": 1,
"decimals": "18",
"address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"symbol": "WETH"
},
"tokenOut": {
"chainId": 1,
"decimals": "6",
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"symbol": "USDC",
"buyFeeBps": "0",
"sellFeeBps": "0"
},
"reserve0": {
"token": {
"chainId": 1,
"decimals": "6",
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"symbol": "USDC",
"buyFeeBps": "0",
"sellFeeBps": "0"
},
"quotient": "43318082931464"
},
"reserve1": {
"token": {
"chainId": 1,
"decimals": "18",
"address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"symbol": "WETH"
},
"quotient": "14156297485330702299324"
},
"amountIn": "328601608598376",
"amountOut": "1002500"
}
]
],
"routeString": "[V2] 100.00% = WETH -- [0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc] --> USDC",
"quoteId": "471c9a76-3b5d-4bc2-9f6e-11b2bb199d57",
"portionBips": 25,
"portionRecipient": "0x27213E28D7fDA5c57Fe9e5dD923818DBCcf71c47",
"portionAmount": "2500",
"portionAmountDecimals": "0.0025",
"requestId": "60fd2230-ef27-49fa-aef7-9a44fe8216e2",
"tradeType": "EXACT_OUTPUT",
"slippage": 0.5
},
"requestId": "60fd2230-ef27-49fa-aef7-9a44fe8216e2",
"allQuotes": [
null,
{
"routing": "CLASSIC",
"quote": {
"methodParameters": {
"calldata": "0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000661ebbb400000000000000000000000000000000000000000000000000000000000000050b0905040c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000012c5b11105b570000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000f4c0400000000000000000000000000000000000000000000000000012c5b11105b5700000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000060000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000027213e28d7fda5c57fe9e5dd923818dbccf71c4700000000000000000000000000000000000000000000000000000000000009c40000000000000000000000000000000000000000000000000000000000000060000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb922660000000000000000000000000000000000000000000000000000000000000000",
"value": "0x012c5b11105b57",
"to": "0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD"
},
"blockNumber": "19669619",
"amount": "1000000",
"amountDecimals": "1",
"quote": "327782153215338",
"quoteDecimals": "0.000327782153215338",
"quoteGasAdjusted": "3754905339323778",
"quoteGasAdjustedDecimals": "0.003754905339323778",
"quoteGasAndPortionAdjusted": "3754905339323778",
"quoteGasAndPortionAdjustedDecimals": "0.003754905339323778",
"gasUseEstimateQuote": "3427123186108440",
"gasUseEstimateQuoteDecimals": "0.00342712318610844",
"gasUseEstimate": "264285",
"gasUseEstimateUSD": "10.481019768575804317",
"simulationStatus": "SUCCESS",
"simulationError": false,
"gasPriceWei": "12967528184",
"route": [
[
{
"type": "v2-pool",
"address": "0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc",
"tokenIn": {
"chainId": 1,
"decimals": "18",
"address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"symbol": "WETH"
},
"tokenOut": {
"chainId": 1,
"decimals": "6",
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"symbol": "USDC",
"buyFeeBps": "0",
"sellFeeBps": "0"
},
"reserve0": {
"token": {
"chainId": 1,
"decimals": "6",
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"symbol": "USDC",
"buyFeeBps": "0",
"sellFeeBps": "0"
},
"quotient": "43318082931464"
},
"reserve1": {
"token": {
"chainId": 1,
"decimals": "18",
"address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"symbol": "WETH"
},
"quotient": "14156297485330702299324"
},
"amountIn": "328601608598376",
"amountOut": "1002500"
}
]
],
"routeString": "[V2] 100.00% = WETH -- [0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc] --> USDC",
"quoteId": "471c9a76-3b5d-4bc2-9f6e-11b2bb199d57",
"portionBips": 25,
"portionRecipient": "0x27213E28D7fDA5c57Fe9e5dD923818DBCcf71c47",
"portionAmount": "2500",
"portionAmountDecimals": "0.0025",
"requestId": "60fd2230-ef27-49fa-aef7-9a44fe8216e2",
"tradeType": "EXACT_OUTPUT",
"slippage": 0.5
}
}
]
}
...@@ -2,7 +2,7 @@ import 'cypress-hardhat/lib/browser' ...@@ -2,7 +2,7 @@ import 'cypress-hardhat/lib/browser'
import { Eip1193Bridge } from '@ethersproject/experimental/lib/eip1193-bridge' import { Eip1193Bridge } from '@ethersproject/experimental/lib/eip1193-bridge'
import { FeatureFlagClient, FeatureFlags, getFeatureFlagName } from 'uniswap/src/features/statsig/flags' import { FeatureFlagClient, FeatureFlags, getFeatureFlagName } from 'uniswap/src/features/gating/flags'
import { UserState, initialState } from '../../src/state/user/reducer' import { UserState, initialState } from '../../src/state/user/reducer'
import { CONNECTED_WALLET_USER_STATE, setInitialUserState } from '../utils/user-state' import { CONNECTED_WALLET_USER_STATE, setInitialUserState } from '../utils/user-state'
...@@ -27,6 +27,11 @@ declare global { ...@@ -27,6 +27,11 @@ declare global {
* @param {string} fixturePath - The path to the fixture to respond with. * @param {string} fixturePath - The path to the fixture to respond with.
*/ */
interceptGraphqlOperation(operationName: string, fixturePath: string): Chainable<Subject> interceptGraphqlOperation(operationName: string, fixturePath: string): Chainable<Subject>
/**
* Intercepts a quote request and responds with the given fixture.
* @param {string} fixturePath - The path to the fixture to respond with.
*/
interceptQuoteRequest(fixturePath: string): Chainable<Subject>
} }
interface VisitOptions { interface VisitOptions {
featureFlags?: Array<{ flag: FeatureFlags; value: boolean }> featureFlags?: Array<{ flag: FeatureFlags; value: boolean }>
...@@ -123,6 +128,7 @@ Cypress.Commands.add('waitForAmplitudeEvent', (eventName, requiredProperties) => ...@@ -123,6 +128,7 @@ Cypress.Commands.add('waitForAmplitudeEvent', (eventName, requiredProperties) =>
Cypress.Commands.add('interceptGraphqlOperation', (operationName, fixturePath) => { Cypress.Commands.add('interceptGraphqlOperation', (operationName, fixturePath) => {
return cy.intercept(/(?:interface|beta).gateway.uniswap.org\/v1\/graphql/, (req) => { return cy.intercept(/(?:interface|beta).gateway.uniswap.org\/v1\/graphql/, (req) => {
req.headers['origin'] = 'https://app.uniswap.org'
if (req.body.operationName === operationName) { if (req.body.operationName === operationName) {
req.reply({ fixture: fixturePath }) req.reply({ fixture: fixturePath })
} else { } else {
...@@ -130,3 +136,10 @@ Cypress.Commands.add('interceptGraphqlOperation', (operationName, fixturePath) = ...@@ -130,3 +136,10 @@ Cypress.Commands.add('interceptGraphqlOperation', (operationName, fixturePath) =
} }
}) })
}) })
Cypress.Commands.add('interceptQuoteRequest', (fixturePath) => {
return cy.intercept(/(?:interface|beta).gateway.uniswap.org\/v2\/quote/, (req) => {
req.headers['origin'] = 'https://app.uniswap.org'
req.reply({ fixture: fixturePath })
})
})
// @ts-ignore // @ts-ignore
import TokenListJSON from '@uniswap/default-token-list'
import { CyHttpMessages } from 'cypress/types/net-stubbing' import { CyHttpMessages } from 'cypress/types/net-stubbing'
beforeEach(() => { beforeEach(() => {
...@@ -41,11 +40,6 @@ beforeEach(() => { ...@@ -41,11 +40,6 @@ beforeEach(() => {
// Mock statsig to allow us to mock flags. // Mock statsig to allow us to mock flags.
cy.intercept(/statsig/, { statusCode: 409 }) cy.intercept(/statsig/, { statusCode: 409 })
// Mock our own token list responses to avoid the latency of IPFS.
cy.intercept('https://gateway.ipfs.io/ipns/tokens.uniswap.org', TokenListJSON)
.intercept('https://gateway.ipfs.io/ipns/extendedtokens.uniswap.org', { statusCode: 404 })
.intercept('https://gateway.ipfs.io/ipns/unsupportedtokens.uniswap.org', { statusCode: 404 })
// Reset hardhat between tests to ensure isolation. // Reset hardhat between tests to ensure isolation.
// This resets the fork, as well as options like automine. // This resets the fork, as well as options like automine.
cy.hardhat().then((hardhat) => hardhat.reset()) cy.hardhat().then((hardhat) => hardhat.reset())
......
...@@ -31,12 +31,6 @@ export const onRequest: PagesFunction = async ({ params, request }) => { ...@@ -31,12 +31,6 @@ export const onRequest: PagesFunction = async ({ params, request }) => {
const networkLogo = getNetworkLogoUrl(networkName.toUpperCase(), origin) const networkLogo = getNetworkLogoUrl(networkName.toUpperCase(), origin)
// Capitalize name such that each word starts with a capital letter
let words = data.name.split(' ')
words = words.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
let name = words.join(' ')
name = name.trim()
return new ImageResponse( return new ImageResponse(
( (
<div <div
...@@ -77,7 +71,6 @@ export const onRequest: PagesFunction = async ({ params, request }) => { ...@@ -77,7 +71,6 @@ export const onRequest: PagesFunction = async ({ params, request }) => {
position: 'absolute', position: 'absolute',
right: '2px', right: '2px',
bottom: '0px', bottom: '0px',
borderRadius: '100%',
}} }}
/> />
)} )}
...@@ -112,7 +105,6 @@ export const onRequest: PagesFunction = async ({ params, request }) => { ...@@ -112,7 +105,6 @@ export const onRequest: PagesFunction = async ({ params, request }) => {
position: 'absolute', position: 'absolute',
right: '2px', right: '2px',
bottom: '0px', bottom: '0px',
borderRadius: '100%',
}} }}
/> />
)} )}
...@@ -127,7 +119,7 @@ export const onRequest: PagesFunction = async ({ params, request }) => { ...@@ -127,7 +119,7 @@ export const onRequest: PagesFunction = async ({ params, request }) => {
marginTop: '24px', marginTop: '24px',
}} }}
> >
{name} {data.name}
</div> </div>
<div <div
style={{ style={{
......
...@@ -10,6 +10,14 @@ export default function getNetworkLogoUrl(network: string, origin: string) { ...@@ -10,6 +10,14 @@ export default function getNetworkLogoUrl(network: string, origin: string) {
return origin + '/images/logos/Optimism_Logo.png' return origin + '/images/logos/Optimism_Logo.png'
case Chain.Celo: case Chain.Celo:
return origin + '/images/logos/Celo_Logo.png' return origin + '/images/logos/Celo_Logo.png'
case Chain.Base:
return origin + '/images/logos/Base_Logo.png'
case Chain.Bnb:
return origin + '/images/logos/BNB_Logo.png'
case Chain.Avalanche:
return origin + '/images/logos/Avax_Logo.png'
case Chain.Blast:
return origin + '/images/logos/Blast_Logo.png'
default: default:
return '' return ''
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
"scripts": { "scripts": {
"ajv": "node scripts/compile-ajv-validators.js", "ajv": "node scripts/compile-ajv-validators.js",
"check:deps:usage": "depcheck", "check:deps:usage": "depcheck",
"check:circular": "concurrently \"../../scripts/check-circular-imports.sh ./src/pages/App.tsx 8\" \"../../scripts/check-circular-imports.sh ./src/setupTests.ts 0\"", "check:circular": "concurrently \"../../scripts/check-circular-imports.sh ./src/pages/App.tsx 7\" \"../../scripts/check-circular-imports.sh ./src/setupTests.ts 0\"",
"contracts:compile:abi": "typechain --target ethers-v5 --out-dir src/abis/types \"./src/abis/**/*.json\"", "contracts:compile:abi": "typechain --target ethers-v5 --out-dir src/abis/types \"./src/abis/**/*.json\"",
"contracts:compile:v3": "typechain --target ethers-v5 --out-dir src/types/v3 \"../../node_modules/@uniswap/**/artifacts/contracts/**/*[!dbg].json\"", "contracts:compile:v3": "typechain --target ethers-v5 --out-dir src/types/v3 \"../../node_modules/@uniswap/**/artifacts/contracts/**/*[!dbg].json\"",
"contracts": "yarn contracts:compile:abi && yarn contracts:compile:v3", "contracts": "yarn contracts:compile:abi && yarn contracts:compile:v3",
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
"typecheck:cloud": "tsc -p functions/tsconfig.json", "typecheck:cloud": "tsc -p functions/tsconfig.json",
"typecheck:cypress": "tsc -p cypress/tsconfig.json", "typecheck:cypress": "tsc -p cypress/tsconfig.json",
"test": "craco test", "test": "craco test",
"test:bundle": "node -r esbuild-register ./src/test-utils/bundle-size-test.ts",
"snapshots": "craco test -u", "snapshots": "craco test -u",
"test:cloud": "yarn jest functions --config=functions/jest.config.json", "test:cloud": "yarn jest functions --config=functions/jest.config.json",
"cypress:open": "cypress open --browser chrome --e2e", "cypress:open": "cypress open --browser chrome --e2e",
...@@ -91,10 +92,12 @@ ...@@ -91,10 +92,12 @@
"@swc/plugin-styled-components": "1.5.97", "@swc/plugin-styled-components": "1.5.97",
"@testing-library/jest-dom": "5.17.0", "@testing-library/jest-dom": "5.17.0",
"@testing-library/react": "13.4.0", "@testing-library/react": "13.4.0",
"@testing-library/react-hooks": "7.0.2",
"@testing-library/user-event": "14.5.1", "@testing-library/user-event": "14.5.1",
"@typechain/ethers-v5": "7.2.0", "@typechain/ethers-v5": "7.2.0",
"@types/array.prototype.flat": "1.2.5", "@types/array.prototype.flat": "1.2.5",
"@types/array.prototype.flatmap": "1.2.6", "@types/array.prototype.flatmap": "1.2.6",
"@types/chrome": "0.0.254",
"@types/d3": "7.4.3", "@types/d3": "7.4.3",
"@types/jest": "29.5.0", "@types/jest": "29.5.0",
"@types/ms": "0.7.31", "@types/ms": "0.7.31",
...@@ -126,6 +129,7 @@ ...@@ -126,6 +129,7 @@
"cypress-hardhat": "2.5.0", "cypress-hardhat": "2.5.0",
"dotenv": "16.0.3", "dotenv": "16.0.3",
"dotenv-cli": "^7.0.0", "dotenv-cli": "^7.0.0",
"esbuild-register": "^3.5.0",
"eslint": "8.44.0", "eslint": "8.44.0",
"eslint-plugin-import": "2.27.5", "eslint-plugin-import": "2.27.5",
"eslint-plugin-rulesdir": "0.2.2", "eslint-plugin-rulesdir": "0.2.2",
...@@ -156,6 +160,7 @@ ...@@ -156,6 +160,7 @@
"tsafe": "1.6.4", "tsafe": "1.6.4",
"typescript": "5.3.3", "typescript": "5.3.3",
"webpack": "5.90.0", "webpack": "5.90.0",
"webpack-bundle-analyzer": "^4.10.2",
"webpack-retry-chunk-load-plugin": "3.1.1", "webpack-retry-chunk-load-plugin": "3.1.1",
"wrangler": "3.15.0", "wrangler": "3.15.0",
"yarn-deduplicate": "6.0.0" "yarn-deduplicate": "6.0.0"
...@@ -171,7 +176,6 @@ ...@@ -171,7 +176,6 @@
"@graphql-codegen/typescript-resolvers": "^3.2.1", "@graphql-codegen/typescript-resolvers": "^3.2.1",
"@juggle/resize-observer": "3.4.0", "@juggle/resize-observer": "3.4.0",
"@looksrare/sdk": "0.10.4", "@looksrare/sdk": "0.10.4",
"@metamask/jazzicon": "2.0.0",
"@opensea/seaport-js": "1.3.0", "@opensea/seaport-js": "1.3.0",
"@popperjs/core": "2.11.8", "@popperjs/core": "2.11.8",
"@reach/dialog": "0.10.5", "@reach/dialog": "0.10.5",
...@@ -182,8 +186,8 @@ ...@@ -182,8 +186,8 @@
"@sentry/core": "7.80.0", "@sentry/core": "7.80.0",
"@sentry/react": "7.80.0", "@sentry/react": "7.80.0",
"@sentry/types": "7.80.0", "@sentry/types": "7.80.0",
"@tamagui/core": "1.94.3", "@tamagui/core": "1.94.5",
"@tamagui/react-native-svg": "1.94.3", "@tamagui/react-native-svg": "1.94.5",
"@tanstack/react-query": "5.28.14", "@tanstack/react-query": "5.28.14",
"@tanstack/react-table": "8.10.7", "@tanstack/react-table": "8.10.7",
"@types/poisson-disk-sampling": "2.2.4", "@types/poisson-disk-sampling": "2.2.4",
...@@ -194,20 +198,20 @@ ...@@ -194,20 +198,20 @@
"@uniswap/governance": "1.0.2", "@uniswap/governance": "1.0.2",
"@uniswap/liquidity-staker": "1.0.2", "@uniswap/liquidity-staker": "1.0.2",
"@uniswap/merkle-distributor": "1.0.1", "@uniswap/merkle-distributor": "1.0.1",
"@uniswap/permit2-sdk": "1.2.0", "@uniswap/permit2-sdk": "1.2.1-beta.1",
"@uniswap/redux-multicall": "1.1.8", "@uniswap/redux-multicall": "1.1.8",
"@uniswap/router-sdk": "1.9.0", "@uniswap/router-sdk": "1.9.1-beta.2",
"@uniswap/sdk-core": "4.2.0", "@uniswap/sdk-core": "4.2.1-beta.1",
"@uniswap/smart-order-router": "3.17.3", "@uniswap/smart-order-router": "3.17.3",
"@uniswap/token-lists": "1.0.0-beta.33", "@uniswap/token-lists": "1.0.0-beta.33",
"@uniswap/uniswapx-sdk": "2.0.1-alpha.4", "@uniswap/uniswapx-sdk": "2.0.3-alpha.1",
"@uniswap/universal-router-sdk": "1.8.2", "@uniswap/universal-router-sdk": "2.0.4-beta.3",
"@uniswap/v2-core": "1.0.1", "@uniswap/v2-core": "1.0.1",
"@uniswap/v2-periphery": "1.1.0-beta.0", "@uniswap/v2-periphery": "1.1.0-beta.0",
"@uniswap/v2-sdk": "4.3.0", "@uniswap/v2-sdk": "4.3.1-beta.2",
"@uniswap/v3-core": "1.0.1", "@uniswap/v3-core": "1.0.1",
"@uniswap/v3-periphery": "1.4.4", "@uniswap/v3-periphery": "1.4.4",
"@uniswap/v3-sdk": "3.11.0", "@uniswap/v3-sdk": "3.11.1-beta.2",
"@vanilla-extract/css": "1.14.0", "@vanilla-extract/css": "1.14.0",
"@vanilla-extract/dynamic": "2.1.0", "@vanilla-extract/dynamic": "2.1.0",
"@vanilla-extract/sprinkles": "1.6.1", "@vanilla-extract/sprinkles": "1.6.1",
...@@ -286,6 +290,7 @@ ...@@ -286,6 +290,7 @@
"statsig-react": "1.32.0", "statsig-react": "1.32.0",
"styled-components": "5.3.11", "styled-components": "5.3.11",
"tiny-invariant": "1.3.1", "tiny-invariant": "1.3.1",
"ui": "workspace:^",
"uniswap": "workspace:^", "uniswap": "workspace:^",
"use-resize-observer": "9.1.0", "use-resize-observer": "9.1.0",
"utilities": "workspace:^", "utilities": "workspace:^",
......
...@@ -85,7 +85,6 @@ ...@@ -85,7 +85,6 @@
"https://*.base.org/", "https://*.base.org/",
"https://*.walletconnect.com", "https://*.walletconnect.com",
"https://ethereum-optimism.github.io/", "https://ethereum-optimism.github.io/",
"https://*.twnodes.com",
"https://forno.celo.org/", "https://forno.celo.org/",
"https://*.gemini.com", "https://*.gemini.com",
"https://gateway.ipfs.io/", "https://gateway.ipfs.io/",
......
apps/web/public/images/logos/Celo_Logo.png

4.45 KB | W: | H:

apps/web/public/images/logos/Celo_Logo.png

705 Bytes | W: | H:

apps/web/public/images/logos/Celo_Logo.png
apps/web/public/images/logos/Celo_Logo.png
apps/web/public/images/logos/Celo_Logo.png
apps/web/public/images/logos/Celo_Logo.png
  • 2-up
  • Swipe
  • Onion skin
...@@ -24,7 +24,7 @@ import { useAppDispatch } from 'state/hooks' ...@@ -24,7 +24,7 @@ import { useAppDispatch } from 'state/hooks'
import { setRecentConnectionDisconnected } from 'state/user/reducer' import { setRecentConnectionDisconnected } from 'state/user/reducer'
import styled from 'styled-components' import styled from 'styled-components'
import { ThemedText } from 'theme/components' import { ThemedText } from 'theme/components'
import { useUnitagByAddressWithoutFlag } from 'uniswap/src/features/unitags/hooksWithoutFlags' import { useUnitagByAddress } from 'uniswap/src/features/unitags/hooks'
import { isPathBlocked } from 'utils/blockedPaths' import { isPathBlocked } from 'utils/blockedPaths'
import { NumberType, useFormatter } from 'utils/formatNumbers' import { NumberType, useFormatter } from 'utils/formatNumbers'
import { useCloseModal, useFiatOnrampAvailability, useOpenModal, useToggleModal } from '../../state/application/hooks' import { useCloseModal, useFiatOnrampAvailability, useOpenModal, useToggleModal } from '../../state/application/hooks'
...@@ -156,14 +156,14 @@ export default function AuthenticatedHeader({ account, openSettings }: { account ...@@ -156,14 +156,14 @@ export default function AuthenticatedHeader({ account, openSettings }: { account
error || (!fiatOnrampAvailable && fiatOnrampAvailabilityChecked) || fiatOnrampAvailabilityLoading error || (!fiatOnrampAvailable && fiatOnrampAvailabilityChecked) || fiatOnrampAvailabilityLoading
) )
const { data: portfolioBalances } = useTokenBalancesQuery({ skip: !accountDrawerOpen }) const { data: portfolioBalances } = useTokenBalancesQuery({ cacheOnly: !accountDrawerOpen })
const portfolio = portfolioBalances?.portfolios?.[0] const portfolio = portfolioBalances?.portfolios?.[0]
const totalBalance = portfolio?.tokensTotalDenominatedValue?.value const totalBalance = portfolio?.tokensTotalDenominatedValue?.value
const absoluteChange = portfolio?.tokensTotalDenominatedValueChange?.absolute?.value const absoluteChange = portfolio?.tokensTotalDenominatedValueChange?.absolute?.value
const percentChange = portfolio?.tokensTotalDenominatedValueChange?.percentage?.value const percentChange = portfolio?.tokensTotalDenominatedValueChange?.percentage?.value
const [showDisconnectConfirm, setShowDisconnectConfirm] = useState(false) const [showDisconnectConfirm, setShowDisconnectConfirm] = useState(false)
const { unitag } = useUnitagByAddressWithoutFlag(account, Boolean(account)) const { unitag } = useUnitagByAddress(account)
const amount = unclaimedAmount?.toFixed(0, { groupSeparator: ',' } ?? '-') const amount = unclaimedAmount?.toFixed(0, { groupSeparator: ',' } ?? '-')
return ( return (
......
import { ChainId, Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core' import { ChainId, Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { import {
CancelLimitsDialog, CancelLimitsDialog,
CancellationState, CancellationState,
...@@ -26,15 +25,10 @@ import { Divider, ThemedText } from 'theme/components' ...@@ -26,15 +25,10 @@ import { Divider, ThemedText } from 'theme/components'
import { UniswapXOrderStatus } from 'types/uniswapx' import { UniswapXOrderStatus } from 'types/uniswapx'
import { ExplorerDataType, getExplorerLink } from 'utils/getExplorerLink' import { ExplorerDataType, getExplorerLink } from 'utils/getExplorerLink'
import { PERMIT2_ADDRESS } from '@uniswap/permit2-sdk'
import { sendAnalyticsEvent } from 'analytics' import { sendAnalyticsEvent } from 'analytics'
import { cancelMultipleUniswapXOrders } from 'components/AccountDrawer/MiniPortfolio/Activity/utils' import { useCancelMultipleOrdersCallback } from 'components/AccountDrawer/MiniPortfolio/Activity/utils'
import AlertTriangleFilled from 'components/Icons/AlertTriangleFilled' import AlertTriangleFilled from 'components/Icons/AlertTriangleFilled'
import { LimitDisclaimer } from 'components/swap/LimitDisclaimer' import { LimitDisclaimer } from 'components/swap/LimitDisclaimer'
import { ContractTransaction } from 'ethers/lib/ethers'
import { useContract } from 'hooks/useContract'
import PERMIT2_ABI from 'uniswap/src/abis/permit2.json'
import { Permit2 } from 'uniswap/src/abis/types/Permit2'
import { PortfolioLogo } from '../PortfolioLogo' import { PortfolioLogo } from '../PortfolioLogo'
import { OffchainOrderLineItem, OffchainOrderLineItemProps, OffchainOrderLineItemType } from './OffchainOrderLineItem' import { OffchainOrderLineItem, OffchainOrderLineItemProps, OffchainOrderLineItemType } from './OffchainOrderLineItem'
...@@ -150,6 +144,8 @@ function getOrderTitle(order: UniswapXOrderDetails): ReactNode { ...@@ -150,6 +144,8 @@ function getOrderTitle(order: UniswapXOrderDetails): ReactNode {
return isLimit ? <Trans>Limit pending</Trans> : <Trans>Order pending</Trans> return isLimit ? <Trans>Limit pending</Trans> : <Trans>Order pending</Trans>
case UniswapXOrderStatus.EXPIRED: case UniswapXOrderStatus.EXPIRED:
return isLimit ? <Trans>Limit expired</Trans> : <Trans>Order expired</Trans> return isLimit ? <Trans>Limit expired</Trans> : <Trans>Order expired</Trans>
case UniswapXOrderStatus.PENDING_CANCELLATION:
return <Trans>Pending cancellation</Trans>
case UniswapXOrderStatus.INSUFFICIENT_FUNDS: case UniswapXOrderStatus.INSUFFICIENT_FUNDS:
case UniswapXOrderStatus.CANCELLED: case UniswapXOrderStatus.CANCELLED:
return isLimit ? <Trans>Limit cancelled</Trans> : <Trans>Order cancelled</Trans> return isLimit ? <Trans>Limit cancelled</Trans> : <Trans>Order cancelled</Trans>
...@@ -160,20 +156,6 @@ function getOrderTitle(order: UniswapXOrderDetails): ReactNode { ...@@ -160,20 +156,6 @@ function getOrderTitle(order: UniswapXOrderDetails): ReactNode {
} }
} }
function useCancelOrder(order?: UniswapXOrderDetails): () => Promise<ContractTransaction[] | undefined> {
const { provider } = useWeb3React()
const permit2 = useContract<Permit2>(PERMIT2_ADDRESS, PERMIT2_ABI, true)
return useCallback(async () => {
if (!order) return undefined
return await cancelMultipleUniswapXOrders({
orders: [{ encodedOrder: order.encodedOrder as string, type: order.type as SignatureType }],
chainId: order.chainId,
provider,
permit2,
})
}, [order, permit2, provider])
}
export function OrderContent({ export function OrderContent({
order, order,
logos, logos,
...@@ -335,7 +317,9 @@ export function OffchainActivityModal() { ...@@ -335,7 +317,9 @@ export function OffchainActivityModal() {
setSelectedOrder((order) => order && { ...order, modalOpen: false }) setSelectedOrder((order) => order && { ...order, modalOpen: false })
}, [setSelectedOrder]) }, [setSelectedOrder])
const cancelOrder = useCancelOrder(syncedSelectedOrder) const cancelOrder = useCancelMultipleOrdersCallback(
useMemo(() => [syncedSelectedOrder].filter(Boolean) as Array<UniswapXOrderDetails>, [syncedSelectedOrder])
)
return ( return (
<> <>
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment