diff --git a/apps/wallet-mobile/ios/Podfile.lock b/apps/wallet-mobile/ios/Podfile.lock index 35e63de24e..f4adb7585a 100644 --- a/apps/wallet-mobile/ios/Podfile.lock +++ b/apps/wallet-mobile/ios/Podfile.lock @@ -34,14 +34,14 @@ PODS: - React-Core - React-RCTAppDelegate - ReactCommon/turbomodule/core - - FBLazyVector (0.71.6) - - FBReactNativeSpec (0.71.6): + - FBLazyVector (0.71.14) + - FBReactNativeSpec (0.71.14): - RCT-Folly (= 2021.07.22.00) - - RCTRequired (= 0.71.6) - - RCTTypeSafety (= 0.71.6) - - React-Core (= 0.71.6) - - React-jsi (= 0.71.6) - - ReactCommon/turbomodule/core (= 0.71.6) + - RCTRequired (= 0.71.14) + - RCTTypeSafety (= 0.71.14) + - React-Core (= 0.71.14) + - React-jsi (= 0.71.14) + - ReactCommon/turbomodule/core (= 0.71.14) - Flipper (0.125.0): - Flipper-Folly (~> 2.6) - Flipper-RSocket (~> 1.4) @@ -105,9 +105,9 @@ PODS: - FlipperKit/FlipperKitNetworkPlugin - fmt (6.2.1) - glog (0.3.5) - - hermes-engine (0.71.6): - - hermes-engine/Pre-built (= 0.71.6) - - hermes-engine/Pre-built (0.71.6) + - hermes-engine (0.71.14): + - hermes-engine/Pre-built (= 0.71.14) + - hermes-engine/Pre-built (0.71.14) - libevent (2.1.12) - MultiplatformBleAdapter (0.1.9) - OpenSSL-Universal (1.1.1100) @@ -140,26 +140,26 @@ PODS: - fmt (~> 6.2.1) - glog - libevent - - RCTRequired (0.71.6) - - RCTTypeSafety (0.71.6): - - FBLazyVector (= 0.71.6) - - RCTRequired (= 0.71.6) - - React-Core (= 0.71.6) - - React (0.71.6): - - React-Core (= 0.71.6) - - React-Core/DevSupport (= 0.71.6) - - React-Core/RCTWebSocket (= 0.71.6) - - React-RCTActionSheet (= 0.71.6) - - React-RCTAnimation (= 0.71.6) - - React-RCTBlob (= 0.71.6) - - React-RCTImage (= 0.71.6) - - React-RCTLinking (= 0.71.6) - - React-RCTNetwork (= 0.71.6) - - React-RCTSettings (= 0.71.6) - - React-RCTText (= 0.71.6) - - React-RCTVibration (= 0.71.6) - - React-callinvoker (0.71.6) - - React-Codegen (0.71.6): + - RCTRequired (0.71.14) + - RCTTypeSafety (0.71.14): + - FBLazyVector (= 0.71.14) + - RCTRequired (= 0.71.14) + - React-Core (= 0.71.14) + - React (0.71.14): + - React-Core (= 0.71.14) + - React-Core/DevSupport (= 0.71.14) + - React-Core/RCTWebSocket (= 0.71.14) + - React-RCTActionSheet (= 0.71.14) + - React-RCTAnimation (= 0.71.14) + - React-RCTBlob (= 0.71.14) + - React-RCTImage (= 0.71.14) + - React-RCTLinking (= 0.71.14) + - React-RCTNetwork (= 0.71.14) + - React-RCTSettings (= 0.71.14) + - React-RCTText (= 0.71.14) + - React-RCTVibration (= 0.71.14) + - React-callinvoker (0.71.14) + - React-Codegen (0.71.14): - FBReactNativeSpec - hermes-engine - RCT-Folly @@ -170,209 +170,209 @@ PODS: - React-jsiexecutor - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - React-Core (0.71.6): + - React-Core (0.71.14): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-Core/Default (= 0.71.6) - - React-cxxreact (= 0.71.6) + - React-Core/Default (= 0.71.14) + - React-cxxreact (= 0.71.14) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.14) + - React-jsiexecutor (= 0.71.14) + - React-perflogger (= 0.71.14) - Yoga - - React-Core/CoreModulesHeaders (0.71.6): + - React-Core/CoreModulesHeaders (0.71.14): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.14) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.14) + - React-jsiexecutor (= 0.71.14) + - React-perflogger (= 0.71.14) - Yoga - - React-Core/Default (0.71.6): + - React-Core/Default (0.71.14): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.14) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.14) + - React-jsiexecutor (= 0.71.14) + - React-perflogger (= 0.71.14) - Yoga - - React-Core/DevSupport (0.71.6): + - React-Core/DevSupport (0.71.14): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-Core/Default (= 0.71.6) - - React-Core/RCTWebSocket (= 0.71.6) - - React-cxxreact (= 0.71.6) + - React-Core/Default (= 0.71.14) + - React-Core/RCTWebSocket (= 0.71.14) + - React-cxxreact (= 0.71.14) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-jsinspector (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.14) + - React-jsiexecutor (= 0.71.14) + - React-jsinspector (= 0.71.14) + - React-perflogger (= 0.71.14) - Yoga - - React-Core/RCTActionSheetHeaders (0.71.6): + - React-Core/RCTActionSheetHeaders (0.71.14): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.14) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.14) + - React-jsiexecutor (= 0.71.14) + - React-perflogger (= 0.71.14) - Yoga - - React-Core/RCTAnimationHeaders (0.71.6): + - React-Core/RCTAnimationHeaders (0.71.14): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.14) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.14) + - React-jsiexecutor (= 0.71.14) + - React-perflogger (= 0.71.14) - Yoga - - React-Core/RCTBlobHeaders (0.71.6): + - React-Core/RCTBlobHeaders (0.71.14): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.14) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.14) + - React-jsiexecutor (= 0.71.14) + - React-perflogger (= 0.71.14) - Yoga - - React-Core/RCTImageHeaders (0.71.6): + - React-Core/RCTImageHeaders (0.71.14): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.14) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.14) + - React-jsiexecutor (= 0.71.14) + - React-perflogger (= 0.71.14) - Yoga - - React-Core/RCTLinkingHeaders (0.71.6): + - React-Core/RCTLinkingHeaders (0.71.14): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.14) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.14) + - React-jsiexecutor (= 0.71.14) + - React-perflogger (= 0.71.14) - Yoga - - React-Core/RCTNetworkHeaders (0.71.6): + - React-Core/RCTNetworkHeaders (0.71.14): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.14) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.14) + - React-jsiexecutor (= 0.71.14) + - React-perflogger (= 0.71.14) - Yoga - - React-Core/RCTSettingsHeaders (0.71.6): + - React-Core/RCTSettingsHeaders (0.71.14): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.14) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.14) + - React-jsiexecutor (= 0.71.14) + - React-perflogger (= 0.71.14) - Yoga - - React-Core/RCTTextHeaders (0.71.6): + - React-Core/RCTTextHeaders (0.71.14): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.14) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.14) + - React-jsiexecutor (= 0.71.14) + - React-perflogger (= 0.71.14) - Yoga - - React-Core/RCTVibrationHeaders (0.71.6): + - React-Core/RCTVibrationHeaders (0.71.14): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.14) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.14) + - React-jsiexecutor (= 0.71.14) + - React-perflogger (= 0.71.14) - Yoga - - React-Core/RCTWebSocket (0.71.6): + - React-Core/RCTWebSocket (0.71.14): - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-Core/Default (= 0.71.6) - - React-cxxreact (= 0.71.6) + - React-Core/Default (= 0.71.14) + - React-cxxreact (= 0.71.14) - React-hermes - - React-jsi (= 0.71.6) - - React-jsiexecutor (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-jsi (= 0.71.14) + - React-jsiexecutor (= 0.71.14) + - React-perflogger (= 0.71.14) - Yoga - - React-CoreModules (0.71.6): + - React-CoreModules (0.71.14): - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.71.6) - - React-Codegen (= 0.71.6) - - React-Core/CoreModulesHeaders (= 0.71.6) - - React-jsi (= 0.71.6) + - RCTTypeSafety (= 0.71.14) + - React-Codegen (= 0.71.14) + - React-Core/CoreModulesHeaders (= 0.71.14) + - React-jsi (= 0.71.14) - React-RCTBlob - - React-RCTImage (= 0.71.6) - - ReactCommon/turbomodule/core (= 0.71.6) - - React-cxxreact (0.71.6): + - React-RCTImage (= 0.71.14) + - ReactCommon/turbomodule/core (= 0.71.14) + - React-cxxreact (0.71.14): - boost (= 1.76.0) - DoubleConversion - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-callinvoker (= 0.71.6) - - React-jsi (= 0.71.6) - - React-jsinspector (= 0.71.6) - - React-logger (= 0.71.6) - - React-perflogger (= 0.71.6) - - React-runtimeexecutor (= 0.71.6) - - React-hermes (0.71.6): + - React-callinvoker (= 0.71.14) + - React-jsi (= 0.71.14) + - React-jsinspector (= 0.71.14) + - React-logger (= 0.71.14) + - React-perflogger (= 0.71.14) + - React-runtimeexecutor (= 0.71.14) + - React-hermes (0.71.14): - DoubleConversion - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - RCT-Folly/Futures (= 2021.07.22.00) - - React-cxxreact (= 0.71.6) + - React-cxxreact (= 0.71.14) - React-jsi - - React-jsiexecutor (= 0.71.6) - - React-jsinspector (= 0.71.6) - - React-perflogger (= 0.71.6) - - React-jsi (0.71.6): + - React-jsiexecutor (= 0.71.14) + - React-jsinspector (= 0.71.14) + - React-perflogger (= 0.71.14) + - React-jsi (0.71.14): - boost (= 1.76.0) - DoubleConversion - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-jsiexecutor (0.71.6): + - React-jsiexecutor (0.71.14): - DoubleConversion - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-cxxreact (= 0.71.6) - - React-jsi (= 0.71.6) - - React-perflogger (= 0.71.6) - - React-jsinspector (0.71.6) - - React-logger (0.71.6): + - React-cxxreact (= 0.71.14) + - React-jsi (= 0.71.14) + - React-perflogger (= 0.71.14) + - React-jsinspector (0.71.14) + - React-logger (0.71.14): - glog - react-native-background-timer (2.4.1): - React-Core @@ -399,90 +399,90 @@ PODS: - React-Core - react-native-webview (11.26.1): - React-Core - - React-perflogger (0.71.6) - - React-RCTActionSheet (0.71.6): - - React-Core/RCTActionSheetHeaders (= 0.71.6) - - React-RCTAnimation (0.71.6): + - React-perflogger (0.71.14) + - React-RCTActionSheet (0.71.14): + - React-Core/RCTActionSheetHeaders (= 0.71.14) + - React-RCTAnimation (0.71.14): - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.71.6) - - React-Codegen (= 0.71.6) - - React-Core/RCTAnimationHeaders (= 0.71.6) - - React-jsi (= 0.71.6) - - ReactCommon/turbomodule/core (= 0.71.6) - - React-RCTAppDelegate (0.71.6): + - RCTTypeSafety (= 0.71.14) + - React-Codegen (= 0.71.14) + - React-Core/RCTAnimationHeaders (= 0.71.14) + - React-jsi (= 0.71.14) + - ReactCommon/turbomodule/core (= 0.71.14) + - React-RCTAppDelegate (0.71.14): - RCT-Folly - RCTRequired - RCTTypeSafety - React-Core - ReactCommon/turbomodule/core - - React-RCTBlob (0.71.6): + - React-RCTBlob (0.71.14): - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-Codegen (= 0.71.6) - - React-Core/RCTBlobHeaders (= 0.71.6) - - React-Core/RCTWebSocket (= 0.71.6) - - React-jsi (= 0.71.6) - - React-RCTNetwork (= 0.71.6) - - ReactCommon/turbomodule/core (= 0.71.6) - - React-RCTImage (0.71.6): + - React-Codegen (= 0.71.14) + - React-Core/RCTBlobHeaders (= 0.71.14) + - React-Core/RCTWebSocket (= 0.71.14) + - React-jsi (= 0.71.14) + - React-RCTNetwork (= 0.71.14) + - ReactCommon/turbomodule/core (= 0.71.14) + - React-RCTImage (0.71.14): - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.71.6) - - React-Codegen (= 0.71.6) - - React-Core/RCTImageHeaders (= 0.71.6) - - React-jsi (= 0.71.6) - - React-RCTNetwork (= 0.71.6) - - ReactCommon/turbomodule/core (= 0.71.6) - - React-RCTLinking (0.71.6): - - React-Codegen (= 0.71.6) - - React-Core/RCTLinkingHeaders (= 0.71.6) - - React-jsi (= 0.71.6) - - ReactCommon/turbomodule/core (= 0.71.6) - - React-RCTNetwork (0.71.6): + - RCTTypeSafety (= 0.71.14) + - React-Codegen (= 0.71.14) + - React-Core/RCTImageHeaders (= 0.71.14) + - React-jsi (= 0.71.14) + - React-RCTNetwork (= 0.71.14) + - ReactCommon/turbomodule/core (= 0.71.14) + - React-RCTLinking (0.71.14): + - React-Codegen (= 0.71.14) + - React-Core/RCTLinkingHeaders (= 0.71.14) + - React-jsi (= 0.71.14) + - ReactCommon/turbomodule/core (= 0.71.14) + - React-RCTNetwork (0.71.14): - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.71.6) - - React-Codegen (= 0.71.6) - - React-Core/RCTNetworkHeaders (= 0.71.6) - - React-jsi (= 0.71.6) - - ReactCommon/turbomodule/core (= 0.71.6) - - React-RCTSettings (0.71.6): + - RCTTypeSafety (= 0.71.14) + - React-Codegen (= 0.71.14) + - React-Core/RCTNetworkHeaders (= 0.71.14) + - React-jsi (= 0.71.14) + - ReactCommon/turbomodule/core (= 0.71.14) + - React-RCTSettings (0.71.14): - RCT-Folly (= 2021.07.22.00) - - RCTTypeSafety (= 0.71.6) - - React-Codegen (= 0.71.6) - - React-Core/RCTSettingsHeaders (= 0.71.6) - - React-jsi (= 0.71.6) - - ReactCommon/turbomodule/core (= 0.71.6) - - React-RCTText (0.71.6): - - React-Core/RCTTextHeaders (= 0.71.6) - - React-RCTVibration (0.71.6): + - RCTTypeSafety (= 0.71.14) + - React-Codegen (= 0.71.14) + - React-Core/RCTSettingsHeaders (= 0.71.14) + - React-jsi (= 0.71.14) + - ReactCommon/turbomodule/core (= 0.71.14) + - React-RCTText (0.71.14): + - React-Core/RCTTextHeaders (= 0.71.14) + - React-RCTVibration (0.71.14): - RCT-Folly (= 2021.07.22.00) - - React-Codegen (= 0.71.6) - - React-Core/RCTVibrationHeaders (= 0.71.6) - - React-jsi (= 0.71.6) - - ReactCommon/turbomodule/core (= 0.71.6) - - React-runtimeexecutor (0.71.6): - - React-jsi (= 0.71.6) - - ReactCommon/turbomodule/bridging (0.71.6): + - React-Codegen (= 0.71.14) + - React-Core/RCTVibrationHeaders (= 0.71.14) + - React-jsi (= 0.71.14) + - ReactCommon/turbomodule/core (= 0.71.14) + - React-runtimeexecutor (0.71.14): + - React-jsi (= 0.71.14) + - ReactCommon/turbomodule/bridging (0.71.14): - DoubleConversion - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-callinvoker (= 0.71.6) - - React-Core (= 0.71.6) - - React-cxxreact (= 0.71.6) - - React-jsi (= 0.71.6) - - React-logger (= 0.71.6) - - React-perflogger (= 0.71.6) - - ReactCommon/turbomodule/core (0.71.6): + - React-callinvoker (= 0.71.14) + - React-Core (= 0.71.14) + - React-cxxreact (= 0.71.14) + - React-jsi (= 0.71.14) + - React-logger (= 0.71.14) + - React-perflogger (= 0.71.14) + - ReactCommon/turbomodule/core (0.71.14): - DoubleConversion - glog - hermes-engine - RCT-Folly (= 2021.07.22.00) - - React-callinvoker (= 0.71.6) - - React-Core (= 0.71.6) - - React-cxxreact (= 0.71.6) - - React-jsi (= 0.71.6) - - React-logger (= 0.71.6) - - React-perflogger (= 0.71.6) + - React-callinvoker (= 0.71.14) + - React-Core (= 0.71.14) + - React-cxxreact (= 0.71.14) + - React-jsi (= 0.71.14) + - React-logger (= 0.71.14) + - React-perflogger (= 0.71.14) - RNBootSplash (4.7.5): - React-Core - RNCAsyncStorage (1.19.3): @@ -855,8 +855,8 @@ SPEC CHECKSUMS: ExpoDevice: 1c1b0c9cad96c292c1de73948649cfd654b2b3c0 ExpoKeepAwake: 69f5f627670d62318410392d03e0b5db0f85759a ExpoModulesCore: 653958063a301098b541ae4dfed1ac0b98db607b - FBLazyVector: a83ceaa8a8581003a623facdb3c44f6d4f342ac5 - FBReactNativeSpec: d850372b600f78cbb92585bfc7b2e48dbb73b3ad + FBLazyVector: 12ea01e587c9594e7b144e1bfc86ac4d9ac28fde + FBReactNativeSpec: faca7d16c37626ca5780a87adef703817722fe61 Flipper: 26fc4b7382499f1281eb8cb921e5c3ad6de91fe0 Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c Flipper-DoubleConversion: 2dc99b02f658daf147069aad9dbd29d8feb06d30 @@ -868,7 +868,7 @@ SPEC CHECKSUMS: FlipperKit: cbdee19bdd4e7f05472a66ce290f1b729ba3cb86 fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b - hermes-engine: b434cea529ad0152c56c7cb6486b0c4c0b23b5de + hermes-engine: d7cc127932c89c53374452d6f93473f1970d8e88 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 MultiplatformBleAdapter: 5a6a897b006764392f9cef785e4360f54fb9477d OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c @@ -879,19 +879,19 @@ SPEC CHECKSUMS: Permission-LocationAlways: 8fd5518716c3045f9c4edf77b901126098d79b60 Permission-LocationWhenInUse: 24d97eeb25d8ff9f2232e070f792eeb1360ccaf0 RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 - RCTRequired: 5c6fd63b03abb06947d348dadac51c93e3485bd8 - RCTTypeSafety: 1c66daedd66f674e39ce9f40782f0d490c78b175 - React: e11ca7cdc7aa4ddd7e6a59278b808cfe17ebbd9f - React-callinvoker: 77a82869505c96945c074b80bbdc8df919646d51 - React-Codegen: 9ee33090c38ab3da3c4dc029924d50fb649f0dfc - React-Core: 44903e47b428a491f48fd0eae54caddb2ea05ebf - React-CoreModules: 83d989defdfc82be1f7386f84a56b6509f54ac74 - React-cxxreact: 058e7e6349649eae9cfcdec5854e702b26298932 - React-hermes: ba19a405804b833c9b832c1f2061ad5038bb97f2 - React-jsi: 3fe6f589c9cafbef85ed5a4be7c6dc8edfb4ab54 - React-jsiexecutor: 7894956638ff3e00819dd3f9f6f4a84da38f2409 - React-jsinspector: d5ce2ef3eb8fd30c28389d0bc577918c70821bd6 - React-logger: 9332c3e7b4ef007a0211c0a9868253aac3e1da82 + RCTRequired: e9df143e880d0e879e7a498dc06923d728809c79 + RCTTypeSafety: c2d89c8308829c12c038ec1f431191eaa0d8c15c + React: 52b89a818f4b2579c98567f3aa8bde880d9e843b + React-callinvoker: 56e399c88c05e037fe99c31978f30e75fad5c286 + React-Codegen: 7ece62f4d4896ad1933f834a7dad697676636318 + React-Core: f06b7b00e0d49433a316760ae61a0f8f5dee6629 + React-CoreModules: bd520e5688b5aa4666965a1b3b8e6d4a2e19df20 + React-cxxreact: ba6a1663685837fa4c2ac97daa95dd2e47f1acdc + React-hermes: c862e573ca0228070936b5ec4f475c3e19e900e0 + React-jsi: 533030c161bcfcbc3a4ad0b357ced8f7b2be457e + React-jsiexecutor: 94cfc1788637ceaf8841ef1f69b10cc0d62baadc + React-jsinspector: 7bf923954b4e035f494b01ac16633963412660d7 + React-logger: 655ff5db8bd922acfbe76a4983ffab048916343e react-native-background-timer: 17ea5e06803401a379ebf1f20505b793ac44d0fe react-native-ble-plx: f10240444452dfb2d2a13a0e4f58d7783e92d76e react-native-config: 86038147314e2e6d10ea9972022aa171e6b1d4d8 @@ -903,19 +903,19 @@ SPEC CHECKSUMS: react-native-slider: 33b8d190b59d4f67a541061bb91775d53d617d9d react-native-timezone: 92fa6c0a7c041efd632a372a515c957cd8ee9e72 react-native-webview: 9f111dfbcfc826084d6c507f569e5e03342ee1c1 - React-perflogger: 43392072a5b867a504e2b4857606f8fc5a403d7f - React-RCTActionSheet: c7b67c125bebeda9fb19fc7b200d85cb9d6899c4 - React-RCTAnimation: c2de79906f607986633a7114bee44854e4c7e2f5 - React-RCTAppDelegate: 96bc933c3228a549718a6475c4d3f9dd4bbae98d - React-RCTBlob: cf72446957310e7da6627a4bdaadf970d3a8f232 - React-RCTImage: c6093f1bf3d67c0428d779b00390617d5bd90699 - React-RCTLinking: 5de47e37937889d22599af4b99d0552bad1b1c3c - React-RCTNetwork: e7d7077e073b08e5dd486fba3fe87ccad90a9bc4 - React-RCTSettings: 72a04921b2e8fb832da7201a60ffffff2a7c62f7 - React-RCTText: 7123c70fef5367e2121fea37e65b9ad6d3747e54 - React-RCTVibration: 73d201599a64ea14b4e0b8f91b64970979fd92e6 - React-runtimeexecutor: 8692ac548bec648fa121980ccb4304afd136d584 - ReactCommon: 0c43eaeaaee231d7d8dc24fc5a6e4cf2b75bf196 + React-perflogger: 4987ad83731c23d11813c84263963b0d3028c966 + React-RCTActionSheet: 5ad952b2a9740d87a5bd77280c4bc23f6f89ea0c + React-RCTAnimation: d2de22af3f536cc80bb5b3918e1a455114d1b985 + React-RCTAppDelegate: 27f7d735cad3d522c13008ea80020d350017c422 + React-RCTBlob: b697e0e2e38ec85bd726176851a3b476a490ad33 + React-RCTImage: a07e8c7d4768f62ebc6277e4680f6b979c619967 + React-RCTLinking: d00ae55db37b2c12ebab91135f06f75391c0708d + React-RCTNetwork: b3a401276e5c08487d8a14fdec1720e78b5888db + React-RCTSettings: d606cbac31403604c5d5746e6dab53bb332f9301 + React-RCTText: b3bd40bc71bca0c3e2cc5ce2c40870a438f303b1 + React-RCTVibration: 64e412b9ac684c4edc938fa1187135ada9af7faf + React-runtimeexecutor: ffe826b7b1cfbc32a35ed5b64d5886c0ff75f501 + ReactCommon: 7f3dd5e98a9ec627c6b03d26c062bf37ea9fc888 RNBootSplash: 85f6b879c080e958afdb4c62ee04497b05fd7552 RNCAsyncStorage: c913ede1fa163a71cea118ed4670bbaaa4b511bb RNCClipboard: 41d8d918092ae8e676f18adada19104fa3e68495 @@ -933,7 +933,7 @@ SPEC CHECKSUMS: Sentry: 97161cac725da1ecbe77d1445bf8a61c1e5667f1 SentryPrivate: 9a76def09fb08f9501997b8df946e8097947b94f SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608 - Yoga: ba09b6b11e6139e3df8229238aa794205ca6a02a + Yoga: e71803b4c1fff832ccf9b92541e00f9b873119b9 YogaKit: f782866e155069a2cca2517aafea43200b01fd5a ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb diff --git a/apps/wallet-mobile/ios/yoroi.xcodeproj/project.pbxproj b/apps/wallet-mobile/ios/yoroi.xcodeproj/project.pbxproj index 8ecc0cdd40..6d011babba 100644 --- a/apps/wallet-mobile/ios/yoroi.xcodeproj/project.pbxproj +++ b/apps/wallet-mobile/ios/yoroi.xcodeproj/project.pbxproj @@ -956,11 +956,7 @@ "-DFOLLY_MOBILE=1", "-DFOLLY_USE_LIBCPP=1", ); - OTHER_LDFLAGS = ( - "$(inherited)", - "-Wl", - "-ld_classic", - ); + OTHER_LDFLAGS = "$(inherited)"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../../../node_modules/react-native"; SDKROOT = iphoneos; }; @@ -1029,11 +1025,7 @@ "-DFOLLY_MOBILE=1", "-DFOLLY_USE_LIBCPP=1", ); - OTHER_LDFLAGS = ( - "$(inherited)", - "-Wl", - "-ld_classic", - ); + OTHER_LDFLAGS = "$(inherited)"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../../../node_modules/react-native"; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; diff --git a/apps/wallet-mobile/src/TxHistory/ActionsBanner.tsx b/apps/wallet-mobile/src/TxHistory/ActionsBanner.tsx index 36eb0da190..1ceb99fa50 100644 --- a/apps/wallet-mobile/src/TxHistory/ActionsBanner.tsx +++ b/apps/wallet-mobile/src/TxHistory/ActionsBanner.tsx @@ -8,7 +8,7 @@ import {Linking, StyleSheet, Text, TouchableOpacity, View} from 'react-native' import {Icon, Spacer} from '../components' import {features} from '../features' import {useSend} from '../features/Send/common/SendContext' -import {useSwapTouched} from '../features/Swap/common/SwapFormProvider' +import {useSwapForm} from '../features/Swap/common/SwapFormProvider' import {actionMessages} from '../i18n/global-messages' import env from '../legacy/env' import {useMetrics} from '../metrics/metricsManager' @@ -27,8 +27,8 @@ export const ActionsBanner = ({disabled = false}: {disabled: boolean}) => { const navigateTo = useNavigateTo() const wallet = useSelectedWallet() const {resetForm} = useSend() - const {orderData, resetState} = useSwap() - const {resetTouches} = useSwapTouched() + const {orderData} = useSwap() + const {resetSwapForm} = useSwapForm() const {track} = useMetrics() const sellTokenInfo = useTokenInfo({ wallet, @@ -64,8 +64,7 @@ export const ActionsBanner = ({disabled = false}: {disabled: boolean}) => { } const handleOnSwap = () => { - resetTouches() - resetState() + resetSwapForm() track.swapInitiated({ from_asset: [ diff --git a/apps/wallet-mobile/src/features/Swap/common/SelectPool/SelectPoolFromList/SelectPoolFromList.tsx b/apps/wallet-mobile/src/features/Swap/common/SelectPool/SelectPoolFromList/SelectPoolFromList.tsx index 2d8799d597..fbd9f9f7df 100644 --- a/apps/wallet-mobile/src/features/Swap/common/SelectPool/SelectPoolFromList/SelectPoolFromList.tsx +++ b/apps/wallet-mobile/src/features/Swap/common/SelectPool/SelectPoolFromList/SelectPoolFromList.tsx @@ -14,7 +14,7 @@ import {asQuantity, Quantities} from '../../../../../yoroi-wallets/utils' import {useNavigateTo} from '../../navigation' import {PoolIcon} from '../../PoolIcon/PoolIcon' import {useStrings} from '../../strings' -import {useSwapTouched} from '../../SwapFormProvider' +import {useSwapForm} from '../../SwapFormProvider' const PRECISION = 14 @@ -25,7 +25,7 @@ export const SelectPoolFromList = ({pools = []}: Props) => { const strings = useStrings() const wallet = useSelectedWallet() const {selectedPoolChanged, orderData} = useSwap() - const {poolTouched} = useSwapTouched() + const {poolTouched} = useSwapForm() const [selectedCardIndex, setSelectedCardIndex] = useState(orderData.selectedPoolId) const navigate = useNavigateTo() const {track} = useMetrics() diff --git a/apps/wallet-mobile/src/features/Swap/common/SwapFormProvider.tsx b/apps/wallet-mobile/src/features/Swap/common/SwapFormProvider.tsx index da574eedb1..96e92c730f 100644 --- a/apps/wallet-mobile/src/features/Swap/common/SwapFormProvider.tsx +++ b/apps/wallet-mobile/src/features/Swap/common/SwapFormProvider.tsx @@ -1,86 +1,433 @@ -import React, {createContext, ReactNode, useContext, useReducer} from 'react' +import {useSwap} from '@yoroi/swap' +import {produce} from 'immer' +import React from 'react' +import {Keyboard, TextInput} from 'react-native' -type TouchedState = { - isSellTouched: boolean - isBuyTouched: boolean - isPoolTouched: boolean -} -type TouchedActions = { - sellTouched: () => void - buyTouched: () => void - switchTouched: () => void - poolTouched: () => void - poolDefaulted: () => void - resetTouches: () => void -} - -const TouchedContext = createContext(undefined) +import {useLanguage} from '../../../i18n' +import {useSelectedWallet} from '../../../SelectedWallet' +import {useBalances, useTokenInfo} from '../../../yoroi-wallets/hooks' +import {Amounts, Quantities} from '../../../yoroi-wallets/utils' +import {useStrings} from './strings' -export const useSwapTouched = () => { - const value = useContext(TouchedContext) - if (!value) { - throw new Error('useSwapTouched must be used within a SwapFormProvider') - } - return value -} +export const useSwapForm = () => React.useContext(SwapFormContext) export const SwapFormProvider = ({ children, initialState, }: { - children: ReactNode - initialState?: Partial + children: React.ReactNode + initialState?: Partial }) => { - const [state, dispatch] = useReducer(touchedReducer, {...defaultState, ...initialState}) - const actions = React.useRef({ - sellTouched: () => dispatch({type: 'sellTouched'}), - buyTouched: () => dispatch({type: 'buyTouched'}), - switchTouched: () => dispatch({type: 'switchTouched'}), - poolTouched: () => dispatch({type: 'poolTouched'}), - poolDefaulted: () => dispatch({type: 'poolDefaulted'}), - resetTouches: () => dispatch({type: 'resetTouches'}), + const { + orderData, + resetState, + buyQuantityChanged, + sellQuantityChanged, + switchTokens, + limitPriceChanged, + resetQuantities, + } = useSwap() + const wallet = useSelectedWallet() + const {numberLocale} = useLanguage() + const strings = useStrings() + + const buyInputRef = React.useRef(null) + const sellInputRef = React.useRef(null) + const limitInputRef = React.useRef(null) + + const pool = orderData.selectedPoolCalculation?.pool + const {tokenId: buyTokenId, quantity: buyQuantity} = orderData.amounts.buy + const {tokenId: sellTokenId, quantity: sellQuantity} = orderData.amounts.sell + + const buyTokenInfo = useTokenInfo({wallet, tokenId: orderData.amounts.buy.tokenId}) + const sellTokenInfo = useTokenInfo({wallet, tokenId: orderData.amounts.sell.tokenId}) + + const balances = useBalances(wallet) + const sellbalance = Amounts.getAmount(balances, sellTokenId).quantity + const primaryTokenBalance = Amounts.getAmount(balances, wallet.primaryTokenInfo.id).quantity + + const poolSupply = buyTokenId === pool?.tokenA.tokenId ? pool?.tokenA.quantity : pool?.tokenB.quantity + const hasBuyTokenSupply = !Quantities.isGreaterThan(buyQuantity, poolSupply ?? Quantities.zero) + const hasSellBalance = !Quantities.isGreaterThan(sellQuantity, sellbalance) + const hasFeesBalance = !Quantities.isGreaterThan( + Quantities.sum([ + sellTokenId === wallet.primaryTokenInfo.id ? sellQuantity : Quantities.zero, + orderData.selectedPoolCalculation?.cost.ptTotalFeeNoFEF.quantity ?? Quantities.zero, + ]), + primaryTokenBalance, + ) + + const denomination = (sellTokenInfo.decimals ?? 0) - (buyTokenInfo.decimals ?? 0) + + const [state, dispatch] = React.useReducer(swapFormReducer, { + ...defaultState, + buyQuantity: { + ...defaultState.buyQuantity, + displayValue: Quantities.format(buyQuantity, buyTokenInfo.decimals ?? 0), + }, + sellQuantity: { + ...defaultState.sellQuantity, + displayValue: Quantities.format(sellQuantity, sellTokenInfo.decimals ?? 0), + }, + ...initialState, + }) + + const noPoolError = + orderData.selectedPoolCalculation === undefined && state.buyQuantity.isTouched && state.sellQuantity.isTouched + ? strings.noPool + : undefined + + const buyError = + noPoolError !== undefined + ? noPoolError + : (!Quantities.isZero(buyQuantity) && !hasBuyTokenSupply) || + (state.sellQuantity.isTouched && state.buyQuantity.isTouched && pool === undefined) + ? strings.notEnoughSupply + : undefined + + const sellError = + noPoolError !== undefined + ? noPoolError + : !Quantities.isZero(sellQuantity) && !hasSellBalance + ? strings.notEnoughBalance + : !Quantities.isZero(sellQuantity) && state.buyQuantity.isTouched && !hasFeesBalance + ? strings.notEnoughFeeBalance + : undefined + + const canSwap = + state.buyQuantity.isTouched && + state.sellQuantity.isTouched && + !Quantities.isZero(buyQuantity) && + !Quantities.isZero(sellQuantity) && + state.buyQuantity.error === undefined && + state.sellQuantity.error === undefined && + ((orderData.type === 'limit' && orderData.limitPrice !== undefined && !Quantities.isZero(orderData.limitPrice)) || + orderData.selectedPoolCalculation !== undefined) + + const actions = React.useRef({ + sellTouched: () => dispatch({type: SwapFormActionType.SellTouched}), + buyTouched: () => dispatch({type: SwapFormActionType.BuyTouched}), + switchTouched: () => dispatch({type: SwapFormActionType.SwitchTouched}), + switchTokens: () => { + switchTokens() + dispatch({type: SwapFormActionType.SwitchTouched}) + }, + poolTouched: () => dispatch({type: SwapFormActionType.PoolTouched}), + poolDefaulted: () => dispatch({type: SwapFormActionType.PoolDefaulted}), + clearSwapForm: () => { + resetQuantities() + dispatch({type: SwapFormActionType.ClearSwapForm}) + + // In certain iOS simulators, the focused input's `onChangeText` may be called before dismissal, using the previous input value. + Keyboard.dismiss() + }, + resetSwapForm: () => { + resetState() + dispatch({type: SwapFormActionType.ResetSwapForm}) + }, + canSwapChanged: (canSwap: boolean) => dispatch({type: SwapFormActionType.CanSwapChanged, canSwap}), + buyInputValueChanged: (value: string) => dispatch({type: SwapFormActionType.BuyInputValueChanged, value}), + sellInputValueChanged: (value: string) => dispatch({type: SwapFormActionType.SellInputValueChanged, value}), + limitPriceInputValueChanged: (value: string) => + dispatch({type: SwapFormActionType.LimitPriceInputValueChanged, value}), + buyAmountErrorChanged: (error: string | undefined) => + dispatch({type: SwapFormActionType.BuyAmountErrorChanged, error}), + sellAmountErrorChanged: (error: string | undefined) => + dispatch({type: SwapFormActionType.SellAmountErrorChanged, error}), }).current - const context = React.useMemo(() => ({...state, ...actions}), [state, actions]) + const updateSellInput = React.useCallback(() => { + if (state.sellQuantity.isTouched && !sellInputRef?.current?.isFocused()) { + actions.sellInputValueChanged(Quantities.format(sellQuantity, sellTokenInfo.decimals ?? 0)) + } + }, [actions, sellQuantity, sellTokenInfo.decimals, state.sellQuantity.isTouched]) + + const updateBuyInput = React.useCallback(() => { + if (state.buyQuantity.isTouched && !buyInputRef?.current?.isFocused()) { + actions.buyInputValueChanged(Quantities.format(buyQuantity, buyTokenInfo.decimals ?? 0)) + } + }, [actions, buyTokenInfo.decimals, buyQuantity, state.buyQuantity.isTouched]) + + const updateLimitPrice = React.useCallback(() => { + if (orderData.type === 'limit' && !limitInputRef?.current?.isFocused()) { + actions.limitPriceInputValueChanged( + Quantities.format(orderData.limitPrice ?? Quantities.zero, denomination, PRECISION), + ) + } else { + actions.limitPriceInputValueChanged( + Quantities.format(orderData.selectedPoolCalculation?.prices.market ?? Quantities.zero, denomination, PRECISION), + ) + } + }, [actions, denomination, orderData.limitPrice, orderData.selectedPoolCalculation?.prices.market, orderData.type]) + + const onChangeSellQuantity = React.useCallback( + (text: string) => { + const [input, quantity] = Quantities.parseFromText(text, sellTokenInfo.decimals ?? 0, numberLocale) + sellQuantityChanged(quantity) + actions.sellInputValueChanged(text === '' ? '' : input) + }, + [actions, numberLocale, sellQuantityChanged, sellTokenInfo.decimals], + ) + + const onChangeBuyQuantity = React.useCallback( + (text: string) => { + const [input, quantity] = Quantities.parseFromText(text, buyTokenInfo.decimals ?? 0, numberLocale) + buyQuantityChanged(quantity) + actions.buyInputValueChanged(text === '' ? '' : input) + }, + [actions, buyQuantityChanged, buyTokenInfo.decimals, numberLocale], + ) + + const onChangeLimitPrice = React.useCallback( + (text: string) => { + const [formattedPrice, price] = Quantities.parseFromText(text, denomination, numberLocale, PRECISION) + actions.limitPriceInputValueChanged(formattedPrice) + limitPriceChanged(price) + }, + [actions, denomination, limitPriceChanged, numberLocale], + ) - return {children} + React.useEffect(() => { + if (buyError !== state.buyQuantity.error) actions.buyAmountErrorChanged(buyError) + }, [actions, buyError, state.buyQuantity.error]) + + React.useEffect(() => { + if (sellError !== state.sellQuantity.error) actions.sellAmountErrorChanged(sellError) + }, [actions, sellError, state.sellQuantity.error]) + + React.useEffect(() => { + if (canSwap !== state.canSwap) actions.canSwapChanged(canSwap) + }, [actions, canSwap, state.canSwap]) + + React.useEffect(() => { + updateSellInput() + }, [sellQuantity, updateSellInput]) + + React.useEffect(() => { + updateBuyInput() + }, [buyQuantity, updateBuyInput]) + + React.useEffect(() => { + updateLimitPrice() + }, [orderData.limitPrice, orderData.selectedPoolCalculation?.prices.market, orderData.type, updateLimitPrice]) + + const context = React.useMemo( + () => ({ + ...state, + buyInputRef, + sellInputRef, + limitInputRef, + onChangeSellQuantity, + onChangeBuyQuantity, + onChangeLimitPrice, + ...actions, + }), + [state, onChangeSellQuantity, onChangeBuyQuantity, onChangeLimitPrice, actions], + ) + + return {children} } -type TouchedAction = - | {type: 'sellTouched'} - | {type: 'buyTouched'} - | {type: 'switchTouched'} - | {type: 'poolTouched'} - | {type: 'poolDefaulted'} - | {type: 'resetTouches'} +const swapFormReducer = (state: SwapFormState, action: SwapFormAction) => { + return produce(state, (draft) => { + switch (action.type) { + case SwapFormActionType.SellTouched: + draft.sellQuantity.isTouched = true + + break + + case SwapFormActionType.BuyTouched: + draft.buyQuantity.isTouched = true -function touchedReducer(state: TouchedState, action: TouchedAction) { - switch (action.type) { - case 'sellTouched': - return {...state, isSellTouched: true} + break - case 'buyTouched': - return {...state, isBuyTouched: true} + case SwapFormActionType.SwitchTouched: + draft.sellQuantity.isTouched = state.buyQuantity.isTouched + draft.buyQuantity.isTouched = state.sellQuantity.isTouched - case 'switchTouched': - return { - ...state, - isSellTouched: state.isBuyTouched, - isBuyTouched: state.isSellTouched, - } + break - case 'poolTouched': - return {...state, isPoolTouched: true} + case SwapFormActionType.PoolTouched: + draft.selectedPool.isTouched = true - case 'poolDefaulted': - return {...state, isPoolTouched: false} + break - case 'resetTouches': - return defaultState + case SwapFormActionType.PoolDefaulted: + draft.selectedPool = defaultState.selectedPool - default: - throw new Error(`touchedReducer invalid action`) + break + + case SwapFormActionType.ResetSwapForm: + case SwapFormActionType.ClearSwapForm: + return defaultState + + case SwapFormActionType.CanSwapChanged: + draft.canSwap = action.canSwap + + break + + case SwapFormActionType.SellInputValueChanged: + draft.sellQuantity.displayValue = action.value + + break + + case SwapFormActionType.BuyInputValueChanged: + draft.buyQuantity.displayValue = action.value + + break + + case SwapFormActionType.LimitPriceInputValueChanged: + draft.limitPrice.displayValue = action.value + + break + + case SwapFormActionType.SellAmountErrorChanged: + draft.sellQuantity.error = action.error + + break + + case SwapFormActionType.BuyAmountErrorChanged: + draft.buyQuantity.error = action.error + + break + + default: + throw new Error(`swapFormReducer invalid action`) + } + }) +} + +const PRECISION = 14 + +const defaultState: SwapFormState = Object.freeze({ + sellQuantity: { + isTouched: true, + disabled: false, + error: undefined, + displayValue: '', + }, + buyQuantity: { + isTouched: false, + disabled: false, + error: undefined, + displayValue: '', + }, + selectedPool: { + isTouched: false, + }, + limitPrice: { + displayValue: '', + }, + canSwap: false, +}) + +/* istanbul ignore next */ +function missingInit() { + console.error('[SwapFormContext] missing initialization') +} + +const initialSwapFormContext: SwapFormContext = { + ...defaultState, + sellTouched: missingInit, + buyTouched: missingInit, + poolTouched: missingInit, + poolDefaulted: missingInit, + switchTouched: missingInit, + switchTokens: missingInit, + clearSwapForm: missingInit, + resetSwapForm: missingInit, + buyInputValueChanged: missingInit, + sellInputValueChanged: missingInit, + limitPriceInputValueChanged: missingInit, + buyAmountErrorChanged: missingInit, + sellAmountErrorChanged: missingInit, + canSwapChanged: missingInit, + sellInputRef: undefined, + buyInputRef: undefined, + limitInputRef: undefined, + onChangeSellQuantity: missingInit, + onChangeBuyQuantity: missingInit, + onChangeLimitPrice: missingInit, +} + +type SwapFormAction = + | {type: SwapFormActionType.SellTouched} + | {type: SwapFormActionType.BuyTouched} + | {type: SwapFormActionType.SwitchTouched} + | {type: SwapFormActionType.PoolTouched} + | {type: SwapFormActionType.PoolDefaulted} + | {type: SwapFormActionType.ClearSwapForm} + | {type: SwapFormActionType.ResetSwapForm} + | {type: SwapFormActionType.CanSwapChanged; canSwap: boolean} + | {type: SwapFormActionType.SellInputValueChanged; value: string} + | {type: SwapFormActionType.BuyInputValueChanged; value: string} + | {type: SwapFormActionType.SellAmountErrorChanged; error: string | undefined} + | {type: SwapFormActionType.LimitPriceInputValueChanged; value: string} + | {type: SwapFormActionType.BuyAmountErrorChanged; error: string | undefined} + +type SwapFormState = { + sellQuantity: { + isTouched: boolean + disabled: boolean + error: string | undefined + displayValue: string } + buyQuantity: { + isTouched: boolean + disabled: boolean + error: string | undefined + displayValue: string + } + selectedPool: { + isTouched: boolean + } + limitPrice: { + displayValue: string + } + canSwap: boolean +} +type SwapFormActions = { + sellTouched: () => void + buyTouched: () => void + switchTouched: () => void + switchTokens: () => void + poolTouched: () => void + poolDefaulted: () => void + clearSwapForm: () => void + resetSwapForm: () => void + canSwapChanged: (canSwap: boolean) => void + buyInputValueChanged: (value: string) => void + sellInputValueChanged: (value: string) => void + limitPriceInputValueChanged: (value: string) => void + buyAmountErrorChanged: (error: string | undefined) => void + sellAmountErrorChanged: (error: string | undefined) => void } -const defaultState: TouchedState = Object.freeze({isSellTouched: true, isBuyTouched: false, isPoolTouched: false}) +enum SwapFormActionType { + SellTouched = 'sellTouched', + BuyTouched = 'buyTouched', + SwitchTouched = 'switchTouched', + SwitchTokens = 'switchTokens', + PoolTouched = 'poolTouched', + PoolDefaulted = 'poolDefaulted', + ClearSwapForm = 'clearSwapForm', + ResetSwapForm = 'resetSwapForm', + CanSwapChanged = 'canSwapChanged', + BuyInputValueChanged = 'buyInputValueChanged', + SellInputValueChanged = 'sellInputValueChanged', + LimitPriceInputValueChanged = 'limitPriceInputValueChanged', + SellAmountErrorChanged = 'sellAmountErrorChanged', + BuyAmountErrorChanged = 'buyAmountErrorChanged', +} + +type SwapFormContext = SwapFormState & + SwapFormActions & { + sellInputRef: React.RefObject | undefined + buyInputRef: React.RefObject | undefined + limitInputRef: React.RefObject | undefined + onChangeSellQuantity: (text: string) => void + onChangeBuyQuantity: (text: string) => void + onChangeLimitPrice: (text: string) => void + } + +const SwapFormContext = React.createContext(initialSwapFormContext) diff --git a/apps/wallet-mobile/src/features/Swap/common/SwapInfoLink/SwapInfoLink.tsx b/apps/wallet-mobile/src/features/Swap/common/SwapInfoLink/SwapInfoLink.tsx index 899bf1b651..3201d2bef7 100644 --- a/apps/wallet-mobile/src/features/Swap/common/SwapInfoLink/SwapInfoLink.tsx +++ b/apps/wallet-mobile/src/features/Swap/common/SwapInfoLink/SwapInfoLink.tsx @@ -3,11 +3,12 @@ import {Linking, StyleSheet, Text, TouchableOpacity} from 'react-native' import {useStrings} from '../strings' +const SWAP_ZENDESK_LINK = 'https://emurgohelpdesk.zendesk.com/hc/en-us/sections/8154256843407-Swap' + export const SwapInfoLink = () => { const strings = useStrings() return ( - // TODO: add real link - Linking.openURL('https://yoroi-wallet.com/#/')} style={styles.link}> + Linking.openURL(SWAP_ZENDESK_LINK)} style={styles.link}> {strings.listOrdersSheetLink} ) diff --git a/apps/wallet-mobile/src/features/Swap/common/strings.ts b/apps/wallet-mobile/src/features/Swap/common/strings.ts index fa4e634723..6c6fc209c5 100644 --- a/apps/wallet-mobile/src/features/Swap/common/strings.ts +++ b/apps/wallet-mobile/src/features/Swap/common/strings.ts @@ -117,6 +117,7 @@ export const useStrings = () => { incorrectPasswordMessage: intl.formatMessage(errorMessages.incorrectPassword.message), notEnoughBalance: intl.formatMessage(messages.notEnoughBalance), notEnoughSupply: intl.formatMessage(messages.notEnoughSupply), + notEnoughFeeBalance: intl.formatMessage(messages.notEnoughFeeBalance), noPool: intl.formatMessage(messages.noPool), generalErrorTitle: intl.formatMessage(errorMessages.generalError.title), generalErrorMessage: (e) => intl.formatMessage(errorMessages.generalError.message, {message: e}), @@ -547,6 +548,10 @@ export const messages = defineMessages({ id: 'swap.swapScreen.notEnoughSupply', defaultMessage: '!!!Not enough supply in the pool', }, + notEnoughFeeBalance: { + id: 'swap.swapScreen.notEnoughFeeBalance', + defaultMessage: '!!!Not enough balance, please consider the fees', + }, noPool: { id: 'swap.swapScreen.noPool', defaultMessage: '!!! This pair is not available in any liquidity pool', diff --git a/apps/wallet-mobile/src/features/Swap/useCases/ConfirmTxScreen/TransactionSummary.tsx b/apps/wallet-mobile/src/features/Swap/useCases/ConfirmTxScreen/TransactionSummary.tsx index e77095d76d..e806d7bc28 100644 --- a/apps/wallet-mobile/src/features/Swap/useCases/ConfirmTxScreen/TransactionSummary.tsx +++ b/apps/wallet-mobile/src/features/Swap/useCases/ConfirmTxScreen/TransactionSummary.tsx @@ -4,9 +4,8 @@ import {capitalize} from 'lodash' import React from 'react' import {StyleSheet, TouchableOpacity, View} from 'react-native' -import {Icon, Spacer, Text} from '../../../../components' +import {Icon, Spacer, Text, useModal} from '../../../../components' import {AmountItem} from '../../../../components/AmountItem/AmountItem' -import {BottomSheetModal} from '../../../../legacy/BottomSheetModal' import {useSelectedWallet} from '../../../../SelectedWallet' import {COLORS} from '../../../../theme' import {useTokenInfo} from '../../../../yoroi-wallets/hooks' @@ -14,17 +13,14 @@ import {Quantities} from '../../../../yoroi-wallets/utils' import {LiquidityPool} from '../../common/LiquidityPool/LiquidityPool' import {PoolIcon} from '../../common/PoolIcon/PoolIcon' import {useStrings} from '../../common/strings' +import {SwapInfoLink} from '../../common/SwapInfoLink/SwapInfoLink' export const TransactionSummary = () => { - const [bottomSheetState, setBottomSheetSate] = React.useState<{isOpen: boolean; title: string; content?: string}>({ - isOpen: false, - title: '', - content: '', - }) const strings = useStrings() const wallet = useSelectedWallet() const {orderData} = useSwap() const {amounts, selectedPoolCalculation} = orderData + const {openModal} = useModal() const buyTokenInfo = useTokenInfo({wallet, tokenId: amounts.buy.tokenId}) const tokenToBuyName = buyTokenInfo.ticker ?? buyTokenInfo.name @@ -67,75 +63,70 @@ export const TransactionSummary = () => { return ( - - - {strings.total} + + {strings.total} - - {label} + + {label} - + - - + + + + + + {feesInfo.map((orderInfo) => { + return ( + + + + + + {orderInfo.label} - - - {feesInfo.map((orderInfo) => { - return ( - - - - - - {orderInfo.label} - - - - {orderInfo.info != undefined && ( - { - setBottomSheetSate({ - isOpen: true, - title: orderInfo.label, - content: orderInfo.info, - }) - }} - > - - - )} - - - {orderInfo.value} + + + {orderInfo.info != undefined && ( + { + openModal( + orderInfo.label, + + {orderInfo.info} + + + + + + + , + ) + }} + > + + + )} - - ) - })} - + {orderInfo.value} + + + ) + })} - {strings.swapFrom} + - + {strings.swapFrom} - + - {strings.swapTo} + - - + {strings.swapTo} - { - setBottomSheetSate({isOpen: false, title: '', content: ''}) - }} - > - {bottomSheetState.content} - + ) } @@ -185,4 +176,15 @@ const styles = StyleSheet.create({ color: '#242838', paddingBottom: 8, }, + modalContent: { + justifyContent: 'space-between', + flex: 1, + }, + modalText: { + fontFamily: 'Rubik', + fontWeight: '400', + fontSize: 16, + lineHeight: 24, + color: '#242838', + }, }) diff --git a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/CreateOrder.tsx b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/CreateOrder.tsx index 79c0b4a74f..79e42ecb70 100644 --- a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/CreateOrder.tsx +++ b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/CreateOrder.tsx @@ -9,14 +9,13 @@ import {Button, Spacer} from '../../../../../components' import {useMetrics} from '../../../../../metrics/metricsManager' import {useSelectedWallet} from '../../../../../SelectedWallet' import {COLORS} from '../../../../../theme' -import {isEmptyString} from '../../../../../utils' import {NotEnoughMoneyToSendError} from '../../../../../yoroi-wallets/cardano/types' -import {useBalance, useTokenInfo} from '../../../../../yoroi-wallets/hooks' +import {useTokenInfo} from '../../../../../yoroi-wallets/hooks' import {Quantities} from '../../../../../yoroi-wallets/utils' import {createYoroiEntry} from '../../../common/helpers' import {useNavigateTo} from '../../../common/navigation' import {useStrings} from '../../../common/strings' -import {useSwapTouched} from '../../../common/SwapFormProvider' +import {useSwapForm} from '../../../common/SwapFormProvider' import {useSwapTx} from '../../../common/useSwapTx' import {EditBuyAmount} from './EditBuyAmount/EditBuyAmount' import {EditLimitPrice} from './EditLimitPrice' @@ -35,8 +34,13 @@ export const CreateOrder = () => { const {orderData, unsignedTxChanged, poolPairsChanged} = useSwap() const wallet = useSelectedWallet() const {track} = useMetrics() - const {isBuyTouched, isSellTouched, poolDefaulted} = useSwapTouched() - const [sellBackendError, setSellBackendError] = React.useState('') + const { + sellQuantity: {isTouched: isSellTouched}, + buyQuantity: {isTouched: isBuyTouched}, + sellAmountErrorChanged, + poolDefaulted, + canSwap, + } = useSwapForm() useSwapPoolsByPair( { @@ -73,7 +77,7 @@ export const CreateOrder = () => { }, onError: (error) => { if (error instanceof NotEnoughMoneyToSendError) { - setSellBackendError(strings.notEnoughBalance) + sellAmountErrorChanged(strings.notEnoughBalance) return } @@ -105,18 +109,6 @@ export const CreateOrder = () => { }, }) - const sellError = useSellError([sellBackendError]) - const buyError = useBuyError() - - const disabled = isLoading - !isBuyTouched || - !isSellTouched || - Quantities.isZero(orderData.amounts.buy.quantity) || - Quantities.isZero(orderData.amounts.sell.quantity) || - (orderData.type === 'limit' && orderData.limitPrice !== undefined && Quantities.isZero(orderData.limitPrice)) || - !isEmptyString(sellError) || - !isEmptyString(buyError) - const swap = () => { if (orderData.selectedPoolCalculation === undefined) return track.swapOrderSelected({ @@ -202,6 +194,8 @@ export const CreateOrder = () => { createUnsignedSwapTx() } + const disabled = isLoading || !canSwap + return ( { - + @@ -227,7 +221,7 @@ export const CreateOrder = () => { - + @@ -249,83 +243,6 @@ export const CreateOrder = () => { const Actions = ({style, ...props}: ViewProps) => -const useSellError = (errors: Array = []): string => { - const noPoolError = useNoPoolError() - const notEnoughBalanceError = useNotEnoughBalanceError() - - const allErrors = [noPoolError, notEnoughBalanceError, ...errors] - const sellError = allErrors.find((error) => !isEmptyString(error)) - - return sellError ?? '' -} - -const useBuyError = (errors: Array = []): string => { - const noPoolError = useNoPoolError() - const notEnoughSupplyError = useNotEnoughSupplyError() - - const allErrors = [noPoolError, notEnoughSupplyError, ...errors] - const buyError = allErrors.find((error) => !isEmptyString(error)) - - return buyError ?? '' -} - -const useNotEnoughSupplyError = (): string => { - const strings = useStrings() - const {orderData} = useSwap() - const {isBuyTouched, isSellTouched} = useSwapTouched() - const pool = orderData.selectedPoolCalculation?.pool - const {tokenId, quantity} = orderData.amounts.buy - const poolSupply = tokenId === pool?.tokenA.tokenId ? pool?.tokenA.quantity : pool?.tokenB.quantity - const hasSupply = !Quantities.isGreaterThan(quantity, poolSupply ?? Quantities.zero) - - const notEnoughSupplyError = - (!Quantities.isZero(quantity) && !hasSupply) || (isSellTouched && isBuyTouched && pool === undefined) - ? strings.notEnoughSupply - : '' - - return notEnoughSupplyError -} - -const useNotEnoughBalanceError = (): string => { - const strings = useStrings() - const {orderData} = useSwap() - const {isBuyTouched} = useSwapTouched() - const wallet = useSelectedWallet() - const {tokenId, quantity} = orderData.amounts.sell - const balance = useBalance({wallet, tokenId}) - - const hasPrimaryTokenBalance = !Quantities.isGreaterThan( - Quantities.sum([ - tokenId === wallet.primaryTokenInfo.id ? orderData.amounts.sell.quantity : Quantities.zero, - orderData.selectedPoolCalculation?.cost.ptTotalFeeNoFEF.quantity ?? Quantities.zero, - ]), - balance, - ) - - const hasSecondaryTokenBalance = !Quantities.isGreaterThan( - tokenId !== wallet.primaryTokenInfo.id ? orderData.amounts.sell.quantity : Quantities.zero, - balance, - ) - - const notEnoughBalanceError = - !Quantities.isZero(quantity) && (!hasPrimaryTokenBalance || !hasSecondaryTokenBalance) && isBuyTouched - ? strings.notEnoughBalance - : '' - - return notEnoughBalanceError -} - -const useNoPoolError = () => { - const strings = useStrings() - const {orderData} = useSwap() - const {isBuyTouched, isSellTouched} = useSwapTouched() - - const noPoolError = - orderData.selectedPoolCalculation === undefined && isBuyTouched && isSellTouched ? strings.noPool : '' - - return noPoolError -} - const styles = StyleSheet.create({ root: { flex: 1, diff --git a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditBuyAmount/EditBuyAmount.tsx b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditBuyAmount/EditBuyAmount.tsx index 27764bf087..2aac51f319 100644 --- a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditBuyAmount/EditBuyAmount.tsx +++ b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditBuyAmount/EditBuyAmount.tsx @@ -1,62 +1,39 @@ import {useSwap} from '@yoroi/swap' import * as React from 'react' -import {TextInput} from 'react-native' -import {useLanguage} from '../../../../../../i18n' import {useSelectedWallet} from '../../../../../../SelectedWallet' -import {useBalance, useTokenInfo} from '../../../../../../yoroi-wallets/hooks' -import {Logger} from '../../../../../../yoroi-wallets/logging' -import {Quantities} from '../../../../../../yoroi-wallets/utils' +import {useBalance} from '../../../../../../yoroi-wallets/hooks' import {AmountCard} from '../../../../common/AmountCard/AmountCard' import {useNavigateTo} from '../../../../common/navigation' import {useStrings} from '../../../../common/strings' -import {useSwapTouched} from '../../../../common/SwapFormProvider' +import {useSwapForm} from '../../../../common/SwapFormProvider' -export const EditBuyAmount = ({error = ''}: {error?: string}) => { +export const EditBuyAmount = () => { const strings = useStrings() const navigate = useNavigateTo() const wallet = useSelectedWallet() - const {numberLocale} = useLanguage() - const inputRef = React.useRef(null) - - const {orderData, buyQuantityChanged} = useSwap() - const {isBuyTouched} = useSwapTouched() + const {orderData} = useSwap() + const { + buyQuantity: {isTouched: isBuyTouched, displayValue: buyDisplayValue, error: buyError}, + onChangeBuyQuantity, + buyInputRef, + } = useSwapForm() const pool = orderData.selectedPoolCalculation?.pool - const {tokenId, quantity} = orderData.amounts.buy - const tokenInfo = useTokenInfo({wallet, tokenId}) - const {decimals} = tokenInfo + const {tokenId} = orderData.amounts.buy const balance = useBalance({wallet, tokenId}) - const [inputValue, setInputValue] = React.useState(Quantities.format(quantity, tokenInfo.decimals ?? 0)) - - React.useEffect(() => { - if (isBuyTouched && !inputRef?.current?.isFocused()) { - setInputValue(Quantities.format(quantity, tokenInfo.decimals ?? 0)) - } - }, [isBuyTouched, quantity, tokenInfo.decimals]) - - const onChangeQuantity = (text: string) => { - try { - const [input, quantity] = Quantities.parseFromText(text, decimals ?? 0, numberLocale) - setInputValue(text === '' ? text : input) - buyQuantityChanged(quantity) - } catch (error) { - Logger.error('SwapAmountScreen::onChangeQuantity', error) - } - } - return ( ) } diff --git a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditBuyAmount/SelectBuyTokenFromListScreen/SelectBuyTokenFromListScreen.tsx b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditBuyAmount/SelectBuyTokenFromListScreen/SelectBuyTokenFromListScreen.tsx index 017021f84c..f1fdb02f31 100644 --- a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditBuyAmount/SelectBuyTokenFromListScreen/SelectBuyTokenFromListScreen.tsx +++ b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditBuyAmount/SelectBuyTokenFromListScreen/SelectBuyTokenFromListScreen.tsx @@ -20,7 +20,7 @@ import {Counter} from '../../../../../common/Counter/Counter' import {filterBySearch} from '../../../../../common/filterBySearch' import {useNavigateTo} from '../../../../../common/navigation' import {useStrings} from '../../../../../common/strings' -import {useSwapTouched} from '../../../../../common/SwapFormProvider' +import {useSwapForm} from '../../../../../common/SwapFormProvider' type TokenForList = { supply: Balance.TokenSupply['total'] @@ -185,7 +185,10 @@ type SelectableTokenProps = {disabled?: boolean; tokenForList: TokenForList; wal const SelectableToken = ({tokenForList, wallet}: SelectableTokenProps) => { const {closeSearch} = useSearch() const {buyTokenIdChanged, orderData} = useSwap() - const {buyTouched, isSellTouched} = useSwapTouched() + const { + sellQuantity: {isTouched: isSellTouched}, + buyTouched, + } = useSwapForm() const navigateTo = useNavigateTo() const balanceAvailable = useBalance({wallet, tokenId: tokenForList.id}) const {track} = useMetrics() diff --git a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditLimitPrice.tsx b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditLimitPrice.tsx index 9c27d2d394..4a3776c798 100644 --- a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditLimitPrice.tsx +++ b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditLimitPrice.tsx @@ -3,58 +3,45 @@ import {useSwap} from '@yoroi/swap' import * as React from 'react' import {StyleSheet, Text, TextInput, View} from 'react-native' -import {useLanguage} from '../../../../../i18n' import {useSelectedWallet} from '../../../../../SelectedWallet' import {COLORS} from '../../../../../theme' import {useTokenInfo} from '../../../../../yoroi-wallets/hooks' -import {Quantities} from '../../../../../yoroi-wallets/utils' import {useStrings} from '../../../common/strings' -import {useSwapTouched} from '../../../common/SwapFormProvider' +import {useSwapForm} from '../../../common/SwapFormProvider' const BORDER_SIZE = 1 -const PRECISION = 14 export const EditLimitPrice = () => { const strings = useStrings() - const {numberLocale} = useLanguage() - const [text, setText] = React.useState('') const wallet = useSelectedWallet() - const inputRef = React.useRef(null) - const {orderData, limitPriceChanged} = useSwap() + const {orderData} = useSwap() const sellTokenInfo = useTokenInfo({wallet, tokenId: orderData.amounts.sell.tokenId}) const buyTokenInfo = useTokenInfo({wallet, tokenId: orderData.amounts.buy.tokenId}) - const denomination = (sellTokenInfo.decimals ?? 0) - (buyTokenInfo.decimals ?? 0) const disabled = orderData.type === 'market' - const {isBuyTouched, isSellTouched} = useSwapTouched() + const { + sellQuantity: {isTouched: isBuyTouched}, + sellQuantity: {isTouched: isSellTouched}, + limitPrice: {displayValue: limitDisplayValue}, + limitInputRef, + onChangeLimitPrice, + } = useSwapForm() const tokenToSellName = isSellTouched ? sellTokenInfo.ticker ?? sellTokenInfo.name : '-' const tokenToBuyName = isBuyTouched ? buyTokenInfo.ticker ?? buyTokenInfo.name : '-' - React.useEffect(() => { - if (orderData.type === 'limit') { - !inputRef?.current?.isFocused() && - setText(Quantities.format(orderData.limitPrice ?? Quantities.zero, denomination, PRECISION)) - } else { - setText( - Quantities.format(orderData.selectedPoolCalculation?.prices.market ?? Quantities.zero, denomination, PRECISION), - ) - } - }, [orderData.type, orderData.limitPrice, orderData.amounts.sell, denomination, orderData.selectedPoolCalculation]) - - const onChange = (text: string) => { - const [formattedPrice, price] = Quantities.parseFromText(text, denomination, numberLocale, PRECISION) - setText(formattedPrice) - limitPriceChanged(price) - } - return ( {disabled ? strings.marketPrice : strings.limitPrice} - + diff --git a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditPool/ShowPoolActions.tsx b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditPool/ShowPoolActions.tsx index a5e7717814..9e04a526d4 100644 --- a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditPool/ShowPoolActions.tsx +++ b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditPool/ShowPoolActions.tsx @@ -17,14 +17,18 @@ import {Quantities} from '../../../../../../yoroi-wallets/utils' import {useNavigateTo} from '../../../../common/navigation' import {PoolIcon} from '../../../../common/PoolIcon/PoolIcon' import {useStrings} from '../../../../common/strings' -import {useSwapTouched} from '../../../../common/SwapFormProvider' +import {useSwapForm} from '../../../../common/SwapFormProvider' import {SwapInfoLink} from '../../../../common/SwapInfoLink/SwapInfoLink' export const ShowPoolActions = () => { const navigateTo = useNavigateTo() const {orderData} = useSwap() const strings = useStrings() - const {isBuyTouched, isSellTouched, isPoolTouched} = useSwapTouched() + const { + buyQuantity: {isTouched: isBuyTouched}, + sellQuantity: {isTouched: isSellTouched}, + selectedPool: {isTouched: isPoolTouched}, + } = useSwapForm() const {selectedPoolCalculation, amounts} = orderData const wallet = useSelectedWallet() const buyTokenInfo = useTokenInfo({wallet, tokenId: amounts.buy.tokenId}) diff --git a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditSellAmount/EditSellAmount.tsx b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditSellAmount/EditSellAmount.tsx index 913448c33f..76722e1af2 100644 --- a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditSellAmount/EditSellAmount.tsx +++ b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditSellAmount/EditSellAmount.tsx @@ -1,61 +1,36 @@ import {useSwap} from '@yoroi/swap' import * as React from 'react' -import {TextInput} from 'react-native' -import {useLanguage} from '../../../../../../i18n' import {useSelectedWallet} from '../../../../../../SelectedWallet' -import {useBalance, useTokenInfo} from '../../../../../../yoroi-wallets/hooks' -import {Logger} from '../../../../../../yoroi-wallets/logging' -import {Quantities} from '../../../../../../yoroi-wallets/utils' +import {useBalance} from '../../../../../../yoroi-wallets/hooks' import {AmountCard} from '../../../../common/AmountCard/AmountCard' import {useNavigateTo} from '../../../../common/navigation' import {useStrings} from '../../../../common/strings' -import {useSwapTouched} from '../../../../common/SwapFormProvider' +import {useSwapForm} from '../../../../common/SwapFormProvider' -export const EditSellAmount = ({error = ''}: {error?: string}) => { +export const EditSellAmount = () => { const strings = useStrings() const navigate = useNavigateTo() const wallet = useSelectedWallet() - const {numberLocale} = useLanguage() - const inputRef = React.useRef(null) - - const {orderData, sellQuantityChanged} = useSwap() - const {isSellTouched} = useSwapTouched() - - const {tokenId, quantity} = orderData.amounts.sell - - const tokenInfo = useTokenInfo({wallet, tokenId}) - const {decimals} = tokenInfo + const {orderData} = useSwap() + const { + sellQuantity: {isTouched: isSellTouched, displayValue: sellDisplayValue, error}, + onChangeSellQuantity, + sellInputRef, + } = useSwapForm() + const {tokenId} = orderData.amounts.sell const balance = useBalance({wallet, tokenId}) - const [inputValue, setInputValue] = React.useState(Quantities.format(quantity, tokenInfo.decimals ?? 0)) - - React.useEffect(() => { - if (isSellTouched && !inputRef?.current?.isFocused()) { - setInputValue(Quantities.format(quantity, tokenInfo.decimals ?? 0)) - } - }, [isSellTouched, quantity, tokenInfo.decimals]) - - const onChangeQuantity = (text: string) => { - try { - const [input, quantity] = Quantities.parseFromText(text, decimals ?? 0, numberLocale) - setInputValue(text === '' ? text : input) - sellQuantityChanged(quantity) - } catch (error) { - Logger.error('SwapAmountScreen::onChangeQuantity', error) - } - } - return ( diff --git a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditSellAmount/SelectSellTokenFromListScreen/SelectSellTokenFromListScreen.tsx b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditSellAmount/SelectSellTokenFromListScreen/SelectSellTokenFromListScreen.tsx index 880eda1f49..5834b85edb 100644 --- a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditSellAmount/SelectSellTokenFromListScreen/SelectSellTokenFromListScreen.tsx +++ b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditSellAmount/SelectSellTokenFromListScreen/SelectSellTokenFromListScreen.tsx @@ -20,7 +20,7 @@ import {Counter} from '../../../../../common/Counter/Counter' import {filterBySearch} from '../../../../../common/filterBySearch' import {useNavigateTo} from '../../../../../common/navigation' import {useStrings} from '../../../../../common/strings' -import {useSwapTouched} from '../../../../../common/SwapFormProvider' +import {useSwapForm} from '../../../../../common/SwapFormProvider' export const SelectSellTokenFromListScreen = () => { const strings = useStrings() @@ -89,7 +89,10 @@ type SelectableTokenProps = {disabled?: boolean; tokenInfo: Balance.TokenInfo; w const SelectableToken = ({tokenInfo, wallet}: SelectableTokenProps) => { const {closeSearch} = useSearch() const {sellTokenIdChanged, orderData} = useSwap() - const {sellTouched, isBuyTouched} = useSwapTouched() + const { + buyQuantity: {isTouched: isBuyTouched}, + sellTouched, + } = useSwapForm() const navigateTo = useNavigateTo() const {track} = useMetrics() diff --git a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditSlippage/ShowSlippageInfo.tsx b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditSlippage/ShowSlippageInfo.tsx index 98ec7c4efe..9801e7d515 100644 --- a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditSlippage/ShowSlippageInfo.tsx +++ b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/EditSlippage/ShowSlippageInfo.tsx @@ -2,14 +2,13 @@ import React from 'react' import {StyleSheet, Text, View} from 'react-native' import {TouchableOpacity} from 'react-native-gesture-handler' -import {Icon, Spacer} from '../../../../../../components' -import {BottomSheetModal} from '../../../../../../legacy/BottomSheetModal' +import {Icon, Spacer, useModal} from '../../../../../../components' import {COLORS} from '../../../../../../theme' import {useStrings} from '../../../../common/strings' export const ShowSlippageInfo = () => { - const [showInfo, setShowInfo] = React.useState(false) const strings = useStrings() + const {openModal} = useModal() return ( @@ -19,15 +18,11 @@ export const ShowSlippageInfo = () => { { - setShowInfo(true) + openModal(strings.slippageTolerance, {strings.slippageToleranceInfo}) }} > - - setShowInfo(false)}> - {strings.slippageToleranceInfo} - ) } @@ -42,9 +37,10 @@ const styles = StyleSheet.create({ color: COLORS.TEXT_INPUT, }, sheetContent: { + fontFamily: 'Rubik', + fontWeight: '400', fontSize: 16, - color: '#242838', lineHeight: 24, - fontWeight: '400', + color: '#242838', }, }) diff --git a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/ShowTokenActions/ClearQuantities.tsx b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/ShowTokenActions/ClearQuantities.tsx index a5873c84c6..5bdad747c8 100644 --- a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/ShowTokenActions/ClearQuantities.tsx +++ b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/ShowTokenActions/ClearQuantities.tsx @@ -1,25 +1,17 @@ -import {useSwap} from '@yoroi/swap' import React from 'react' -import {Keyboard, StyleSheet, Text} from 'react-native' +import {StyleSheet, Text} from 'react-native' import {TouchableOpacity} from 'react-native-gesture-handler' import {COLORS} from '../../../../../../theme' import {useStrings} from '../../../../common/strings' -import {useSwapTouched} from '../../../../common/SwapFormProvider' +import {useSwapForm} from '../../../../common/SwapFormProvider' export const ClearQuantities = () => { const strings = useStrings() - const {resetQuantities} = useSwap() - const {poolDefaulted} = useSwapTouched() - - const handleReset = () => { - Keyboard.dismiss() - resetQuantities() - poolDefaulted() - } + const {clearSwapForm} = useSwapForm() return ( - + {strings.clear} ) diff --git a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/ShowTokenActions/SwitchTokens.tsx b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/ShowTokenActions/SwitchTokens.tsx index 5ea78fd311..5bc79d04ec 100644 --- a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/ShowTokenActions/SwitchTokens.tsx +++ b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/ShowTokenActions/SwitchTokens.tsx @@ -1,21 +1,14 @@ -import {useSwap} from '@yoroi/swap' import React from 'react' import {TouchableOpacity} from 'react-native-gesture-handler' import {Icon} from '../../../../../../components/Icon' -import {useSwapTouched} from '../../../../common/SwapFormProvider' +import {useSwapForm} from '../../../../common/SwapFormProvider' export const SwitchTokens = () => { - const {switchTokens} = useSwap() - const {switchTouched} = useSwapTouched() - - const handleSwitch = () => { - switchTokens() - switchTouched() - } + const {switchTokens} = useSwapForm() return ( - + ) diff --git a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/ShowTokenActions/TopTokenActions.tsx b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/ShowTokenActions/TopTokenActions.tsx index e9de48f9ce..896a9cb220 100644 --- a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/ShowTokenActions/TopTokenActions.tsx +++ b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/CreateOrder/ShowTokenActions/TopTokenActions.tsx @@ -7,13 +7,16 @@ import {LoadingOverlay} from '../../../../../../components/LoadingOverlay' import {COLORS} from '../../../../../../theme' import {ButtonGroup} from '../../../../common/ButtonGroup/ButtonGroup' import {useStrings} from '../../../../common/strings' -import {useSwapTouched} from '../../../../common/SwapFormProvider' +import {useSwapForm} from '../../../../common/SwapFormProvider' export const TopTokenActions = () => { const strings = useStrings() const orderTypeLabels = [strings.marketButton, strings.limitButton] const {orderData, orderTypeChanged, poolPairsChanged} = useSwap() - const {isBuyTouched, isSellTouched} = useSwapTouched() + const { + buyQuantity: {isTouched: isBuyTouched}, + sellQuantity: {isTouched: isSellTouched}, + } = useSwapForm() const isDisabled = !isBuyTouched || !isSellTouched || orderData.selectedPoolCalculation === undefined const orderTypeIndex = orderData.type === 'market' ? 0 : 1 diff --git a/apps/wallet-mobile/src/i18n/locales/en-US.json b/apps/wallet-mobile/src/i18n/locales/en-US.json index 280880c586..a229a6bf51 100644 --- a/apps/wallet-mobile/src/i18n/locales/en-US.json +++ b/apps/wallet-mobile/src/i18n/locales/en-US.json @@ -133,6 +133,7 @@ "swap.swapScreen.swapTo": "Swap to", "swap.swapScreen.currentBalance": "Current balance", "swap.swapScreen.notEnoughBalance": "Not enough balance", + "swap.swapScreen.notEnoughFeeBalance": "Not enough balance, please consider the fees", "swap.swapScreen.notEnoughSupply": "Not enough supply in the pool", "swap.swapScreen.noPool": "This pair is not available in any liquidity pool", "swap.swapScreen.balance": "Balance", diff --git a/apps/wallet-mobile/translations/messages/src/features/Swap/common/strings.json b/apps/wallet-mobile/translations/messages/src/features/Swap/common/strings.json index 77890e69d8..8afac3ad6b 100644 --- a/apps/wallet-mobile/translations/messages/src/features/Swap/common/strings.json +++ b/apps/wallet-mobile/translations/messages/src/features/Swap/common/strings.json @@ -4,14 +4,14 @@ "defaultMessage": "!!!Incorrect password.", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 137, + "line": 138, "column": 24, - "index": 8805 + "index": 8880 }, "end": { - "line": 140, + "line": 141, "column": 3, - "index": 8914 + "index": 8989 } }, { @@ -19,14 +19,14 @@ "defaultMessage": "!!!Swap", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 141, + "line": 142, "column": 13, - "index": 8929 + "index": 9004 }, "end": { - "line": 144, + "line": 145, "column": 3, - "index": 9002 + "index": 9077 } }, { @@ -34,14 +34,14 @@ "defaultMessage": "!!!Token swap", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 145, + "line": 146, "column": 13, - "index": 9017 + "index": 9092 }, "end": { - "line": 148, + "line": 149, "column": 3, - "index": 9099 + "index": 9174 } }, { @@ -49,14 +49,14 @@ "defaultMessage": "!!!Orders", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 149, + "line": 150, "column": 13, - "index": 9114 + "index": 9189 }, "end": { - "line": 152, + "line": 153, "column": 3, - "index": 9193 + "index": 9268 } }, { @@ -64,14 +64,14 @@ "defaultMessage": "!!!Market Button", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 153, + "line": 154, "column": 16, - "index": 9211 + "index": 9286 }, "end": { - "line": 156, + "line": 157, "column": 3, - "index": 9296 + "index": 9371 } }, { @@ -79,14 +79,14 @@ "defaultMessage": "!!!Limit", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 157, + "line": 158, "column": 15, - "index": 9313 + "index": 9388 }, "end": { - "line": 160, + "line": 161, "column": 3, - "index": 9389 + "index": 9464 } }, { @@ -94,14 +94,14 @@ "defaultMessage": "!!!Swap from", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 161, + "line": 162, "column": 12, - "index": 9403 + "index": 9478 }, "end": { - "line": 164, + "line": 165, "column": 3, - "index": 9480 + "index": 9555 } }, { @@ -109,14 +109,14 @@ "defaultMessage": "!!!Swap to", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 165, + "line": 166, "column": 10, - "index": 9492 + "index": 9567 }, "end": { - "line": 168, + "line": 169, "column": 3, - "index": 9565 + "index": 9640 } }, { @@ -124,14 +124,14 @@ "defaultMessage": "!!!Current Balance", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 169, + "line": 170, "column": 18, - "index": 9585 + "index": 9660 }, "end": { - "line": 172, + "line": 173, "column": 3, - "index": 9674 + "index": 9749 } }, { @@ -139,14 +139,14 @@ "defaultMessage": "!!!Balance", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 173, + "line": 174, "column": 11, - "index": 9687 + "index": 9762 }, "end": { - "line": 176, + "line": 177, "column": 3, - "index": 9761 + "index": 9836 } }, { @@ -154,14 +154,14 @@ "defaultMessage": "!!!Select Token", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 177, + "line": 178, "column": 15, - "index": 9778 + "index": 9853 }, "end": { - "line": 180, + "line": 181, "column": 3, - "index": 9861 + "index": 9936 } }, { @@ -169,14 +169,14 @@ "defaultMessage": "!!!Market Price", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 181, + "line": 182, "column": 15, - "index": 9878 + "index": 9953 }, "end": { - "line": 184, + "line": 185, "column": 3, - "index": 9961 + "index": 10036 } }, { @@ -184,14 +184,14 @@ "defaultMessage": "!!!Limit Price", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 185, + "line": 186, "column": 14, - "index": 9977 + "index": 10052 }, "end": { - "line": 188, + "line": 189, "column": 3, - "index": 10058 + "index": 10133 } }, { @@ -199,14 +199,14 @@ "defaultMessage": "!!!Slippage Tolerance", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 189, + "line": 190, "column": 21, - "index": 10081 + "index": 10156 }, "end": { - "line": 192, + "line": 193, "column": 3, - "index": 10176 + "index": 10251 } }, { @@ -214,14 +214,14 @@ "defaultMessage": "!!!Slippage must be a number between 0 and 100 and have up to 1 decimal", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 193, + "line": 194, "column": 26, - "index": 10204 + "index": 10279 }, "end": { - "line": 196, + "line": 197, "column": 3, - "index": 10354 + "index": 10429 } }, { @@ -229,14 +229,14 @@ "defaultMessage": "!!!Slippage Tolerance Info", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 197, + "line": 198, "column": 25, - "index": 10381 + "index": 10456 }, "end": { - "line": 200, + "line": 201, "column": 3, - "index": 10485 + "index": 10560 } }, { @@ -244,14 +244,14 @@ "defaultMessage": "!!!Verified by {pool}", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 201, + "line": 202, "column": 14, - "index": 10501 + "index": 10576 }, "end": { - "line": 204, + "line": 205, "column": 3, - "index": 10589 + "index": 10664 } }, { @@ -259,14 +259,14 @@ "defaultMessage": "!!!This asset is in my portfolio", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 205, + "line": 206, "column": 12, - "index": 10603 + "index": 10678 }, "end": { - "line": 208, + "line": 209, "column": 3, - "index": 10700 + "index": 10775 } }, { @@ -274,14 +274,14 @@ "defaultMessage": "!!!Default Slippage Tolerance", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 209, + "line": 210, "column": 19, - "index": 10721 + "index": 10796 }, "end": { - "line": 212, + "line": 213, "column": 3, - "index": 10822 + "index": 10897 } }, { @@ -289,14 +289,14 @@ "defaultMessage": "!!!Slippage tolerance is set as a percentage of the total swap value.", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 213, + "line": 214, "column": 16, - "index": 10840 + "index": 10915 }, "end": { - "line": 216, + "line": 217, "column": 3, - "index": 10978 + "index": 11053 } }, { @@ -304,14 +304,14 @@ "defaultMessage": "!!!(auto)", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 217, + "line": 218, "column": 12, - "index": 10992 + "index": 11067 }, "end": { - "line": 220, + "line": 221, "column": 3, - "index": 11066 + "index": 11141 } }, { @@ -319,14 +319,14 @@ "defaultMessage": "!!!change dex", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 221, + "line": 222, "column": 14, - "index": 11082 + "index": 11157 }, "end": { - "line": 224, + "line": 225, "column": 3, - "index": 11162 + "index": 11237 } }, { @@ -334,14 +334,14 @@ "defaultMessage": "!!!Min-ADA is the minimum ADA amount required to be contained when holding or sending Cardano native assets.", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 225, + "line": 226, "column": 14, - "index": 11178 + "index": 11253 }, "end": { - "line": 229, + "line": 230, "column": 3, - "index": 11359 + "index": 11434 } }, { @@ -349,14 +349,14 @@ "defaultMessage": "!!!Min ADA", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 230, + "line": 231, "column": 19, - "index": 11380 + "index": 11455 }, "end": { - "line": 233, + "line": 234, "column": 3, - "index": 11462 + "index": 11537 } }, { @@ -364,14 +364,14 @@ "defaultMessage": "!!!Swap fees include the following:\n • Matchmaker Fee\n • Frontend Fee\n • Liquidity Provider Fee", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 234, + "line": 235, "column": 12, - "index": 11476 + "index": 11551 }, "end": { - "line": 237, + "line": 238, "column": 3, - "index": 11639 + "index": 11714 } }, { @@ -379,14 +379,14 @@ "defaultMessage": "!!!Fees", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 238, + "line": 239, "column": 17, - "index": 11658 + "index": 11733 }, "end": { - "line": 241, + "line": 242, "column": 3, - "index": 11735 + "index": 11810 } }, { @@ -394,14 +394,14 @@ "defaultMessage": "!!!Liquidity provider fee", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 242, + "line": 243, "column": 20, - "index": 11757 + "index": 11832 }, "end": { - "line": 245, + "line": 246, "column": 3, - "index": 11855 + "index": 11930 } }, { @@ -409,14 +409,14 @@ "defaultMessage": "!!!Liq. prov. fee", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 246, + "line": 247, "column": 18, - "index": 11875 + "index": 11950 }, "end": { - "line": 249, + "line": 250, "column": 3, - "index": 11963 + "index": 12038 } }, { @@ -424,14 +424,14 @@ "defaultMessage": "!!!Liquidity provider fee is a fixed {fee}% operational fee from the whole transaction volume, that is taken to support DEX “liquidity” allowing traders to buy and sell assets on the decentralized Cardano network.", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 250, + "line": 251, "column": 24, - "index": 11989 + "index": 12064 }, "end": { - "line": 254, + "line": 255, "column": 3, - "index": 12285 + "index": 12360 } }, { @@ -439,14 +439,14 @@ "defaultMessage": "!!!Minimum amount of assets you can get because of the slippage tolerance.", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 255, + "line": 256, "column": 19, - "index": 12306 + "index": 12381 }, "end": { - "line": 258, + "line": 259, "column": 3, - "index": 12452 + "index": 12527 } }, { @@ -454,14 +454,14 @@ "defaultMessage": "!!!Min Received", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 259, + "line": 260, "column": 24, - "index": 12478 + "index": 12553 }, "end": { - "line": 262, + "line": 263, "column": 3, - "index": 12570 + "index": 12645 } }, { @@ -469,14 +469,14 @@ "defaultMessage": "!!!Enter a value from 0% to 100%. You can also enter up to 1 decimal", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 263, + "line": 264, "column": 17, - "index": 12589 + "index": 12664 }, "end": { - "line": 266, + "line": 267, "column": 3, - "index": 12727 + "index": 12802 } }, { @@ -484,14 +484,14 @@ "defaultMessage": "!!!{pool} verification", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 267, + "line": 268, "column": 20, - "index": 12749 + "index": 12824 }, "end": { - "line": 270, + "line": 271, "column": 3, - "index": 12844 + "index": 12919 } }, { @@ -499,14 +499,14 @@ "defaultMessage": "!!!Volume, 24h", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 271, + "line": 272, "column": 10, - "index": 12856 + "index": 12931 }, "end": { - "line": 274, + "line": 275, "column": 3, - "index": 12933 + "index": 13008 } }, { @@ -514,14 +514,14 @@ "defaultMessage": "!!!Cardano projects that list their own tokens can apply for an additional {pool} verification. This verification is a manual validation that {pool} team performs with the help of Cardano Foundation.", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 275, + "line": 276, "column": 24, - "index": 12959 + "index": 13034 }, "end": { - "line": 279, + "line": 280, "column": 3, - "index": 13241 + "index": 13316 } }, { @@ -529,14 +529,14 @@ "defaultMessage": "!!! Price", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 280, + "line": 281, "column": 9, - "index": 13252 + "index": 13327 }, "end": { - "line": 283, + "line": 284, "column": 3, - "index": 13314 + "index": 13389 } }, { @@ -544,14 +544,14 @@ "defaultMessage": "!!!No assets found for this pair", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 284, + "line": 285, "column": 17, - "index": 13333 + "index": 13408 }, "end": { - "line": 287, + "line": 288, "column": 3, - "index": 13435 + "index": 13510 } }, { @@ -559,14 +559,14 @@ "defaultMessage": "!!!No assets found for \"{search}\"", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 288, + "line": 289, "column": 20, - "index": 13457 + "index": 13532 }, "end": { - "line": 291, + "line": 292, "column": 3, - "index": 13563 + "index": 13638 } }, { @@ -574,14 +574,14 @@ "defaultMessage": "!!!Each verified tokens gets", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 292, + "line": 293, "column": 21, - "index": 13586 + "index": 13661 }, "end": { - "line": 295, + "line": 296, "column": 3, - "index": 13688 + "index": 13763 } }, { @@ -589,14 +589,14 @@ "defaultMessage": "!!!verified badge", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 296, + "line": 297, "column": 17, - "index": 13707 + "index": 13782 }, "end": { - "line": 299, + "line": 300, "column": 3, - "index": 13794 + "index": 13869 } }, { @@ -604,14 +604,14 @@ "defaultMessage": "!!!Open orders", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 300, + "line": 301, "column": 14, - "index": 13810 + "index": 13885 }, "end": { - "line": 303, + "line": 304, "column": 3, - "index": 13891 + "index": 13966 } }, { @@ -619,14 +619,14 @@ "defaultMessage": "!!!Completed orders", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 304, + "line": 305, "column": 19, - "index": 13912 + "index": 13987 }, "end": { - "line": 307, + "line": 308, "column": 3, - "index": 14003 + "index": 14078 } }, { @@ -634,14 +634,14 @@ "defaultMessage": "!!!TVL", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 308, + "line": 309, "column": 7, - "index": 14012 + "index": 14087 }, "end": { - "line": 311, + "line": 312, "column": 3, - "index": 14078 + "index": 14153 } }, { @@ -649,14 +649,14 @@ "defaultMessage": "!!! Dex Fee", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 312, + "line": 313, "column": 11, - "index": 14091 + "index": 14166 }, "end": { - "line": 315, + "line": 316, "column": 3, - "index": 14166 + "index": 14241 } }, { @@ -664,14 +664,14 @@ "defaultMessage": "!!! Batcher Fee", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 316, + "line": 317, "column": 14, - "index": 14182 + "index": 14257 }, "end": { - "line": 319, + "line": 320, "column": 3, - "index": 14264 + "index": 14339 } }, { @@ -679,14 +679,14 @@ "defaultMessage": "!!!Limit price", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 320, + "line": 321, "column": 26, - "index": 14292 + "index": 14367 }, "end": { - "line": 323, + "line": 324, "column": 3, - "index": 14385 + "index": 14460 } }, { @@ -694,14 +694,14 @@ "defaultMessage": "!!!Are you sure you want to proceed this order with the limit price that is 10% or more higher than the\nmarket price?", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 324, + "line": 325, "column": 32, - "index": 14419 + "index": 14494 }, "end": { - "line": 329, + "line": 330, "column": 3, - "index": 14639 + "index": 14714 } }, { @@ -709,14 +709,14 @@ "defaultMessage": "!!!Your limit price", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 330, + "line": 331, "column": 30, - "index": 14671 + "index": 14746 }, "end": { - "line": 333, + "line": 334, "column": 3, - "index": 14773 + "index": 14848 } }, { @@ -724,14 +724,14 @@ "defaultMessage": "!!!Market price", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 334, + "line": 335, "column": 32, - "index": 14807 + "index": 14882 }, "end": { - "line": 337, + "line": 338, "column": 3, - "index": 14907 + "index": 14982 } }, { @@ -739,14 +739,14 @@ "defaultMessage": "!!!Back", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 338, + "line": 339, "column": 25, - "index": 14934 + "index": 15009 }, "end": { - "line": 341, + "line": 342, "column": 3, - "index": 15019 + "index": 15094 } }, { @@ -754,14 +754,14 @@ "defaultMessage": "!!!Swap", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 342, + "line": 343, "column": 28, - "index": 15049 + "index": 15124 }, "end": { - "line": 345, + "line": 346, "column": 3, - "index": 15137 + "index": 15212 } }, { @@ -769,14 +769,14 @@ "defaultMessage": "!!!Transaction submitted", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 346, + "line": 347, "column": 21, - "index": 15160 + "index": 15235 }, "end": { - "line": 349, + "line": 350, "column": 3, - "index": 15258 + "index": 15333 } }, { @@ -784,14 +784,14 @@ "defaultMessage": "!!!Your transactions will be displayed both in the list of transaction and Open swap orders", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 350, + "line": 351, "column": 22, - "index": 15282 + "index": 15357 }, "end": { - "line": 353, + "line": 354, "column": 3, - "index": 15448 + "index": 15523 } }, { @@ -799,14 +799,14 @@ "defaultMessage": "!!! dex", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 354, + "line": 355, "column": 7, - "index": 15457 + "index": 15532 }, "end": { - "line": 357, + "line": 358, "column": 3, - "index": 15524 + "index": 15599 } }, { @@ -814,14 +814,14 @@ "defaultMessage": "!!!see on explorer", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 358, + "line": 359, "column": 17, - "index": 15543 + "index": 15618 }, "end": { - "line": 361, + "line": 362, "column": 3, - "index": 15631 + "index": 15706 } }, { @@ -829,14 +829,14 @@ "defaultMessage": "!!!GO to Orders", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 362, + "line": 363, "column": 14, - "index": 15647 + "index": 15722 }, "end": { - "line": 365, + "line": 366, "column": 3, - "index": 15729 + "index": 15804 } }, { @@ -844,14 +844,14 @@ "defaultMessage": "!!!Asset", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 366, + "line": 367, "column": 9, - "index": 15740 + "index": 15815 }, "end": { - "line": 369, + "line": 370, "column": 3, - "index": 15813 + "index": 15888 } }, { @@ -859,14 +859,14 @@ "defaultMessage": "!!!Clear", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 370, + "line": 371, "column": 9, - "index": 15824 + "index": 15899 }, "end": { - "line": 373, + "line": 374, "column": 3, - "index": 15885 + "index": 15960 } }, { @@ -874,14 +874,14 @@ "defaultMessage": "!!!Sign transaction", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 374, + "line": 375, "column": 19, - "index": 15906 + "index": 15981 }, "end": { - "line": 377, + "line": 378, "column": 3, - "index": 15988 + "index": 16063 } }, { @@ -889,14 +889,14 @@ "defaultMessage": "!!!Spending Password", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 378, + "line": 379, "column": 20, - "index": 16010 + "index": 16085 }, "end": { - "line": 381, + "line": 382, "column": 3, - "index": 16094 + "index": 16169 } }, { @@ -904,14 +904,14 @@ "defaultMessage": "!!!Enter spending password to sign this transaction", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 382, + "line": 383, "column": 25, - "index": 16121 + "index": 16196 }, "end": { - "line": 385, + "line": 386, "column": 3, - "index": 16241 + "index": 16316 } }, { @@ -919,14 +919,14 @@ "defaultMessage": "!!!Sign", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 386, + "line": 387, "column": 8, - "index": 16251 + "index": 16326 }, "end": { - "line": 389, + "line": 390, "column": 3, - "index": 16310 + "index": 16385 } }, { @@ -934,14 +934,14 @@ "defaultMessage": "!!!Swap", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 390, + "line": 391, "column": 14, - "index": 16326 + "index": 16401 }, "end": { - "line": 393, + "line": 394, "column": 3, - "index": 16385 + "index": 16460 } }, { @@ -949,14 +949,14 @@ "defaultMessage": "!!!completed orders", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 394, + "line": 395, "column": 23, - "index": 16410 + "index": 16485 }, "end": { - "line": 397, + "line": 398, "column": 3, - "index": 16495 + "index": 16570 } }, { @@ -964,14 +964,14 @@ "defaultMessage": "!!!open orders", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 398, + "line": 399, "column": 18, - "index": 16515 + "index": 16590 }, "end": { - "line": 401, + "line": 402, "column": 3, - "index": 16590 + "index": 16665 } }, { @@ -979,14 +979,14 @@ "defaultMessage": "!!!Confirm order cancellation", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 402, + "line": 403, "column": 24, - "index": 16616 + "index": 16691 }, "end": { - "line": 405, + "line": 406, "column": 3, - "index": 16068 + "index": 16788 } }, { @@ -994,14 +994,14 @@ "defaultMessage": "!!!Cancel order", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 406, + "line": 407, "column": 29, - "index": 16099 + "index": 16819 }, "end": { - "line": 409, + "line": 410, "column": 3, - "index": 16186 + "index": 16906 } }, { @@ -1009,14 +1009,14 @@ "defaultMessage": "!!!Are you sure you want to cancel this order?", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 410, + "line": 411, "column": 31, - "index": 16219 + "index": 16939 }, "end": { - "line": 413, + "line": 414, "column": 3, - "index": 16340 + "index": 17060 } }, { @@ -1024,14 +1024,14 @@ "defaultMessage": "!!!Learn more about swap orders in Yoroi", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 414, + "line": 415, "column": 23, - "index": 16365 + "index": 17085 }, "end": { - "line": 417, + "line": 418, "column": 3, - "index": 16472 + "index": 17192 } }, { @@ -1039,14 +1039,14 @@ "defaultMessage": "!!!Asset price", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 418, + "line": 419, "column": 29, - "index": 16503 + "index": 17223 }, "end": { - "line": 421, + "line": 422, "column": 3, - "index": 16590 + "index": 17310 } }, { @@ -1054,14 +1054,14 @@ "defaultMessage": "!!!Asset amount", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 422, + "line": 423, "column": 30, - "index": 16622 + "index": 17342 }, "end": { - "line": 425, + "line": 426, "column": 3, - "index": 16711 + "index": 17431 } }, { @@ -1069,14 +1069,14 @@ "defaultMessage": "!!!Total returned", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 426, + "line": 427, "column": 32, - "index": 16745 + "index": 17465 }, "end": { - "line": 429, + "line": 430, "column": 3, - "index": 16838 + "index": 17558 } }, { @@ -1084,14 +1084,14 @@ "defaultMessage": "!!!Cancellation Fee", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 430, + "line": 431, "column": 34, - "index": 16874 + "index": 17594 }, "end": { - "line": 433, + "line": 434, "column": 3, - "index": 16971 + "index": 17691 } }, { @@ -1099,14 +1099,14 @@ "defaultMessage": "!!!Confirm", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 434, + "line": 435, "column": 26, - "index": 16999 + "index": 17719 }, "end": { - "line": 437, + "line": 438, "column": 3, - "index": 17079 + "index": 17799 } }, { @@ -1114,14 +1114,14 @@ "defaultMessage": "!!!Back", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 438, + "line": 439, "column": 23, - "index": 17104 + "index": 17824 }, "end": { - "line": 441, + "line": 442, "column": 3, - "index": 17178 + "index": 17898 } }, { @@ -1129,14 +1129,14 @@ "defaultMessage": "!!!Total", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 442, + "line": 443, "column": 19, - "index": 17199 + "index": 17919 }, "end": { - "line": 445, + "line": 446, "column": 3, - "index": 17269 + "index": 17989 } }, { @@ -1144,14 +1144,14 @@ "defaultMessage": "!!!Liquidity Pool", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 446, + "line": 447, "column": 27, - "index": 17298 + "index": 18018 }, "end": { - "line": 449, + "line": 450, "column": 3, - "index": 17385 + "index": 18105 } }, { @@ -1159,14 +1159,29 @@ "defaultMessage": "!!!Time Created", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 450, + "line": 451, "column": 25, - "index": 17412 + "index": 18132 }, "end": { - "line": 453, + "line": 454, "column": 3, - "index": 17495 + "index": 18215 + } + }, + { + "id": "swap.listOrders.timeCompleted", + "defaultMessage": "!!!Time Completed", + "file": "src/features/Swap/common/strings.ts", + "start": { + "line": 455, + "column": 27, + "index": 18244 + }, + "end": { + "line": 458, + "column": 3, + "index": 18331 } }, { @@ -1174,14 +1189,14 @@ "defaultMessage": "!!!Transaction ID", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 458, + "line": 459, "column": 18, - "index": 17515 + "index": 18351 }, "end": { - "line": 461, + "line": 462, "column": 3, - "index": 17593 + "index": 18429 } }, { @@ -1189,14 +1204,14 @@ "defaultMessage": "!!!Choose Connection Method", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 462, + "line": 463, "column": 26, - "index": 17621 + "index": 18457 }, "end": { - "line": 465, + "line": 466, "column": 3, - "index": 17739 + "index": 18575 } }, { @@ -1204,14 +1219,14 @@ "defaultMessage": "!!!Choose this option if you want to connect to a Ledger Nano model X or S using an on-the-go USB cable adaptor:", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 466, + "line": 467, "column": 18, - "index": 17759 + "index": 18595 }, "end": { - "line": 471, + "line": 472, "column": 3, - "index": 17988 + "index": 18824 } }, { @@ -1219,14 +1234,14 @@ "defaultMessage": "!!!Connect with USB", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 472, + "line": 473, "column": 13, - "index": 18003 + "index": 18839 }, "end": { - "line": 475, + "line": 476, "column": 3, - "index": 18117 + "index": 18953 } }, { @@ -1234,14 +1249,14 @@ "defaultMessage": "!!! USB connection is blocked by iOS devices", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 476, + "line": 477, "column": 26, - "index": 18145 + "index": 18981 }, "end": { - "line": 479, + "line": 480, "column": 3, - "index": 18297 + "index": 19133 } }, { @@ -1249,14 +1264,14 @@ "defaultMessage": "!!!Choose this option if you want to connect to a Ledger Nano model X through Bluetooth:", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 480, + "line": 481, "column": 24, - "index": 18323 + "index": 19159 }, "end": { - "line": 483, + "line": 484, "column": 3, - "index": 18517 + "index": 19353 } }, { @@ -1264,14 +1279,14 @@ "defaultMessage": "!!!Connect with Bluetooth", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 484, + "line": 485, "column": 19, - "index": 18538 + "index": 19374 }, "end": { - "line": 487, + "line": 488, "column": 3, - "index": 18664 + "index": 19500 } }, { @@ -1279,14 +1294,14 @@ "defaultMessage": "!!!Connect with Bluetooth", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 488, + "line": 489, "column": 18, - "index": 18684 + "index": 19520 }, "end": { - "line": 491, + "line": 492, "column": 3, - "index": 18794 + "index": 19630 } }, { @@ -1294,14 +1309,14 @@ "defaultMessage": "!!!You have", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 494, + "line": 495, "column": 11, - "index": 18853 + "index": 19689 }, "end": { - "line": 497, + "line": 498, "column": 3, - "index": 18948 + "index": 19784 } }, { @@ -1309,14 +1324,14 @@ "defaultMessage": "!!!No assets found", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 498, + "line": 499, "column": 12, - "index": 18962 + "index": 19798 }, "end": { - "line": 501, + "line": 502, "column": 3, - "index": 19065 + "index": 19901 } }, { @@ -1324,14 +1339,14 @@ "defaultMessage": "!!!found", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 502, + "line": 503, "column": 9, - "index": 19076 + "index": 19912 }, "end": { - "line": 505, + "line": 506, "column": 3, - "index": 19166 + "index": 20002 } }, { @@ -1339,14 +1354,14 @@ "defaultMessage": "!!!Search tokens", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 506, + "line": 507, "column": 16, - "index": 19184 + "index": 20020 }, "end": { - "line": 509, + "line": 510, "column": 3, - "index": 19280 + "index": 20116 } }, { @@ -1354,14 +1369,14 @@ "defaultMessage": "!!!Select asset", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 510, + "line": 511, "column": 20, - "index": 19302 + "index": 20138 }, "end": { - "line": 513, + "line": 514, "column": 3, - "index": 19391 + "index": 20227 } }, { @@ -1369,14 +1384,14 @@ "defaultMessage": "!!!Confirm", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 514, + "line": 515, "column": 11, - "index": 19404 + "index": 20240 }, "end": { - "line": 517, + "line": 518, "column": 3, - "index": 19498 + "index": 20334 } }, { @@ -1384,14 +1399,14 @@ "defaultMessage": "!!!Assign collateral", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 518, + "line": 519, "column": 20, - "index": 19520 + "index": 20356 }, "end": { - "line": 521, + "line": 522, "column": 3, - "index": 19627 + "index": 20463 } }, { @@ -1399,14 +1414,14 @@ "defaultMessage": "!!!Collateral not found", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 522, + "line": 523, "column": 22, - "index": 19651 + "index": 20487 }, "end": { - "line": 525, + "line": 526, "column": 3, - "index": 19763 + "index": 20599 } }, { @@ -1414,14 +1429,14 @@ "defaultMessage": "!!!You don't have an active collateral utxo", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 526, + "line": 527, "column": 22, - "index": 19787 + "index": 20623 }, "end": { - "line": 529, + "line": 530, "column": 3, - "index": 19919 + "index": 20755 } }, { @@ -1429,14 +1444,14 @@ "defaultMessage": "!!!Transaction failed", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 530, + "line": 531, "column": 17, - "index": 19938 + "index": 20774 }, "end": { - "line": 533, + "line": 534, "column": 3, - "index": 20040 + "index": 20876 } }, { @@ -1444,14 +1459,14 @@ "defaultMessage": "!!!Your transaction has not been processed properly due to technical issues", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 534, + "line": 535, "column": 16, - "index": 20058 + "index": 20894 }, "end": { - "line": 537, + "line": 538, "column": 3, - "index": 20213 + "index": 21049 } }, { @@ -1459,14 +1474,14 @@ "defaultMessage": "!!!Try again", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 538, + "line": 539, "column": 18, - "index": 20233 + "index": 21069 }, "end": { - "line": 541, + "line": 542, "column": 3, - "index": 20327 + "index": 21163 } }, { @@ -1474,14 +1489,14 @@ "defaultMessage": "!!!Not enough balance", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 542, + "line": 543, "column": 20, - "index": 20349 + "index": 21185 }, "end": { - "line": 545, + "line": 546, "column": 3, - "index": 20443 + "index": 21279 } }, { @@ -1489,14 +1504,29 @@ "defaultMessage": "!!!Not enough supply in the pool", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 546, + "line": 547, "column": 19, - "index": 20464 + "index": 21300 + }, + "end": { + "line": 550, + "column": 3, + "index": 21404 + } + }, + { + "id": "swap.swapScreen.notEnoughFeeBalance", + "defaultMessage": "!!!Not enough balance, please consider the fees", + "file": "src/features/Swap/common/strings.ts", + "start": { + "line": 551, + "column": 23, + "index": 21429 }, "end": { - "line": 549, + "line": 554, "column": 3, - "index": 20568 + "index": 21552 } }, { @@ -1504,14 +1534,14 @@ "defaultMessage": "!!! This pair is not available in any liquidity pool", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 550, + "line": 555, "column": 10, - "index": 20580 + "index": 21564 }, "end": { - "line": 553, + "line": 558, "column": 3, - "index": 20695 + "index": 21679 } }, { @@ -1519,14 +1549,14 @@ "defaultMessage": "!!!Continue on Ledger", "file": "src/features/Swap/common/strings.ts", "start": { - "line": 554, + "line": 559, "column": 20, - "index": 20717 + "index": 21701 }, "end": { - "line": 557, + "line": 562, "column": 3, - "index": 20817 + "index": 21801 } } ] \ No newline at end of file