ci(release): publish latest release

parent fc68138e
IPFS hash of the deployment: IPFS hash of the deployment:
- CIDv0: `QmQcU3yDYBfnzcB31iYwTcW41JwYaQabvdaaM28WCXf8Ws` - CIDv0: `QmZCHeoJuPsFdadwYDZ1gxfLvYaaRxv5pGxTRcmSGXqSgP`
- CIDv1: `bafybeibbyso4k2bvdabn3u3s3ubzaxmszuwtjlhppj5zjjfeex2g4rhoga` - CIDv1: `bafybeifbjqm3qbn3nu6diizot5gr24pw2dai5r6l5iafo5y4t5nufursoa`
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,15 +10,39 @@ You can also access the Uniswap Interface from an IPFS gateway. ...@@ -10,15 +10,39 @@ 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://bafybeibbyso4k2bvdabn3u3s3ubzaxmszuwtjlhppj5zjjfeex2g4rhoga.ipfs.dweb.link/ - https://bafybeifbjqm3qbn3nu6diizot5gr24pw2dai5r6l5iafo5y4t5nufursoa.ipfs.dweb.link/
- https://bafybeibbyso4k2bvdabn3u3s3ubzaxmszuwtjlhppj5zjjfeex2g4rhoga.ipfs.cf-ipfs.com/ - https://bafybeifbjqm3qbn3nu6diizot5gr24pw2dai5r6l5iafo5y4t5nufursoa.ipfs.cf-ipfs.com/
- [ipfs://QmQcU3yDYBfnzcB31iYwTcW41JwYaQabvdaaM28WCXf8Ws/](ipfs://QmQcU3yDYBfnzcB31iYwTcW41JwYaQabvdaaM28WCXf8Ws/) - [ipfs://QmZCHeoJuPsFdadwYDZ1gxfLvYaaRxv5pGxTRcmSGXqSgP/](ipfs://QmZCHeoJuPsFdadwYDZ1gxfLvYaaRxv5pGxTRcmSGXqSgP/)
### 5.25.7 (2024-05-09) ## 5.26.0 (2024-05-09)
### Features
* **web:** add dynamic metatag updating w/ react-helmet-async (#7732) 4afd49c
* **web:** add multichain ux flag (#7796) 870f18f
* **web:** automate sitemap generation during prod deploy (#7846) 6010986
* **web:** migrate user state back to localStorage (#7452) b8ff545
### Bug Fixes ### Bug Fixes
* **web:** hotfix warning modified extensions (#8042) ac4781d * **web:** add "Safe" RPC URLs to CSP (#7844) 7880af0
* **web:** align price impact in details and warning (#7734) 65303d4
* **web:** convert useQuery to use QueryOptions (#7729) da4104c
* **web:** disable flaky tests in merge queue runs (#7771) c5fc13b
* **web:** fix token lookups from network for backend-unsupported chains (#7894) 2bcd438
* **web:** fix tokens lookups for avax (#7893) f4deeb6
* **web:** Flip logic for Sells/Buys (#7880) cffd9ec
* **web:** hotfix warning modified extensions (#8073) deeeb4f
* **web:** infinite loop when connecting to unsupported chain (#7891) 4df2b6a
* **web:** pool page stuck in rerender loop (#7892) 45541af
* **web:** reduce gap in AdvancedSwapDetails component (#7733) 278f948
* **web:** refactor chain URL param handling (#7807) a33bc3d
* **web:** remove limits+send feature flags & fix broken /limit page refresh (#7870) 6c5eaa9
* **web:** serialize polling tx receipts (#7908) 3c44924
* **web:** support swapping spam tokens (#7793) 020a1e4
* **web:** update the CTAs on pools page to link to explore/pools page (#7808) cb625d8
* **web:** width of account bottom sheet on mobile (#7886) 03ebbd0
web/5.25.7 web/5.26.0
\ No newline at end of file \ No newline at end of file
...@@ -131,17 +131,17 @@ android { ...@@ -131,17 +131,17 @@ android {
dev { dev {
isDefault(true) isDefault(true)
applicationIdSuffix ".dev" applicationIdSuffix ".dev"
versionName "1.26" versionName "1.27"
dimension "variant" dimension "variant"
} }
beta { beta {
applicationIdSuffix ".beta" applicationIdSuffix ".beta"
versionName "1.26" versionName "1.27"
dimension "variant" dimension "variant"
} }
prod { prod {
dimension "variant" dimension "variant"
versionName "1.26" versionName "1.27"
} }
} }
......
...@@ -185,6 +185,7 @@ ...@@ -185,6 +185,7 @@
9FEC9B8B2A858CF1003CD019 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9FEC9B8A2A858CF1003CD019 /* AppDelegate.m */; }; 9FEC9B8B2A858CF1003CD019 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9FEC9B8A2A858CF1003CD019 /* AppDelegate.m */; };
A32F9FBD272343C9002CFCDB /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = A32F9FBC272343C8002CFCDB /* GoogleService-Info.plist */; }; A32F9FBD272343C9002CFCDB /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = A32F9FBC272343C8002CFCDB /* GoogleService-Info.plist */; };
A3F0A5B1272B1DFA00895B25 /* KeychainSwiftDistrib.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3F0A5B0272B1DFA00895B25 /* KeychainSwiftDistrib.swift */; }; A3F0A5B1272B1DFA00895B25 /* KeychainSwiftDistrib.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3F0A5B0272B1DFA00895B25 /* KeychainSwiftDistrib.swift */; };
AC0EE0982BD826E700BCCF07 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = AC0EE0972BD826E700BCCF07 /* PrivacyInfo.xcprivacy */; };
AEE498F72A85AD86000DDF8E /* Basel-Book.ttf in Resources */ = {isa = PBXBuildFile; fileRef = AEE498F52A85AD86000DDF8E /* Basel-Book.ttf */; }; AEE498F72A85AD86000DDF8E /* Basel-Book.ttf in Resources */ = {isa = PBXBuildFile; fileRef = AEE498F52A85AD86000DDF8E /* Basel-Book.ttf */; };
AEE498F82A85AD86000DDF8E /* Basel-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = AEE498F62A85AD86000DDF8E /* Basel-Medium.ttf */; }; AEE498F82A85AD86000DDF8E /* Basel-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = AEE498F62A85AD86000DDF8E /* Basel-Medium.ttf */; };
B8649A8D70B018E583494128 /* libPods-WidgetsCoreTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F9B12416ED2E83444B0936B2 /* libPods-WidgetsCoreTests.a */; }; B8649A8D70B018E583494128 /* libPods-WidgetsCoreTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F9B12416ED2E83444B0936B2 /* libPods-WidgetsCoreTests.a */; };
...@@ -489,6 +490,7 @@ ...@@ -489,6 +490,7 @@
A721D9DBF345F037F45E92BE /* Pods-WidgetsCore.beta.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WidgetsCore.beta.xcconfig"; path = "Target Support Files/Pods-WidgetsCore/Pods-WidgetsCore.beta.xcconfig"; sourceTree = "<group>"; }; A721D9DBF345F037F45E92BE /* Pods-WidgetsCore.beta.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WidgetsCore.beta.xcconfig"; path = "Target Support Files/Pods-WidgetsCore/Pods-WidgetsCore.beta.xcconfig"; sourceTree = "<group>"; };
A82B0304EEE753C6DEB3943E /* libPods-OneSignalNotificationServiceExtension.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-OneSignalNotificationServiceExtension.a"; sourceTree = BUILT_PRODUCTS_DIR; }; A82B0304EEE753C6DEB3943E /* libPods-OneSignalNotificationServiceExtension.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-OneSignalNotificationServiceExtension.a"; sourceTree = BUILT_PRODUCTS_DIR; };
A87B4C3727F6D91B4DAABF14 /* Pods-Uniswap.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Uniswap.debug.xcconfig"; path = "Target Support Files/Pods-Uniswap/Pods-Uniswap.debug.xcconfig"; sourceTree = "<group>"; }; A87B4C3727F6D91B4DAABF14 /* Pods-Uniswap.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Uniswap.debug.xcconfig"; path = "Target Support Files/Pods-Uniswap/Pods-Uniswap.debug.xcconfig"; sourceTree = "<group>"; };
AC0EE0972BD826E700BCCF07 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = Uniswap/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
AEE498F52A85AD86000DDF8E /* Basel-Book.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Basel-Book.ttf"; path = "../src/assets/fonts/Basel-Book.ttf"; sourceTree = "<group>"; }; AEE498F52A85AD86000DDF8E /* Basel-Book.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Basel-Book.ttf"; path = "../src/assets/fonts/Basel-Book.ttf"; sourceTree = "<group>"; };
AEE498F62A85AD86000DDF8E /* Basel-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Basel-Medium.ttf"; path = "../src/assets/fonts/Basel-Medium.ttf"; sourceTree = "<group>"; }; AEE498F62A85AD86000DDF8E /* Basel-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Basel-Medium.ttf"; path = "../src/assets/fonts/Basel-Medium.ttf"; sourceTree = "<group>"; };
B398F0A4DA17159EA0E2D6DF /* Pods-Uniswap.dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Uniswap.dev.xcconfig"; path = "Target Support Files/Pods-Uniswap/Pods-Uniswap.dev.xcconfig"; sourceTree = "<group>"; }; B398F0A4DA17159EA0E2D6DF /* Pods-Uniswap.dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Uniswap.dev.xcconfig"; path = "Target Support Files/Pods-Uniswap/Pods-Uniswap.dev.xcconfig"; sourceTree = "<group>"; };
...@@ -880,6 +882,7 @@ ...@@ -880,6 +882,7 @@
13B07FAE1A68108700A75B9A /* Uniswap */ = { 13B07FAE1A68108700A75B9A /* Uniswap */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
AC0EE0972BD826E700BCCF07 /* PrivacyInfo.xcprivacy */,
8EA8AB3F2AB7ED76004E7EF3 /* Icons */, 8EA8AB3F2AB7ED76004E7EF3 /* Icons */,
8E566D9F2AA1095000D4AA76 /* Components */, 8E566D9F2AA1095000D4AA76 /* Components */,
07B067692A7D6EC8001DD9B9 /* Widget */, 07B067692A7D6EC8001DD9B9 /* Widget */,
...@@ -1433,6 +1436,7 @@ ...@@ -1433,6 +1436,7 @@
77CF6065C8A24FE48204A2C1 /* SplashScreen.storyboard in Resources */, 77CF6065C8A24FE48204A2C1 /* SplashScreen.storyboard in Resources */,
681301B42A3726EE00A5BF43 /* pending_swap.riv in Resources */, 681301B42A3726EE00A5BF43 /* pending_swap.riv in Resources */,
681301B22A3726EE00A5BF43 /* pending_send.riv in Resources */, 681301B22A3726EE00A5BF43 /* pending_send.riv in Resources */,
AC0EE0982BD826E700BCCF07 /* PrivacyInfo.xcprivacy in Resources */,
AEE498F72A85AD86000DDF8E /* Basel-Book.ttf in Resources */, AEE498F72A85AD86000DDF8E /* Basel-Book.ttf in Resources */,
0767E02F2A61BBDC0042ADA2 /* Basel-Regular.otf in Resources */, 0767E02F2A61BBDC0042ADA2 /* Basel-Regular.otf in Resources */,
0767E0352A61BBDC0042ADA2 /* Basel-Bold.otf in Resources */, 0767E0352A61BBDC0042ADA2 /* Basel-Bold.otf in Resources */,
...@@ -2450,7 +2454,7 @@ ...@@ -2450,7 +2454,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.26; MARKETING_VERSION = 1.27;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
...@@ -2496,7 +2500,7 @@ ...@@ -2496,7 +2500,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.26; MARKETING_VERSION = 1.27;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.widgets; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.widgets;
...@@ -2542,7 +2546,7 @@ ...@@ -2542,7 +2546,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.26; MARKETING_VERSION = 1.27;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.dev.widgets; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.dev.widgets;
...@@ -2588,7 +2592,7 @@ ...@@ -2588,7 +2592,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.26; MARKETING_VERSION = 1.27;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.beta.widgets; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.beta.widgets;
...@@ -2630,7 +2634,7 @@ ...@@ -2630,7 +2634,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.26; MARKETING_VERSION = 1.27;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
...@@ -2673,7 +2677,7 @@ ...@@ -2673,7 +2677,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.26; MARKETING_VERSION = 1.27;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.WidgetIntentExtension; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.WidgetIntentExtension;
...@@ -2716,7 +2720,7 @@ ...@@ -2716,7 +2720,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.26; MARKETING_VERSION = 1.27;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.dev.WidgetIntentExtension; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.dev.WidgetIntentExtension;
...@@ -2759,7 +2763,7 @@ ...@@ -2759,7 +2763,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.26; MARKETING_VERSION = 1.27;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.beta.WidgetIntentExtension; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.beta.WidgetIntentExtension;
...@@ -2795,7 +2799,7 @@ ...@@ -2795,7 +2799,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.26; MARKETING_VERSION = 1.27;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"$(inherited)", "$(inherited)",
"-ObjC", "-ObjC",
...@@ -2833,7 +2837,7 @@ ...@@ -2833,7 +2837,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.26; MARKETING_VERSION = 1.27;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"$(inherited)", "$(inherited)",
"-ObjC", "-ObjC",
...@@ -3003,7 +3007,7 @@ ...@@ -3003,7 +3007,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.26; MARKETING_VERSION = 1.27;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
...@@ -3047,7 +3051,7 @@ ...@@ -3047,7 +3051,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.26; MARKETING_VERSION = 1.27;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.OneSignalNotificationServiceExtension; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.OneSignalNotificationServiceExtension;
...@@ -3143,7 +3147,7 @@ ...@@ -3143,7 +3147,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.26; MARKETING_VERSION = 1.27;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"$(inherited)", "$(inherited)",
"-ObjC", "-ObjC",
...@@ -3214,7 +3218,7 @@ ...@@ -3214,7 +3218,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.26; MARKETING_VERSION = 1.27;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.beta.OneSignalNotificationServiceExtension; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.beta.OneSignalNotificationServiceExtension;
...@@ -3310,7 +3314,7 @@ ...@@ -3310,7 +3314,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.26; MARKETING_VERSION = 1.27;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"$(inherited)", "$(inherited)",
"-ObjC", "-ObjC",
...@@ -3381,7 +3385,7 @@ ...@@ -3381,7 +3385,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.26; MARKETING_VERSION = 1.27;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.dev.OneSignalNotificationServiceExtension; PRODUCT_BUNDLE_IDENTIFIER = com.uniswap.mobile.dev.OneSignalNotificationServiceExtension;
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
<string>C56D.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>35F9.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>E174.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>C617.1</string>
<string>0A2A.1</string>
</array>
</dict>
</array>
</dict>
</plist>
...@@ -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.1-beta.1", "@uniswap/sdk-core": "4.2.1",
"@uniswap/v3-sdk": "3.11.1-beta.2", "@uniswap/v3-sdk": "3.11.1",
"@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",
......
...@@ -169,12 +169,10 @@ function App(): JSX.Element | null { ...@@ -169,12 +169,10 @@ function App(): JSX.Element | null {
function SentryTags({ children }: PropsWithChildren): JSX.Element { function SentryTags({ children }: PropsWithChildren): JSX.Element {
useEffect(() => { useEffect(() => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (const [_, flagKey] of WALLET_FEATURE_FLAG_NAMES.entries()) { for (const [_, flagKey] of WALLET_FEATURE_FLAG_NAMES.entries()) {
Sentry.setTag(`featureFlag.${flagKey}`, Statsig.checkGateWithExposureLoggingDisabled(flagKey)) Sentry.setTag(`featureFlag.${flagKey}`, Statsig.checkGateWithExposureLoggingDisabled(flagKey))
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (const [_, experimentDef] of WALLET_EXPERIMENTS.entries()) { for (const [_, experimentDef] of WALLET_EXPERIMENTS.entries()) {
Sentry.setTag( Sentry.setTag(
`experiment.${experimentDef.name}`, `experiment.${experimentDef.name}`,
......
...@@ -75,7 +75,7 @@ function useHandleShareNft(): (args: ShareNftArgs) => Promise<void> { ...@@ -75,7 +75,7 @@ function useHandleShareNft(): (args: ShareNftArgs) => Promise<void> {
function useHandleShareToken(): (args: ShareTokenArgs) => Promise<void> { function useHandleShareToken(): (args: ShareTokenArgs) => Promise<void> {
return useCallback(async ({ currencyId }: ShareTokenArgs): Promise<void> => { return useCallback(async ({ currencyId }: ShareTokenArgs): Promise<void> => {
const url = getTokenUrl(currencyId) const url = getTokenUrl(currencyId, true)
if (!url) { if (!url) {
logger.error(new Error('Failed to get token URL'), { logger.error(new Error('Failed to get token URL'), {
......
...@@ -14,13 +14,13 @@ import { useSagaStatus } from 'src/utils/useSagaStatus' ...@@ -14,13 +14,13 @@ import { useSagaStatus } from 'src/utils/useSagaStatus'
import { import {
Button, Button,
Flex, Flex,
Icons,
Text, Text,
TouchableArea, TouchableArea,
useDeviceDimensions, useDeviceDimensions,
useDeviceInsets, useDeviceInsets,
useSporeColors, useSporeColors,
} from 'ui/src' } from 'ui/src'
import { Plus } from 'ui/src/components/icons'
import { spacing } from 'ui/src/theme' import { spacing } from 'ui/src/theme'
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'
...@@ -298,7 +298,7 @@ export function AccountSwitcher({ onClose }: { onClose: () => void }): JSX.Eleme ...@@ -298,7 +298,7 @@ export function AccountSwitcher({ onClose }: { onClose: () => void }): JSX.Eleme
<TouchableArea hapticFeedback mt="$spacing16" onPress={onPressAddWallet}> <TouchableArea hapticFeedback mt="$spacing16" onPress={onPressAddWallet}>
<Flex row alignItems="center" gap="$spacing16" ml="$spacing24"> <Flex row alignItems="center" gap="$spacing16" ml="$spacing24">
<Flex borderColor="$surface3" borderRadius="$roundedFull" borderWidth={1} p="$spacing8"> <Flex borderColor="$surface3" borderRadius="$roundedFull" borderWidth={1} p="$spacing8">
<Icons.Plus color="$neutral2" size="$icon.12" strokeWidth={2} /> <Plus color="$neutral2" size="$icon.12" strokeWidth={2} />
</Flex> </Flex>
<Text color="$neutral2" variant="buttonLabel3"> <Text color="$neutral2" variant="buttonLabel3">
{t('account.wallet.button.add')} {t('account.wallet.button.add')}
......
...@@ -6,33 +6,9 @@ import { useAppDispatch, useAppSelector } from 'src/app/hooks' ...@@ -6,33 +6,9 @@ import { useAppDispatch, useAppSelector } from 'src/app/hooks'
import { closeModal } from 'src/features/modals/modalSlice' import { closeModal } from 'src/features/modals/modalSlice'
import { selectCustomEndpoint } from 'src/features/tweaks/selectors' import { selectCustomEndpoint } from 'src/features/tweaks/selectors'
import { setCustomEndpoint } from 'src/features/tweaks/slice' import { setCustomEndpoint } from 'src/features/tweaks/slice'
import { import { Accordion, Button, Flex, Text, useDeviceInsets } from 'ui/src'
Accordion,
Button,
Flex,
Icons,
Separator,
Text,
useDeviceInsets,
useSporeColors,
} from 'ui/src'
import { spacing } from 'ui/src/theme' import { spacing } from 'ui/src/theme'
import { import { AccordionHeader, GatingOverrides } from 'wallet/src/components/gating/GatingOverrides'
Experiments,
WALLET_EXPERIMENTS,
getExperimentDefinition,
} from 'uniswap/src/features/gating/experiments'
import {
FeatureFlags,
WALLET_FEATURE_FLAG_NAMES,
getFeatureFlagName,
} from 'uniswap/src/features/gating/flags'
import {
useExperimentValueWithExposureLoggingDisabled,
useFeatureFlagWithExposureLoggingDisabled,
} from 'uniswap/src/features/gating/hooks'
import { Statsig } from 'uniswap/src/features/gating/sdk/statsig'
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'
import { ModalName } from 'wallet/src/telemetry/constants' import { ModalName } from 'wallet/src/telemetry/constants'
...@@ -65,16 +41,6 @@ export function ExperimentsModal(): JSX.Element { ...@@ -65,16 +41,6 @@ export function ExperimentsModal(): JSX.Element {
} }
} }
const featureFlagRows: JSX.Element[] = []
for (const [flag, flagName] of WALLET_FEATURE_FLAG_NAMES.entries()) {
featureFlagRows.push(<FeatureFlagRow key={flagName} flag={flag} />)
}
const experimentRows: JSX.Element[] = []
for (const [experiment, experimentDef] of WALLET_EXPERIMENTS.entries()) {
experimentRows.push(<ExperimentRow key={experimentDef.name} experiment={experiment} />)
}
return ( return (
<BottomSheetModal <BottomSheetModal
fullScreen fullScreen
...@@ -132,119 +98,9 @@ export function ExperimentsModal(): JSX.Element { ...@@ -132,119 +98,9 @@ export function ExperimentsModal(): JSX.Element {
</Accordion.Content> </Accordion.Content>
</Accordion.Item> </Accordion.Item>
<Accordion.Item value="feature-flags"> <GatingOverrides />
<AccordionHeader title="⛳️ Feature Flags" />
<Accordion.Content>
<Text variant="body2">
Overridden feature flags are reset when the app is restarted
</Text>
<Flex gap="$spacing12" mt="$spacing12">
{featureFlagRows}
</Flex>
</Accordion.Content>
</Accordion.Item>
<Accordion.Item value="experiments">
<AccordionHeader title="🔬 Experiments" />
<Accordion.Content>
<Text variant="body2">
Overridden experiments are reset when the app is restarted
</Text>
<Flex gap="$spacing24" mt="$spacing12">
{experimentRows}
</Flex>
</Accordion.Content>
</Accordion.Item>
</Accordion> </Accordion>
</ScrollView> </ScrollView>
</BottomSheetModal> </BottomSheetModal>
) )
} }
function AccordionHeader({ title }: { title: React.ReactNode }): JSX.Element {
return (
<Accordion.Header mt="$spacing12">
<Accordion.Trigger>
{({ open }: { open: boolean }): JSX.Element => (
<>
<Flex row justifyContent="space-between" width="100%">
<Text variant="subheading1">{title}</Text>
<Icons.RotatableChevron direction={open ? 'up' : 'down'} />
</Flex>
</>
)}
</Accordion.Trigger>
</Accordion.Header>
)
}
function FeatureFlagRow({ flag }: { flag: FeatureFlags }): JSX.Element {
const status = useFeatureFlagWithExposureLoggingDisabled(flag)
const name = getFeatureFlagName(flag)
return (
<Flex row alignItems="center" gap="$spacing16" justifyContent="space-between">
<Text variant="body1">{name}</Text>
<Switch
value={status}
onValueChange={(newValue: boolean): void => {
Statsig.overrideGate(name, newValue)
}}
/>
</Flex>
)
}
function ExperimentRow({ experiment }: { experiment: Experiments }): JSX.Element {
const experimentDef = getExperimentDefinition(experiment)
return (
<>
<Separator />
<Flex>
<Text variant="body1">{experimentDef.name}</Text>
<Flex gap="$spacing4">
<Flex
key={experimentDef.name}
row
alignItems="center"
gap="$spacing16"
justifyContent="space-between"
paddingStart="$spacing16">
<Text variant="body2" />
<ExperimentValueSwitch experiment={experiment} />
</Flex>
</Flex>
</Flex>
</>
)
}
function ExperimentValueSwitch({ experiment }: { experiment: Experiments }): JSX.Element {
const colors = useSporeColors()
const experimentDef = getExperimentDefinition(experiment)
const currentValue = useExperimentValueWithExposureLoggingDisabled(experiment)
return (
<Flex gap="$spacing8">
{experimentDef.values.map((value) => (
<Flex
key={value}
gap="$spacing4"
onPressOut={() => {
Statsig.overrideConfig(experimentDef.name, {
[experimentDef.key]: value,
})
}}>
<Text color={value === currentValue ? colors.accent1.val : colors.neutral1.val}>
{value}
</Text>
</Flex>
))}
</Flex>
)
}
...@@ -5,7 +5,6 @@ import { useAppDispatch } from 'src/app/hooks' ...@@ -5,7 +5,6 @@ import { useAppDispatch } from 'src/app/hooks'
import { import {
Button, Button,
Flex, Flex,
Icons,
Text, Text,
Unicon, Unicon,
UniconV2, UniconV2,
...@@ -13,6 +12,7 @@ import { ...@@ -13,6 +12,7 @@ import {
useIsDarkMode, useIsDarkMode,
useUniconColors, useUniconColors,
} from 'ui/src' } from 'ui/src'
import { RightArrow } from 'ui/src/components/icons'
import { spacing } from 'ui/src/theme' import { spacing } from 'ui/src/theme'
import { UniconGradient } from 'wallet/src/components/accounts/AccountIcon' import { UniconGradient } from 'wallet/src/components/accounts/AccountIcon'
import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal' import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal'
...@@ -47,7 +47,7 @@ export function UniconsV2Modal({ address }: UniconsV2ModalProps): JSX.Element { ...@@ -47,7 +47,7 @@ export function UniconsV2Modal({ address }: UniconsV2ModalProps): JSX.Element {
<Unicon address={address} size={UNICON_SIZE - UNICON_PADDING} /> <Unicon address={address} size={UNICON_SIZE - UNICON_PADDING} />
<UniconGradient color={uniconColor} size={UNICON_SIZE} /> <UniconGradient color={uniconColor} size={UNICON_SIZE} />
</Flex> </Flex>
<Icons.RightArrow color="$neutral3" size="$icon.16" /> <RightArrow color="$neutral3" size="$icon.16" />
<UniconV2 address={address} size={UNICON_SIZE} /> <UniconV2 address={address} size={UNICON_SIZE} />
</Flex> </Flex>
<Flex alignItems="center" gap="$spacing12"> <Flex alignItems="center" gap="$spacing12">
......
...@@ -21,7 +21,6 @@ import { ...@@ -21,7 +21,6 @@ import {
Flex, Flex,
FlexProps, FlexProps,
HapticFeedback, HapticFeedback,
Icons,
LinearGradient, LinearGradient,
Text, Text,
TouchableArea, TouchableArea,
...@@ -29,6 +28,7 @@ import { ...@@ -29,6 +28,7 @@ import {
useIsDarkMode, useIsDarkMode,
useSporeColors, useSporeColors,
} from 'ui/src' } from 'ui/src'
import { Search } from 'ui/src/components/icons'
import { borderRadii, fonts } from 'ui/src/theme' import { borderRadii, fonts } from 'ui/src/theme'
import { isAndroid, isIOS } from 'uniswap/src/utils/platform' import { isAndroid, isIOS } from 'uniswap/src/utils/platform'
import { useHighestBalanceNativeCurrencyId } from 'wallet/src/features/dataApi/balances' import { useHighestBalanceNativeCurrencyId } from 'wallet/src/features/dataApi/balances'
...@@ -250,7 +250,7 @@ function ExploreTabBarButton({ activeScale = 0.98 }: ExploreTabBarButtonProps): ...@@ -250,7 +250,7 @@ function ExploreTabBarButton({ activeScale = 0.98 }: ExploreTabBarButtonProps):
shadowOffset={SWAP_BUTTON_SHADOW_OFFSET} shadowOffset={SWAP_BUTTON_SHADOW_OFFSET}
shadowOpacity={isDarkMode ? 0.6 : 0.4} shadowOpacity={isDarkMode ? 0.6 : 0.4}
shadowRadius={borderRadii.rounded20}> shadowRadius={borderRadii.rounded20}>
<Icons.Search color="$neutral2" size="$icon.24" /> <Search color="$neutral2" size="$icon.24" />
<Text <Text
allowFontScaling={false} allowFontScaling={false}
color="$neutral2" color="$neutral2"
......
...@@ -61,7 +61,8 @@ import { SettingsWalletEdit } from 'src/screens/SettingsWalletEdit' ...@@ -61,7 +61,8 @@ import { SettingsWalletEdit } from 'src/screens/SettingsWalletEdit'
import { SettingsWalletManageConnection } from 'src/screens/SettingsWalletManageConnection' import { SettingsWalletManageConnection } from 'src/screens/SettingsWalletManageConnection'
import { TokenDetailsScreen } from 'src/screens/TokenDetailsScreen' 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 { useDeviceInsets, useSporeColors } from 'ui/src'
import { RotatableChevron } from 'ui/src/components/icons'
import { spacing } from 'ui/src/theme' import { spacing } from 'ui/src/theme'
import { FeatureFlags } from 'uniswap/src/features/gating/flags' import { FeatureFlags } from 'uniswap/src/features/gating/flags'
import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks'
...@@ -211,7 +212,7 @@ export function FiatOnRampStackNavigator(): JSX.Element { ...@@ -211,7 +212,7 @@ export function FiatOnRampStackNavigator(): JSX.Element {
} }
const renderHeaderBackImage = (): JSX.Element => ( const renderHeaderBackImage = (): JSX.Element => (
<Icons.RotatableChevron color="$neutral2" height={28} width={28} /> <RotatableChevron color="$neutral2" height={28} width={28} />
) )
export function OnboardingStackNavigator(): JSX.Element { export function OnboardingStackNavigator(): JSX.Element {
......
...@@ -2,7 +2,8 @@ import React from 'react' ...@@ -2,7 +2,8 @@ import React from 'react'
import { useAnimatedStyle } from 'react-native-reanimated' import { useAnimatedStyle } from 'react-native-reanimated'
import { useLineChartDatetime } from 'react-native-wagmi-charts' import { useLineChartDatetime } from 'react-native-wagmi-charts'
import { AnimatedText } from 'src/components/text/AnimatedText' import { AnimatedText } from 'src/components/text/AnimatedText'
import { Flex, Icons, useSporeColors } from 'ui/src' import { Flex, useSporeColors } from 'ui/src'
import { AnimatedCaretChange } from 'ui/src/components/icons'
import { isAndroid } from 'uniswap/src/utils/platform' import { isAndroid } from 'uniswap/src/utils/platform'
import { FiatCurrency } from 'wallet/src/features/fiatCurrency/constants' import { FiatCurrency } from 'wallet/src/features/fiatCurrency/constants'
import { useAppFiatCurrency, useAppFiatCurrencyInfo } from 'wallet/src/features/fiatCurrency/hooks' import { useAppFiatCurrency, useAppFiatCurrencyInfo } from 'wallet/src/features/fiatCurrency/hooks'
...@@ -65,7 +66,7 @@ export function RelativeChangeText({ loading }: { loading: boolean }): JSX.Eleme ...@@ -65,7 +66,7 @@ export function RelativeChangeText({ loading }: { loading: boolean }): JSX.Eleme
alignItems={isAndroid ? 'center' : 'flex-end'} alignItems={isAndroid ? 'center' : 'flex-end'}
gap="$spacing2" gap="$spacing2"
mt={isAndroid ? '$none' : '$spacing2'}> mt={isAndroid ? '$none' : '$spacing2'}>
<Icons.AnimatedCaretChange <AnimatedCaretChange
size="$icon.16" size="$icon.16"
strokeWidth={2} strokeWidth={2}
style={[ style={[
......
...@@ -7,16 +7,9 @@ import { Alert, LayoutChangeEvent, LayoutRectangle, StyleSheet } from 'react-nat ...@@ -7,16 +7,9 @@ import { Alert, LayoutChangeEvent, LayoutRectangle, StyleSheet } from 'react-nat
import { launchImageLibrary } from 'react-native-image-picker' import { launchImageLibrary } from 'react-native-image-picker'
import { FadeIn, FadeOut } from 'react-native-reanimated' import { FadeIn, FadeOut } from 'react-native-reanimated'
import { Defs, LinearGradient, Path, Rect, Stop, Svg } from 'react-native-svg' import { Defs, LinearGradient, Path, Rect, Stop, Svg } from 'react-native-svg'
import { import { AnimatedFlex, Button, Flex, Text, useDeviceDimensions, useSporeColors } from 'ui/src'
AnimatedFlex,
Button,
Flex,
Icons,
Text,
useDeviceDimensions,
useSporeColors,
} from 'ui/src'
import CameraScan from 'ui/src/assets/icons/camera-scan.svg' import CameraScan from 'ui/src/assets/icons/camera-scan.svg'
import { Global, Photo } from 'ui/src/components/icons'
import { iconSizes, spacing } from 'ui/src/theme' import { iconSizes, spacing } from 'ui/src/theme'
import { Sentry } from 'utilities/src/logger/Sentry' import { Sentry } from 'utilities/src/logger/Sentry'
import { DevelopmentOnly } from 'wallet/src/components/DevelopmentOnly/DevelopmentOnly' import { DevelopmentOnly } from 'wallet/src/components/DevelopmentOnly/DevelopmentOnly'
...@@ -264,14 +257,14 @@ export function QRCodeScanner(props: QRCodeScannerProps | WCScannerProps): JSX.E ...@@ -264,14 +257,14 @@ export function QRCodeScanner(props: QRCodeScannerProps | WCScannerProps): JSX.E
{isReadingImageFile ? ( {isReadingImageFile ? (
<SpinningLoader size={iconSizes.icon28} /> <SpinningLoader size={iconSizes.icon28} />
) : ( ) : (
<Icons.Photo color="$neutral1" size={iconSizes.icon28} /> <Photo color="$neutral1" size={iconSizes.icon28} />
)} )}
</Flex> </Flex>
{isWalletConnectModal && props.numConnections > 0 && ( {isWalletConnectModal && props.numConnections > 0 && (
<Button <Button
fontFamily="$body" fontFamily="$body"
icon={<Icons.Global color="$neutral2" />} icon={<Global color="$neutral2" />}
theme="secondary" theme="secondary"
onPress={props.onPressConnections}> onPress={props.onPressConnections}>
{t('qrScanner.button.connections', { count: props.numConnections })} {t('qrScanner.button.connections', { count: props.numConnections })}
......
...@@ -9,7 +9,8 @@ import { ...@@ -9,7 +9,8 @@ import {
} from 'src/app/navigation/types' } from 'src/app/navigation/types'
import { openModal } from 'src/features/modals/modalSlice' import { openModal } from 'src/features/modals/modalSlice'
import { Screens } from 'src/screens/Screens' import { Screens } from 'src/screens/Screens'
import { Flex, Icons, Text, TouchableArea, useSporeColors } from 'ui/src' import { Flex, Text, TouchableArea, useSporeColors } from 'ui/src'
import { RotatableChevron } from 'ui/src/components/icons'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { Switch } from 'wallet/src/components/buttons/Switch' import { Switch } from 'wallet/src/components/buttons/Switch'
import { Arrow } from 'wallet/src/components/icons/Arrow' import { Arrow } from 'wallet/src/components/icons/Arrow'
...@@ -123,7 +124,7 @@ export function SettingsRow({ ...@@ -123,7 +124,7 @@ export function SettingsRow({
</Text> </Text>
</Flex> </Flex>
) : null} ) : null}
<Icons.RotatableChevron <RotatableChevron
color="$neutral3" color="$neutral3"
direction="end" direction="end"
height={iconSizes.icon24} height={iconSizes.icon24}
......
...@@ -2,7 +2,14 @@ import React, { useState } from 'react' ...@@ -2,7 +2,14 @@ import React, { useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import Animated, { FadeIn, FadeOut } from 'react-native-reanimated' import Animated, { FadeIn, FadeOut } from 'react-native-reanimated'
import { LongText } from 'src/components/text/LongText' import { LongText } from 'src/components/text/LongText'
import { Flex, Icons, Text, TouchableArea, useSporeColors } from 'ui/src' import { Flex, Text, TouchableArea, useSporeColors } from 'ui/src'
import {
ChartBar,
ChartPie,
Language as LanguageIcon,
TrendDown,
TrendUp,
} from 'ui/src/components/icons'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { TokenDetailsScreenQuery } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { TokenDetailsScreenQuery } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks'
import { NumberType } from 'utilities/src/format/types' import { NumberType } from 'utilities/src/format/types'
...@@ -58,45 +65,35 @@ export function TokenDetailsMarketData({ ...@@ -58,45 +65,35 @@ export function TokenDetailsMarketData({
<Flex gap="$spacing8"> <Flex gap="$spacing8">
<StatsRow <StatsRow
label={t('token.stats.marketCap')} label={t('token.stats.marketCap')}
statsIcon={ statsIcon={<ChartPie color={tokenColor ?? defaultTokenColor} size={iconSizes.icon16} />}>
<Icons.ChartPie color={tokenColor ?? defaultTokenColor} size={iconSizes.icon16} />
}>
<Text loading={isLoading} variant="body2"> <Text loading={isLoading} variant="body2">
{convertFiatAmountFormatted(marketCap, NumberType.FiatTokenStats)} {convertFiatAmountFormatted(marketCap, NumberType.FiatTokenStats)}
</Text> </Text>
</StatsRow> </StatsRow>
<StatsRow <StatsRow
label={t('token.stats.fullyDilutedValuation')} label={t('token.stats.fullyDilutedValuation')}
statsIcon={ statsIcon={<ChartPie color={tokenColor ?? defaultTokenColor} size={iconSizes.icon16} />}>
<Icons.ChartPie color={tokenColor ?? defaultTokenColor} size={iconSizes.icon16} />
}>
<Text loading={isLoading} variant="body2"> <Text loading={isLoading} variant="body2">
{convertFiatAmountFormatted(fullyDilutedValuation, NumberType.FiatTokenStats)} {convertFiatAmountFormatted(fullyDilutedValuation, NumberType.FiatTokenStats)}
</Text> </Text>
</StatsRow> </StatsRow>
<StatsRow <StatsRow
label={t('token.stats.volume')} label={t('token.stats.volume')}
statsIcon={ statsIcon={<ChartBar color={tokenColor ?? defaultTokenColor} size={iconSizes.icon16} />}>
<Icons.ChartBar color={tokenColor ?? defaultTokenColor} size={iconSizes.icon16} />
}>
<Text loading={isLoading} variant="body2"> <Text loading={isLoading} variant="body2">
{convertFiatAmountFormatted(volume, NumberType.FiatTokenStats)} {convertFiatAmountFormatted(volume, NumberType.FiatTokenStats)}
</Text> </Text>
</StatsRow> </StatsRow>
<StatsRow <StatsRow
label={t('token.stats.priceHighYear')} label={t('token.stats.priceHighYear')}
statsIcon={ statsIcon={<TrendUp color={tokenColor ?? defaultTokenColor} size={iconSizes.icon16} />}>
<Icons.TrendUp color={tokenColor ?? defaultTokenColor} size={iconSizes.icon16} />
}>
<Text loading={isLoading} variant="body2"> <Text loading={isLoading} variant="body2">
{convertFiatAmountFormatted(priceHight52W, NumberType.FiatTokenDetails)} {convertFiatAmountFormatted(priceHight52W, NumberType.FiatTokenDetails)}
</Text> </Text>
</StatsRow> </StatsRow>
<StatsRow <StatsRow
label={t('token.stats.priceLowYear')} label={t('token.stats.priceLowYear')}
statsIcon={ statsIcon={<TrendDown color={tokenColor ?? defaultTokenColor} size={iconSizes.icon16} />}>
<Icons.TrendDown color={tokenColor ?? defaultTokenColor} size={iconSizes.icon16} />
}>
<Text loading={isLoading} variant="body2"> <Text loading={isLoading} variant="body2">
{convertFiatAmountFormatted(priceLow52W, NumberType.FiatTokenDetails)} {convertFiatAmountFormatted(priceLow52W, NumberType.FiatTokenDetails)}
</Text> </Text>
...@@ -171,7 +168,7 @@ export function TokenDetailsStats({ ...@@ -171,7 +168,7 @@ export function TokenDetailsStats({
{showTranslation ? ( {showTranslation ? (
<Flex row alignItems="center" gap="$spacing12" width="100%"> <Flex row alignItems="center" gap="$spacing12" width="100%">
<Flex fill row alignItems="center" gap="$spacing12"> <Flex fill row alignItems="center" gap="$spacing12">
<Icons.Language color="$neutral2" size="$icon.20" /> <LanguageIcon color="$neutral2" size="$icon.20" />
<Text color="$neutral2" variant="body3"> <Text color="$neutral2" variant="body3">
{currentLanguageInfo.displayName} {currentLanguageInfo.displayName}
</Text> </Text>
...@@ -183,7 +180,7 @@ export function TokenDetailsStats({ ...@@ -183,7 +180,7 @@ export function TokenDetailsStats({
) : ( ) : (
<Animated.View entering={FadeIn.duration(100)} exiting={FadeOut.duration(100)}> <Animated.View entering={FadeIn.duration(100)} exiting={FadeOut.duration(100)}>
<Flex row alignItems="center" gap="$spacing12"> <Flex row alignItems="center" gap="$spacing12">
<Icons.Language color="$neutral2" size="$icon.20" /> <LanguageIcon color="$neutral2" size="$icon.20" />
<Text color="$neutral2" variant="body3"> <Text color="$neutral2" variant="body3">
{t('token.stats.translation.translate', { {t('token.stats.translation.translate', {
language: currentLanguageInfo.displayName, language: currentLanguageInfo.displayName,
......
...@@ -11,7 +11,8 @@ import { ...@@ -11,7 +11,8 @@ import {
WalletConnectSession, WalletConnectSession,
removePendingSession, removePendingSession,
} from 'src/features/walletConnect/walletConnectSlice' } from 'src/features/walletConnect/walletConnectSlice'
import { AnimatedFlex, Flex, Icons, Text, TouchableArea, useDeviceDimensions } from 'ui/src' import { AnimatedFlex, Flex, Text, TouchableArea, useDeviceDimensions } from 'ui/src'
import { Edit, Scan } from 'ui/src/components/icons'
import { spacing } from 'ui/src/theme' import { spacing } from 'ui/src/theme'
import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants' import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants'
import { ModalName } from 'wallet/src/telemetry/constants' import { ModalName } from 'wallet/src/telemetry/constants'
...@@ -60,14 +61,14 @@ export function ConnectedDappsList({ backButton, sessions }: ConnectedDappsProps ...@@ -60,14 +61,14 @@ export function ConnectedDappsList({ backButton, sessions }: ConnectedDappsProps
setIsEditing(!isEditing) setIsEditing(!isEditing)
}}> }}>
{isEditing ? ( {isEditing ? (
<Icons.Edit color="$accent1" size="$icon.20" /> <Edit color="$accent1" size="$icon.20" />
) : ( ) : (
<Icons.Edit color="$neutral2" size="$icon.20" /> <Edit color="$neutral2" size="$icon.20" />
)} )}
</TouchableArea> </TouchableArea>
) : ( ) : (
<TouchableArea onPress={onPressScan}> <TouchableArea onPress={onPressScan}>
<Icons.Scan color="$neutral2" size="$icon.20" /> <Scan color="$neutral2" size="$icon.20" />
</TouchableArea> </TouchableArea>
)} )}
</Flex> </Flex>
......
...@@ -20,7 +20,8 @@ import { ...@@ -20,7 +20,8 @@ import {
addSession, addSession,
removePendingSession, removePendingSession,
} from 'src/features/walletConnect/walletConnectSlice' } from 'src/features/walletConnect/walletConnectSlice'
import { Flex, Icons, Text, TouchableArea, useSporeColors } from 'ui/src' import { Flex, Text, TouchableArea, useSporeColors } from 'ui/src'
import { Check, X } from 'ui/src/components/icons'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { ONE_SECOND_MS } from 'utilities/src/time/time' import { ONE_SECOND_MS } from 'utilities/src/time/time'
import { AccountDetails } from 'wallet/src/components/accounts/AccountDetails' import { AccountDetails } from 'wallet/src/components/accounts/AccountDetails'
...@@ -76,7 +77,7 @@ const SitePermissions = (): JSX.Element => { ...@@ -76,7 +77,7 @@ const SitePermissions = (): JSX.Element => {
</Flex> </Flex>
<Flex gap="$spacing8" pt="$spacing12"> <Flex gap="$spacing8" pt="$spacing12">
<Flex centered row gap="$spacing4"> <Flex centered row gap="$spacing4">
<Icons.Check color="$statusSuccess" size={iconSizes.icon16} /> <Check color="$statusSuccess" size={iconSizes.icon16} />
<Text <Text
$short={{ variant: infoTextSize }} $short={{ variant: infoTextSize }}
allowFontScaling={false} allowFontScaling={false}
...@@ -87,7 +88,7 @@ const SitePermissions = (): JSX.Element => { ...@@ -87,7 +88,7 @@ const SitePermissions = (): JSX.Element => {
</Text> </Text>
</Flex> </Flex>
<Flex centered row gap="$spacing4"> <Flex centered row gap="$spacing4">
<Icons.Check color="$statusSuccess" size={iconSizes.icon16} /> <Check color="$statusSuccess" size={iconSizes.icon16} />
<Text <Text
$short={{ variant: infoTextSize }} $short={{ variant: infoTextSize }}
allowFontScaling={false} allowFontScaling={false}
...@@ -98,7 +99,7 @@ const SitePermissions = (): JSX.Element => { ...@@ -98,7 +99,7 @@ const SitePermissions = (): JSX.Element => {
</Text> </Text>
</Flex> </Flex>
<Flex centered row gap="$spacing4"> <Flex centered row gap="$spacing4">
<Icons.X color="$statusCritical" size={iconSizes.icon16} /> <X color="$statusCritical" size={iconSizes.icon16} />
<Text <Text
$short={{ variant: infoTextSize }} $short={{ variant: infoTextSize }}
allowFontScaling={false} allowFontScaling={false}
......
...@@ -186,7 +186,21 @@ export function WalletConnectModal({ ...@@ -186,7 +186,21 @@ export function WalletConnectModal({
chainId: parsedUwulinkRequest.chainId, chainId: parsedUwulinkRequest.chainId,
} }
if (parsedUwulinkRequest.method === UwULinkMethod.Erc20Send) { if (parsedUwulinkRequest.method === EthMethod.PersonalSign) {
dispatch(
addRequest({
account: activeAccount.address,
request: {
...newRequest,
type: EthMethod.PersonalSign,
message: parsedUwulinkRequest.message,
// rawMessage should be the hex version of `message`, but our wallet will only use
// `message` if it exists. so this is mostly to appease Typescript
rawMessage: parsedUwulinkRequest.message,
},
})
)
} else if (parsedUwulinkRequest.method === UwULinkMethod.Erc20Send) {
const preparedTransaction = await toTokenTransferRequest( const preparedTransaction = await toTokenTransferRequest(
parsedUwulinkRequest, parsedUwulinkRequest,
activeAccount, activeAccount,
......
...@@ -18,6 +18,7 @@ import { getTokenTransferRequest } from 'wallet/src/features/transactions/transf ...@@ -18,6 +18,7 @@ import { getTokenTransferRequest } from 'wallet/src/features/transactions/transf
import { TransferCurrencyParams } from 'wallet/src/features/transactions/transfer/types' import { TransferCurrencyParams } from 'wallet/src/features/transactions/transfer/types'
import { Account } from 'wallet/src/features/wallet/accounts/types' import { Account } from 'wallet/src/features/wallet/accounts/types'
import { import {
EthMethod,
EthTransaction, EthTransaction,
UwULinkErc20SendRequest, UwULinkErc20SendRequest,
UwULinkMethod, UwULinkMethod,
...@@ -188,6 +189,10 @@ export function isAllowedUwuLinkRequest( ...@@ -188,6 +189,10 @@ export function isAllowedUwuLinkRequest(
return Boolean(findAllowedTokenRecipient(request, allowlist)) return Boolean(findAllowedTokenRecipient(request, allowlist))
} }
if (request.method === EthMethod.PersonalSign) {
return true
}
// generic transactions // generic transactions
const { to, value } = request.value const { to, value } = request.value
const belowMaximumValue = const belowMaximumValue =
......
...@@ -5,7 +5,8 @@ import { openModal } from 'src/features/modals/modalSlice' ...@@ -5,7 +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 { Flex, HapticFeedback, Icons, ImpactFeedbackStyle, Text, TouchableArea } from 'ui/src' import { Flex, HapticFeedback, ImpactFeedbackStyle, Text, TouchableArea } from 'ui/src'
import { CopyAlt, Settings } from 'ui/src/components/icons'
import { isDevEnv } from 'uniswap/src/utils/env' 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'
...@@ -106,7 +107,7 @@ export function AccountHeader(): JSX.Element { ...@@ -106,7 +107,7 @@ export function AccountHeader(): JSX.Element {
hitSlop={20} hitSlop={20}
testID="account-header/settings-button" testID="account-header/settings-button"
onPress={onPressSettings}> onPress={onPressSettings}>
<Icons.Settings color="$neutral2" opacity={0.8} size="$icon.24" /> <Settings color="$neutral2" opacity={0.8} size="$icon.24" />
</TouchableArea> </TouchableArea>
</Flex> </Flex>
{walletHasName ? ( {walletHasName ? (
...@@ -138,7 +139,7 @@ export function AccountHeader(): JSX.Element { ...@@ -138,7 +139,7 @@ export function AccountHeader(): JSX.Element {
variant="subheading2"> variant="subheading2">
{sanitizeAddressText(shortenAddress(activeAddress))} {sanitizeAddressText(shortenAddress(activeAddress))}
</Text> </Text>
<Icons.CopyAlt color="$neutral1" size="$icon.16" /> <CopyAlt color="$neutral1" size="$icon.16" />
</Flex> </Flex>
</TouchableArea> </TouchableArea>
)} )}
......
import React from 'react' import React from 'react'
import { ColorTokens, IconProps, Icons, TouchableArea, TouchableAreaProps } from 'ui/src' import { ColorTokens, IconProps, TouchableArea, TouchableAreaProps } from 'ui/src'
import { X } from 'ui/src/components/icons'
type Props = { type Props = {
onPress: () => void onPress: () => void
...@@ -11,7 +12,7 @@ type Props = { ...@@ -11,7 +12,7 @@ type Props = {
export function CloseButton({ onPress, size, strokeWidth, color, ...rest }: Props): JSX.Element { export function CloseButton({ onPress, size, strokeWidth, color, ...rest }: Props): JSX.Element {
return ( return (
<TouchableArea onPress={onPress} {...rest} testID="buttons/close-button"> <TouchableArea onPress={onPress} {...rest} testID="buttons/close-button">
<Icons.X color={color} size={size ?? '$icon.20'} strokeWidth={strokeWidth ?? 2} /> <X color={color} size={size ?? '$icon.20'} strokeWidth={strokeWidth ?? 2} />
</TouchableArea> </TouchableArea>
) )
} }
import { default as React } from 'react' import { default as React } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Flex, Icons, Text, TouchableArea } from 'ui/src' import { Flex, Text, TouchableArea } from 'ui/src'
import { TripleDots } from 'ui/src/components/icons'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
export function FavoriteHeaderRow({ export function FavoriteHeaderRow({
...@@ -32,7 +33,7 @@ export function FavoriteHeaderRow({ ...@@ -32,7 +33,7 @@ export function FavoriteHeaderRow({
hitSlop={16} hitSlop={16}
testID="favorite-header-row/favorite-button" testID="favorite-header-row/favorite-button"
onPress={onPress}> onPress={onPress}>
<Icons.TripleDots <TripleDots
color="$neutral2" color="$neutral2"
size={iconSizes.icon20} size={iconSizes.icon20}
strokeLinecap="round" strokeLinecap="round"
......
...@@ -9,7 +9,8 @@ import { ...@@ -9,7 +9,8 @@ import {
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 { disableOnPress } from 'src/utils/disableOnPress' import { disableOnPress } from 'src/utils/disableOnPress'
import { Flex, Icons, Text, TouchableArea, useIsDarkMode } from 'ui/src' import { Flex, Text, TouchableArea, useIsDarkMode } from 'ui/src'
import { RotatableChevron } from 'ui/src/components/icons'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { TokenSortableField } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { TokenSortableField } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks'
import { logger } from 'utilities/src/logger/logger' import { logger } from 'utilities/src/logger/logger'
...@@ -86,7 +87,7 @@ function _SortButton({ orderBy }: FilterGroupProps): JSX.Element { ...@@ -86,7 +87,7 @@ function _SortButton({ orderBy }: FilterGroupProps): JSX.Element {
<Text ellipse color="$neutral2" flexShrink={1} numberOfLines={1} variant="buttonLabel3"> <Text ellipse color="$neutral2" flexShrink={1} numberOfLines={1} variant="buttonLabel3">
{getTokensOrderBySelectedLabel(orderBy, t)} {getTokensOrderBySelectedLabel(orderBy, t)}
</Text> </Text>
<Icons.RotatableChevron <RotatableChevron
color="$neutral2" color="$neutral2"
direction="down" direction="down"
height={iconSizes.icon20} height={iconSizes.icon20}
......
...@@ -7,14 +7,15 @@ import { SearchPopularNFTCollections } from 'src/components/explore/search/Searc ...@@ -7,14 +7,15 @@ import { SearchPopularNFTCollections } from 'src/components/explore/search/Searc
import { SearchPopularTokens } from 'src/components/explore/search/SearchPopularTokens' import { SearchPopularTokens } from 'src/components/explore/search/SearchPopularTokens'
import { renderSearchItem } from 'src/components/explore/search/SearchResultsSection' import { renderSearchItem } from 'src/components/explore/search/SearchResultsSection'
import { SectionHeaderText } from 'src/components/explore/search/SearchSectionHeader' import { SectionHeaderText } from 'src/components/explore/search/SearchSectionHeader'
import { AnimatedFlex, Flex, Icons, Text, TouchableArea, useSporeColors } from 'ui/src' import { AnimatedFlex, Flex, 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 { TrendUp } from 'ui/src/components/icons'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { clearSearchHistory } from 'wallet/src/features/search/searchHistorySlice' import { clearSearchHistory } from 'wallet/src/features/search/searchHistorySlice'
import { SearchResultType, WalletSearchResult } from 'wallet/src/features/search/SearchResult' import { 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 = <TrendUp color="$neutral2" size="$icon.24" />
export const SUGGESTED_WALLETS: WalletSearchResult[] = [ export const SUGGESTED_WALLETS: WalletSearchResult[] = [
{ {
......
...@@ -2,7 +2,8 @@ import React from 'react' ...@@ -2,7 +2,8 @@ import React from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { FadeIn, FadeOut } from 'react-native-reanimated' import { FadeIn, FadeOut } from 'react-native-reanimated'
import { SectionHeaderText } from 'src/components/explore/search/SearchSectionHeader' import { SectionHeaderText } from 'src/components/explore/search/SearchSectionHeader'
import { AnimatedFlex, Flex, Icons, Loader } from 'ui/src' import { AnimatedFlex, Flex, Loader } from 'ui/src'
import { Coin, Gallery, Person } from 'ui/src/components/icons'
export const SearchResultsLoader = (): JSX.Element => { export const SearchResultsLoader = (): JSX.Element => {
const { t } = useTranslation() const { t } = useTranslation()
...@@ -10,7 +11,7 @@ export const SearchResultsLoader = (): JSX.Element => { ...@@ -10,7 +11,7 @@ export const SearchResultsLoader = (): JSX.Element => {
<Flex gap="$spacing16"> <Flex gap="$spacing16">
<Flex gap="$spacing12"> <Flex gap="$spacing12">
<SectionHeaderText <SectionHeaderText
icon={<Icons.Coin color="$neutral2" size="$icon.24" />} icon={<Coin color="$neutral2" size="$icon.24" />}
title={t('explore.search.section.tokens')} title={t('explore.search.section.tokens')}
/> />
<AnimatedFlex entering={FadeIn} exiting={FadeOut} mx="$spacing8"> <AnimatedFlex entering={FadeIn} exiting={FadeOut} mx="$spacing8">
...@@ -19,7 +20,7 @@ export const SearchResultsLoader = (): JSX.Element => { ...@@ -19,7 +20,7 @@ export const SearchResultsLoader = (): JSX.Element => {
</Flex> </Flex>
<Flex gap="$spacing12"> <Flex gap="$spacing12">
<SectionHeaderText <SectionHeaderText
icon={<Icons.Gallery color="$neutral2" size="$icon.24" />} icon={<Gallery color="$neutral2" size="$icon.24" />}
title={t('explore.search.section.nft')} title={t('explore.search.section.nft')}
/> />
<AnimatedFlex entering={FadeIn} exiting={FadeOut} mx="$spacing8"> <AnimatedFlex entering={FadeIn} exiting={FadeOut} mx="$spacing8">
...@@ -28,7 +29,7 @@ export const SearchResultsLoader = (): JSX.Element => { ...@@ -28,7 +29,7 @@ export const SearchResultsLoader = (): JSX.Element => {
</Flex> </Flex>
<Flex gap="$spacing12"> <Flex gap="$spacing12">
<SectionHeaderText <SectionHeaderText
icon={<Icons.Person color="$neutral2" size="$icon.24" />} icon={<Person color="$neutral2" size="$icon.24" />}
title={t('explore.search.section.wallets')} title={t('explore.search.section.wallets')}
/> />
<AnimatedFlex entering={FadeIn} exiting={FadeOut} mx="$spacing8"> <AnimatedFlex entering={FadeIn} exiting={FadeOut} mx="$spacing8">
......
...@@ -16,7 +16,8 @@ import { ...@@ -16,7 +16,8 @@ import {
formatTokenSearchResults, formatTokenSearchResults,
getSearchResultId, getSearchResultId,
} from 'src/components/explore/search/utils' } from 'src/components/explore/search/utils'
import { AnimatedFlex, Flex, Icons, Text } from 'ui/src' import { AnimatedFlex, Flex, Text } from 'ui/src'
import { Coin, Gallery, Person } from 'ui/src/components/icons'
import { useExploreSearchQuery } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { useExploreSearchQuery } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks'
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'
...@@ -36,17 +37,17 @@ const ICON_SIZE = '$icon.24' ...@@ -36,17 +37,17 @@ const ICON_SIZE = '$icon.24'
const ICON_COLOR = '$neutral2' const ICON_COLOR = '$neutral2'
const WalletHeaderItem: SearchResultOrHeader = { const WalletHeaderItem: SearchResultOrHeader = {
icon: <Icons.Person color={ICON_COLOR} size={ICON_SIZE} />, icon: <Person color={ICON_COLOR} size={ICON_SIZE} />,
type: SEARCH_RESULT_HEADER_KEY, type: SEARCH_RESULT_HEADER_KEY,
title: i18n.t('explore.search.section.wallets'), title: i18n.t('explore.search.section.wallets'),
} }
const TokenHeaderItem: SearchResultOrHeader = { const TokenHeaderItem: SearchResultOrHeader = {
icon: <Icons.Coin color={ICON_COLOR} size={ICON_SIZE} />, icon: <Coin color={ICON_COLOR} size={ICON_SIZE} />,
type: SEARCH_RESULT_HEADER_KEY, type: SEARCH_RESULT_HEADER_KEY,
title: i18n.t('explore.search.section.tokens'), title: i18n.t('explore.search.section.tokens'),
} }
const NFTHeaderItem: SearchResultOrHeader = { const NFTHeaderItem: SearchResultOrHeader = {
icon: <Icons.Gallery color={ICON_COLOR} size={ICON_SIZE} />, icon: <Gallery color={ICON_COLOR} size={ICON_SIZE} />,
type: SEARCH_RESULT_HEADER_KEY, type: SEARCH_RESULT_HEADER_KEY,
title: i18n.t('explore.search.section.nft'), title: i18n.t('explore.search.section.nft'),
} }
......
...@@ -4,7 +4,8 @@ import { useAppStackNavigation } from 'src/app/navigation/types' ...@@ -4,7 +4,8 @@ import { useAppStackNavigation } from 'src/app/navigation/types'
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 { Flex, Icons, ImpactFeedbackStyle, Text, TouchableArea } from 'ui/src' import { Flex, ImpactFeedbackStyle, Text, TouchableArea } from 'ui/src'
import { Verified } from 'ui/src/components/icons'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { NFTViewer } from 'wallet/src/features/images/NFTViewer' import { NFTViewer } from 'wallet/src/features/images/NFTViewer'
import { SearchContext } from 'wallet/src/features/search/SearchContext' import { SearchContext } from 'wallet/src/features/search/SearchContext'
...@@ -94,7 +95,7 @@ export function SearchNFTCollectionItem({ ...@@ -94,7 +95,7 @@ export function SearchNFTCollectionItem({
</Text> </Text>
</Flex> </Flex>
<Flex grow alignItems="flex-start" width="$spacing36"> <Flex grow alignItems="flex-start" width="$spacing36">
{isVerified ? <Icons.Verified color="$accent1" size="$icon.16" /> : null} {isVerified ? <Verified color="$accent1" size="$icon.16" /> : null}
</Flex> </Flex>
</Flex> </Flex>
</TouchableArea> </TouchableArea>
......
import React from 'react' import React from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Button, Icons } from 'ui/src' import { Button } from 'ui/src'
import { InfoCircleFilled } from 'ui/src/components/icons'
import { SpinningLoader } from 'wallet/src/components/loading/SpinningLoader' import { SpinningLoader } from 'wallet/src/components/loading/SpinningLoader'
interface FiatOnRampCtaButtonProps { interface FiatOnRampCtaButtonProps {
...@@ -31,7 +32,7 @@ export function FiatOnRampCtaButton({ ...@@ -31,7 +32,7 @@ export function FiatOnRampCtaButton({
isLoading ? ( isLoading ? (
<SpinningLoader color="$sporeWhite" /> <SpinningLoader color="$sporeWhite" />
) : !eligible ? ( ) : !eligible ? (
<Icons.InfoCircleFilled color="$neutral3" /> <InfoCircleFilled color="$neutral3" />
) : undefined ) : undefined
} }
size="large" size="large"
......
...@@ -9,7 +9,8 @@ import { TAB_BAR_HEIGHT, TabProps } from 'src/components/layout/TabHelpers' ...@@ -9,7 +9,8 @@ import { TAB_BAR_HEIGHT, TabProps } from 'src/components/layout/TabHelpers'
import { Loader } from 'src/components/loading' import { Loader } from 'src/components/loading'
import { openModal } from 'src/features/modals/modalSlice' import { openModal } from 'src/features/modals/modalSlice'
import { removePendingSession } from 'src/features/walletConnect/walletConnectSlice' import { removePendingSession } from 'src/features/walletConnect/walletConnectSlice'
import { Flex, Icons, Text, useDeviceInsets, useSporeColors } from 'ui/src' import { Flex, Text, useDeviceInsets, useSporeColors } from 'ui/src'
import { NoTransactions } from 'ui/src/components/icons'
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 { BaseCard } from 'wallet/src/components/BaseCard/BaseCard' import { BaseCard } from 'wallet/src/components/BaseCard/BaseCard'
...@@ -86,7 +87,7 @@ export const FeedTab = memo( ...@@ -86,7 +87,7 @@ export const FeedTab = memo(
<Flex grow style={containerProps?.emptyContainerStyle}> <Flex grow style={containerProps?.emptyContainerStyle}>
<BaseCard.EmptyState <BaseCard.EmptyState
description={t('home.feed.empty.description')} description={t('home.feed.empty.description')}
icon={<Icons.NoTransactions color="$neutral3" size="$icon.70" />} icon={<NoTransactions color="$neutral3" size="$icon.70" />}
title={t('home.feed.empty.title')} title={t('home.feed.empty.title')}
onPress={onPressReceive} onPress={onPressReceive}
/> />
......
...@@ -9,7 +9,8 @@ import { WalletEmptyState } from 'src/components/home/WalletEmptyState' ...@@ -9,7 +9,8 @@ import { WalletEmptyState } from 'src/components/home/WalletEmptyState'
import { TabContentProps, TabProps } from 'src/components/layout/TabHelpers' import { TabContentProps, TabProps } from 'src/components/layout/TabHelpers'
import { openModal } from 'src/features/modals/modalSlice' import { openModal } from 'src/features/modals/modalSlice'
import { Screens } from 'src/screens/Screens' import { Screens } from 'src/screens/Screens'
import { Flex, Icons } from 'ui/src' import { Flex } from 'ui/src'
import { NoTokens } from 'ui/src/components/icons'
import { GQLQueries } from 'uniswap/src/data/graphql/uniswap-data-api/queries' import { GQLQueries } from 'uniswap/src/data/graphql/uniswap-data-api/queries'
import { CurrencyId } from 'uniswap/src/types/currency' import { CurrencyId } from 'uniswap/src/types/currency'
import { BaseCard } from 'wallet/src/components/BaseCard/BaseCard' import { BaseCard } from 'wallet/src/components/BaseCard/BaseCard'
...@@ -71,7 +72,7 @@ export const TokensTab = memo( ...@@ -71,7 +72,7 @@ export const TokensTab = memo(
return isExternalProfile ? ( return isExternalProfile ? (
<BaseCard.EmptyState <BaseCard.EmptyState
description={t('home.tokens.empty.description')} description={t('home.tokens.empty.description')}
icon={<Icons.NoTokens color="$neutral3" size="$icon.70" />} icon={<NoTokens color="$neutral3" size="$icon.70" />}
title={t('home.tokens.empty.title')} title={t('home.tokens.empty.title')}
onPress={onPressAction} onPress={onPressAction}
/> />
......
import { useDeviceSupportsBiometricAuth } from 'src/features/biometrics/hooks' import { useDeviceSupportsBiometricAuth } from 'src/features/biometrics/hooks'
import { Icons } from 'ui/src' import { Faceid, Fingerprint } from 'ui/src/components/icons'
export function BiometricsIcon(): JSX.Element | null { export function BiometricsIcon(): JSX.Element | null {
const { touchId: isTouchIdSupported, faceId: isFaceIdSupported } = const { touchId: isTouchIdSupported, faceId: isFaceIdSupported } =
useDeviceSupportsBiometricAuth() useDeviceSupportsBiometricAuth()
if (isTouchIdSupported) { if (isTouchIdSupported) {
return <Icons.Fingerprint color="white" size="$icon.20" /> return <Fingerprint color="white" size="$icon.20" />
} }
if (isFaceIdSupported) { if (isFaceIdSupported) {
return <Icons.Faceid color="white" size="$icon.20" /> return <Faceid color="white" size="$icon.20" />
} }
return null return null
......
import React from 'react' import React from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { ColorTokens, Flex, Icons, Text } from 'ui/src' import { ColorTokens, Flex, Text } from 'ui/src'
import { RotatableChevron } from 'ui/src/components/icons'
type Props = { type Props = {
size?: number size?: number
...@@ -13,7 +14,7 @@ export function BackButtonView({ size, color, showButtonLabel }: Props): JSX.Ele ...@@ -13,7 +14,7 @@ export function BackButtonView({ size, color, showButtonLabel }: Props): JSX.Ele
return ( return (
<Flex row alignItems="center" gap="$spacing8"> <Flex row alignItems="center" gap="$spacing8">
<Icons.RotatableChevron color={color ?? '$neutral2'} height={size} width={size} /> <RotatableChevron color={color ?? '$neutral2'} height={size} width={size} />
{showButtonLabel && ( {showButtonLabel && (
<Text color="$neutral2" variant="subheading1"> <Text color="$neutral2" variant="subheading1">
{t('common.button.back')} {t('common.button.back')}
......
...@@ -3,7 +3,8 @@ import { useEffect, useState } from 'react' ...@@ -3,7 +3,8 @@ import { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { ActivityIndicator, EmitterSubscription, Keyboard } from 'react-native' import { ActivityIndicator, EmitterSubscription, Keyboard } from 'react-native'
import { getUniqueId } from 'react-native-device-info' import { getUniqueId } from 'react-native-device-info'
import { Button, Flex, Icons, Text, useSporeColors } from 'ui/src' import { Button, Flex, Text, useSporeColors } from 'ui/src'
import { AlertTriangle } from 'ui/src/components/icons'
import { fonts, spacing } from 'ui/src/theme' import { fonts, spacing } from 'ui/src/theme'
import { useUnitagUpdater } from 'uniswap/src/features/unitags/context' import { useUnitagUpdater } from 'uniswap/src/features/unitags/context'
import { UnitagErrorCodes } from 'uniswap/src/features/unitags/types' import { UnitagErrorCodes } from 'uniswap/src/features/unitags/types'
...@@ -311,7 +312,7 @@ function ChangeUnitagConfirmModal({ ...@@ -311,7 +312,7 @@ function ChangeUnitagConfirmModal({
height="$spacing48" height="$spacing48"
mb="$spacing8" mb="$spacing8"
minWidth="$spacing48"> minWidth="$spacing48">
<Icons.AlertTriangle color="$statusCritical" size="$icon.24" /> <AlertTriangle color="$statusCritical" size="$icon.24" />
</Flex> </Flex>
<Text textAlign="center" variant="subheading1"> <Text textAlign="center" variant="subheading1">
{t('unitags.editUsername.confirm.title')} {t('unitags.editUsername.confirm.title')}
......
...@@ -2,7 +2,8 @@ import React, { useState } from 'react' ...@@ -2,7 +2,8 @@ import React, { useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { selectPhotoFromLibrary } from 'src/components/unitags/AvatarSelection' import { selectPhotoFromLibrary } from 'src/components/unitags/AvatarSelection'
import { ChooseNftModal } from 'src/components/unitags/ChooseNftModal' import { ChooseNftModal } from 'src/components/unitags/ChooseNftModal'
import { Flex, Icons, Text, useSporeColors } from 'ui/src' import { Flex, Text, useSporeColors } from 'ui/src'
import { Camera, Photo, Trash } from 'ui/src/components/icons'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal' import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal'
import { ElementName, ModalName } from 'wallet/src/telemetry/constants' import { ElementName, ModalName } from 'wallet/src/telemetry/constants'
...@@ -115,13 +116,11 @@ const ChoosePhotoOption = ({ type }: { type: PhotoAction }): JSX.Element => { ...@@ -115,13 +116,11 @@ const ChoosePhotoOption = ({ type }: { type: PhotoAction }): JSX.Element => {
justifyContent="flex-start" justifyContent="flex-start"
p="$spacing24"> p="$spacing24">
{type === PhotoAction.BrowseCameraRoll && ( {type === PhotoAction.BrowseCameraRoll && (
<Icons.Camera color="$neutral1" size={iconSizes.icon24} /> <Camera color="$neutral1" size={iconSizes.icon24} />
)}
{type === PhotoAction.BrowseNftsList && (
<Icons.Photo color="$neutral1" size={iconSizes.icon24} />
)} )}
{type === PhotoAction.BrowseNftsList && <Photo color="$neutral1" size={iconSizes.icon24} />}
{type === PhotoAction.RemovePhoto && ( {type === PhotoAction.RemovePhoto && (
<Icons.Trash color="$statusCritical" size={iconSizes.icon24} /> <Trash color="$statusCritical" size={iconSizes.icon24} />
)} )}
<Flex shrink alignItems="flex-start"> <Flex shrink alignItems="flex-start">
<Text <Text
......
...@@ -2,7 +2,8 @@ import { useNavigation } from '@react-navigation/native' ...@@ -2,7 +2,8 @@ import { useNavigation } from '@react-navigation/native'
import { useState } from 'react' import { useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { ActivityIndicator } from 'react-native' import { ActivityIndicator } from 'react-native'
import { Button, Flex, Icons, Text, useSporeColors } from 'ui/src' import { Button, Flex, Text, useSporeColors } from 'ui/src'
import { AlertTriangle } from 'ui/src/components/icons'
import { fonts } from 'ui/src/theme' import { fonts } from 'ui/src/theme'
import { useUnitagUpdater } from 'uniswap/src/features/unitags/context' import { useUnitagUpdater } from 'uniswap/src/features/unitags/context'
import { logger } from 'utilities/src/logger/logger' import { logger } from 'utilities/src/logger/logger'
...@@ -90,7 +91,7 @@ export function DeleteUnitagModal({ ...@@ -90,7 +91,7 @@ export function DeleteUnitagModal({
height="$spacing48" height="$spacing48"
mb="$spacing8" mb="$spacing8"
minWidth="$spacing48"> minWidth="$spacing48">
<Icons.AlertTriangle color="$statusCritical" size="$icon.24" /> <AlertTriangle color="$statusCritical" size="$icon.24" />
</Flex> </Flex>
<Text textAlign="center" variant="subheading1"> <Text textAlign="center" variant="subheading1">
{t('unitags.delete.confirm.title')} {t('unitags.delete.confirm.title')}
......
...@@ -8,8 +8,9 @@ import { closeModal } from 'src/features/modals/modalSlice' ...@@ -8,8 +8,9 @@ import { closeModal } from 'src/features/modals/modalSlice'
import { selectModalState } from 'src/features/modals/selectModalState' import { selectModalState } from 'src/features/modals/selectModalState'
import { TermsOfService } from 'src/screens/Onboarding/TermsOfService' import { TermsOfService } from 'src/screens/Onboarding/TermsOfService'
import { Screens, UnitagScreens } from 'src/screens/Screens' import { Screens, UnitagScreens } from 'src/screens/Screens'
import { Button, Flex, GeneratedIcon, Icons, Image, Text, useIsDarkMode } from 'ui/src' import { Button, Flex, GeneratedIcon, Image, Text, useIsDarkMode } from 'ui/src'
import { UNITAGS_INTRO_BANNER_DARK, UNITAGS_INTRO_BANNER_LIGHT } from 'ui/src/assets' import { UNITAGS_INTRO_BANNER_DARK, UNITAGS_INTRO_BANNER_LIGHT } from 'ui/src/assets'
import { Lightning, Ticket, UserSquare } from 'ui/src/components/icons'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal' import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal'
import { setHasCompletedUnitagsIntroModal } from 'wallet/src/features/behaviorHistory/slice' import { setHasCompletedUnitagsIntroModal } from 'wallet/src/features/behaviorHistory/slice'
...@@ -64,9 +65,9 @@ export function UnitagsIntroModal(): JSX.Element { ...@@ -64,9 +65,9 @@ export function UnitagsIntroModal(): JSX.Element {
/> />
</Flex> </Flex>
<Flex gap="$spacing16" px="$spacing20"> <Flex gap="$spacing16" px="$spacing20">
<BodyItem Icon={Icons.UserSquare} title={t('unitags.intro.features.profile')} /> <BodyItem Icon={UserSquare} title={t('unitags.intro.features.profile')} />
<BodyItem Icon={Icons.Ticket} title={t('unitags.intro.features.free')} /> <BodyItem Icon={Ticket} title={t('unitags.intro.features.free')} />
<BodyItem Icon={Icons.Lightning} title={t('unitags.intro.features.ens')} /> <BodyItem Icon={Lightning} title={t('unitags.intro.features.ens')} />
</Flex> </Flex>
<Flex gap="$spacing8"> <Flex gap="$spacing8">
<Button size="medium" theme="primary" onPress={onPressClaimOneNow}> <Button size="medium" theme="primary" onPress={onPressClaimOneNow}>
......
...@@ -3,7 +3,8 @@ import { useTranslation } from 'react-i18next' ...@@ -3,7 +3,8 @@ import { useTranslation } from 'react-i18next'
import { Keyboard, TextInput } from 'react-native' import { Keyboard, TextInput } from 'react-native'
import { PasswordInput } from 'src/components/input/PasswordInput' import { PasswordInput } from 'src/components/input/PasswordInput'
import { PasswordError } from 'src/features/onboarding/PasswordError' import { PasswordError } from 'src/features/onboarding/PasswordError'
import { Button, Flex, Icons, Text } from 'ui/src' import { Button, Flex, Text } from 'ui/src'
import { DiamondExclamation } from 'ui/src/components/icons'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { useDebounce } from 'utilities/src/time/timing' import { useDebounce } from 'utilities/src/time/timing'
import { ElementName } from 'wallet/src/telemetry/constants' import { ElementName } from 'wallet/src/telemetry/constants'
...@@ -118,7 +119,7 @@ export function CloudBackupPasswordForm({ ...@@ -118,7 +119,7 @@ export function CloudBackupPasswordForm({
</Flex> </Flex>
{!isConfirmation && ( {!isConfirmation && (
<Flex centered row gap="$spacing12" px="$spacing16"> <Flex centered row gap="$spacing12" px="$spacing16">
<Icons.DiamondExclamation color="$neutral2" size={iconSizes.icon20} /> <DiamondExclamation color="$neutral2" size={iconSizes.icon20} />
<Text color="$neutral2" variant="body3"> <Text color="$neutral2" variant="body3">
{t('settings.setting.backup.password.disclaimer')} {t('settings.setting.backup.password.disclaimer')}
</Text> </Text>
......
...@@ -13,7 +13,6 @@ import { openModal } from 'src/features/modals/modalSlice' ...@@ -13,7 +13,6 @@ import { openModal } from 'src/features/modals/modalSlice'
import { import {
AnimatedFlex, AnimatedFlex,
Flex, Flex,
Icons,
Image, Image,
LinearGradient, LinearGradient,
ScrollView, ScrollView,
...@@ -26,6 +25,7 @@ import { ...@@ -26,6 +25,7 @@ import {
useUniconColors, useUniconColors,
} from 'ui/src' } from 'ui/src'
import { ENS_LOGO } from 'ui/src/assets' import { ENS_LOGO } from 'ui/src/assets'
import { SendAction, XTwitter } from 'ui/src/components/icons'
import { iconSizes, imageSizes } from 'ui/src/theme' import { iconSizes, imageSizes } from 'ui/src/theme'
import { FeatureFlags } from 'uniswap/src/features/gating/flags' import { FeatureFlags } from 'uniswap/src/features/gating/flags'
import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks'
...@@ -221,7 +221,7 @@ export const ProfileHeader = memo(function ProfileHeader({ ...@@ -221,7 +221,7 @@ export const ProfileHeader = memo(function ProfileHeader({
{twitter ? ( {twitter ? (
<TouchableArea onPress={onPressTwitter}> <TouchableArea onPress={onPressTwitter}>
<Flex centered row gap="$spacing4"> <Flex centered row gap="$spacing4">
<Icons.XTwitter color={colors.neutral1.val} size={iconSizes.icon16} /> <XTwitter color={colors.neutral1.val} size={iconSizes.icon16} />
<Text color="$neutral1" variant="buttonLabel3"> <Text color="$neutral1" variant="buttonLabel3">
{twitter} {twitter}
</Text> </Text>
...@@ -277,7 +277,7 @@ export const ProfileHeader = memo(function ProfileHeader({ ...@@ -277,7 +277,7 @@ export const ProfileHeader = memo(function ProfileHeader({
testID={ElementName.Send} testID={ElementName.Send}
onPress={onPressSend}> onPress={onPressSend}>
<Flex row alignItems="center" gap="$spacing8"> <Flex row alignItems="center" gap="$spacing8">
<Icons.SendAction color="$neutral2" size="$icon.20" /> <SendAction color="$neutral2" size="$icon.20" />
<Text <Text
allowFontScaling={true} allowFontScaling={true}
color="$neutral2" color="$neutral2"
......
...@@ -16,11 +16,11 @@ import { ...@@ -16,11 +16,11 @@ import {
ColorTokens, ColorTokens,
Flex, Flex,
HapticFeedback, HapticFeedback,
Icons,
Text, Text,
TouchableArea, TouchableArea,
useSporeColors, useSporeColors,
} from 'ui/src' } from 'ui/src'
import { RotatableChevron } from 'ui/src/components/icons'
import { fonts, iconSizes, spacing } from 'ui/src/theme' import { fonts, iconSizes, spacing } from 'ui/src/theme'
import { CurrencyInfo } from 'uniswap/src/features/dataApi/types' import { CurrencyInfo } from 'uniswap/src/features/dataApi/types'
import { NumberType } from 'utilities/src/format/types' import { NumberType } from 'utilities/src/format/types'
...@@ -275,7 +275,7 @@ function SelectTokenButton({ ...@@ -275,7 +275,7 @@ function SelectTokenButton({
<Text color={textColor} pl="$spacing1" variant="body1"> <Text color={textColor} pl="$spacing1" variant="body1">
{getSymbolDisplayText(selectedCurrencyInfo.currency.symbol)} {getSymbolDisplayText(selectedCurrencyInfo.currency.symbol)}
</Text> </Text>
<Icons.RotatableChevron color={textColor} direction="end" height={iconSizes.icon16} /> <RotatableChevron color={textColor} direction="end" height={iconSizes.icon16} />
</Flex> </Flex>
</TouchableArea> </TouchableArea>
) )
......
import React from 'react' import React from 'react'
import { SvgUri } from 'react-native-svg' import { SvgUri } from 'react-native-svg'
import Trace from 'src/components/Trace/Trace' import Trace from 'src/components/Trace/Trace'
import { Flex, Icons, TouchableArea } from 'ui/src' import { Flex, TouchableArea } from 'ui/src'
import { RotatableChevron } from 'ui/src/components/icons'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { getCountryFlagSvgUrl } from 'wallet/src/features/fiatOnRamp/utils' import { getCountryFlagSvgUrl } from 'wallet/src/features/fiatOnRamp/utils'
import { ElementName } from 'wallet/src/telemetry/constants' import { ElementName } from 'wallet/src/telemetry/constants'
...@@ -36,7 +37,7 @@ export function FiatOnRampCountryPicker({ ...@@ -36,7 +37,7 @@ export function FiatOnRampCountryPicker({
<Flex borderRadius="$roundedFull" overflow="hidden"> <Flex borderRadius="$roundedFull" overflow="hidden">
<SvgUri height={ICON_SIZE} uri={countryFlagUrl} width={ICON_SIZE} /> <SvgUri height={ICON_SIZE} uri={countryFlagUrl} width={ICON_SIZE} />
</Flex> </Flex>
<Icons.RotatableChevron color="$neutral3" direction="down" width={iconSizes.icon20} /> <RotatableChevron color="$neutral3" direction="down" width={iconSizes.icon20} />
</Flex> </Flex>
</TouchableArea> </TouchableArea>
</Trace> </Trace>
......
...@@ -2,8 +2,9 @@ import { default as React } from 'react' ...@@ -2,8 +2,9 @@ import { default as React } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Loader } from 'src/components/loading' import { Loader } from 'src/components/loading'
import { PriceAmount } from 'src/features/nfts/collection/ListPriceCard' import { PriceAmount } from 'src/features/nfts/collection/ListPriceCard'
import { Flex, Icons, Text, TouchableArea, useSporeColors } from 'ui/src' import { Flex, Text, TouchableArea, useSporeColors } from 'ui/src'
import VerifiedIcon from 'ui/src/assets/icons/verified.svg' import VerifiedIcon from 'ui/src/assets/icons/verified.svg'
import { RotatableChevron } from 'ui/src/components/icons'
import { iconSizes, imageSizes, spacing } from 'ui/src/theme' import { iconSizes, imageSizes, spacing } from 'ui/src/theme'
import { import {
Currency, Currency,
...@@ -94,7 +95,7 @@ export function CollectionPreviewCard({ ...@@ -94,7 +95,7 @@ export function CollectionPreviewCard({
</Flex> </Flex>
</Flex> </Flex>
{isViewableCollection ? ( {isViewableCollection ? (
<Icons.RotatableChevron <RotatableChevron
color="$neutral1" color="$neutral1"
direction="end" direction="end"
height={iconSizes.icon24} height={iconSizes.icon24}
......
import React from 'react' import React from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Flex, Icons } from 'ui/src' import { Flex } from 'ui/src'
import { Check, Laptop } from 'ui/src/components/icons'
import { NotificationToast } from 'wallet/src/features/notifications/components/NotificationToast' import { NotificationToast } from 'wallet/src/features/notifications/components/NotificationToast'
import { ScantasticCompleteNotification as ScantasticCompleteNotificationType } from 'wallet/src/features/notifications/types' import { ScantasticCompleteNotification as ScantasticCompleteNotificationType } from 'wallet/src/features/notifications/types'
...@@ -16,7 +17,7 @@ export function ScantasticCompleteNotification({ ...@@ -16,7 +17,7 @@ export function ScantasticCompleteNotification({
icon={ icon={
<Flex position="relative"> <Flex position="relative">
<Flex backgroundColor="$accent2" borderRadius="$roundedFull" p="$spacing12"> <Flex backgroundColor="$accent2" borderRadius="$roundedFull" p="$spacing12">
<Icons.Laptop color="$accent1" size="$icon.24" /> <Laptop color="$accent1" size="$icon.24" />
</Flex> </Flex>
<Flex <Flex
backgroundColor="$statusSuccess" backgroundColor="$statusSuccess"
...@@ -27,7 +28,7 @@ export function ScantasticCompleteNotification({ ...@@ -27,7 +28,7 @@ export function ScantasticCompleteNotification({
p="$spacing4" p="$spacing4"
position="absolute" position="absolute"
right={0}> right={0}>
<Icons.Check color="$white" size="$icon.8" /> <Check color="$white" size="$icon.8" />
</Flex> </Flex>
</Flex> </Flex>
} }
......
...@@ -2,7 +2,8 @@ import { useTranslation } from 'react-i18next' ...@@ -2,7 +2,8 @@ import { useTranslation } from 'react-i18next'
import { useAppSelector } from 'src/app/hooks' import { useAppSelector } from 'src/app/hooks'
import { closeModal } from 'src/features/modals/modalSlice' import { closeModal } from 'src/features/modals/modalSlice'
import { selectModalState } from 'src/features/modals/selectModalState' import { selectModalState } from 'src/features/modals/selectModalState'
import { Button, Flex, Icons, Text, TouchableArea } from 'ui/src' import { Button, Flex, Text, TouchableArea } from 'ui/src'
import { AlertTriangle, DocumentList } from 'ui/src/components/icons'
import { uniswapUrls } from 'uniswap/src/constants/urls' import { uniswapUrls } from 'uniswap/src/constants/urls'
import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal' import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal'
import { useAppDispatch } from 'wallet/src/state' import { useAppDispatch } from 'wallet/src/state'
...@@ -32,9 +33,9 @@ export function ExtensionWaitlistModal(): JSX.Element { ...@@ -32,9 +33,9 @@ export function ExtensionWaitlistModal(): JSX.Element {
p="$spacing12" p="$spacing12"
width="$spacing48"> width="$spacing48">
{isUserOnWaitlist ? ( {isUserOnWaitlist ? (
<Icons.DocumentList color="$neutral2" size="$icon.28" /> <DocumentList color="$neutral2" size="$icon.28" />
) : ( ) : (
<Icons.AlertTriangle color="$neutral2" size="$icon.28" /> <AlertTriangle color="$neutral2" size="$icon.28" />
)} )}
</Flex> </Flex>
<Flex alignItems="center" gap="$spacing8"> <Flex alignItems="center" gap="$spacing8">
......
...@@ -4,7 +4,8 @@ import { useAppDispatch, useAppSelector } from 'src/app/hooks' ...@@ -4,7 +4,8 @@ import { useAppDispatch, useAppSelector } from 'src/app/hooks'
import { useBiometricAppSettings, useBiometricPrompt } from 'src/features/biometrics/hooks' import { useBiometricAppSettings, useBiometricPrompt } from 'src/features/biometrics/hooks'
import { closeAllModals } from 'src/features/modals/modalSlice' import { closeAllModals } from 'src/features/modals/modalSlice'
import { selectModalState } from 'src/features/modals/selectModalState' import { selectModalState } from 'src/features/modals/selectModalState'
import { Button, Flex, Icons, Text, TouchableArea, useSporeColors } from 'ui/src' import { Button, Flex, Text, TouchableArea, useSporeColors } from 'ui/src'
import { AlertTriangle, Faceid, Laptop, LinkBrokenHorizontal } from 'ui/src/components/icons'
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 { logger } from 'utilities/src/logger/logger' import { logger } from 'utilities/src/logger/logger'
...@@ -211,7 +212,7 @@ export function ScantasticModal(): JSX.Element | null { ...@@ -211,7 +212,7 @@ export function ScantasticModal(): JSX.Element | null {
} }
}, [OTP, uuid]) }, [OTP, uuid])
useInterval(checkOTPState, 6000, true) useInterval(checkOTPState, ONE_SECOND_MS, true)
if (expired) { if (expired) {
return ( return (
...@@ -221,7 +222,7 @@ export function ScantasticModal(): JSX.Element | null { ...@@ -221,7 +222,7 @@ export function ScantasticModal(): JSX.Element | null {
onClose={onClose}> onClose={onClose}>
<Flex centered gap="$spacing16" px="$spacing16" py="$spacing12"> <Flex centered gap="$spacing16" px="$spacing16" py="$spacing12">
<Flex centered backgroundColor="$surface2" borderRadius="$rounded12" p="$spacing12"> <Flex centered backgroundColor="$surface2" borderRadius="$rounded12" p="$spacing12">
<Icons.LinkBrokenHorizontal color="$neutral2" size={iconSizes.icon24} /> <LinkBrokenHorizontal color="$neutral2" size={iconSizes.icon24} />
</Flex> </Flex>
<Text variant="subheading1">{t('scantastic.error.timeout.title')}</Text> <Text variant="subheading1">{t('scantastic.error.timeout.title')}</Text>
<Text color="$neutral2" mb="$spacing12" textAlign="center" variant="body3"> <Text color="$neutral2" mb="$spacing12" textAlign="center" variant="body3">
...@@ -243,7 +244,7 @@ export function ScantasticModal(): JSX.Element | null { ...@@ -243,7 +244,7 @@ export function ScantasticModal(): JSX.Element | null {
onClose={onClose}> onClose={onClose}>
<Flex centered gap="$spacing16" px="$spacing16" py="$spacing12"> <Flex centered gap="$spacing16" px="$spacing16" py="$spacing12">
<Flex centered backgroundColor="$accent2" borderRadius="$rounded12" p="$spacing12"> <Flex centered backgroundColor="$accent2" borderRadius="$rounded12" p="$spacing12">
<Icons.Laptop color="$accent1" size={iconSizes.icon24} /> <Laptop color="$accent1" size={iconSizes.icon24} />
</Flex> </Flex>
<Text variant="subheading1">{t('scantastic.code.title')}</Text> <Text variant="subheading1">{t('scantastic.code.title')}</Text>
<Text color="$neutral2" textAlign="center" variant="body3"> <Text color="$neutral2" textAlign="center" variant="body3">
...@@ -269,7 +270,7 @@ export function ScantasticModal(): JSX.Element | null { ...@@ -269,7 +270,7 @@ export function ScantasticModal(): JSX.Element | null {
onClose={onClose}> onClose={onClose}>
<Flex centered gap="$spacing16" px="$spacing16" py="$spacing12"> <Flex centered gap="$spacing16" px="$spacing16" py="$spacing12">
<Flex centered backgroundColor="$accent2" borderRadius="$rounded12" p="$spacing12"> <Flex centered backgroundColor="$accent2" borderRadius="$rounded12" p="$spacing12">
<Icons.AlertTriangle color="$statusCritical" size={iconSizes.icon24} /> <AlertTriangle color="$statusCritical" size={iconSizes.icon24} />
</Flex> </Flex>
<Text variant="subheading1">{t('common.text.error')}</Text> <Text variant="subheading1">{t('common.text.error')}</Text>
<Text color="$neutral2" textAlign="center" variant="body3"> <Text color="$neutral2" textAlign="center" variant="body3">
...@@ -294,7 +295,7 @@ export function ScantasticModal(): JSX.Element | null { ...@@ -294,7 +295,7 @@ export function ScantasticModal(): JSX.Element | null {
onClose={onClose}> onClose={onClose}>
<Flex centered gap="$spacing16" px="$spacing16" py="$spacing12"> <Flex centered gap="$spacing16" px="$spacing16" py="$spacing12">
<Flex centered backgroundColor="$accent2" borderRadius="$rounded12" p="$spacing12"> <Flex centered backgroundColor="$accent2" borderRadius="$rounded12" p="$spacing12">
<Icons.Laptop color="$accent1" size={iconSizes.icon24} /> <Laptop color="$accent1" size={iconSizes.icon24} />
</Flex> </Flex>
<Text variant="subheading1">{t('scantastic.confirmation.title')}</Text> <Text variant="subheading1">{t('scantastic.confirmation.title')}</Text>
<Text color="$neutral2" textAlign="center" variant="body3"> <Text color="$neutral2" textAlign="center" variant="body3">
...@@ -334,14 +335,14 @@ export function ScantasticModal(): JSX.Element | null { ...@@ -334,14 +335,14 @@ export function ScantasticModal(): JSX.Element | null {
gap="$spacing8" gap="$spacing8"
p="$spacing16" p="$spacing16"
width="100%"> width="100%">
<Icons.AlertTriangle color="$neutral2" size="$icon.20" /> <AlertTriangle color="$neutral2" size="$icon.20" />
<Text color="$neutral2" variant="body4"> <Text color="$neutral2" variant="body4">
{t('scantastic.confirmation.warning')} {t('scantastic.confirmation.warning')}
</Text> </Text>
</Flex> </Flex>
<Flex flexDirection="column" gap="$spacing4" width="100%"> <Flex flexDirection="column" gap="$spacing4" width="100%">
<Button <Button
icon={requiresBiometricAuth ? <Icons.Faceid size={iconSizes.icon16} /> : undefined} icon={requiresBiometricAuth ? <Faceid size={iconSizes.icon16} /> : undefined}
mb="$spacing4" mb="$spacing4"
theme="primary" theme="primary"
onPress={onConfirmSync}> onPress={onConfirmSync}>
......
...@@ -9,7 +9,8 @@ import { UnitagProfilePicture } from 'src/components/unitags/UnitagProfilePictur ...@@ -9,7 +9,8 @@ import { UnitagProfilePicture } from 'src/components/unitags/UnitagProfilePictur
import { SafeKeyboardOnboardingScreen } from 'src/features/onboarding/SafeKeyboardOnboardingScreen' import { SafeKeyboardOnboardingScreen } from 'src/features/onboarding/SafeKeyboardOnboardingScreen'
import { UnitagName } from 'src/features/unitags/UnitagName' import { UnitagName } from 'src/features/unitags/UnitagName'
import { OnboardingScreens, Screens, UnitagScreens } from 'src/screens/Screens' import { OnboardingScreens, Screens, UnitagScreens } from 'src/screens/Screens'
import { Button, Flex, Icons, Text, useIsDarkMode, useSporeColors } from 'ui/src' import { Button, Flex, Text, useIsDarkMode, useSporeColors } from 'ui/src'
import { Pen } from 'ui/src/components/icons'
import { fonts, iconSizes, imageSizes, spacing } from 'ui/src/theme' import { fonts, iconSizes, imageSizes, spacing } from 'ui/src/theme'
import { UnitagClaimSource } from 'uniswap/src/features/unitags/types' import { UnitagClaimSource } from 'uniswap/src/features/unitags/types'
import { ChainId } from 'wallet/src/constants/chains' import { ChainId } from 'wallet/src/constants/chains'
...@@ -133,7 +134,7 @@ export function ChooseProfilePictureScreen({ ...@@ -133,7 +134,7 @@ export function ChooseProfilePictureScreen({
backgroundColor={isDarkMode ? '$neutral3' : '$neutral2'} backgroundColor={isDarkMode ? '$neutral3' : '$neutral2'}
borderRadius="$roundedFull" borderRadius="$roundedFull"
p={8}> p={8}>
<Icons.Pen color={isDarkMode ? '$neutral1' : '$surface1'} size={iconSizes.icon16} /> <Pen color={isDarkMode ? '$neutral1' : '$surface1'} size={iconSizes.icon16} />
</Flex> </Flex>
</Flex> </Flex>
</Flex> </Flex>
......
...@@ -17,13 +17,13 @@ import { ...@@ -17,13 +17,13 @@ import {
AnimatedFlex, AnimatedFlex,
Button, Button,
Flex, Flex,
Icons,
Image, Image,
Text, Text,
TouchableArea, TouchableArea,
useSporeColors, useSporeColors,
} from 'ui/src' } from 'ui/src'
import { ENS_LOGO } from 'ui/src/assets' import { ENS_LOGO } from 'ui/src/assets'
import { InfoCircleFilled, LinkHorizontalAlt } from 'ui/src/components/icons'
import { fonts, iconSizes, imageSizes, spacing } from 'ui/src/theme' import { fonts, iconSizes, imageSizes, spacing } from 'ui/src/theme'
import { uniswapUrls } from 'uniswap/src/constants/urls' import { uniswapUrls } from 'uniswap/src/constants/urls'
import { logger } from 'utilities/src/logger/logger' import { logger } from 'utilities/src/logger/logger'
...@@ -338,7 +338,7 @@ export function ClaimUnitagScreen({ navigation, route }: Props): JSX.Element { ...@@ -338,7 +338,7 @@ export function ClaimUnitagScreen({ navigation, route }: Props): JSX.Element {
Keyboard.dismiss() Keyboard.dismiss()
setShowInfoModal(true) setShowInfoModal(true)
}}> }}>
<Icons.InfoCircleFilled color={colors.neutral3.get()} size="$icon.20" /> <InfoCircleFilled color={colors.neutral3.get()} size="$icon.20" />
</TouchableArea> </TouchableArea>
</AnimatedFlex> </AnimatedFlex>
{canClaimUnitagNameError && unitagToCheck === unitagInputValue && ( {canClaimUnitagNameError && unitagToCheck === unitagInputValue && (
...@@ -436,7 +436,7 @@ const InfoModal = ({ ...@@ -436,7 +436,7 @@ const InfoModal = ({
width={FIXED_INFO_PILL_WIDTH} width={FIXED_INFO_PILL_WIDTH}
/> />
<Flex p="$spacing2" shadowColor="$accent1" shadowOpacity={1} shadowRadius="$spacing16"> <Flex p="$spacing2" shadowColor="$accent1" shadowOpacity={1} shadowRadius="$spacing16">
<Icons.LinkHorizontalAlt color={colors.neutral3.get()} size={iconSizes.icon24} /> <LinkHorizontalAlt color={colors.neutral3.get()} size={iconSizes.icon24} />
</Flex> </Flex>
<Pill <Pill
customBackgroundColor={colors.surface1.val} customBackgroundColor={colors.surface1.val}
......
/* eslint-disable max-lines */
import React, { useEffect, useMemo, useState } from 'react' import React, { useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Keyboard, KeyboardAvoidingView, StyleSheet } from 'react-native' import { Keyboard, KeyboardAvoidingView, StyleSheet } from 'react-native'
...@@ -17,7 +16,6 @@ import { Screens, UnitagScreens } from 'src/screens/Screens' ...@@ -17,7 +16,6 @@ import { Screens, UnitagScreens } from 'src/screens/Screens'
import { import {
Button, Button,
Flex, Flex,
Icons,
LinearGradient, LinearGradient,
ScrollView, ScrollView,
Text, Text,
...@@ -26,6 +24,7 @@ import { ...@@ -26,6 +24,7 @@ import {
useSporeColors, useSporeColors,
useUniconColors, useUniconColors,
} from 'ui/src' } from 'ui/src'
import { Pen, TripleDots } from 'ui/src/components/icons'
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/gating/flags' import { FeatureFlags } from 'uniswap/src/features/gating/flags'
...@@ -297,7 +296,7 @@ export function EditUnitagProfileScreen({ ...@@ -297,7 +296,7 @@ export function EditUnitagProfileScreen({
} }
}}> }}>
<Flex pr="$spacing8"> <Flex pr="$spacing8">
<Icons.TripleDots color="$neutral2" size={iconSizes.icon24} /> <TripleDots color="$neutral2" size={iconSizes.icon24} />
</Flex> </Flex>
</ContextMenu> </ContextMenu>
) : undefined ) : undefined
...@@ -366,10 +365,7 @@ export function EditUnitagProfileScreen({ ...@@ -366,10 +365,7 @@ export function EditUnitagProfileScreen({
backgroundColor={isDarkMode ? '$neutral3' : '$neutral2'} backgroundColor={isDarkMode ? '$neutral3' : '$neutral2'}
borderRadius="$roundedFull" borderRadius="$roundedFull"
p={6}> p={6}>
<Icons.Pen <Pen color={isDarkMode ? '$neutral1' : '$surface1'} size={iconSizes.icon16} />
color={isDarkMode ? '$neutral1' : '$surface1'}
size={iconSizes.icon16}
/>
</Flex> </Flex>
</Flex> </Flex>
</Flex> </Flex>
......
import { Flex, Icons, Text } from 'ui/src' import { Flex, Text } from 'ui/src'
import { Unitag } from 'ui/src/components/icons'
import { fonts, spacing } from 'ui/src/theme' import { fonts, spacing } from 'ui/src/theme'
export function UnitagName({ export function UnitagName({
...@@ -37,7 +38,7 @@ export function UnitagName({ ...@@ -37,7 +38,7 @@ export function UnitagName({
position="absolute" position="absolute"
right={-spacing.spacing4} right={-spacing.spacing4}
top={-spacing.spacing4}> top={-spacing.spacing4}>
<Icons.Unitag size="$icon.24" /> <Unitag size="$icon.24" />
</Flex> </Flex>
</Flex> </Flex>
) )
......
...@@ -82,7 +82,7 @@ export function* signWcRequest(params: SignMessageParams | SignTransactionParams ...@@ -82,7 +82,7 @@ export function* signWcRequest(params: SignMessageParams | SignTransactionParams
Accept: 'application/json', Accept: 'application/json',
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
body: JSON.stringify({ method: 'eth_sendTransaction', response: signature, chainId }), body: JSON.stringify({ method: params.method, response: signature, chainId }),
// TODO: consider adding analytics to track UwuLink usage // TODO: consider adding analytics to track UwuLink usage
}).catch((error) => }).catch((error) =>
logger.error(error, { logger.error(error, {
......
...@@ -12,16 +12,8 @@ import { useFiatOnRampContext } from 'src/features/fiatOnRamp/FiatOnRampContext' ...@@ -12,16 +12,8 @@ import { useFiatOnRampContext } from 'src/features/fiatOnRamp/FiatOnRampContext'
import { InitialQuoteSelection } from 'src/features/fiatOnRamp/types' import { InitialQuoteSelection } from 'src/features/fiatOnRamp/types'
import { getServiceProviderForQuote } from 'src/features/fiatOnRamp/utils' import { getServiceProviderForQuote } from 'src/features/fiatOnRamp/utils'
import { FiatOnRampScreens } from 'src/screens/Screens' import { FiatOnRampScreens } from 'src/screens/Screens'
import { import { AnimatedFlex, ColorTokens, Flex, GeneratedIcon, Inset, Separator, Text } from 'ui/src'
AnimatedFlex, import { TimePast } from 'ui/src/components/icons'
ColorTokens,
Flex,
GeneratedIcon,
Icons,
Inset,
Separator,
Text,
} from 'ui/src'
import { HandleBar } from 'wallet/src/components/modals/HandleBar' import { HandleBar } from 'wallet/src/components/modals/HandleBar'
import { useBottomSheetFocusHook } from 'wallet/src/components/modals/hooks' import { useBottomSheetFocusHook } from 'wallet/src/components/modals/hooks'
import { FORQuote } from 'wallet/src/features/fiatOnRamp/types' import { FORQuote } from 'wallet/src/features/fiatOnRamp/types'
...@@ -94,7 +86,7 @@ export function FiatOnRampServiceProvidersScreen({ navigation }: Props): JSX.Ele ...@@ -94,7 +86,7 @@ export function FiatOnRampServiceProvidersScreen({ navigation }: Props): JSX.Ele
<Flex px="$spacing12"> <Flex px="$spacing12">
{type === InitialQuoteSelection.Best ? null : type === InitialQuoteSelection.MostRecent ? ( {type === InitialQuoteSelection.Best ? null : type === InitialQuoteSelection.MostRecent ? (
<SectionHeader <SectionHeader
Icon={Icons.TimePast} Icon={TimePast}
iconColor="$neutral3" iconColor="$neutral3"
title={t('fiatOnRamp.quote.type.recent')} title={t('fiatOnRamp.quote.type.recent')}
/> />
......
...@@ -353,15 +353,13 @@ export function HomeScreen(props?: AppStackScreenProp<Screens.Home>): JSX.Elemen ...@@ -353,15 +353,13 @@ 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 (cexTransferProviders.length > 0) {
dispatch( dispatch(
openModal({ name: ModalName.ReceiveCryptoModal, initialState: cexTransferProviders }) openModal(
cexTransferProviders.length > 0
? { name: ModalName.ReceiveCryptoModal, initialState: cexTransferProviders }
: { name: ModalName.WalletConnectScan, initialState: ScannerModalState.WalletQr }
) )
} else {
dispatch(
openModal({ name: ModalName.WalletConnectScan, initialState: ScannerModalState.WalletQr })
) )
}
}, [dispatch, cexTransferProviders]) }, [dispatch, cexTransferProviders])
const onPressViewOnlyLabel = useCallback( const onPressViewOnlyLabel = useCallback(
() => dispatch(openModal({ name: ModalName.ViewOnlyExplainer })), () => dispatch(openModal({ name: ModalName.ViewOnlyExplainer })),
......
...@@ -10,8 +10,9 @@ import { OnboardingScreen } from 'src/features/onboarding/OnboardingScreen' ...@@ -10,8 +10,9 @@ import { OnboardingScreen } from 'src/features/onboarding/OnboardingScreen'
import { OptionCard } from 'src/features/onboarding/OptionCard' import { OptionCard } from 'src/features/onboarding/OptionCard'
import { OnboardingScreens } from 'src/screens/Screens' import { OnboardingScreens } from 'src/screens/Screens'
import { useAddBackButton } from 'src/utils/useAddBackButton' import { useAddBackButton } from 'src/utils/useAddBackButton'
import { Flex, Icons, Text, TouchableArea, useSporeColors } from 'ui/src' import { Flex, Text, TouchableArea, useSporeColors } from 'ui/src'
import EyeIcon from 'ui/src/assets/icons/eye.svg' import EyeIcon from 'ui/src/assets/icons/eye.svg'
import { OSDynamicCloudIcon, PaperStack } from 'ui/src/components/icons'
import { useIsDarkMode } from 'ui/src/hooks/useIsDarkMode' import { useIsDarkMode } from 'ui/src/hooks/useIsDarkMode'
import { AppTFunction } from 'ui/src/i18n/types' import { AppTFunction } from 'ui/src/i18n/types'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
...@@ -37,7 +38,7 @@ const options: ImportMethodOption[] = [ ...@@ -37,7 +38,7 @@ const options: ImportMethodOption[] = [
{ {
title: (t: AppTFunction) => t('onboarding.import.method.import.title'), title: (t: AppTFunction) => t('onboarding.import.method.import.title'),
blurb: (t: AppTFunction) => t('onboarding.import.method.import.message'), blurb: (t: AppTFunction) => t('onboarding.import.method.import.message'),
icon: <Icons.PaperStack color="$accent1" size={18} strokeWidth={1.5} />, icon: <PaperStack color="$accent1" size={18} strokeWidth={1.5} />,
nav: OnboardingScreens.SeedPhraseInput, nav: OnboardingScreens.SeedPhraseInput,
importType: ImportType.SeedPhrase, importType: ImportType.SeedPhrase,
name: ElementName.OnboardingImportSeedPhrase, name: ElementName.OnboardingImportSeedPhrase,
...@@ -48,7 +49,7 @@ const options: ImportMethodOption[] = [ ...@@ -48,7 +49,7 @@ const options: ImportMethodOption[] = [
isAndroid isAndroid
? t(`onboarding.import.method.restore.message.android`) ? t(`onboarding.import.method.restore.message.android`)
: t(`onboarding.import.method.restore.message.ios`), : t(`onboarding.import.method.restore.message.ios`),
icon: <Icons.OSDynamicCloudIcon color="$accent1" size="$icon.24" />, icon: <OSDynamicCloudIcon color="$accent1" size="$icon.24" />,
nav: OnboardingScreens.RestoreCloudBackup, nav: OnboardingScreens.RestoreCloudBackup,
importType: ImportType.Restore, importType: ImportType.Restore,
name: ElementName.RestoreFromCloud, name: ElementName.RestoreFromCloud,
......
...@@ -13,7 +13,8 @@ import { useCloudBackups } from 'src/features/CloudBackup/hooks' ...@@ -13,7 +13,8 @@ import { useCloudBackups } from 'src/features/CloudBackup/hooks'
import { OnboardingScreen } from 'src/features/onboarding/OnboardingScreen' import { OnboardingScreen } from 'src/features/onboarding/OnboardingScreen'
import { OnboardingScreens } from 'src/screens/Screens' import { OnboardingScreens } from 'src/screens/Screens'
import { useAddBackButton } from 'src/utils/useAddBackButton' import { useAddBackButton } from 'src/utils/useAddBackButton'
import { Flex, Icons, Loader } from 'ui/src' import { Flex, Loader } from 'ui/src'
import { OSDynamicCloudIcon } from 'ui/src/components/icons'
import { imageSizes } from 'ui/src/theme' import { imageSizes } from 'ui/src/theme'
import { getCloudProviderName } from 'uniswap/src/utils/cloud-backup/getCloudProviderName' import { getCloudProviderName } from 'uniswap/src/utils/cloud-backup/getCloudProviderName'
import { logger } from 'utilities/src/logger/logger' import { logger } from 'utilities/src/logger/logger'
...@@ -139,7 +140,7 @@ export function RestoreCloudBackupLoadingScreen({ ...@@ -139,7 +140,7 @@ export function RestoreCloudBackupLoadingScreen({
<Flex alignSelf="center" px="$spacing16"> <Flex alignSelf="center" px="$spacing16">
<BaseCard.ErrorState <BaseCard.ErrorState
description={t('account.cloud.error.backup.message')} description={t('account.cloud.error.backup.message')}
icon={<Icons.OSDynamicCloudIcon color="$neutral3" size={imageSizes.image48} />} icon={<OSDynamicCloudIcon color="$neutral3" size={imageSizes.image48} />}
retryButtonLabel={t('common.button.retry')} retryButtonLabel={t('common.button.retry')}
title={t('account.cloud.error.backup.title')} title={t('account.cloud.error.backup.title')}
onRetry={fetchCloudStorageBackups} onRetry={fetchCloudStorageBackups}
...@@ -162,7 +163,7 @@ export function RestoreCloudBackupLoadingScreen({ ...@@ -162,7 +163,7 @@ export function RestoreCloudBackupLoadingScreen({
description={t('account.cloud.empty.description', { description={t('account.cloud.empty.description', {
cloudProviderName: getCloudProviderName(), cloudProviderName: getCloudProviderName(),
})} })}
icon={<Icons.OSDynamicCloudIcon color="$neutral3" size={imageSizes.image48} />} icon={<OSDynamicCloudIcon color="$neutral3" size={imageSizes.image48} />}
retryButtonLabel={t('common.button.retry')} retryButtonLabel={t('common.button.retry')}
title={t('account.cloud.empty.title')} title={t('account.cloud.empty.title')}
onRetry={fetchCloudStorageBackups} onRetry={fetchCloudStorageBackups}
......
...@@ -9,7 +9,8 @@ import { CloudStorageMnemonicBackup } from 'src/features/CloudBackup/types' ...@@ -9,7 +9,8 @@ import { CloudStorageMnemonicBackup } from 'src/features/CloudBackup/types'
import { OnboardingScreen } from 'src/features/onboarding/OnboardingScreen' import { OnboardingScreen } from 'src/features/onboarding/OnboardingScreen'
import { OnboardingScreens } from 'src/screens/Screens' 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, Text, TouchableArea, Unicon, UniconV2, useIsDarkMode } from 'ui/src'
import { RotatableChevron } from 'ui/src/components/icons'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { FeatureFlags } from 'uniswap/src/features/gating/flags' import { FeatureFlags } from 'uniswap/src/features/gating/flags'
import { useFeatureFlag } from 'uniswap/src/features/gating/hooks' import { useFeatureFlag } from 'uniswap/src/features/gating/hooks'
...@@ -85,7 +86,7 @@ export function RestoreCloudBackupScreen({ navigation, route: { params } }: Prop ...@@ -85,7 +86,7 @@ export function RestoreCloudBackupScreen({ navigation, route: { params } }: Prop
</Text> </Text>
</Flex> </Flex>
</Flex> </Flex>
<Icons.RotatableChevron <RotatableChevron
color="$neutral2" color="$neutral2"
direction="end" direction="end"
height={iconSizes.icon20} height={iconSizes.icon20}
......
...@@ -9,7 +9,8 @@ import { GenericImportForm } from 'src/features/import/GenericImportForm' ...@@ -9,7 +9,8 @@ import { GenericImportForm } from 'src/features/import/GenericImportForm'
import { SafeKeyboardOnboardingScreen } from 'src/features/onboarding/SafeKeyboardOnboardingScreen' import { SafeKeyboardOnboardingScreen } from 'src/features/onboarding/SafeKeyboardOnboardingScreen'
import { OnboardingScreens } from 'src/screens/Screens' import { OnboardingScreens } from 'src/screens/Screens'
import { useAddBackButton } from 'src/utils/useAddBackButton' import { useAddBackButton } from 'src/utils/useAddBackButton'
import { Button, Flex, Icons, Text, TouchableArea } from 'ui/src' import { Button, Flex, Text, TouchableArea } from 'ui/src'
import { QuestionInCircleFilled } from 'ui/src/components/icons'
import { uniswapUrls } from 'uniswap/src/constants/urls' import { uniswapUrls } from 'uniswap/src/constants/urls'
import { ImportType } from 'wallet/src/features/onboarding/types' import { ImportType } from 'wallet/src/features/onboarding/types'
import { useNonPendingSignerAccounts } from 'wallet/src/features/wallet/hooks' import { useNonPendingSignerAccounts } from 'wallet/src/features/wallet/hooks'
...@@ -149,7 +150,7 @@ export function SeedPhraseInputScreen({ navigation, route: { params } }: Props): ...@@ -149,7 +150,7 @@ export function SeedPhraseInputScreen({ navigation, route: { params } }: Props):
flexDirection="row" flexDirection="row"
gap="$spacing8" gap="$spacing8"
onPress={isRestoringMnemonic ? onPressTryAgainButton : onPressRecoveryHelpButton}> onPress={isRestoringMnemonic ? onPressTryAgainButton : onPressRecoveryHelpButton}>
<Icons.QuestionInCircleFilled color="$surface1" size="$icon.20" /> <QuestionInCircleFilled color="$surface1" size="$icon.20" />
<Text $short={{ variant: 'body3' }} color="$neutral3" variant="body2"> <Text $short={{ variant: 'body3' }} color="$neutral3" variant="body2">
{isRestoringMnemonic {isRestoringMnemonic
? t('account.recoveryPhrase.helpText.restoring') ? t('account.recoveryPhrase.helpText.restoring')
......
...@@ -12,7 +12,8 @@ import { useCompleteOnboardingCallback } from 'src/features/onboarding/hooks' ...@@ -12,7 +12,8 @@ import { useCompleteOnboardingCallback } from 'src/features/onboarding/hooks'
import { sendMobileAnalyticsEvent } from 'src/features/telemetry' import { sendMobileAnalyticsEvent } from 'src/features/telemetry'
import { OnboardingScreens } from 'src/screens/Screens' import { OnboardingScreens } from 'src/screens/Screens'
import { useAddBackButton } from 'src/utils/useAddBackButton' import { useAddBackButton } from 'src/utils/useAddBackButton'
import { Button, Flex, Icons, Text } from 'ui/src' import { Button, Flex, Text } from 'ui/src'
import { GraduationCap } from 'ui/src/components/icons'
import { normalizeTextInput } from 'utilities/src/primitives/string' import { normalizeTextInput } from 'utilities/src/primitives/string'
import { ChainId } from 'wallet/src/constants/chains' import { ChainId } from 'wallet/src/constants/chains'
import { usePortfolioBalances } from 'wallet/src/features/dataApi/balances' import { usePortfolioBalances } from 'wallet/src/features/dataApi/balances'
...@@ -191,7 +192,7 @@ export function WatchWalletScreen({ navigation, route: { params } }: Props): JSX ...@@ -191,7 +192,7 @@ export function WatchWalletScreen({ navigation, route: { params } }: Props): JSX
borderRadius="$rounded16" borderRadius="$rounded16"
gap="$spacing16" gap="$spacing16"
p="$spacing16"> p="$spacing16">
<Icons.GraduationCap color="$neutral2" size="$icon.20" /> <GraduationCap color="$neutral2" size="$icon.20" />
<Text color="$neutral2" flexShrink={1} variant="body3"> <Text color="$neutral2" flexShrink={1} variant="body3">
{t('account.wallet.watch.message')} {t('account.wallet.watch.message')}
</Text> </Text>
......
...@@ -16,8 +16,9 @@ import { isCloudStorageAvailable } from 'src/features/CloudBackup/RNCloudStorage ...@@ -16,8 +16,9 @@ import { isCloudStorageAvailable } from 'src/features/CloudBackup/RNCloudStorage
import { OnboardingScreen } from 'src/features/onboarding/OnboardingScreen' import { OnboardingScreen } from 'src/features/onboarding/OnboardingScreen'
import { OptionCard } from 'src/features/onboarding/OptionCard' import { OptionCard } from 'src/features/onboarding/OptionCard'
import { OnboardingScreens, Screens } from 'src/screens/Screens' import { OnboardingScreens, Screens } from 'src/screens/Screens'
import { Button, Flex, Icons, Text, TouchableArea, useIsDarkMode, useSporeColors } from 'ui/src' import { Button, Flex, Text, TouchableArea, useIsDarkMode, useSporeColors } from 'ui/src'
import PaperIcon from 'ui/src/assets/icons/paper-stack.svg' import PaperIcon from 'ui/src/assets/icons/paper-stack.svg'
import { OSDynamicCloudIcon, QuestionInCircleFilled } from 'ui/src/components/icons'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
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'
...@@ -132,7 +133,7 @@ export function BackupScreen({ navigation, route: { params } }: Props): JSX.Elem ...@@ -132,7 +133,7 @@ export function BackupScreen({ navigation, route: { params } }: Props): JSX.Elem
blurb={t('onboarding.backup.option.cloud.description')} blurb={t('onboarding.backup.option.cloud.description')}
disabled={hasCloudBackup} disabled={hasCloudBackup}
elementName={ElementName.AddCloudBackup} elementName={ElementName.AddCloudBackup}
icon={<Icons.OSDynamicCloudIcon color="$accent1" size="$icon.16" />} icon={<OSDynamicCloudIcon color="$accent1" size="$icon.16" />}
title={t('onboarding.backup.option.cloud.title', { title={t('onboarding.backup.option.cloud.title', {
cloudProviderName: getCloudProviderName(), cloudProviderName: getCloudProviderName(),
})} })}
...@@ -199,7 +200,7 @@ function RecoveryPhraseTooltip({ ...@@ -199,7 +200,7 @@ function RecoveryPhraseTooltip({
gap="$spacing8" gap="$spacing8"
py="$spacing8" py="$spacing8"
onPress={onPressEducationButton}> onPress={onPressEducationButton}>
<Icons.QuestionInCircleFilled color="$surface1" size="$icon.20" /> <QuestionInCircleFilled color="$surface1" size="$icon.20" />
<Text color="$neutral3" variant="body2"> <Text color="$neutral3" variant="body2">
{t('onboarding.tooltip.recoveryPhrase.trigger')} {t('onboarding.tooltip.recoveryPhrase.trigger')}
</Text> </Text>
......
...@@ -6,13 +6,13 @@ import { selectModalState } from 'src/features/modals/selectModalState' ...@@ -6,13 +6,13 @@ import { selectModalState } from 'src/features/modals/selectModalState'
import { import {
Flex, Flex,
HapticFeedback, HapticFeedback,
Icons,
ImpactFeedbackStyle, ImpactFeedbackStyle,
Separator, Separator,
Text, Text,
TouchableArea, TouchableArea,
useSporeColors, useSporeColors,
} from 'ui/src' } from 'ui/src'
import { CopySheets, QrCode } from 'ui/src/components/icons'
import { iconSizes } from 'ui/src/theme' import { iconSizes } from 'ui/src/theme'
import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants' import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants'
import { AddressDisplay } from 'wallet/src/components/accounts/AddressDisplay' import { AddressDisplay } from 'wallet/src/components/accounts/AddressDisplay'
...@@ -84,7 +84,7 @@ function AccountCardItem({ onClose }: { onClose: () => void }): JSX.Element { ...@@ -84,7 +84,7 @@ function AccountCardItem({ onClose }: { onClose: () => void }): JSX.Element {
borderRadius={ICON_BORDER_RADIUS} borderRadius={ICON_BORDER_RADIUS}
height={ICON_SIZE} height={ICON_SIZE}
width={ICON_SIZE}> width={ICON_SIZE}>
<Icons.CopySheets color="$neutral2" size={iconSizes.icon16} /> <CopySheets color="$neutral2" size={iconSizes.icon16} />
</Flex> </Flex>
</TouchableArea> </TouchableArea>
<Flex <Flex
...@@ -94,7 +94,7 @@ function AccountCardItem({ onClose }: { onClose: () => void }): JSX.Element { ...@@ -94,7 +94,7 @@ function AccountCardItem({ onClose }: { onClose: () => void }): JSX.Element {
borderRadius={ICON_BORDER_RADIUS} borderRadius={ICON_BORDER_RADIUS}
height={ICON_SIZE} height={ICON_SIZE}
width={ICON_SIZE}> width={ICON_SIZE}>
<Icons.QrCode color="$neutral2" size={iconSizes.icon16} /> <QrCode color="$neutral2" size={iconSizes.icon16} />
</Flex> </Flex>
</Flex> </Flex>
</Flex> </Flex>
......
...@@ -7,7 +7,8 @@ import { BackHeader } from 'src/components/layout/BackHeader' ...@@ -7,7 +7,8 @@ import { BackHeader } from 'src/components/layout/BackHeader'
import { Screen } from 'src/components/layout/Screen' import { Screen } from 'src/components/layout/Screen'
import { CloudBackupPasswordForm } from 'src/features/CloudBackup/CloudBackupPasswordForm' import { CloudBackupPasswordForm } from 'src/features/CloudBackup/CloudBackupPasswordForm'
import { Screens } from 'src/screens/Screens' import { Screens } from 'src/screens/Screens'
import { Button, Flex, Icons, Text, useSporeColors } from 'ui/src' import { Button, Flex, Text, useSporeColors } from 'ui/src'
import { OSDynamicCloudIcon } from 'ui/src/components/icons'
import { getCloudProviderName } from 'uniswap/src/utils/cloud-backup/getCloudProviderName' import { getCloudProviderName } from 'uniswap/src/utils/cloud-backup/getCloudProviderName'
import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal' import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal'
import { ElementName, ModalName } from 'wallet/src/telemetry/constants' import { ElementName, ModalName } from 'wallet/src/telemetry/constants'
...@@ -64,7 +65,7 @@ export function SettingsCloudBackupPasswordCreateScreen({ ...@@ -64,7 +65,7 @@ export function SettingsCloudBackupPasswordCreateScreen({
<Flex px="$spacing16" py="$spacing12"> <Flex px="$spacing16" py="$spacing12">
<Flex centered gap="$spacing16"> <Flex centered gap="$spacing16">
<Flex backgroundColor="$accentSoft" borderRadius="$rounded12" p="$spacing12"> <Flex backgroundColor="$accentSoft" borderRadius="$rounded12" p="$spacing12">
<Icons.OSDynamicCloudIcon color="$accent1" size="$icon.24" /> <OSDynamicCloudIcon color="$accent1" size="$icon.24" />
</Flex> </Flex>
<Text textAlign="center" variant="subheading1"> <Text textAlign="center" variant="subheading1">
{t('settings.setting.backup.modal.title', { {t('settings.setting.backup.modal.title', {
......
...@@ -4,7 +4,8 @@ import { Action } from 'redux' ...@@ -4,7 +4,8 @@ import { Action } from 'redux'
import { useAppDispatch } from 'src/app/hooks' import { useAppDispatch } from 'src/app/hooks'
import { VirtualizedList } from 'src/components/layout/VirtualizedList' import { VirtualizedList } from 'src/components/layout/VirtualizedList'
import { closeModal } from 'src/features/modals/modalSlice' import { closeModal } from 'src/features/modals/modalSlice'
import { Flex, Icons, Text, TouchableArea, useSporeColors } from 'ui/src' import { Flex, Text, TouchableArea, useSporeColors } from 'ui/src'
import { Check } from 'ui/src/components/icons'
import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal' import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal'
import { FiatCurrency, ORDERED_CURRENCIES } from 'wallet/src/features/fiatCurrency/constants' import { FiatCurrency, ORDERED_CURRENCIES } from 'wallet/src/features/fiatCurrency/constants'
import { useAppFiatCurrency, useFiatCurrencyInfo } from 'wallet/src/features/fiatCurrency/hooks' import { useAppFiatCurrency, useFiatCurrencyInfo } from 'wallet/src/features/fiatCurrency/hooks'
...@@ -80,7 +81,7 @@ function FiatCurrencyOption({ active, currency, onPress }: FiatCurrencyOptionPro ...@@ -80,7 +81,7 @@ function FiatCurrencyOption({ active, currency, onPress }: FiatCurrencyOptionPro
{code} {code}
</Text> </Text>
</Flex> </Flex>
{active && <Icons.Check color={colors.accent1.val} size="$icon.24" />} {active && <Check color={colors.accent1.val} size="$icon.24" />}
</Flex> </Flex>
</TouchableArea> </TouchableArea>
) )
......
...@@ -4,7 +4,8 @@ import { Linking } from 'react-native' ...@@ -4,7 +4,8 @@ import { Linking } from 'react-native'
import { Action } from 'redux' import { Action } from 'redux'
import { useAppDispatch } from 'src/app/hooks' import { useAppDispatch } from 'src/app/hooks'
import { closeModal } from 'src/features/modals/modalSlice' import { closeModal } from 'src/features/modals/modalSlice'
import { Button, Flex, Icons, Text } from 'ui/src' import { Button, Flex, Text } from 'ui/src'
import { Language } from 'ui/src/components/icons'
import { isAndroid } from 'uniswap/src/utils/platform' import { isAndroid } from 'uniswap/src/utils/platform'
import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal' import { BottomSheetModal } from 'wallet/src/components/modals/BottomSheetModal'
import { ElementName, ModalName } from 'wallet/src/telemetry/constants' import { ElementName, ModalName } from 'wallet/src/telemetry/constants'
...@@ -33,7 +34,7 @@ export function SettingsLanguageModal(): JSX.Element { ...@@ -33,7 +34,7 @@ export function SettingsLanguageModal(): JSX.Element {
<BottomSheetModal name={ModalName.LanguageSelector} onClose={onClose}> <BottomSheetModal name={ModalName.LanguageSelector} onClose={onClose}>
<Flex centered mt="$spacing16"> <Flex centered mt="$spacing16">
<Flex borderRadius="$rounded12" p="$spacing12" style={{ backgroundColor: LIGHT_BLUE }}> <Flex borderRadius="$rounded12" p="$spacing12" style={{ backgroundColor: LIGHT_BLUE }}>
<Icons.Language color="$DEP_blue300" size="$icon.24" strokeWidth={1.5} /> <Language color="$DEP_blue300" size="$icon.24" strokeWidth={1.5} />
</Flex> </Flex>
</Flex> </Flex>
<Flex gap="$spacing24" pt="$spacing24" px="$spacing24"> <Flex gap="$spacing24" pt="$spacing24" px="$spacing24">
......
...@@ -30,7 +30,6 @@ import { ...@@ -30,7 +30,6 @@ import {
Button, Button,
Flex, Flex,
IconProps, IconProps,
Icons,
Text, Text,
TouchableArea, TouchableArea,
useDeviceInsets, useDeviceInsets,
...@@ -45,6 +44,17 @@ import FingerprintIcon from 'ui/src/assets/icons/fingerprint.svg' ...@@ -45,6 +44,17 @@ import FingerprintIcon from 'ui/src/assets/icons/fingerprint.svg'
import LockIcon from 'ui/src/assets/icons/lock.svg' import LockIcon from 'ui/src/assets/icons/lock.svg'
import MessageQuestion from 'ui/src/assets/icons/message-question.svg' 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 {
Chart,
Coins,
Feedback,
Key,
Language,
LineChartDots,
OSDynamicCloudIcon,
RotatableChevron,
ShieldQuestion,
} from 'ui/src/components/icons'
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/gating/flags' import { FeatureFlags } from 'uniswap/src/features/gating/flags'
...@@ -152,7 +162,7 @@ export function SettingsScreen(): JSX.Element { ...@@ -152,7 +162,7 @@ export function SettingsScreen(): JSX.Element {
modal: ModalName.FiatCurrencySelector, modal: ModalName.FiatCurrencySelector,
text: t('settings.setting.currency.title'), text: t('settings.setting.currency.title'),
currentSetting: currentFiatCurrencyInfo.code, currentSetting: currentFiatCurrencyInfo.code,
icon: <Icons.Coins {...iconProps} />, icon: <Coins {...iconProps} />,
}, },
] as SettingsSectionItem[]) ] as SettingsSectionItem[])
: []), : []),
...@@ -160,22 +170,22 @@ export function SettingsScreen(): JSX.Element { ...@@ -160,22 +170,22 @@ export function SettingsScreen(): JSX.Element {
modal: ModalName.LanguageSelector, modal: ModalName.LanguageSelector,
text: t('settings.setting.language.title'), text: t('settings.setting.language.title'),
currentSetting: currentLanguage, currentSetting: currentLanguage,
icon: <Icons.Language {...iconProps} />, icon: <Language {...iconProps} />,
}, },
{ {
screen: Screens.SettingsPrivacy, screen: Screens.SettingsPrivacy,
text: t('settings.setting.privacy.title'), text: t('settings.setting.privacy.title'),
icon: <Icons.LineChartDots {...iconProps} />, icon: <LineChartDots {...iconProps} />,
}, },
{ {
text: t('settings.setting.smallBalances.title'), text: t('settings.setting.smallBalances.title'),
icon: <Icons.Chart {...iconProps} />, icon: <Chart {...iconProps} />,
isToggleEnabled: hideSmallBalances, isToggleEnabled: hideSmallBalances,
onToggle: onToggleHideSmallBalances, onToggle: onToggleHideSmallBalances,
}, },
{ {
text: t('settings.setting.unknownTokens.title'), text: t('settings.setting.unknownTokens.title'),
icon: <Icons.ShieldQuestion {...iconProps} />, icon: <ShieldQuestion {...iconProps} />,
isToggleEnabled: hideSpamTokens, isToggleEnabled: hideSpamTokens,
onToggle: onToggleHideSpamTokens, onToggle: onToggleHideSpamTokens,
}, },
...@@ -203,7 +213,7 @@ export function SettingsScreen(): JSX.Element { ...@@ -203,7 +213,7 @@ export function SettingsScreen(): JSX.Element {
{ {
screen: Screens.SettingsViewSeedPhrase, screen: Screens.SettingsViewSeedPhrase,
text: t('settings.setting.recoveryPhrase.title'), text: t('settings.setting.recoveryPhrase.title'),
icon: <Icons.Key {...iconProps} />, icon: <Key {...iconProps} />,
screenProps: { address: signerAccount?.address ?? '', walletNeedsRestore }, screenProps: { address: signerAccount?.address ?? '', walletNeedsRestore },
isHidden: noSignerAccountImported, isHidden: noSignerAccountImported,
}, },
...@@ -225,7 +235,7 @@ export function SettingsScreen(): JSX.Element { ...@@ -225,7 +235,7 @@ export function SettingsScreen(): JSX.Element {
text: t('settings.setting.backup.selected', { text: t('settings.setting.backup.selected', {
cloudProviderName: getCloudProviderName(), cloudProviderName: getCloudProviderName(),
}), }),
icon: <Icons.OSDynamicCloudIcon color="$neutral2" size="$icon.24" />, icon: <OSDynamicCloudIcon color="$neutral2" size="$icon.24" />,
isHidden: noSignerAccountImported, isHidden: noSignerAccountImported,
}, },
], ],
...@@ -240,7 +250,7 @@ export function SettingsScreen(): JSX.Element { ...@@ -240,7 +250,7 @@ export function SettingsScreen(): JSX.Element {
headerTitle: t('settings.action.feedback'), headerTitle: t('settings.action.feedback'),
}, },
text: t('settings.action.feedback'), text: t('settings.action.feedback'),
icon: <Icons.Feedback color="$neutral2" size="$icon.24" />, icon: <Feedback color="$neutral2" size="$icon.24" />,
}, },
{ {
screen: Screens.WebView, screen: Screens.WebView,
...@@ -374,7 +384,7 @@ function OnboardingRow({ iconProps }: { iconProps: SvgProps }): JSX.Element { ...@@ -374,7 +384,7 @@ function OnboardingRow({ iconProps }: { iconProps: SvgProps }): JSX.Element {
Onboarding Onboarding
</Text> </Text>
</Flex> </Flex>
<Icons.RotatableChevron <RotatableChevron
color="$neutral3" color="$neutral3"
direction="end" direction="end"
height={iconSizes.icon24} height={iconSizes.icon24}
...@@ -444,7 +454,7 @@ function WalletSettings(): JSX.Element { ...@@ -444,7 +454,7 @@ function WalletSettings(): JSX.Element {
size={iconSizes.icon40} size={iconSizes.icon40}
variant="body1" variant="body1"
/> />
<Icons.RotatableChevron <RotatableChevron
color="$neutral3" color="$neutral3"
direction="end" direction="end"
height={iconSizes.icon24} height={iconSizes.icon24}
......
...@@ -12,7 +12,8 @@ import { SettingsStackParamList } from 'src/app/navigation/types' ...@@ -12,7 +12,8 @@ import { SettingsStackParamList } from 'src/app/navigation/types'
import { BackHeader } from 'src/components/layout/BackHeader' import { BackHeader } from 'src/components/layout/BackHeader'
import { Screen } from 'src/components/layout/Screen' 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, Text } from 'ui/src'
import { PenLine } from 'ui/src/components/icons'
import { fonts } from 'ui/src/theme' import { fonts } from 'ui/src/theme'
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'
...@@ -122,7 +123,7 @@ export function SettingsWalletEdit({ ...@@ -122,7 +123,7 @@ export function SettingsWalletEdit({
{showEditButton && accountNameIsEditable && ( {showEditButton && accountNameIsEditable && (
<Button <Button
backgroundless backgroundless
icon={<Icons.PenLine color="$neutral3" />} icon={<PenLine color="$neutral3" />}
m="$none" m="$none"
size="medium" size="medium"
onPress={onEditButtonPress} onPress={onEditButtonPress}
......
...@@ -60,6 +60,7 @@ ignores: [ ...@@ -60,6 +60,7 @@ ignores: [
"pages", "pages",
"polyfills", "polyfills",
"rpc", "rpc",
"shared-cloud",
"state", "state",
"test-utils", "test-utils",
"theme", "theme",
......
...@@ -2,7 +2,11 @@ ...@@ -2,7 +2,11 @@
## Purpose ## Purpose
These functions utilize Cloudflare Functions to dynamically inject meta tags server side for richer link sharing capabilities. These functions utilize Cloudflare Functions to dynamically inject meta tags server-side for richer link sharing capabilities.
Search engines and social media platforms' crawlers read the initial HTML of a page to index and understand its content. These crawlers often do not execute JavaScript, meaning dynamically added client-side content, including metatags, may not be indexed or recognized. This is why we render our metatags on server-side.
However, these server-side injected metatags do not automatically update during client-side navigation managed by react-router. To address this, we implement additional client-side logic - see `src/pages/metatags.ts`. This client-side metatag management is particularly important for compatibility with features like Safari's native share, which relies on metatags like `og:url` to represent the shared page.
## Functions ## Functions
......
...@@ -16,26 +16,54 @@ test('should append meta tag to element', () => { ...@@ -16,26 +16,54 @@ test('should append meta tag to element', () => {
new Request('http://localhost') new Request('http://localhost')
) )
injector.append(element, property, content) injector.append(element, property, content)
expect(element.append).toHaveBeenCalledWith(`<meta property="${property}" content="${content}"/>`, { html: true }) expect(element.append).toHaveBeenCalledWith(`<meta property="${property}" content="${content}" data-rh="true">`, {
html: true,
})
injector.element(element) injector.element(element)
expect(element.append).toHaveBeenCalledWith(`<meta property="og:title" content="test"/>`, { html: true }) expect(element.append).toHaveBeenCalledWith(`<meta property="og:title" content="test" data-rh="true">`, {
expect(element.append).toHaveBeenCalledWith(`<meta property="og:description" content="testDescription"/>`, { html: true,
})
expect(element.append).toHaveBeenCalledWith(
`<meta property="og:description" content="testDescription" data-rh="true">`,
{
html: true,
}
)
expect(element.append).toHaveBeenCalledWith(`<meta property="og:image" content="testImage" data-rh="true">`, {
html: true,
})
expect(element.append).toHaveBeenCalledWith(`<meta property="og:image:width" content="1200" data-rh="true">`, {
html: true,
})
expect(element.append).toHaveBeenCalledWith(`<meta property="og:image:height" content="630" data-rh="true">`, {
html: true,
})
expect(element.append).toHaveBeenCalledWith(`<meta property="og:image:alt" content="test" data-rh="true">`, {
html: true,
})
expect(element.append).toHaveBeenCalledWith(`<meta property="og:type" content="website" data-rh="true">`, {
html: true,
})
expect(element.append).toHaveBeenCalledWith(`<meta property="og:url" content="testUrl" data-rh="true">`, {
html: true, html: true,
}) })
expect(element.append).toHaveBeenCalledWith(`<meta property="og:image" content="testImage"/>`, { html: true })
expect(element.append).toHaveBeenCalledWith(`<meta property="og:image:width" content="1200"/>`, { html: true })
expect(element.append).toHaveBeenCalledWith(`<meta property="og:image:height" content="630"/>`, { html: true })
expect(element.append).toHaveBeenCalledWith(`<meta property="og:image:alt" content="test"/>`, { html: true })
expect(element.append).toHaveBeenCalledWith(`<meta property="og:type" content="website"/>`, { html: true })
expect(element.append).toHaveBeenCalledWith(`<meta property="og:url" content="testUrl"/>`, { html: true })
expect(element.append).toHaveBeenCalledWith(`<meta property="twitter:card" content="summary_large_image"/>`, { expect(element.append).toHaveBeenCalledWith(
`<meta property="twitter:card" content="summary_large_image" data-rh="true">`,
{
html: true,
}
)
expect(element.append).toHaveBeenCalledWith(`<meta property="twitter:title" content="test" data-rh="true">`, {
html: true,
})
expect(element.append).toHaveBeenCalledWith(`<meta property="twitter:image" content="testImage" data-rh="true">`, {
html: true,
})
expect(element.append).toHaveBeenCalledWith(`<meta property="twitter:image:alt" content="test" data-rh="true">`, {
html: true, html: true,
}) })
expect(element.append).toHaveBeenCalledWith(`<meta property="twitter:title" content="test"/>`, { html: true })
expect(element.append).toHaveBeenCalledWith(`<meta property="twitter:image" content="testImage"/>`, { html: true })
expect(element.append).toHaveBeenCalledWith(`<meta property="twitter:image:alt" content="test"/>`, { html: true })
expect(element.append).toHaveBeenCalledTimes(13) expect(element.append).toHaveBeenCalledTimes(13)
}) })
...@@ -56,5 +84,7 @@ test('should pass through header blocked paths', () => { ...@@ -56,5 +84,7 @@ test('should pass through header blocked paths', () => {
request request
) )
injector.element(element) injector.element(element)
expect(element.append).toHaveBeenCalledWith(`<meta property="x:blocked-paths" content="/"/>`, { html: true }) expect(element.append).toHaveBeenCalledWith(`<meta property="x:blocked-paths" content="/" data-rh="true">`, {
html: true,
})
}) })
type MetaTagInjectorInput = { import { MetaTagInjectorInput } from 'shared-cloud/metatags'
title: string
image?: string
url: string
description?: string
}
/** /**
* Listener class for Cloudflare's HTMLRewriter {@link https://developers.cloudflare.com/workers/runtime-apis/html-rewriter} * Listener class for Cloudflare's HTMLRewriter {@link https://developers.cloudflare.com/workers/runtime-apis/html-rewriter}
...@@ -15,7 +10,8 @@ export class MetaTagInjector implements HTMLRewriterElementContentHandlers { ...@@ -15,7 +10,8 @@ export class MetaTagInjector implements HTMLRewriterElementContentHandlers {
constructor(private input: MetaTagInjectorInput, private request: Request) {} constructor(private input: MetaTagInjectorInput, private request: Request) {}
append(element: Element, property: string, content: string) { append(element: Element, property: string, content: string) {
element.append(`<meta property="${property}" content="${content}"/>`, { html: true }) // without adding data-rh="true", react-helmet-async doesn't overwrite existing metatags
element.append(`<meta property="${property}" content="${content}" data-rh="true">`, { html: true })
} }
element(element: Element) { element(element: Element) {
......
...@@ -2,21 +2,19 @@ const defaultUrls = ['http://127.0.0.1:3000/', 'http://127.0.0.1:3000/swap', 'ht ...@@ -2,21 +2,19 @@ const defaultUrls = ['http://127.0.0.1:3000/', 'http://127.0.0.1:3000/swap', 'ht
test.each(defaultUrls)('should inject metadata for valid collections', async (defaultUrl) => { test.each(defaultUrls)('should inject metadata for valid collections', async (defaultUrl) => {
const body = await fetch(new Request(defaultUrl)).then((res) => res.text()) const body = await fetch(new Request(defaultUrl)).then((res) => res.text())
expect(body).toContain(`<meta property="og:title" content="Uniswap Interface"/>`) expect(body).toContain(`<meta property="og:title" content="Uniswap Interface"`)
expect(body).toContain(`<meta property="og:description" content="Swap or provide liquidity on the Uniswap Protocol"`)
expect(body).toContain( expect(body).toContain(
`<meta property="og:description" content="Swap or provide liquidity on the Uniswap Protocol"/>` `<meta property="og:image" content="http://127.0.0.1:3000/images/1200x630_Rich_Link_Preview_Image.png"`
) )
expect(body).toContain(`<meta property="og:image:width" content="1200"`)
expect(body).toContain(`<meta property="og:image:height" content="630"`)
expect(body).toContain(`<meta property="og:type" content="website"`)
expect(body).toContain(`<meta property="og:image:alt" content="Uniswap Interface"`)
expect(body).toContain(`<meta property="twitter:card" content="summary_large_image"`)
expect(body).toContain(`<meta property="twitter:title" content="Uniswap Interface"`)
expect(body).toContain( expect(body).toContain(
`<meta property="og:image" content="http://127.0.0.1:3000/images/1200x630_Rich_Link_Preview_Image.png"/>` `<meta property="twitter:image" content="http://127.0.0.1:3000/images/1200x630_Rich_Link_Preview_Image.png"`
) )
expect(body).toContain(`<meta property="og:image:width" content="1200"/>`) expect(body).toContain(`<meta property="twitter:image:alt" content="Uniswap Interface"`)
expect(body).toContain(`<meta property="og:image:height" content="630"/>`)
expect(body).toContain(`<meta property="og:type" content="website"/>`)
expect(body).toContain(`<meta property="og:image:alt" content="Uniswap Interface"/>`)
expect(body).toContain(`<meta property="twitter:card" content="summary_large_image"/>`)
expect(body).toContain(`<meta property="twitter:title" content="Uniswap Interface"/>`)
expect(body).toContain(
`<meta property="twitter:image" content="http://127.0.0.1:3000/images/1200x630_Rich_Link_Preview_Image.png"/>`
)
expect(body).toContain(`<meta property="twitter:image:alt" content="Uniswap Interface"/>`)
}) })
...@@ -31,18 +31,18 @@ test.each(tokens)('should inject metadata for valid tokens', async (token) => { ...@@ -31,18 +31,18 @@ test.each(tokens)('should inject metadata for valid tokens', async (token) => {
const url = 'http://127.0.0.1:3000/explore/tokens/' + token.network + '/' + token.address const url = 'http://127.0.0.1:3000/explore/tokens/' + token.network + '/' + token.address
const body = await fetch(new Request(url)).then((res) => res.text()) const body = await fetch(new Request(url)).then((res) => res.text())
expect(body).toMatchSnapshot() expect(body).toMatchSnapshot()
expect(body).toContain(`<meta property="og:title" content="Get ${token.symbol} on Uniswap"/>`) expect(body).toContain(`<meta property="og:title" content="Get ${token.symbol} on Uniswap" data-rh="true">`)
expect(body).not.toContain(`<meta property="og:description"`) expect(body).not.toContain(`<meta property="og:description"`)
expect(body).toContain(`<meta property="og:image" content="${token.image}"/>`) expect(body).toContain(`<meta property="og:image" content="${token.image}" data-rh="true">`)
expect(body).toContain(`<meta property="og:image:width" content="1200"/>`) expect(body).toContain(`<meta property="og:image:width" content="1200" data-rh="true">`)
expect(body).toContain(`<meta property="og:image:height" content="630"/>`) expect(body).toContain(`<meta property="og:image:height" content="630" data-rh="true">`)
expect(body).toContain(`<meta property="og:type" content="website"/>`) expect(body).toContain(`<meta property="og:type" content="website" data-rh="true">`)
expect(body).toContain(`<meta property="og:url" content="${url}"/>`) expect(body).toContain(`<meta property="og:url" content="${url}" data-rh="true">`)
expect(body).toContain(`<meta property="og:image:alt" content="Get ${token.symbol} on Uniswap"/>`) expect(body).toContain(`<meta property="og:image:alt" content="Get ${token.symbol} on Uniswap" data-rh="true">`)
expect(body).toContain(`<meta property="twitter:card" content="summary_large_image"/>`) expect(body).toContain(`<meta property="twitter:card" content="summary_large_image" data-rh="true">`)
expect(body).toContain(`<meta property="twitter:title" content="Get ${token.symbol} on Uniswap"/>`) expect(body).toContain(`<meta property="twitter:title" content="Get ${token.symbol} on Uniswap" data-rh="true">`)
expect(body).toContain(`<meta property="twitter:image" content="${token.image}"/>`) expect(body).toContain(`<meta property="twitter:image" content="${token.image}" data-rh="true">`)
expect(body).toContain(`<meta property="twitter:image:alt" content="Get ${token.symbol} on Uniswap"/>`) expect(body).toContain(`<meta property="twitter:image:alt" content="Get ${token.symbol} on Uniswap" data-rh="true">`)
}) })
const invalidTokens = [ const invalidTokens = [
......
/* eslint-disable import/no-unused-modules */ /* eslint-disable import/no-unused-modules */
import getAsset from '../../utils/getAsset' import getAsset from 'utils/getAsset'
import { transformResponse } from '../../utils/transformResponse' import { transformResponse } from '../../utils/transformResponse'
export const onRequest: PagesFunction = async ({ params, request, next }) => { export const onRequest: PagesFunction = async ({ params, request, next }) => {
......
...@@ -23,18 +23,24 @@ test.each(assets)('should inject metadata for valid assets', async (nft) => { ...@@ -23,18 +23,24 @@ test.each(assets)('should inject metadata for valid assets', async (nft) => {
const url = 'http://127.0.0.1:3000/nfts/asset/' + nft.address + '/' + nft.assetId const url = 'http://127.0.0.1:3000/nfts/asset/' + nft.address + '/' + nft.assetId
const body = await fetch(new Request(url)).then((res) => res.text()) const body = await fetch(new Request(url)).then((res) => res.text())
expect(body).toMatchSnapshot(nft.collectionName) expect(body).toMatchSnapshot(nft.collectionName)
expect(body).toContain(`<meta property="og:title" content="${nft.collectionName} #${nft.assetId}"/>`) expect(body).toContain(`<meta property="og:title" content="${nft.collectionName} #${nft.assetId}" data-rh="true">`)
expect(body).not.toContain(`<meta property="og:description"`) expect(body).not.toContain(`<meta property="og:description"`)
expect(body).toContain(`<meta property="og:image" content="${nft.image}"/>`) expect(body).toContain(`<meta property="og:image" content="${nft.image}" data-rh="true">`)
expect(body).toContain(`<meta property="og:image:width" content="1200"/>`) expect(body).toContain(`<meta property="og:image:width" content="1200" data-rh="true">`)
expect(body).toContain(`<meta property="og:image:height" content="630"/>`) expect(body).toContain(`<meta property="og:image:height" content="630" data-rh="true">`)
expect(body).toContain(`<meta property="og:type" content="website"/>`) expect(body).toContain(`<meta property="og:type" content="website" data-rh="true">`)
expect(body).toContain(`<meta property="og:url" content="${url}"/>`) expect(body).toContain(`<meta property="og:url" content="${url}" data-rh="true">`)
expect(body).toContain(`<meta property="og:image:alt" content="${nft.collectionName} #${nft.assetId}"/>`) expect(body).toContain(
expect(body).toContain(`<meta property="twitter:card" content="summary_large_image"/>`) `<meta property="og:image:alt" content="${nft.collectionName} #${nft.assetId}" data-rh="true">`
expect(body).toContain(`<meta property="twitter:title" content="${nft.collectionName} #${nft.assetId}"/>`) )
expect(body).toContain(`<meta property="twitter:image" content="${nft.image}"/>`) expect(body).toContain(`<meta property="twitter:card" content="summary_large_image" data-rh="true">`)
expect(body).toContain(`<meta property="twitter:image:alt" content="${nft.collectionName} #${nft.assetId}"/>`) expect(body).toContain(
`<meta property="twitter:title" content="${nft.collectionName} #${nft.assetId}" data-rh="true">`
)
expect(body).toContain(`<meta property="twitter:image" content="${nft.image}" data-rh="true">`)
expect(body).toContain(
`<meta property="twitter:image:alt" content="${nft.collectionName} #${nft.assetId}" data-rh="true">`
)
}) })
const invalidAssets = [ const invalidAssets = [
......
...@@ -20,18 +20,24 @@ test.each([...collections])('should inject metadata for collections', async (col ...@@ -20,18 +20,24 @@ test.each([...collections])('should inject metadata for collections', async (col
const url = 'http://127.0.0.1:3000/nfts/collection/' + collection.address const url = 'http://127.0.0.1:3000/nfts/collection/' + collection.address
const body = await fetch(new Request(url)).then((res) => res.text()) const body = await fetch(new Request(url)).then((res) => res.text())
expect(body).toMatchSnapshot() expect(body).toMatchSnapshot()
expect(body).toContain(`<meta property="og:title" content="${collection.collectionName} on Uniswap"/>`) expect(body).toContain(`<meta property="og:title" content="${collection.collectionName} on Uniswap" data-rh="true">`)
expect(body).not.toContain(`<meta property="og:description"`) expect(body).not.toContain(`<meta property="og:description"`)
expect(body).toContain(`<meta property="og:image" content="${collection.image}"/>`) expect(body).toContain(`<meta property="og:image" content="${collection.image}" data-rh="true">`)
expect(body).toContain(`<meta property="og:image:width" content="1200"/>`) expect(body).toContain(`<meta property="og:image:width" content="1200" data-rh="true">`)
expect(body).toContain(`<meta property="og:image:height" content="630"/>`) expect(body).toContain(`<meta property="og:image:height" content="630" data-rh="true">`)
expect(body).toContain(`<meta property="og:type" content="website"/>`) expect(body).toContain(`<meta property="og:type" content="website" data-rh="true">`)
expect(body).toContain(`<meta property="og:url" content="${url}"/>`) expect(body).toContain(`<meta property="og:url" content="${url}" data-rh="true">`)
expect(body).toContain(`<meta property="og:image:alt" content="${collection.collectionName} on Uniswap"/>`) expect(body).toContain(
expect(body).toContain(`<meta property="twitter:card" content="summary_large_image"/>`) `<meta property="og:image:alt" content="${collection.collectionName} on Uniswap" data-rh="true">`
expect(body).toContain(`<meta property="twitter:title" content="${collection.collectionName} on Uniswap"/>`) )
expect(body).toContain(`<meta property="twitter:image" content="${collection.image}"/>`) expect(body).toContain(`<meta property="twitter:card" content="summary_large_image" data-rh="true">`)
expect(body).toContain(`<meta property="twitter:image:alt" content="${collection.collectionName} on Uniswap"/>`) expect(body).toContain(
`<meta property="twitter:title" content="${collection.collectionName} on Uniswap" data-rh="true">`
)
expect(body).toContain(`<meta property="twitter:image" content="${collection.image}" data-rh="true">`)
expect(body).toContain(
`<meta property="twitter:image:alt" content="${collection.collectionName} on Uniswap" data-rh="true">`
)
}) })
const nonexistentCollections = [ const nonexistentCollections = [
......
...@@ -5,8 +5,11 @@ ...@@ -5,8 +5,11 @@
"composite": false, "composite": false,
"incremental": true, "incremental": true,
"isolatedModules": false, "isolatedModules": false,
"paths": {
"shared-cloud/*": ["../src/shared-cloud/*"]
},
"tsBuildInfoFile": "../node_modules/.cache/tsbuildinfo/functions", // avoid clobbering the build tsbuildinfo "tsBuildInfoFile": "../node_modules/.cache/tsbuildinfo/functions", // avoid clobbering the build tsbuildinfo
"types": ["jest", "node", "@cloudflare/workers-types"] "types": ["jest", "node", "@cloudflare/workers-types"],
}, },
"include": ["**/*.ts", "**/*.tsx"], "include": ["**/*.ts", "**/*.tsx"],
} }
import { formatNFTAssetMetatagTitleName } from 'shared-cloud/metatags'
import { AssetDocument, AssetQuery } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' import { AssetDocument, AssetQuery } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks'
import client from '../client' import client from '../client'
function formatTitleName(name: string | undefined, collectionName: string | undefined, tokenId: string) {
if (name) {
return name
}
if (collectionName && tokenId) {
return collectionName + ' #' + tokenId
}
if (tokenId) {
return 'Asset #' + tokenId
}
return 'View NFT on Uniswap'
}
export default async function getAsset(collectionAddress: string, tokenId: string, url: string) { export default async function getAsset(collectionAddress: string, tokenId: string, url: string) {
const origin = new URL(url).origin const origin = new URL(url).origin
const image = origin + '/api/image/nfts/asset/' + collectionAddress + '/' + tokenId const image = origin + '/api/image/nfts/asset/' + collectionAddress + '/' + tokenId
...@@ -30,7 +18,7 @@ export default async function getAsset(collectionAddress: string, tokenId: strin ...@@ -30,7 +18,7 @@ export default async function getAsset(collectionAddress: string, tokenId: strin
if (!asset) { if (!asset) {
return undefined return undefined
} }
const title = formatTitleName(asset.name, asset.collection?.name, asset.tokenId) const title = formatNFTAssetMetatagTitleName(asset.name, asset.collection?.name, asset.tokenId)
const formattedAsset = { const formattedAsset = {
title, title,
image, image,
......
import { formatTokenMetatagTitleName } from 'shared-cloud/metatags'
import { import {
Chain, Chain,
TokenWebDocument, TokenWebDocument,
...@@ -6,16 +7,6 @@ import { ...@@ -6,16 +7,6 @@ import {
import { NATIVE_CHAIN_ID } from '../../src/constants/tokens' import { NATIVE_CHAIN_ID } from '../../src/constants/tokens'
import client from '../client' import client from '../client'
function formatTitleName(symbol: string | undefined, name: string | undefined) {
if (symbol) {
return 'Get ' + symbol + ' on Uniswap'
}
if (name) {
return 'Get ' + name + ' on Uniswap'
}
return 'View Token on Uniswap'
}
const convertTokenAddress = (networkName: string, tokenAddress: string) => { const convertTokenAddress = (networkName: string, tokenAddress: string) => {
if (tokenAddress === NATIVE_CHAIN_ID) { if (tokenAddress === NATIVE_CHAIN_ID) {
switch (networkName) { switch (networkName) {
...@@ -47,7 +38,7 @@ export default async function getToken(networkName: string, tokenAddress: string ...@@ -47,7 +38,7 @@ export default async function getToken(networkName: string, tokenAddress: string
return undefined return undefined
} }
const title = formatTitleName(asset.symbol, asset.name) const title = formatTokenMetatagTitleName(asset.symbol, asset.name)
const formattedAsset = { const formattedAsset = {
title, title,
......
...@@ -7,9 +7,6 @@ ...@@ -7,9 +7,6 @@
"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 7\" \"../../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: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",
"graphql:schema": "node scripts/fetch-schema.js", "graphql:schema": "node scripts/fetch-schema.js",
"graphql:generate:thegraph": "graphql-codegen --config graphql.thegraph.codegen.config.ts", "graphql:generate:thegraph": "graphql-codegen --config graphql.thegraph.codegen.config.ts",
"graphql:generate": "yarn graphql:generate:thegraph", "graphql:generate": "yarn graphql:generate:thegraph",
...@@ -19,7 +16,6 @@ ...@@ -19,7 +16,6 @@
"i18n:download": "./scripts/crowdin.sh download", "i18n:download": "./scripts/crowdin.sh download",
"i18n:download:if-missing": "ONLY_IF_MISSING=1 ./scripts/crowdin.sh download", "i18n:download:if-missing": "ONLY_IF_MISSING=1 ./scripts/crowdin.sh download",
"i18n:extract": "i18next && node ./scripts/fix-empty-i18n-values.js", "i18n:extract": "i18next && node ./scripts/fix-empty-i18n-values.js",
"prepare": "concurrently \"npm:ajv\"",
"start": "craco start", "start": "craco start",
"start:cloud": "NODE_OPTIONS=--dns-result-order=ipv4first PORT=3001 npx wrangler pages dev --compatibility-flags=nodejs_compat --compatibility-date=2023-08-01 --proxy=3001 --port=3000 -- yarn start", "start:cloud": "NODE_OPTIONS=--dns-result-order=ipv4first PORT=3001 npx wrangler pages dev --compatibility-flags=nodejs_compat --compatibility-date=2023-08-01 --proxy=3001 --port=3000 -- yarn start",
"build:production": "yarn i18n:download:if-missing && craco build", "build:production": "yarn i18n:download:if-missing && craco build",
...@@ -198,20 +194,20 @@ ...@@ -198,20 +194,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.1-beta.1", "@uniswap/permit2-sdk": "1.2.1",
"@uniswap/redux-multicall": "1.1.8", "@uniswap/redux-multicall": "1.1.8",
"@uniswap/router-sdk": "1.9.1-beta.2", "@uniswap/router-sdk": "1.9.1",
"@uniswap/sdk-core": "4.2.1-beta.1", "@uniswap/sdk-core": "4.2.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.3-alpha.1", "@uniswap/uniswapx-sdk": "2.0.4-alpha.1",
"@uniswap/universal-router-sdk": "2.0.4-beta.3", "@uniswap/universal-router-sdk": "2.0.4",
"@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.1-beta.2", "@uniswap/v2-sdk": "4.3.1",
"@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.1-beta.2", "@uniswap/v3-sdk": "3.11.1",
"@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",
...@@ -274,7 +270,6 @@ ...@@ -274,7 +270,6 @@
"react-markdown": "4.3.1", "react-markdown": "4.3.1",
"react-native-gesture-handler": "2.15.0", "react-native-gesture-handler": "2.15.0",
"react-popper": "2.3.0", "react-popper": "2.3.0",
"react-query": "3.39.1",
"react-redux": "8.0.5", "react-redux": "8.0.5",
"react-router-dom": "6.10.0", "react-router-dom": "6.10.0",
"react-scroll-sync": "0.11.2", "react-scroll-sync": "0.11.2",
......
...@@ -4,13 +4,9 @@ ...@@ -4,13 +4,9 @@
], ],
"scriptSrc": [ "scriptSrc": [
"'self'", "'self'",
"'unsafe-eval'",
"'unsafe-inline'",
"'wasm-unsafe-eval'", "'wasm-unsafe-eval'",
"data:", "data:",
"https://translate.googleapis.com/", "https://translate.googleapis.com/",
"https://vercel.com",
"https://vercel.live/",
"https://www.google-analytics.com", "https://www.google-analytics.com",
"https://www.googletagmanager.com" "https://www.googletagmanager.com"
], ],
...@@ -21,35 +17,12 @@ ...@@ -21,35 +17,12 @@
], ],
"imgSrc": [ "imgSrc": [
"*", "*",
"'self'",
"blob:", "blob:",
"data:", "data:"
"https://*.uniswap.org",
"https://uniswap.org",
"https://assets.coingecko.com/",
"https://*.amazonaws.com",
"https://basescan.org",
"https://celo-org.github.io/",
"https://cdn.center.app/",
"https://ethereum-optimism.github.io/",
"https://explorer-api.walletconnect.com/",
"https://i.seadn.io/",
"https://lh3.googleusercontent.com/",
"https://openseauserdata.com/",
"https://raw.githubusercontent.com/",
"https://raw.seadn.io/",
"https://s2.coinmarketcap.com/",
"https://static.optimism.io/",
"https://vercel.com",
"https://vercel.live/",
"https://trustwallet.com/",
"https://cloudflare-ipfs.com/"
], ],
"frameSrc": [ "frameSrc": [
"'self'", "'self'",
"https://buy.moonpay.com/", "https://buy.moonpay.com/",
"https://vercel.com",
"https://vercel.live/",
"https://verify.walletconnect.com/", "https://verify.walletconnect.com/",
"https://verify.walletconnect.org/" "https://verify.walletconnect.org/"
], ],
...@@ -57,81 +30,79 @@ ...@@ -57,81 +30,79 @@
"'self'", "'self'",
"blob:", "blob:",
"data:", "data:",
"wss://*.uniswap.org",
"https://*.uniswap.org",
"https://uniswap.org",
"https://arb1.arbitrum.io",
"https://*.coingecko.com/",
"https://*.alchemy.com", "https://*.alchemy.com",
"https://buy.moonpay.com/", "https://*.arbitrum.io",
"https://bsc-dataseed1.binance.org/", "https://*.base.org/",
"https://cdn.center.app/",
"https://cdn.jsdelivr.net/npm/@rive-app/canvas@2.8.3/rive.wasm",
"https://*.coinbase.com", "https://*.coinbase.com",
"https://statsigapi.net", "https://*.coingecko.com/",
"https://*.coinmarketcap.com/",
"https://*.drpc.org/",
"https://*.gemini.com",
"https://*.googleapis.com",
"https://*.infura.io",
"https://*.nodereal.io",
"https://*.optimism.io",
"https://*.quiknode.pro",
"https://*.twnodes.com",
"https://*.uniswap.org",
"https://*.walletconnect.com",
"https://*.zerion.io",
"https://alfajores-forno.celo-testnet.org",
"https://api.avax.network/ext/bc/C/rpc",
"https://api.moonpay.com/", "https://api.moonpay.com/",
"https://api.mycryptoapi.com/eth",
"https://api.opensea.io", "https://api.opensea.io",
"https://api.studio.thegraph.com/",
"https://api.thegraph.com/", "https://api.thegraph.com/",
"https://arbitrum-mainnet.infura.io/", "https://bsc-dataseed1.binance.org/",
"https://assets.coingecko.com", "https://bsc-dataseed1.bnbchain.org",
"https://avalanche-mainnet.infura.io/", "https://buy.moonpay.com/",
"https://base-mainnet.infura.io/", "https://cdn.center.app/",
"https://bridge.arbitrum.io", "https://cdn.jsdelivr.net/npm/@rive-app/canvas@2.8.3/rive.wasm",
"https://celo-mainnet.infura.io/",
"https://celo-org.github.io", "https://celo-org.github.io",
"https://cloudflare-ipfs.com", "https://cloudflare-ipfs.com",
"https://*.zerion.io",
"https://*.drpc.org/",
"https://*.base.org/",
"https://*.walletconnect.com",
"https://ethereum-optimism.github.io/", "https://ethereum-optimism.github.io/",
"https://forno.celo.org/", "https://forno.celo.org/",
"https://*.gemini.com",
"https://gateway.ipfs.io/", "https://gateway.ipfs.io/",
"https://i.seadn.io/", "https://i.seadn.io/",
"https://invalid.rpki.cloudflare.com/",
"https://ipfs.io/", "https://ipfs.io/",
"https://ipv4-check-perf.radar.cloudflare.com",
"https://ipv6-check-perf.radar.cloudflare.com/",
"https://lh3.googleusercontent.com/", "https://lh3.googleusercontent.com/",
"https://mainnet.infura.io", "https://mainnet.base.org/",
"https://*.nodereal.io",
"https://o1037921.ingest.sentry.io", "https://o1037921.ingest.sentry.io",
"https://old-wispy-arrow.bsc.quiknode.pro/",
"https://openseauserdata.com/", "https://openseauserdata.com/",
"https://performance.radar.cloudflare.com/", "https://performance.radar.cloudflare.com/",
"https://valid.rpki.cloudflare.com", "https://polygon-rpc.com/",
"https://sparrow.cloudflare.com/",
"https://ipv4-check-perf.radar.cloudflare.com",
"https://ipv6-check-perf.radar.cloudflare.com/",
"https://invalid.rpki.cloudflare.com/",
"https://raw.githubusercontent.com", "https://raw.githubusercontent.com",
"https://raw.seadn.io/", "https://raw.seadn.io/",
"https://rpc-mainnet.maticvigil.com",
"https://rpc-mumbai.maticvigil.com",
"https://rpc.ankr.com", "https://rpc.ankr.com",
"https://rpc.blast.io/",
"https://rpc.degen.tips", "https://rpc.degen.tips",
"https://rpc-mainnet.maticvigil.com", "https://rpc.goerli.mudit.blog/",
"https://rpc.mevblocker.io/", "https://rpc.mevblocker.io/",
"https://rpc.scroll.io/", "https://rpc.scroll.io/",
"https://*.coinmarketcap.com/", "https://rpc.sepolia.org/",
"https://*.optimism.io",
"https://sockjs-us3.pusher.com/", "https://sockjs-us3.pusher.com/",
"https://api.studio.thegraph.com/", "https://sparrow.cloudflare.com/",
"https://*.googleapis.com", "https://statsigapi.net",
"https://trustwallet.com", "https://trustwallet.com",
"https://*.arbitrum.io", "https://uniswap.org",
"https://tokens.coingecko.com",
"https://*.twnodes.com",
"https://ultra-blue-flower.quiknode.pro",
"https://unpkg.com/@rive-app/canvas@2.8.3/rive.wasm", "https://unpkg.com/@rive-app/canvas@2.8.3/rive.wasm",
"https://us-central1-uniswap-mobile.cloudfunctions.net/", "https://us-central1-uniswap-mobile.cloudfunctions.net/",
"https://valid.rpki.cloudflare.com",
"https://vercel.com", "https://vercel.com",
"https://vercel.live/", "https://vercel.live/",
"https://wallet.crypto.com", "https://wallet.crypto.com",
"https://web3.1inch.io", "https://web3.1inch.io",
"https://www.gemini.com", "wss://*.uniswap.org",
"https://*.quiknode.pro",
"https://*.infura.io",
"wss://relay.walletconnect.com", "wss://relay.walletconnect.com",
"wss://relay.walletconnect.org", "wss://relay.walletconnect.org",
"wss://www.walletlink.org", "wss://ws-us3.pusher.com/",
"wss://ws-us3.pusher.com/" "wss://www.walletlink.org"
], ],
"workerSrc": [ "workerSrc": [
"'self'", "'self'",
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta name="theme-color" content="#fff" /> <meta name="theme-color" content="#fff" />
<% const cspConfig = require('./csp.json'); %> <% let cspConfig = require('./csp.json'); %>
<!-- Allow vercel feedback in preview environments -->
<% if (process.env.REACT_APP_STAGING) { %>
<% const cspDevConfig = require('./vercel-csp.json'); %>
<% Object.entries(cspDevConfig).forEach(([key, value]) => cspConfig[key] = cspConfig[key].concat(value)) %>
<% } %>
<meta <meta
http-equiv="Content-Security-Policy" http-equiv="Content-Security-Policy"
content="default-src <%= cspConfig.defaultSrc.join(' ') %>; script-src <%= cspConfig.scriptSrc.join(' ') %>; style-src <%= cspConfig.styleSrc.join(' ') %>; img-src <%= cspConfig.imgSrc.join(' ') %>; frame-src <%= cspConfig.frameSrc.join(' ') %>; connect-src <%= cspConfig.connectSrc.join(' ') %>; worker-src <%= cspConfig.workerSrc.join(' ') %>;" content="default-src <%= cspConfig.defaultSrc.join(' ') %>; script-src <%= cspConfig.scriptSrc.join(' ') %>; style-src <%= cspConfig.styleSrc.join(' ') %>; img-src <%= cspConfig.imgSrc.join(' ') %>; frame-src <%= cspConfig.frameSrc.join(' ') %>; connect-src <%= cspConfig.connectSrc.join(' ') %>; worker-src <%= cspConfig.workerSrc.join(' ') %>;"
......
{
"scriptSrc": [
"https://vercel.live/"
],
"styleSrc": [
"https://vercel.live/"
],
"frameSrc": [
"https://vercel.live/",
"https://vercel.com"
]
}
import { ChainId, Currency } from '@uniswap/sdk-core' import { Currency } from '@uniswap/sdk-core'
import { SupportedInterfaceChainId, chainIdToBackendChain } from 'constants/chains'
import { NATIVE_CHAIN_ID, nativeOnChain } from 'constants/tokens' import { NATIVE_CHAIN_ID, nativeOnChain } from 'constants/tokens'
import { apolloClient } from 'graphql/data/apollo/client' import { apolloClient } from 'graphql/data/apollo/client'
import { gqlTokenToCurrencyInfo } from 'graphql/data/types' import { gqlTokenToCurrencyInfo } from 'graphql/data/types'
import { chainIdToBackendName } from 'graphql/data/util'
import { import {
SimpleTokenDocument, SimpleTokenDocument,
SimpleTokenQuery, SimpleTokenQuery,
Token, Token,
} from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks' } from 'uniswap/src/data/graphql/uniswap-data-api/__generated__/types-and-hooks'
export async function getCurrency(currencyId: string, chainId: ChainId): Promise<Currency | undefined> { export async function getCurrency(
currencyId: string,
chainId: SupportedInterfaceChainId
): Promise<Currency | undefined> {
const isNative = const isNative =
currencyId === NATIVE_CHAIN_ID || currencyId?.toLowerCase() === 'native' || currencyId?.toLowerCase() === 'eth' currencyId === NATIVE_CHAIN_ID || currencyId?.toLowerCase() === 'native' || currencyId?.toLowerCase() === 'eth'
if (isNative) { if (isNative) {
...@@ -19,7 +22,7 @@ export async function getCurrency(currencyId: string, chainId: ChainId): Promise ...@@ -19,7 +22,7 @@ export async function getCurrency(currencyId: string, chainId: ChainId): Promise
query: SimpleTokenDocument, query: SimpleTokenDocument,
variables: { variables: {
address: currencyId, address: currencyId,
chain: chainIdToBackendName(chainId), chain: chainIdToBackendChain({ chainId }),
}, },
}) })
return gqlTokenToCurrencyInfo(data?.token as Token)?.currency return gqlTokenToCurrencyInfo(data?.token as Token)?.currency
......
...@@ -3,7 +3,6 @@ import { ChainId, Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core' ...@@ -3,7 +3,6 @@ import { ChainId, Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core'
import UniswapXBolt from 'assets/svg/bolt.svg' import UniswapXBolt from 'assets/svg/bolt.svg'
import { nativeOnChain } from 'constants/tokens' import { nativeOnChain } from 'constants/tokens'
import { t } from 'i18n' import { t } from 'i18n'
import { useCallback } from 'react'
import { isOnChainOrder, useAllSignatures } from 'state/signatures/hooks' import { isOnChainOrder, useAllSignatures } from 'state/signatures/hooks'
import { SignatureDetails, SignatureType } from 'state/signatures/types' import { SignatureDetails, SignatureType } from 'state/signatures/types'
import { useMultichainTransactions } from 'state/transactions/hooks' import { useMultichainTransactions } from 'state/transactions/hooks'
...@@ -26,9 +25,10 @@ import { TransactionStatus } from 'uniswap/src/data/graphql/uniswap-data-api/__g ...@@ -26,9 +25,10 @@ import { TransactionStatus } from 'uniswap/src/data/graphql/uniswap-data-api/__g
import { isAddress } from 'utilities/src/addresses' import { isAddress } from 'utilities/src/addresses'
import { NumberType, useFormatter } from 'utils/formatNumbers' import { NumberType, useFormatter } from 'utils/formatNumbers'
import { queryOptions, useQuery } from '@tanstack/react-query'
import { getCurrency } from 'components/AccountDrawer/MiniPortfolio/Activity/getCurrency' import { getCurrency } from 'components/AccountDrawer/MiniPortfolio/Activity/getCurrency'
import { useQuery } from 'react-query' import { SupportedInterfaceChainId } from 'constants/chains'
import { CancelledTransactionTitleTable, getActivityTitle, LimitOrderTextTable, OrderTextTable } from '../constants' import { CancelledTransactionTitleTable, LimitOrderTextTable, OrderTextTable, getActivityTitle } from '../constants'
import { Activity, ActivityMap } from './types' import { Activity, ActivityMap } from './types'
type FormatNumberFunctionType = ReturnType<typeof useFormatter>['formatNumber'] type FormatNumberFunctionType = ReturnType<typeof useFormatter>['formatNumber']
...@@ -60,7 +60,7 @@ function buildCurrencyDescriptor( ...@@ -60,7 +60,7 @@ function buildCurrencyDescriptor(
async function parseSwap( async function parseSwap(
swap: ExactInputSwapTransactionInfo | ExactOutputSwapTransactionInfo, swap: ExactInputSwapTransactionInfo | ExactOutputSwapTransactionInfo,
chainId: ChainId, chainId: SupportedInterfaceChainId,
formatNumber: FormatNumberFunctionType formatNumber: FormatNumberFunctionType
): Promise<Partial<Activity>> { ): Promise<Partial<Activity>> {
const [tokenIn, tokenOut] = await Promise.all([ const [tokenIn, tokenOut] = await Promise.all([
...@@ -104,7 +104,7 @@ function parseWrap( ...@@ -104,7 +104,7 @@ function parseWrap(
async function parseApproval( async function parseApproval(
approval: ApproveTransactionInfo, approval: ApproveTransactionInfo,
chainId: ChainId, chainId: SupportedInterfaceChainId,
status: TransactionStatus status: TransactionStatus
): Promise<Partial<Activity>> { ): Promise<Partial<Activity>> {
const currency = await getCurrency(approval.tokenAddress, chainId) const currency = await getCurrency(approval.tokenAddress, chainId)
...@@ -126,7 +126,7 @@ type GenericLPInfo = Omit< ...@@ -126,7 +126,7 @@ type GenericLPInfo = Omit<
> >
async function parseLP( async function parseLP(
lp: GenericLPInfo, lp: GenericLPInfo,
chainId: ChainId, chainId: SupportedInterfaceChainId,
formatNumber: FormatNumberFunctionType formatNumber: FormatNumberFunctionType
): Promise<Partial<Activity>> { ): Promise<Partial<Activity>> {
const [baseCurrency, quoteCurrency] = await Promise.all([ const [baseCurrency, quoteCurrency] = await Promise.all([
...@@ -141,7 +141,7 @@ async function parseLP( ...@@ -141,7 +141,7 @@ async function parseLP(
async function parseCollectFees( async function parseCollectFees(
collect: CollectFeesTransactionInfo, collect: CollectFeesTransactionInfo,
chainId: ChainId, chainId: SupportedInterfaceChainId,
formatNumber: FormatNumberFunctionType formatNumber: FormatNumberFunctionType
): Promise<Partial<Activity>> { ): Promise<Partial<Activity>> {
// Adapts CollectFeesTransactionInfo to generic LP type // Adapts CollectFeesTransactionInfo to generic LP type
...@@ -160,7 +160,7 @@ async function parseCollectFees( ...@@ -160,7 +160,7 @@ async function parseCollectFees(
async function parseMigrateCreateV3( async function parseMigrateCreateV3(
lp: MigrateV2LiquidityToV3TransactionInfo | CreateV3PoolTransactionInfo, lp: MigrateV2LiquidityToV3TransactionInfo | CreateV3PoolTransactionInfo,
chainId: ChainId chainId: SupportedInterfaceChainId
): Promise<Partial<Activity>> { ): Promise<Partial<Activity>> {
const [baseCurrency, quoteCurrency] = await Promise.all([ const [baseCurrency, quoteCurrency] = await Promise.all([
getCurrency(lp.baseCurrencyId, chainId), getCurrency(lp.baseCurrencyId, chainId),
...@@ -175,7 +175,7 @@ async function parseMigrateCreateV3( ...@@ -175,7 +175,7 @@ async function parseMigrateCreateV3(
async function parseSend( async function parseSend(
send: SendTransactionInfo, send: SendTransactionInfo,
chainId: ChainId, chainId: SupportedInterfaceChainId,
formatNumber: FormatNumberFunctionType formatNumber: FormatNumberFunctionType
): Promise<Partial<Activity>> { ): Promise<Partial<Activity>> {
const { currencyId, amount, recipient } = send const { currencyId, amount, recipient } = send
...@@ -202,22 +202,9 @@ export function getTransactionStatus(details: TransactionDetails): TransactionSt ...@@ -202,22 +202,9 @@ export function getTransactionStatus(details: TransactionDetails): TransactionSt
: TransactionStatus.Failed : TransactionStatus.Failed
} }
// useQuery wrapper for transactionToActivity, for async fetching
export function useTransactionToActivity(transaction: TransactionDetails | undefined, chainId: ChainId) {
const { formatNumber } = useFormatter()
const activityFetcher = useCallback(
async () => transactionToActivity(transaction, chainId, formatNumber),
[chainId, formatNumber, transaction]
)
const { data: activity } = useQuery(`transactionToActivity-${transaction?.hash}-${chainId}`, activityFetcher, {
enabled: !!transaction,
})
return activity
}
export async function transactionToActivity( export async function transactionToActivity(
details: TransactionDetails | undefined, details: TransactionDetails | undefined,
chainId: ChainId, chainId: SupportedInterfaceChainId,
formatNumber: FormatNumberFunctionType formatNumber: FormatNumberFunctionType
): Promise<Activity | undefined> { ): Promise<Activity | undefined> {
if (!details) return undefined if (!details) return undefined
...@@ -271,13 +258,25 @@ export async function transactionToActivity( ...@@ -271,13 +258,25 @@ export async function transactionToActivity(
} }
} }
export function useSignatureToActivity(signature: SignatureDetails | undefined) { export function getTransactionToActivityQueryOptions(
const { formatNumber } = useFormatter() transaction: TransactionDetails | undefined,
chainId: SupportedInterfaceChainId,
formatNumber: FormatNumberFunctionType
) {
return queryOptions({
queryKey: ['transactionToActivity', transaction, chainId],
queryFn: async () => transactionToActivity(transaction, chainId, formatNumber),
})
}
const { data: activity } = useQuery(`signatureToActivity-${signature?.orderHash}`, async () => { export function getSignatureToActivityQueryOptions(
return await signatureToActivity(signature, formatNumber) signature: SignatureDetails | undefined,
formatNumber: FormatNumberFunctionType
) {
return queryOptions({
queryKey: ['signatureToActivity', signature],
queryFn: async () => signatureToActivity(signature, formatNumber),
}) })
return activity
} }
function convertToSecTimestamp(timestamp: number) { function convertToSecTimestamp(timestamp: number) {
...@@ -342,7 +341,9 @@ export function useLocalActivities(account: string): ActivityMap { ...@@ -342,7 +341,9 @@ export function useLocalActivities(account: string): ActivityMap {
const allSignatures = useAllSignatures() const allSignatures = useAllSignatures()
const { formatNumber } = useFormatter() const { formatNumber } = useFormatter()
const activityParser = useCallback(async () => { const { data } = useQuery({
queryKey: ['localActivities', account],
queryFn: async () => {
const transactions = Object.values(allTransactions) const transactions = Object.values(allTransactions)
.filter(([transaction]) => transaction.from === account) .filter(([transaction]) => transaction.from === account)
.map(([transaction, chainId]) => transactionToActivity(transaction, chainId, formatNumber)) .map(([transaction, chainId]) => transactionToActivity(transaction, chainId, formatNumber))
...@@ -354,12 +355,8 @@ export function useLocalActivities(account: string): ActivityMap { ...@@ -354,12 +355,8 @@ export function useLocalActivities(account: string): ActivityMap {
if (activity) acc[activity.hash] = activity if (activity) acc[activity.hash] = activity
return acc return acc
}, {} as ActivityMap) }, {} as ActivityMap)
}, [account, allSignatures, allTransactions, formatNumber]) },
})
const { data } = useQuery(
`localActivities-${account}-${allSignatures.length}-${allTransactions.length}`,
activityParser
)
return data ?? {} return data ?? {}
} }
import { ChainId, Currency, NONFUNGIBLE_POSITION_MANAGER_ADDRESSES, TradeType, UNI_ADDRESSES } from '@uniswap/sdk-core' import { ChainId, Currency, NONFUNGIBLE_POSITION_MANAGER_ADDRESSES, TradeType, UNI_ADDRESSES } from '@uniswap/sdk-core'
import UniswapXBolt from 'assets/svg/bolt.svg' import UniswapXBolt from 'assets/svg/bolt.svg'
import moonpayLogoSrc from 'assets/svg/moonpay.svg' import moonpayLogoSrc from 'assets/svg/moonpay.svg'
import { asSupportedChain } from 'constants/chains'
import { NATIVE_CHAIN_ID, nativeOnChain } from 'constants/tokens' import { NATIVE_CHAIN_ID, nativeOnChain } from 'constants/tokens'
import { BigNumber } from 'ethers/lib/ethers' import { BigNumber } from 'ethers/lib/ethers'
import { formatUnits, parseUnits } from 'ethers/lib/utils' import { formatUnits, parseUnits } from 'ethers/lib/utils'
...@@ -272,7 +271,7 @@ export function offchainOrderDetailsFromGraphQLTransactionActivity( ...@@ -272,7 +271,7 @@ export function offchainOrderDetailsFromGraphQLTransactionActivity(
changes: TransactionChanges, changes: TransactionChanges,
formatNumberOrString: FormatNumberOrStringFunctionType formatNumberOrString: FormatNumberOrStringFunctionType
): UniswapXOrderDetails | undefined { ): UniswapXOrderDetails | undefined {
const chainId = asSupportedChain(supportedChainIdFromGQLChain(activity.chain)) const chainId = supportedChainIdFromGQLChain(activity.chain)
if (!activity || !activity.details || !chainId) return undefined if (!activity || !activity.details || !chainId) return undefined
if (changes.TokenTransfer.length < 2) return undefined if (changes.TokenTransfer.length < 2) return undefined
......
...@@ -8,7 +8,7 @@ import type { AddressMap } from '@uniswap/smart-order-router' ...@@ -8,7 +8,7 @@ import type { AddressMap } from '@uniswap/smart-order-router'
import NFTPositionManagerJSON from '@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json' import NFTPositionManagerJSON from '@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json'
import MulticallJSON from '@uniswap/v3-periphery/artifacts/contracts/lens/UniswapInterfaceMulticall.sol/UniswapInterfaceMulticall.json' import MulticallJSON from '@uniswap/v3-periphery/artifacts/contracts/lens/UniswapInterfaceMulticall.sol/UniswapInterfaceMulticall.json'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { isSupportedChain } from 'constants/chains' import { useIsSupportedChainIdCallback } from 'constants/chains'
import { RPC_PROVIDERS } from 'constants/providers' import { RPC_PROVIDERS } from 'constants/providers'
import { BaseContract } from 'ethers/lib/ethers' import { BaseContract } from 'ethers/lib/ethers'
import { toContractInput } from 'graphql/data/util' import { toContractInput } from 'graphql/data/util'
...@@ -32,6 +32,7 @@ export function useContractMultichain<T extends BaseContract>( ...@@ -32,6 +32,7 @@ export function useContractMultichain<T extends BaseContract>(
chainIds?: ChainId[] chainIds?: ChainId[]
): ContractMap<T> { ): ContractMap<T> {
const { chainId: walletChainId, provider: walletProvider } = useWeb3React() const { chainId: walletChainId, provider: walletProvider } = useWeb3React()
const isSupportedChain = useIsSupportedChainIdCallback()
return useMemo(() => { return useMemo(() => {
const relevantChains = const relevantChains =
...@@ -52,7 +53,7 @@ export function useContractMultichain<T extends BaseContract>( ...@@ -52,7 +53,7 @@ export function useContractMultichain<T extends BaseContract>(
} }
return acc return acc
}, {}) }, {})
}, [ABI, addressMap, chainIds, walletChainId, walletProvider]) }, [ABI, addressMap, chainIds, isSupportedChain, walletChainId, walletProvider])
} }
export function useV3ManagerContracts(chainIds: ChainId[]): ContractMap<NonfungiblePositionManager> { export function useV3ManagerContracts(chainIds: ChainId[]): ContractMap<NonfungiblePositionManager> {
......
...@@ -10,6 +10,7 @@ import { UniswapV3PoolInterface } from 'uniswap/src/abis/types/v3/UniswapV3Pool' ...@@ -10,6 +10,7 @@ import { UniswapV3PoolInterface } from 'uniswap/src/abis/types/v3/UniswapV3Pool'
import { DEFAULT_ERC20_DECIMALS } from 'utilities/src/tokens/constants' import { DEFAULT_ERC20_DECIMALS } from 'utilities/src/tokens/constants'
import { currencyKey } from 'utils/currencyKey' import { currencyKey } from 'utils/currencyKey'
import { L1_CHAIN_IDS, L2_CHAIN_IDS, TESTNET_CHAIN_IDS } from 'constants/chains'
import { PositionInfo, useCachedPositions, useGetCachedTokens, usePoolAddressCache } from './cache' import { PositionInfo, useCachedPositions, useGetCachedTokens, usePoolAddressCache } from './cache'
import { Call, DEFAULT_GAS_LIMIT } from './getTokensAsync' import { Call, DEFAULT_GAS_LIMIT } from './getTokensAsync'
import { useInterfaceMulticallContracts, usePoolPriceMap, useV3ManagerContracts } from './hooks' import { useInterfaceMulticallContracts, usePoolPriceMap, useV3ManagerContracts } from './hooks'
...@@ -39,17 +40,9 @@ type FeeAmounts = [BigNumber, BigNumber] ...@@ -39,17 +40,9 @@ type FeeAmounts = [BigNumber, BigNumber]
const MAX_UINT128 = BigNumber.from(2).pow(128).sub(1) const MAX_UINT128 = BigNumber.from(2).pow(128).sub(1)
const DEFAULT_CHAINS = [ const DEFAULT_CHAINS = [...L1_CHAIN_IDS, ...L2_CHAIN_IDS].filter((chain: number) => {
ChainId.MAINNET, return !TESTNET_CHAIN_IDS.includes(chain)
ChainId.ARBITRUM_ONE, })
ChainId.OPTIMISM,
ChainId.POLYGON,
ChainId.CELO,
ChainId.BNB,
ChainId.AVALANCHE,
ChainId.BASE,
ChainId.BLAST,
]
type UseMultiChainPositionsData = { positions?: PositionInfo[]; loading: boolean } type UseMultiChainPositionsData = { positions?: PositionInfo[]; loading: boolean }
......
...@@ -10,7 +10,7 @@ import { useRef, useState } from 'react' ...@@ -10,7 +10,7 @@ import { useRef, useState } from 'react'
import { MoreHorizontal } from 'react-feather' import { MoreHorizontal } from 'react-feather'
import styled from 'styled-components' import styled from 'styled-components'
import { ClickableStyle, CopyHelper, EllipsisStyle, ThemedText } from 'theme/components' import { ClickableStyle, CopyHelper, EllipsisStyle, ThemedText } from 'theme/components'
import { Unitag } from 'ui/src/components/icons/Unitag' import { Unitag } from 'ui/src/components/icons'
import { shortenAddress } from 'utilities/src/addresses' import { shortenAddress } from 'utilities/src/addresses'
const Container = styled.div` const Container = styled.div`
......
...@@ -103,6 +103,7 @@ const AccountDrawerWrapper = styled.div<{ open: boolean }>` ...@@ -103,6 +103,7 @@ const AccountDrawerWrapper = styled.div<{ open: boolean }>`
height: calc(100% - ${DRAWER_TOP_MARGIN_MOBILE_WEB}); height: calc(100% - ${DRAWER_TOP_MARGIN_MOBILE_WEB});
width: 100%; width: 100%;
max-width: 100%;
border-bottom-right-radius: 0px; border-bottom-right-radius: 0px;
border-bottom-left-radius: 0px; border-bottom-left-radius: 0px;
box-shadow: unset; box-shadow: unset;
......
import { ChainId } from '@uniswap/sdk-core' import { ChainId } from '@uniswap/sdk-core'
import { Container, PopupContainer, StyledXButton, TextContainer } from 'components/Banner/shared/styled' import { Container, PopupContainer, StyledXButton, TextContainer } from 'components/Banner/shared/styled'
import { chainIdToBackendChain } from 'constants/chains'
import { ChainOutageData } from 'featureFlags/flags/outageBanner' import { ChainOutageData } from 'featureFlags/flags/outageBanner'
import { chainIdToBackendName } from 'graphql/data/util'
import { Trans } from 'i18n' import { Trans } from 'i18n'
import { useState } from 'react' import { useState } from 'react'
import { Globe } from 'react-feather' import { Globe } from 'react-feather'
...@@ -43,7 +43,7 @@ export function OutageBanner({ chainId, version }: ChainOutageData) { ...@@ -43,7 +43,7 @@ export function OutageBanner({ chainId, version }: ChainOutageData) {
const [hidden, setHidden] = useState(false) const [hidden, setHidden] = useState(false)
const theme = useTheme() const theme = useTheme()
const versionName = version ? version.toString().toLowerCase() + ' data' : 'Data' const versionName = version ? version.toString().toLowerCase() + ' data' : 'Data'
const chainName = capitalize(chainIdToBackendName(chainId).toLowerCase()) const chainName = capitalize(chainIdToBackendChain({ chainId, withFallback: true }).toLowerCase())
const versionDescription = version ? ' ' + version.toString().toLowerCase() : '' const versionDescription = version ? ' ' + version.toString().toLowerCase() : ''
return ( return (
......
import { InterfacePageName } from '@uniswap/analytics-events' import { InterfacePageName } from '@uniswap/analytics-events'
import { ChainId } from '@uniswap/sdk-core' import { ChainId } from '@uniswap/sdk-core'
import { OutageBanner, getOutageBannerSessionStorageKey } from 'components/Banner/Outage/OutageBanner' import { OutageBanner, getOutageBannerSessionStorageKey } from 'components/Banner/Outage/OutageBanner'
import { getChainFromChainUrlParam, isChainUrlParam } from 'constants/chains'
import { manualChainOutageAtom, useOutageBanners } from 'featureFlags/flags/outageBanner' import { manualChainOutageAtom, useOutageBanners } from 'featureFlags/flags/outageBanner'
import { getValidUrlChainId } from 'graphql/data/util'
import { useAtomValue } from 'jotai/utils' import { useAtomValue } from 'jotai/utils'
import { useMemo } from 'react' import { useMemo } from 'react'
import { useLocation } from 'react-router-dom' import { useLocation } from 'react-router-dom'
...@@ -17,11 +17,8 @@ export function Banners() { ...@@ -17,11 +17,8 @@ export function Banners() {
// Calculate the chainId for the current page's contextual chain (e.g. /tokens/ethereum or /tokens/arbitrum), if it exists. // Calculate the chainId for the current page's contextual chain (e.g. /tokens/ethereum or /tokens/arbitrum), if it exists.
const pageChainId = useMemo(() => { const pageChainId = useMemo(() => {
const chainName = pathname.split('/').find((maybeChainName) => { const chainUrlParam = pathname.split('/').find(isChainUrlParam)
const validatedChainId = getValidUrlChainId(maybeChainName) return chainUrlParam ? getChainFromChainUrlParam(chainUrlParam)?.id : ChainId.MAINNET
return validatedChainId !== undefined
})
return chainName ? getValidUrlChainId(chainName) : ChainId.MAINNET
}, [pathname]) }, [pathname])
const currentPageHasManualOutage = manualOutage?.chainId === pageChainId const currentPageHasManualOutage = manualOutage?.chainId === pageChainId
...@@ -29,7 +26,7 @@ export function Banners() { ...@@ -29,7 +26,7 @@ export function Banners() {
return ( return (
currentPage && currentPage &&
pageChainId && pageChainId &&
(outageBanners[pageChainId as ChainId] || currentPageHasManualOutage) && (outageBanners[pageChainId] || currentPageHasManualOutage) &&
!sessionStorage.getItem(getOutageBannerSessionStorageKey(pageChainId)) && !sessionStorage.getItem(getOutageBannerSessionStorageKey(pageChainId)) &&
[ [
InterfacePageName.EXPLORE_PAGE, InterfacePageName.EXPLORE_PAGE,
......
...@@ -55,6 +55,7 @@ export function ConfirmSwapModal({ ...@@ -55,6 +55,7 @@ export function ConfirmSwapModal({
fiatValueOutput, fiatValueOutput,
swapResult, swapResult,
swapError, swapError,
priceImpact,
clearSwapState, clearSwapState,
onAcceptChanges, onAcceptChanges,
onConfirm, onConfirm,
...@@ -70,6 +71,7 @@ export function ConfirmSwapModal({ ...@@ -70,6 +71,7 @@ export function ConfirmSwapModal({
fiatValueOutput: { data?: number; isLoading: boolean } fiatValueOutput: { data?: number; isLoading: boolean }
swapResult?: SwapResult swapResult?: SwapResult
swapError?: Error swapError?: Error
priceImpact?: Percent
clearSwapState: () => void clearSwapState: () => void
onAcceptChanges?: () => void onAcceptChanges?: () => void
onConfirm: () => void onConfirm: () => void
...@@ -219,6 +221,7 @@ export function ConfirmSwapModal({ ...@@ -219,6 +221,7 @@ export function ConfirmSwapModal({
showAcceptChanges={Boolean(showAcceptChanges)} showAcceptChanges={Boolean(showAcceptChanges)}
onAcceptChanges={onAcceptChanges} onAcceptChanges={onAcceptChanges}
swapErrorMessage={swapFailed ? swapError?.message : undefined} swapErrorMessage={swapFailed ? swapError?.message : undefined}
priceImpact={priceImpact}
/> />
</AutoColumn> </AutoColumn>
</FadePresence> </FadePresence>
......
...@@ -8,7 +8,7 @@ import { LoadingOpacityContainer } from 'components/Loader/styled' ...@@ -8,7 +8,7 @@ import { LoadingOpacityContainer } from 'components/Loader/styled'
import CurrencyLogo from 'components/Logo/CurrencyLogo' import CurrencyLogo from 'components/Logo/CurrencyLogo'
import { StyledNumericalInput } from 'components/NumericalInput' import { StyledNumericalInput } from 'components/NumericalInput'
import Tooltip from 'components/Tooltip' import Tooltip from 'components/Tooltip'
import { isSupportedChain } from 'constants/chains' import { useIsSupportedChainId } from 'constants/chains'
import { Trans } from 'i18n' import { Trans } from 'i18n'
import ms from 'ms' import ms from 'ms'
import { darken } from 'polished' import { darken } from 'polished'
...@@ -269,6 +269,7 @@ const SwapCurrencyInputPanel = forwardRef<HTMLInputElement, SwapCurrencyInputPan ...@@ -269,6 +269,7 @@ const SwapCurrencyInputPanel = forwardRef<HTMLInputElement, SwapCurrencyInputPan
) => { ) => {
const [modalOpen, setModalOpen] = useState(false) const [modalOpen, setModalOpen] = useState(false)
const { account, chainId } = useWeb3React() const { account, chainId } = useWeb3React()
const chainAllowed = useIsSupportedChainId(chainId)
const selectedCurrencyBalance = useCurrencyBalance(account ?? undefined, currency ?? undefined) const selectedCurrencyBalance = useCurrencyBalance(account ?? undefined, currency ?? undefined)
const theme = useTheme() const theme = useTheme()
const { formatCurrencyAmount } = useFormatter() const { formatCurrencyAmount } = useFormatter()
...@@ -286,8 +287,6 @@ const SwapCurrencyInputPanel = forwardRef<HTMLInputElement, SwapCurrencyInputPan ...@@ -286,8 +287,6 @@ const SwapCurrencyInputPanel = forwardRef<HTMLInputElement, SwapCurrencyInputPan
} }
}, [tooltipVisible, numericalInputSettings]) }, [tooltipVisible, numericalInputSettings])
const chainAllowed = isSupportedChain(chainId)
// reset tooltip state when currency changes // reset tooltip state when currency changes
useEffect(() => setTooltipVisible(false), [currency]) useEffect(() => setTooltipVisible(false), [currency])
......
...@@ -4,7 +4,7 @@ import { Pair } from '@uniswap/v2-sdk' ...@@ -4,7 +4,7 @@ import { Pair } from '@uniswap/v2-sdk'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { TraceEvent } from 'analytics' import { TraceEvent } from 'analytics'
import { LoadingOpacityContainer, loadingOpacityMixin } from 'components/Loader/styled' import { LoadingOpacityContainer, loadingOpacityMixin } from 'components/Loader/styled'
import { isSupportedChain } from 'constants/chains' import { useIsSupportedChainId } from 'constants/chains'
import { Trans } from 'i18n' import { Trans } from 'i18n'
import { darken } from 'polished' import { darken } from 'polished'
import { ReactNode, useCallback, useState } from 'react' import { ReactNode, useCallback, useState } from 'react'
...@@ -215,6 +215,7 @@ export default function CurrencyInputPanel({ ...@@ -215,6 +215,7 @@ export default function CurrencyInputPanel({
}: CurrencyInputPanelProps) { }: CurrencyInputPanelProps) {
const [modalOpen, setModalOpen] = useState(false) const [modalOpen, setModalOpen] = useState(false)
const { account, chainId } = useWeb3React() const { account, chainId } = useWeb3React()
const chainAllowed = useIsSupportedChainId(chainId)
const selectedCurrencyBalance = useCurrencyBalance(account ?? undefined, currency ?? undefined) const selectedCurrencyBalance = useCurrencyBalance(account ?? undefined, currency ?? undefined)
const theme = useTheme() const theme = useTheme()
const { formatCurrencyAmount } = useFormatter() const { formatCurrencyAmount } = useFormatter()
...@@ -223,8 +224,6 @@ export default function CurrencyInputPanel({ ...@@ -223,8 +224,6 @@ export default function CurrencyInputPanel({
setModalOpen(false) setModalOpen(false)
}, [setModalOpen]) }, [setModalOpen])
const chainAllowed = isSupportedChain(chainId)
return ( return (
<InputPanel id={id} hideInput={hideInput} {...rest}> <InputPanel id={id} hideInput={hideInput} {...rest}>
{!locked && ( {!locked && (
......
...@@ -224,12 +224,10 @@ export default function FeatureFlagModal() { ...@@ -224,12 +224,10 @@ export default function FeatureFlagModal() {
</CloseButton> </CloseButton>
</Header> </Header>
<FlagsColumn> <FlagsColumn>
<FeatureFlagOption flag={FeatureFlags.SendEnabled} label="Send on swap component" />
<FeatureFlagOption <FeatureFlagOption
flag={FeatureFlags.Eip6936Enabled} flag={FeatureFlags.Eip6936Enabled}
label="Enable EIP-6963: Multi Injected Provider Discovery" label="Enable EIP-6963: Multi Injected Provider Discovery"
/> />
<FeatureFlagOption flag={FeatureFlags.LimitsEnabled} label="Enable Limits" />
<FeatureFlagOption flag={FeatureFlags.LimitsFees} label="Enable Limits fees" /> <FeatureFlagOption flag={FeatureFlags.LimitsFees} label="Enable Limits fees" />
<FeatureFlagOption flag={FeatureFlags.CurrencyConversion} label="Enable currency conversion" /> <FeatureFlagOption flag={FeatureFlags.CurrencyConversion} label="Enable currency conversion" />
<FeatureFlagOption flag={FeatureFlags.UniconsV2} label="Unicon V2" /> <FeatureFlagOption flag={FeatureFlags.UniconsV2} label="Unicon V2" />
...@@ -238,6 +236,7 @@ export default function FeatureFlagModal() { ...@@ -238,6 +236,7 @@ export default function FeatureFlagModal() {
<FeatureFlagOption flag={FeatureFlags.V2Explore} label="Enable V2 Explore Data" /> <FeatureFlagOption flag={FeatureFlags.V2Explore} label="Enable V2 Explore Data" />
<FeatureFlagOption flag={FeatureFlags.Realtime} label="Realtime activity updates" /> <FeatureFlagOption flag={FeatureFlags.Realtime} label="Realtime activity updates" />
<FeatureFlagOption flag={FeatureFlags.MultipleRoutingOptions} label="Enable Multiple Routing Options" /> <FeatureFlagOption flag={FeatureFlags.MultipleRoutingOptions} label="Enable Multiple Routing Options" />
<FeatureFlagOption flag={FeatureFlags.MultichainUX} label="Enable Multichain Swap/Send UX" />
<FeatureFlagGroup name="Quick routes"> <FeatureFlagGroup name="Quick routes">
<FeatureFlagOption flag={FeatureFlags.QuickRouteMainnet} label="Enable quick routes for Mainnet" /> <FeatureFlagOption flag={FeatureFlags.QuickRouteMainnet} label="Enable quick routes for Mainnet" />
<DynamicConfigDropdown <DynamicConfigDropdown
......
...@@ -10,19 +10,7 @@ export const FEE_AMOUNT_DETAIL: Record< ...@@ -10,19 +10,7 @@ export const FEE_AMOUNT_DETAIL: Record<
[FeeAmount.LOWEST]: { [FeeAmount.LOWEST]: {
label: '0.01', label: '0.01',
description: <Trans>Best for very stable pairs.</Trans>, description: <Trans>Best for very stable pairs.</Trans>,
supportedChains: [ supportedChains: SUPPORTED_CHAINS,
ChainId.ARBITRUM_ONE,
ChainId.BNB,
ChainId.CELO,
ChainId.CELO_ALFAJORES,
ChainId.MAINNET,
ChainId.OPTIMISM,
ChainId.POLYGON,
ChainId.POLYGON_MUMBAI,
ChainId.AVALANCHE,
ChainId.BASE,
ChainId.BLAST,
],
}, },
[FeeAmount.LOW]: { [FeeAmount.LOW]: {
label: '0.05', label: '0.05',
......
...@@ -74,7 +74,7 @@ export default function FiatOnrampModal() { ...@@ -74,7 +74,7 @@ export default function FiatOnrampModal() {
const closeModal = useCloseModal() const closeModal = useCloseModal()
const fiatOnrampModalOpen = useModalIsOpen(ApplicationModal.FIAT_ONRAMP) const fiatOnrampModalOpen = useModalIsOpen(ApplicationModal.FIAT_ONRAMP)
const { network, tokenAddress } = parsePathParts(location.pathname) const { chain, tokenAddress } = parsePathParts(location.pathname)
const [signedIframeUrl, setSignedIframeUrl] = useState<string | null>(null) const [signedIframeUrl, setSignedIframeUrl] = useState<string | null>(null)
const [error, setError] = useState<string | null>(null) const [error, setError] = useState<string | null>(null)
...@@ -100,7 +100,7 @@ export default function FiatOnrampModal() { ...@@ -100,7 +100,7 @@ export default function FiatOnrampModal() {
body: JSON.stringify({ body: JSON.stringify({
theme: isDarkMode ? 'dark' : 'light', theme: isDarkMode ? 'dark' : 'light',
colorCode: theme.accent1, colorCode: theme.accent1,
defaultCurrencyCode: getDefaultCurrencyCode(tokenAddress, network), defaultCurrencyCode: getDefaultCurrencyCode(tokenAddress, chain?.backendChain.chain),
redirectUrl: swapUrl, redirectUrl: swapUrl,
walletAddresses: JSON.stringify( walletAddresses: JSON.stringify(
MOONPAY_SUPPORTED_CURRENCY_CODES.reduce( MOONPAY_SUPPORTED_CURRENCY_CODES.reduce(
...@@ -121,7 +121,7 @@ export default function FiatOnrampModal() { ...@@ -121,7 +121,7 @@ export default function FiatOnrampModal() {
} finally { } finally {
setLoading(false) setLoading(false)
} }
}, [account, isDarkMode, network, swapUrl, theme.accent1, tokenAddress]) }, [account, chain, isDarkMode, swapUrl, theme.accent1, tokenAddress])
useEffect(() => { useEffect(() => {
fetchSignedIframeUrl() fetchSignedIframeUrl()
......
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.
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