diff --git a/ios/Bridge.swift b/ios/Bridge.swift new file mode 100644 index 0000000000..56b71f2f9a --- /dev/null +++ b/ios/Bridge.swift @@ -0,0 +1,9 @@ +// +// Bridge.swift +// StatusIm +// +// Created by Andrea Franz on 02/12/2020. +// Copyright © 2020 Status. All rights reserved. +// + +import Foundation diff --git a/ios/Podfile b/ios/Podfile index 4d7348123a..80fb99be25 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -19,16 +19,20 @@ abstract_target 'Status' do pod 'Permission-Microphone', :path => "#{permissions_path}/Microphone.podspec" pod 'Permission-Camera', :path => "#{permissions_path}/Camera.podspec" + pod "react-native-status-keycard", path: "../node_modules/react-native-status-keycard" + pod "Keycard", git: "https://github.com/status-im/Keycard.swift.git" + pod 'secp256k1', git: "https://github.com/status-im/secp256k1.swift.git", submodules: true + target 'StatusIm' do target 'StatusImTests' do inherit! :complete # Pods for testing end end - + target 'StatusImPR' do end - + use_flipper! post_install do |installer| flipper_post_install(installer) @@ -36,4 +40,5 @@ abstract_target 'Status' do use_native_modules! -end \ No newline at end of file +end + diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 4c2adbca6f..99b65012f3 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -2,8 +2,9 @@ PODS: - boost-for-react-native (1.63.0) - BVLinearGradient (2.5.6): - React - - CocoaAsyncSocket (7.6.4) + - CocoaAsyncSocket (7.6.5) - CocoaLibEvent (1.0.0) + - CryptoSwift (1.3.8) - DoubleConversion (1.1.6) - FBLazyVector (0.63.4) - FBReactNativeSpec (0.63.4): @@ -69,6 +70,18 @@ PODS: - DoubleConversion - glog - glog (0.3.5) + - Keycard (3.0.4): + - CryptoSwift + - secp256k1 + - libwebp (1.1.0): + - libwebp/demux (= 1.1.0) + - libwebp/mux (= 1.1.0) + - libwebp/webp (= 1.1.0) + - libwebp/demux (1.1.0): + - libwebp/webp + - libwebp/mux (1.1.0): + - libwebp/demux + - libwebp/webp (1.1.0) - OpenSSL-Universal (1.0.2.20): - OpenSSL-Universal/Static (= 1.0.2.20) - OpenSSL-Universal/Static (1.0.2.20) @@ -266,6 +279,9 @@ PODS: - React - react-native-splash-screen (3.2.0): - React + - react-native-status-keycard (2.5.30): + - Keycard + - React - react-native-webview (10.9.2): - React-Core - React-RCTActionSheet (0.63.4): @@ -369,13 +385,20 @@ PODS: - React - RNSVG (9.13.6): - React + - SDWebImage (5.10.2): + - SDWebImage/Core (= 5.10.2) + - SDWebImage/Core (5.10.2) + - SDWebImageWebPCoder (0.6.1): + - libwebp (~> 1.0) + - SDWebImage/Core (~> 5.7) + - secp256k1 (0.1.6) - SQLCipher (3.4.2): - SQLCipher/standard (= 3.4.2) - SQLCipher/common (3.4.2) - SQLCipher/standard (3.4.2): - SQLCipher/common - SSZipArchive (2.2.3) - - TOCropViewController (2.5.5) + - TOCropViewController (2.6.0) - TouchID (4.4.1): - React - Yoga (1.14.0) @@ -408,6 +431,7 @@ DEPENDENCIES: - FlipperKit/SKIOSNetworkPlugin (~> 0.54.0) - Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) + - Keycard (from `https://github.com/status-im/Keycard.swift.git`) - Permission-Camera (from `../node_modules/react-native-permissions/ios/Camera.podspec`) - Permission-Microphone (from `../node_modules/react-native-permissions/ios/Microphone.podspec`) - RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`) @@ -433,6 +457,7 @@ DEPENDENCIES: - react-native-shake (from `../node_modules/react-native-shake`) - "react-native-slider (from `../node_modules/@react-native-community/slider`)" - react-native-splash-screen (from `../node_modules/react-native-splash-screen`) + - react-native-status-keycard (from `../node_modules/react-native-status-keycard`) - react-native-webview (from `../node_modules/react-native-webview`) - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`) - React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`) @@ -461,6 +486,7 @@ DEPENDENCIES: - RNReanimated (from `../node_modules/react-native-reanimated`) - RNScreens (from `../node_modules/react-native-screens`) - RNSVG (from `../node_modules/react-native-svg`) + - secp256k1 (from `https://github.com/status-im/secp256k1.swift.git`) - SQLCipher (~> 3.0) - SSZipArchive - TouchID (from `../node_modules/react-native-touch-id`) @@ -471,6 +497,7 @@ SPEC REPOS: - boost-for-react-native - CocoaAsyncSocket - CocoaLibEvent + - CryptoSwift - Flipper - Flipper-DoubleConversion - Flipper-Folly @@ -497,6 +524,8 @@ EXTERNAL SOURCES: :podspec: "../node_modules/react-native/third-party-podspecs/Folly.podspec" glog: :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" + Keycard: + :git: https://github.com/status-im/Keycard.swift.git Permission-Camera: :path: "../node_modules/react-native-permissions/ios/Camera.podspec" Permission-Microphone: @@ -543,6 +572,8 @@ EXTERNAL SOURCES: :path: "../node_modules/@react-native-community/slider" react-native-splash-screen: :path: "../node_modules/react-native-splash-screen" + react-native-status-keycard: + :path: "../node_modules/react-native-status-keycard" react-native-webview: :path: "../node_modules/react-native-webview" React-RCTActionSheet: @@ -599,16 +630,29 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-screens" RNSVG: :path: "../node_modules/react-native-svg" + secp256k1: + :git: https://github.com/status-im/secp256k1.swift.git + :submodules: true TouchID: :path: "../node_modules/react-native-touch-id" Yoga: :path: "../node_modules/react-native/ReactCommon/yoga" +CHECKOUT OPTIONS: + Keycard: + :commit: 36e260cfafc2755a47f1e5f542858ceb0c6c37df + :git: https://github.com/status-im/Keycard.swift.git + secp256k1: + :commit: 46a1fa30d9b8babeae85ff519050f42394ab5fcc + :git: https://github.com/status-im/secp256k1.swift.git + :submodules: true + SPEC CHECKSUMS: boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872 - CocoaAsyncSocket: 694058e7c0ed05a9e217d1b3c7ded962f4180845 + CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f + CryptoSwift: 01b0f0cba1d5c212e5a335ff6c054fb75a204f00 DoubleConversion: cde416483dac037923206447da6e1454df403714 FBLazyVector: 3bb422f41b18121b71783a905c10e58606f7dc3e FBReactNativeSpec: f2c97f2529dd79c083355182cc158c9f98f4bd6e @@ -621,6 +665,8 @@ SPEC CHECKSUMS: FlipperKit: ab353d41aea8aae2ea6daaf813e67496642f3d7d Folly: b73c3869541e86821df3c387eb0af5f65addfab4 glog: cee4319f395bad5865ef3f32466c2e0ae677432c + Keycard: dd96182888da0aacf4de821b641103143bbb26cc + libwebp: 946cb3063cea9236285f7e9a8505d806d30e07f3 OpenSSL-Universal: ff34003318d5e1163e9529b08470708e389ffcdd Permission-Camera: afad27bf90337684d4a86f3825112d648c8c4d3b Permission-Microphone: 0ffabc3fe1c75cfb260525ee3f529383c9f4368c @@ -645,6 +691,7 @@ SPEC CHECKSUMS: react-native-shake: de052eaa3eadc4a326b8ddd7ac80c06e8d84528c react-native-slider: 12bd76d3d568c9c5500825db54123d44b48e4ad4 react-native-splash-screen: 200d11d188e2e78cea3ad319964f6142b6384865 + react-native-status-keycard: a001766cf8f27de56406ac712a52a982f1f28744 react-native-webview: 4e96d493f9f90ba4f03b28933f30b2964df07e39 React-RCTActionSheet: 89a0ca9f4a06c1f93c26067af074ccdce0f40336 React-RCTAnimation: 1bde3ecc0c104c55df246eda516e0deb03c4e49b @@ -673,13 +720,16 @@ SPEC CHECKSUMS: RNReanimated: 89f5e0a04d1dd52fbf27e7e7030d8f80a646a3fc RNScreens: b748efec66e095134c7166ca333b628cd7e6f3e2 RNSVG: 8ba35cbeb385a52fd960fd28db9d7d18b4c2974f + SDWebImage: b969dcfc02c40a5da71eac0b03b8f1a0c794a86f + SDWebImageWebPCoder: d0dac55073088d24b2ac1b191a71a8f8d0adac21 + secp256k1: f61d67e6fdcb85fd727acf1bf35ace6036db540c SQLCipher: f9fcf29b2e59ced7defc2a2bdd0ebe79b40d4990 SSZipArchive: 62d4947b08730e4cda640473b0066d209ff033c9 - TOCropViewController: da59f531f8ac8a94ef6d6c0fc34009350f9e8bfe + TOCropViewController: 3105367e808b7d3d886a74ff59bf4804e7d3ab38 TouchID: ba4c656d849cceabc2e4eef722dea5e55959ecf4 Yoga: 4bd86afe9883422a7c4028c00e34790f560923d6 YogaKit: f782866e155069a2cca2517aafea43200b01fd5a -PODFILE CHECKSUM: 8752b77562edc2969e7016627fa83c23a152cf3c +PODFILE CHECKSUM: 5d4b89aa09f8d53bc530d173622952e85d5d7662 -COCOAPODS: 1.10.0 +COCOAPODS: 1.10.1 diff --git a/ios/StatusIm.xcodeproj/project.pbxproj b/ios/StatusIm.xcodeproj/project.pbxproj index 910988255f..401a9c51b1 100644 --- a/ios/StatusIm.xcodeproj/project.pbxproj +++ b/ios/StatusIm.xcodeproj/project.pbxproj @@ -40,6 +40,9 @@ 57C854A7993C47A3B1AECD32 /* Inter-MediumItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = C6B1215047604CD59A4C74D6 /* Inter-MediumItalic.otf */; }; 68E19BBDF749E72ED1F9DEF5 /* libPods-Status-StatusIm.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 132CE3B093884B0FB239A0AB /* libPods-Status-StatusIm.a */; }; 6C137817D5298C82BC79177C /* libPods-Status-StatusImPR.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D4CB5416994C913628B8754 /* libPods-Status-StatusImPR.a */; }; + 65F6941925780A4F00A45E76 /* Bridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65F6941825780A4F00A45E76 /* Bridge.swift */; }; + 65F6941A25780A4F00A45E76 /* Bridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65F6941825780A4F00A45E76 /* Bridge.swift */; }; + 65F6941B25780A4F00A45E76 /* Bridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65F6941825780A4F00A45E76 /* Bridge.swift */; }; 70ADBB5ECF934DCF8A0E4919 /* Inter-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 1426DF592BA248FC81D955CB /* Inter-Regular.otf */; }; 74B758FC20D7C00B003343C3 /* launch-image-universal.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 74B758FB20D7C00B003343C3 /* launch-image-universal.storyboard */; }; 8391E8E0E93C41A98AAA6631 /* Inter-SemiBoldItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = A4F2BBE8D4DD4140A6CCAC39 /* Inter-SemiBoldItalic.otf */; }; @@ -124,6 +127,11 @@ 4C16DE0B1F89508700AA10DB /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; 4E586E1B0E544F64AA9F5BD1 /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; 5D4CB5416994C913628B8754 /* libPods-Status-StatusImPR.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Status-StatusImPR.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 5E9C2936B3890356C5BE1078 /* Pods-StatusIm-StatusImTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-StatusIm-StatusImTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-StatusIm-StatusImTests/Pods-StatusIm-StatusImTests.debug.xcconfig"; sourceTree = ""; }; + 65F693BD2578002500A45E76 /* CoreNFC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreNFC.framework; path = System/Library/Frameworks/CoreNFC.framework; sourceTree = SDKROOT; }; + 65F693BF2578003600A45E76 /* CoreNFC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreNFC.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk/System/iOSSupport/System/Library/Frameworks/CoreNFC.framework; sourceTree = DEVELOPER_DIR; }; + 65F6941725780A4E00A45E76 /* StatusImTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "StatusImTests-Bridging-Header.h"; sourceTree = ""; }; + 65F6941825780A4F00A45E76 /* Bridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bridge.swift; sourceTree = ""; }; 69291A6222A63434694EA2A6 /* Pods-Status-StatusImPR.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Status-StatusImPR.release.xcconfig"; path = "Pods/Target Support Files/Pods-Status-StatusImPR/Pods-Status-StatusImPR.release.xcconfig"; sourceTree = ""; }; 693A62DB37BC4CD5A30E5C96 /* Inter-SemiBold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-SemiBold.otf"; path = "../resources/fonts/Inter-SemiBold.otf"; sourceTree = ""; }; 74B758FB20D7C00B003343C3 /* launch-image-universal.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "launch-image-universal.storyboard"; sourceTree = ""; }; @@ -279,6 +287,7 @@ 83CBB9F61A601CBA00E9B192 = { isa = PBXGroup; children = ( + 65F6941825780A4F00A45E76 /* Bridge.swift */, 3AAD2AB624A3A5F10075D594 /* StatusImPR */, 13B07FAE1A68108700A75B9A /* StatusIm */, 832341AE1AAA6A7D00B99B32 /* Libraries */, @@ -287,6 +296,7 @@ A97BA941B2FB44B4B66EE6D3 /* Frameworks */, 1E7837547A9A40E18AD63CF3 /* Resources */, 5C1C8762251D6EF495FB2384 /* Pods */, + 65F6941725780A4E00A45E76 /* StatusImTests-Bridging-Header.h */, ); indentWidth = 2; sourceTree = ""; @@ -314,6 +324,8 @@ A97BA941B2FB44B4B66EE6D3 /* Frameworks */ = { isa = PBXGroup; children = ( + 65F693BD2578002500A45E76 /* CoreNFC.framework */, + 65F693BF2578003600A45E76 /* CoreNFC.framework */, 3A8F8EA924A4D31600BF206D /* GameKit.framework */, 4C16DE0B1F89508700AA10DB /* JavaScriptCore.framework */, B24FC7FE1DE7195F00D694FF /* MessageUI.framework */, @@ -724,6 +736,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 65F6941A25780A4F00A45E76 /* Bridge.swift in Sources */, 00E356F31AD99517003FC87E /* StatusImTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -732,6 +745,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 65F6941925780A4F00A45E76 /* Bridge.swift in Sources */, 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, 3A2626CF245C3F2200D5F94B /* Dummy.swift in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, @@ -742,6 +756,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 65F6941B25780A4F00A45E76 /* Bridge.swift in Sources */, 3AAD2ABC24A3A60E0075D594 /* AppDelegate.m in Sources */, 3AAD2ABD24A3A60E0075D594 /* Dummy.swift in Sources */, 3AAD2ABE24A3A60E0075D594 /* main.m in Sources */, @@ -766,6 +781,7 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_ID_SUFFIX = .debug; BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; DEVELOPMENT_TEAM = DTX7Z4U3YA; FRAMEWORK_SEARCH_PATHS = ( @@ -777,13 +793,16 @@ "$(inherited)", ); INFOPLIST_FILE = StatusImTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.2; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = im.status.ethereum; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "StatusImTests-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/StatusIm.app/StatusIm"; }; name = Debug; @@ -795,6 +814,7 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_ID_SUFFIX = ""; BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Distribution"; COPY_PHASE_STRIP = NO; DEVELOPMENT_TEAM = DTX7Z4U3YA; @@ -803,13 +823,15 @@ "$(inherited)", ); INFOPLIST_FILE = StatusImTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.2; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = im.status.ethereum; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "StatusImTests-Bridging-Header.h"; + SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/StatusIm.app/StatusIm"; }; name = Release; @@ -1137,7 +1159,7 @@ "$(SRCROOT)/../node_modules/react-native-image-resizer/ios/RCTImageResizer", "$(SRCROOT)/../node_modules/react-native-splash-screen/ios/**", ); - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LIBRARY_SEARCH_PATHS = ( "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", "\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"", @@ -1211,7 +1233,7 @@ "$(SRCROOT)/../node_modules/react-native-image-resizer/ios/RCTImageResizer", "$(SRCROOT)/../node_modules/react-native-splash-screen/ios/**", ); - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LIBRARY_SEARCH_PATHS = ( "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", "\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"", diff --git a/ios/StatusIm/Info.plist b/ios/StatusIm/Info.plist index 741e2746e6..bc9264967d 100644 --- a/ios/StatusIm/Info.plist +++ b/ios/StatusIm/Info.plist @@ -127,5 +127,12 @@ UIViewControllerBasedStatusBarAppearance + com.apple.developer.nfc.readersession.iso7816.select-identifiers + + A00000080400010101 + A00000080400010301 + + NFCReaderUsageDescription + Enable Keycard diff --git a/ios/StatusIm/StatusIm.entitlements b/ios/StatusIm/StatusIm.entitlements index 0407edb0e5..00074aa872 100644 --- a/ios/StatusIm/StatusIm.entitlements +++ b/ios/StatusIm/StatusIm.entitlements @@ -2,6 +2,11 @@ + com.apple.developer.nfc.readersession.formats + + NDEF + TAG + aps-environment development com.apple.developer.associated-domains diff --git a/ios/StatusImPR/Info.plist b/ios/StatusImPR/Info.plist index 05ec5f0ef1..b93d2c175c 100644 --- a/ios/StatusImPR/Info.plist +++ b/ios/StatusImPR/Info.plist @@ -133,5 +133,12 @@ UIViewControllerBasedStatusBarAppearance + com.apple.developer.nfc.readersession.iso7816.select-identifiers + + A00000080400010101 + A00000080400010301 + + NFCReaderUsageDescription + Enable Keycard diff --git a/ios/StatusImPR/StatusImPR.entitlements b/ios/StatusImPR/StatusImPR.entitlements index 88fdb457af..cc0f12eac4 100644 --- a/ios/StatusImPR/StatusImPR.entitlements +++ b/ios/StatusImPR/StatusImPR.entitlements @@ -2,6 +2,11 @@ + com.apple.developer.nfc.readersession.formats + + NDEF + TAG + aps-environment development com.apple.developer.associated-domains diff --git a/ios/StatusImTests-Bridging-Header.h b/ios/StatusImTests-Bridging-Header.h new file mode 100644 index 0000000000..1b2cb5d6d0 --- /dev/null +++ b/ios/StatusImTests-Bridging-Header.h @@ -0,0 +1,4 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + diff --git a/ios/StatusImTests/Info.plist b/ios/StatusImTests/Info.plist index 48e8360435..51031e10b1 100644 --- a/ios/StatusImTests/Info.plist +++ b/ios/StatusImTests/Info.plist @@ -20,5 +20,12 @@ ???? CFBundleVersion 1 + com.apple.developer.nfc.readersession.iso7816.select-identifiers + + A00000080400010101 + A00000080400010301 + + NFCReaderUsageDescription + Enable Keycard diff --git a/modules/react-native-status/ios/RCTStatus/RCTStatus.m b/modules/react-native-status/ios/RCTStatus/RCTStatus.m index 015a1f52f7..7c53f00633 100644 --- a/modules/react-native-status/ios/RCTStatus/RCTStatus.m +++ b/modules/react-native-status/ios/RCTStatus/RCTStatus.m @@ -122,7 +122,7 @@ RCT_EXPORT_METHOD(initKeystore:(NSString *)keyUID NSURL *commonKeystoreDir = [rootUrl URLByAppendingPathComponent:@"keystore"]; NSURL *keystoreDir = [commonKeystoreDir URLByAppendingPathComponent:keyUID]; - + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { @@ -301,6 +301,37 @@ RCT_EXPORT_METHOD(hashTransaction:(NSString *)txArgsJSON callback(@[result]); } +//////////////////////////////////////////////////////////////////// hashMessage +RCT_EXPORT_METHOD(hashMessage:(NSString *)message + callback:(RCTResponseSenderBlock)callback) { +#if DEBUG + NSLog(@"hashMessage() method called"); +#endif + NSString *result = StatusgoHashMessage(message); + callback(@[result]); +} + +//////////////////////////////////////////////////////////////////// hashTypedData +RCT_EXPORT_METHOD(hashTypedData:(NSString *)data + callback:(RCTResponseSenderBlock)callback) { +#if DEBUG + NSLog(@"hashTypedData() method called"); +#endif + NSString *result = StatusgoHashTypedData(data); + callback(@[result]); +} + +//////////////////////////////////////////////////////////////////// sendTransactionWithSignature +RCT_EXPORT_METHOD(sendTransactionWithSignature:(NSString *)txArgsJSON + signature:(NSString *)signature + callback:(RCTResponseSenderBlock)callback) { +#if DEBUG + NSLog(@"sendTransactionWithSignature() method called"); +#endif + NSString *result = StatusgoSendTransactionWithSignature(txArgsJSON, signature); + callback(@[result]); +} + //////////////////////////////////////////////////////////////////// multiAccountImportMnemonic RCT_EXPORT_METHOD(multiAccountImportMnemonic:(NSString *)json callback:(RCTResponseSenderBlock)callback) { @@ -327,7 +358,7 @@ RCT_EXPORT_METHOD(multiAccountDeriveAddresses:(NSString *)json JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; - + return [json valueForKey:@"key-uid"]; } @@ -456,10 +487,10 @@ RCT_EXPORT_METHOD(saveAccountAndLoginWithKeycard:(NSString *)multiaccountData NSURL *rootUrl =[[fileManager URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] lastObject]; - + NSURL *oldKeystoreDir = [rootUrl URLByAppendingPathComponent:@"keystore"]; NSURL *multiaccountKeystoreDir = [oldKeystoreDir URLByAppendingPathComponent:keyUID]; - + return multiaccountKeystoreDir; } @@ -473,12 +504,12 @@ RCT_EXPORT_METHOD(saveAccountAndLoginWithKeycard:(NSString *)multiaccountData NSString *keyUID = [self getKeyUID:accountData]; NSURL *oldKeystoreDir = [rootUrl URLByAppendingPathComponent:@"keystore"]; NSURL *multiaccountKeystoreDir = [self getKeyStoreDir:keyUID]; - + NSArray *keys = [fileManager contentsOfDirectoryAtPath:multiaccountKeystoreDir.path error:nil]; if (keys.count == 0) { NSString *migrationResult = StatusgoMigrateKeyStoreDir(accountData, password, oldKeystoreDir.path, multiaccountKeystoreDir.path); NSLog(@"keystore migration result %@", migrationResult); - + NSString *initKeystoreResult = StatusgoInitKeystore(multiaccountKeystoreDir.path); NSLog(@"InitKeyStore result %@", initKeystoreResult); } @@ -503,7 +534,7 @@ RCT_EXPORT_METHOD(loginWithKeycard:(NSString *)accountData NSLog(@"LoginWithKeycard() method called"); #endif [self migrateKeystore:accountData password:password]; - + NSString *result = StatusgoLoginWithKeycard(accountData, password, chatKey); NSLog(@"%@", result); diff --git a/package.json b/package.json index 6ad186b1fd..e52b74ec66 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "private": true, "scripts": { "start": "react-native start", + "ios": "react-native run-ios", "app:compile:android": "shadow-cljs compile android", "app:watch": "shadow-cljs watch android", "app:packager": "react-native start --host 0.0.0.0 --port 8081", @@ -60,7 +61,7 @@ "react-native-screens": "^2.10.1", "react-native-shake": "^3.3.1", "react-native-splash-screen": "^3.2.0", - "react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#v2.5.28", + "react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#v2.5.30", "react-native-svg": "^9.8.4", "react-native-touch-id": "^4.4.1", "react-native-webview": "git+https://github.com/status-im/react-native-webview.git#v10.9.2", diff --git a/src/quo/components/bottom_sheet/view.cljs b/src/quo/components/bottom_sheet/view.cljs index bb605ed7f0..078d1ea401 100644 --- a/src/quo/components/bottom_sheet/view.cljs +++ b/src/quo/components/bottom_sheet/view.cljs @@ -31,6 +31,7 @@ disable-drag? :disableDrag? show-handle? :showHandle? visible? :visible? + transparent :transparent backdrop-dismiss? :backdropDismiss? back-button-cancel :backButtonCancel children :children @@ -189,6 +190,7 @@ (when back-button-cancel (close-sheet)))} [rn/view {:style styles/container + :opacity (if transparent 0 1) :pointer-events :box-none} [gesture-handler/tap-gesture-handler (merge {:enabled backdrop-dismiss?} tap-gesture-handler) diff --git a/src/status_im/keycard/card.cljs b/src/status_im/keycard/card.cljs index 41dd1c2ab1..715f359206 100644 --- a/src/status_im/keycard/card.cljs +++ b/src/status_im/keycard/card.cljs @@ -1,61 +1,57 @@ (ns status-im.keycard.card (:require [re-frame.core :as re-frame] - [status-im.keycard.ios-keycard :as ios-keycard] [status-im.keycard.keycard :as keycard] [status-im.keycard.real-keycard :as real-keycard] [status-im.keycard.simulated-keycard :as simulated-keycard] [status-im.utils.config :as config] - [status-im.utils.platform :as platform] [taoensso.timbre :as log])) (defonce card (if config/keycard-test-menu-enabled? (simulated-keycard/SimulatedKeycard.) - (if platform/android? - (real-keycard/RealKeycard.) - (ios-keycard/IOSKeycard.)))) + (real-keycard/RealKeycard.))) (defn check-nfc-support [] - (log/info "[keycard] check-nfc-support") + (log/debug "[keycard] check-nfc-support") (keycard/check-nfc-support card {:on-success (fn [response] - (log/info "[keycard response] check-nfc-support") + (log/debug "[keycard response] check-nfc-support") (re-frame/dispatch [:keycard.callback/check-nfc-support-success response]))})) (defn check-nfc-enabled [] - (log/info "[keycard] check-nfc-enabled") + (log/debug "[keycard] check-nfc-enabled") (keycard/check-nfc-enabled card {:on-success (fn [response] - (log/info "[keycard response] check-nfc-enabled") + (log/debug "[keycard response] check-nfc-enabled") (re-frame/dispatch [:keycard.callback/check-nfc-enabled-success response]))})) (defn open-nfc-settings [] - (log/info "[keycard] open-nfc-settings") + (log/debug "[keycard] open-nfc-settings") (keycard/open-nfc-settings card)) (defn remove-event-listener [event] - (log/info "[keycard] remove-event-listener") + (log/debug "[keycard] remove-event-listener") (keycard/remove-event-listener card event)) (defn on-card-disconnected [callback] - (log/info "[keycard] on-card-disconnected") + (log/debug "[keycard] on-card-disconnected") (keycard/on-card-disconnected card callback)) (defn on-card-connected [callback] - (log/info "[keycard] on-card-connected") + (log/debug "[keycard] on-card-connected") (keycard/on-card-connected card callback)) (defn remove-event-listeners [] - (log/info "[keycard] remove-event-listeners") + (log/debug "[keycard] remove-event-listeners") (keycard/remove-event-listeners card)) (defn register-card-events [] - (log/info "[keycard] register-card-events") + (log/debug "[keycard] register-card-events") (keycard/register-card-events card {:on-card-connected @@ -64,6 +60,12 @@ :on-card-disconnected #(re-frame/dispatch [:keycard.callback/on-card-disconnected]) + :on-nfc-user-cancelled + #(re-frame/dispatch [:keycard.callback/on-nfc-user-cancelled]) + + :on-nfc-timeout + #(re-frame/dispatch [:keycard.callback/on-nfc-timeout]) + :on-nfc-enabled #(re-frame/dispatch [:keycard.callback/check-nfc-enabled-success true]) @@ -75,188 +77,188 @@ :error (.-message object)}) (defn get-application-info [{:keys [on-success] :as args}] - (log/info "[keycard] get-application-info") + (log/debug "[keycard] get-application-info") (keycard/get-application-info card (merge args {:on-success (fn [response] - (log/info "[keycard response succ] get-application-info") + (log/debug "[keycard response succ] get-application-info") (re-frame/dispatch [:keycard.callback/on-get-application-info-success response on-success])) :on-failure (fn [response] - (log/info "[keycard response fail] get-application-info") + (log/debug "[keycard response fail] get-application-info") (re-frame/dispatch [:keycard.callback/on-get-application-info-error (error-object->map response)]))}))) (defn install-applet [] - (log/info "[keycard] install-applet") + (log/debug "[keycard] install-applet") (keycard/install-applet card {:on-success (fn [response] - (log/info "[keycard response succ] install-applet") + (log/debug "[keycard response succ] install-applet") (re-frame/dispatch [:keycard.callback/on-install-applet-success response])) :on-failure (fn [response] - (log/info "[keycard response fail] install-applet") + (log/debug "[keycard response fail] install-applet") (re-frame/dispatch [:keycard.callback/on-install-applet-error (error-object->map response)]))})) (defn init-card [pin] - (log/info "[keycard] init-card") + (log/debug "[keycard] init-card") (keycard/init-card card {:pin pin :on-success (fn [response] - (log/info "[keycard response succ] init-card") + (log/debug "[keycard response succ] init-card") (re-frame/dispatch [:keycard.callback/on-init-card-success response])) :on-failure (fn [response] - (log/info "[keycard response fail] init-card") + (log/debug "[keycard response fail] init-card") (re-frame/dispatch [:keycard.callback/on-init-card-error (error-object->map response)]))})) (defn install-applet-and-init-card [pin] - (log/info "[keycard] install-applet-and-init-card") + (log/debug "[keycard] install-applet-and-init-card") (keycard/install-applet-and-init-card card {:pin pin :on-success (fn [response] - (log/info "[keycard response succ] install-applet-and-init-card") + (log/debug "[keycard response succ] install-applet-and-init-card") #(re-frame/dispatch [:keycard.callback/on-install-applet-and-init-card-success response])) :on-failure (fn [response] - (log/info "[keycard response fail] install-applet-and-init-card") + (log/debug "[keycard response fail] install-applet-and-init-card") (re-frame/dispatch [:keycard.callback/on-install-applet-and-init-card-error (error-object->map response)]))})) (defn pair [args] - (log/info "[keycard] pair") + (log/debug "[keycard] pair") (keycard/pair card (merge args {:on-success (fn [response] - (log/info "[keycard response succ] pair") + (log/debug "[keycard response succ] pair") (re-frame/dispatch [:keycard.callback/on-pair-success response])) :on-failure (fn [response] - (log/info "[keycard response fail] pair") + (log/debug "[keycard response fail] pair") (re-frame/dispatch [:keycard.callback/on-pair-error (error-object->map response)]))}))) (defn generate-and-load-key [args] - (log/info "[keycard] generate-and-load-key") + (log/debug "[keycard] generate-and-load-key") (keycard/generate-and-load-key card (merge args {:on-success (fn [response] - (log/info "[keycard response succ] generate-and-load-key") + (log/debug "[keycard response succ] generate-and-load-key") (re-frame/dispatch [:keycard.callback/on-generate-and-load-key-success response])) :on-failure (fn [response] - (log/info "[keycard response fail] generate-and-load-key") + (log/debug "[keycard response fail] generate-and-load-key") (re-frame/dispatch [:keycard.callback/on-generate-and-load-key-error (error-object->map response)]))}))) (defn unblock-pin [args] - (log/info "[keycard] unblock-pin") + (log/debug "[keycard] unblock-pin") (keycard/unblock-pin card (merge args {:on-success (fn [response] - (log/info "[keycard response succ] unblock-pin") + (log/debug "[keycard response succ] unblock-pin") (re-frame/dispatch [:keycard.callback/on-unblock-pin-success response])) :on-failure (fn [response] - (log/info "[keycard response fail] unblock-pin") + (log/debug "[keycard response fail] unblock-pin") (re-frame/dispatch [:keycard.callback/on-unblock-pin-error (error-object->map response)]))}))) (defn verify-pin [args] - (log/info "[keycard] verify-pin") + (log/debug "[keycard] verify-pin") (keycard/verify-pin card (merge args {:on-success (fn [response] - (log/info "[keycard response succ] verify-pin") + (log/debug "[keycard response succ] verify-pin") (re-frame/dispatch [:keycard.callback/on-verify-pin-success response])) :on-failure (fn [response] - (log/info "[keycard response fail] verify-pin") + (log/debug "[keycard response fail] verify-pin") (re-frame/dispatch [:keycard.callback/on-verify-pin-error (error-object->map response)]))}))) (defn change-pin [args] - (log/info "[keycard] change-pin") + (log/debug "[keycard] change-pin") (keycard/change-pin card (merge args {:on-success (fn [response] - (log/info "[keycard response succ] change-pin") + (log/debug "[keycard response succ] change-pin") (re-frame/dispatch [:keycard.callback/on-change-pin-success response])) :on-failure (fn [response] - (log/info "[keycard response fail] change-pin") + (log/debug "[keycard response fail] change-pin") (re-frame/dispatch [:keycard.callback/on-change-pin-error (error-object->map response)]))}))) (defn unpair [args] - (log/info "[keycard] unpair") + (log/debug "[keycard] unpair") (keycard/unpair card (merge args {:on-success (fn [response] - (log/info "[keycard response succ] unpair") + (log/debug "[keycard response succ] unpair") (re-frame/dispatch [:keycard.callback/on-unpair-success response])) :on-failure (fn [response] - (log/info "[keycard response fail] unpair") + (log/debug "[keycard response fail] unpair") (re-frame/dispatch [:keycard.callback/on-unpair-error (error-object->map response)]))}))) (defn delete [] - (log/info "[keycard] delete") + (log/debug "[keycard] delete") (keycard/delete card {:on-success (fn [response] - (log/info "[keycard response succ] delete") + (log/debug "[keycard response succ] delete") (re-frame/dispatch [:keycard.callback/on-delete-success response])) :on-failure @@ -267,107 +269,107 @@ (error-object->map response)]))})) (defn remove-key [args] - (log/info "[keycard] remove-key") + (log/debug "[keycard] remove-key") (keycard/remove-key card (merge args {:on-success (fn [response] - (log/info "[keycard response succ] remove-key") + (log/debug "[keycard response succ] remove-key") (re-frame/dispatch [:keycard.callback/on-remove-key-success response])) :on-failure (fn [response] - (log/info "[keycard response fail] remove-key") + (log/debug "[keycard response fail] remove-key") (re-frame/dispatch [:keycard.callback/on-remove-key-error (error-object->map response)]))}))) (defn remove-key-with-unpair [args] - (log/info "[keycard] remove-key-with-unpair") + (log/debug "[keycard] remove-key-with-unpair") (keycard/remove-key-with-unpair card (merge args {:on-success (fn [response] - (log/info "[keycard response succ] remove-key-with-unpair") + (log/debug "[keycard response succ] remove-key-with-unpair") (re-frame/dispatch [:keycard.callback/on-remove-key-success response])) :on-failure (fn [response] - (log/info "[keycard response fail] remove-key-with-unpair") + (log/debug "[keycard response fail] remove-key-with-unpair") (re-frame/dispatch [:keycard.callback/on-remove-key-error (error-object->map response)]))}))) (defn export-key [args] - (log/info "[keycard] export-key") + (log/debug "[keycard] export-key") (keycard/export-key card (merge args {:on-success (fn [response] - (log/info "[keycard response succ] export-key") + (log/debug "[keycard response succ] export-key") (re-frame/dispatch [:keycard.callback/on-export-key-success response])) :on-failure (fn [response] - (log/info "[keycard response fail] export-key") + (log/debug "[keycard response fail] export-key") (re-frame/dispatch [:keycard.callback/on-export-key-error (error-object->map response)]))}))) (defn unpair-and-delete [args] - (log/info "[keycard] unpair-and-delete") + (log/debug "[keycard] unpair-and-delete") (keycard/unpair-and-delete card (merge args {:on-success (fn [response] - (log/info "[keycard response succ] unpair-and-delete") + (log/debug "[keycard response succ] unpair-and-delete") (re-frame/dispatch [:keycard.callback/on-delete-success response])) :on-failure (fn [response] - (log/info "[keycard response fail] unpair-and-delete") + (log/debug "[keycard response fail] unpair-and-delete") (re-frame/dispatch [:keycard.callback/on-delete-error (error-object->map response)]))}))) (defn get-keys [{:keys [on-success] :as args}] - (log/info "[keycard] get-keys") + (log/debug "[keycard] get-keys") (keycard/get-keys card (merge args {:on-success (fn [response] - (log/info "[keycard response succ] get-keys") + (log/debug "[keycard response succ] get-keys") (re-frame/dispatch [(or on-success :keycard.callback/on-get-keys-success) response])) :on-failure (fn [response] - (log/info "[keycard response fail] get-keys" - (error-object->map response)) + (log/debug "[keycard response fail] get-keys" + (error-object->map response)) (re-frame/dispatch [:keycard.callback/on-get-keys-error (error-object->map response)]))}))) (defn sign [{:keys [on-success on-failure] :as args}] - (log/info "[keycard] sign") + (log/debug "[keycard] sign") (keycard/sign card (merge args {:on-success (fn [response] - (log/info "[keycard response succ] sign") + (log/debug "[keycard response succ] sign") (if on-success (on-success response) (re-frame/dispatch [:keycard.callback/on-sign-success response]))) :on-failure (fn [response] - (log/info "[keycard response fail] sign") + (log/debug "[keycard response fail] sign") (if on-failure (on-failure response) (re-frame/dispatch @@ -375,35 +377,35 @@ (error-object->map response)])))}))) (defn install-cash-applet [] - (log/info "[keycard] install-cash-applet") + (log/debug "[keycard] install-cash-applet") (keycard/install-cash-applet card {:on-success (fn [response] - (log/info "[keycard response succ] install-cash-applet") + (log/debug "[keycard response succ] install-cash-applet") (re-frame/dispatch [:keycard.callback/on-install-applet-success response])) :on-failure (fn [response] - (log/info "[keycard response fail] install-cash-applet") + (log/debug "[keycard response fail] install-cash-applet") (re-frame/dispatch [:keycard.callback/on-install-applet-error (error-object->map response)]))})) (defn sign-typed-data [{:keys [hash]}] - (log/info "[keycard] sign-typed-data") + (log/debug "[keycard] sign-typed-data") (keycard/sign-typed-data card {:hash hash :on-success (fn [response] - (log/info "[keycard response succ] sign-typed-data") + (log/debug "[keycard response succ] sign-typed-data") (re-frame/dispatch [:keycard.callback/on-sign-success response])) :on-failure (fn [response] - (log/info "[keycard response fail] sign-typed-data") + (log/debug "[keycard response fail] sign-typed-data") (re-frame/dispatch [:keycard.callback/on-sign-error (error-object->map response)]))})) @@ -416,3 +418,12 @@ (defn send-transaction-with-signature [args] (keycard/send-transaction-with-signature card args)) + +(defn start-nfc [args] + (keycard/start-nfc card args)) + +(defn stop-nfc [args] + (keycard/stop-nfc card args)) + +(defn set-nfc-message [args] + (keycard/set-nfc-message card args)) diff --git a/src/status_im/keycard/change_pin.cljs b/src/status_im/keycard/change_pin.cljs index 9e96b3c3b3..5e23db4ac4 100644 --- a/src/status_im/keycard/change_pin.cljs +++ b/src/status_im/keycard/change_pin.cljs @@ -96,23 +96,27 @@ {:events [:keycard.callback/on-change-pin-error]} [{:keys [db] :as cofx} error] (log/debug "[keycard] change pin error" error) - (let [tag-was-lost? (= "Tag was lost." (:error error)) - pairing (common/get-pairing db)] + (let [tag-was-lost? (common/tag-lost? (:error error)) + pairing (common/get-pairing db) + pin-retries (common/pin-retries (:error error))] (fx/merge cofx (if tag-was-lost? (fx/merge cofx {:db (assoc-in db [:keycard :pin :status] nil)} (common/set-on-card-connected :keycard/change-pin)) - (if (re-matches common/pin-mismatch-error (:error error)) + (if-not (nil? pin-retries) (fx/merge cofx - {:db (update-in db [:keycard :pin] merge {:status :error - :enter-step :current - :puk [] - :current [] - :original [] - :confirmation [] - :sign [] - :error-label :t/pin-mismatch})} - (navigation/navigate-to-cofx :enter-pin-settings nil) - (common/get-application-info pairing nil)) + {:db (-> db + (assoc-in [:keycard :application-info :pin-retry-counter] pin-retries) + (update-in [:keycard :pin] assoc + :status :error + :enter-step :current + :puk [] + :current [] + :original [] + :confirmation [] + :sign [] + :error-label :t/pin-mismatch))} + (when (zero? pin-retries) (common/frozen-keycard-popup)) + (navigation/navigate-to-cofx :enter-pin-settings nil)) (common/show-wrong-keycard-alert true)))))) diff --git a/src/status_im/keycard/common.cljs b/src/status_im/keycard/common.cljs index cbf78582bd..4784ba9dbe 100644 --- a/src/status_im/keycard/common.cljs +++ b/src/status_im/keycard/common.cljs @@ -10,11 +10,15 @@ [status-im.utils.keychain.core :as keychain] [status-im.utils.types :as types] [taoensso.timbre :as log] - [status-im.bottom-sheet.core :as bottom-sheet])) + [status-im.bottom-sheet.core :as bottom-sheet] + [status-im.utils.platform :as platform])) (def default-pin "000000") -(def pin-mismatch-error #"Unexpected error SW, 0x63C\d+") +(def pin-mismatch-error #"Unexpected error SW, 0x63C(\d+)|wrongPIN\(retryCounter: (\d+)\)") + +(defn pin-retries [error] + (when-let [matched-error (re-matches pin-mismatch-error error)] (js/parseInt (second (filter some? matched-error))))) (fx/defn dispatch-event [_ event] @@ -51,7 +55,10 @@ :no-pairing-slots)) (defn tag-lost? [error] - (= error "Tag was lost.")) + (or + (= error "Tag was lost.") + (= error "NFCError:100") + (re-matches #".*NFCError:100.*" error))) (defn find-multiaccount-by-keycard-instance-uid [db keycard-instance-uid] @@ -168,7 +175,7 @@ :on-connect ::on-card-connected :on-disconnect ::on-card-disconnected}))) -(fx/defn show-connection-sheet +(fx/defn show-connection-sheet-component [{:keys [db] :as cofx} {:keys [on-card-connected on-card-read handler] {:keys [on-cancel] :or {on-cancel [::cancel-sheet-confirm]}} @@ -182,7 +189,8 @@ cofx {:dismiss-keyboard true} (bottom-sheet/show-bottom-sheet - {:view {:show-handle? false + {:view {:transparent platform/ios? + :show-handle? false :backdrop-dismiss? false :disable-drag? true :back-button-cancel false @@ -195,7 +203,21 @@ (when connected? handler)))) -(fx/defn hide-connection-sheet +(fx/defn show-connection-sheet + [{:keys [db] :as cofx} args] + (let [nfc-running? (get-in db [:keycard :nfc-running?])] + (log/debug "show connection; already running?" nfc-running?) + (if nfc-running? + (show-connection-sheet-component cofx args) + {:keycard/start-nfc-and-show-connection-sheet args}))) + +(fx/defn on-nfc-ready-for-sheet + {:events [:keycard.callback/show-connection-sheet]} + [cofx args] + (log/debug "on-nfc-ready-for-sheet") + (show-connection-sheet-component cofx args)) + +(fx/defn hide-connection-sheet-component [{:keys [db] :as cofx}] (fx/merge cofx {:db (assoc-in db [:keycard :card-read-in-progress?] false)} @@ -203,6 +225,17 @@ (restore-on-card-read) (bottom-sheet/hide-bottom-sheet))) +(fx/defn hide-connection-sheet + [cofx] + (log/debug "hide-connection-sheet") + {:keycard/stop-nfc-and-hide-connection-sheet nil}) + +(fx/defn on-nfc-ready-to-close-sheet + {:events [:keycard.callback/hide-connection-sheet]} + [cofx] + (log/debug "on-nfc-ready-to-close-sheet") + (hide-connection-sheet-component cofx)) + (fx/defn clear-pin [{:keys [db] :as cofx}] (fx/merge @@ -286,7 +319,8 @@ (defn- tag-lost-exception? [code error] (or (= code "android.nfc.TagLostException") - (= error "Tag was lost."))) + (= error "Tag was lost.") + (= error "NFCError:100"))) (fx/defn process-error [{:keys [db]} code error] (when-not (tag-lost-exception? code error) @@ -342,28 +376,37 @@ (clear-on-card-read) (hide-connection-sheet)))) +(fx/defn frozen-keycard-popup + [{:keys [db] :as cofx}] + (if (:multiaccounts/login db) + (fx/merge + cofx + {:db (assoc-in db [:keycard :pin :status] :frozen-card)} + hide-connection-sheet) + {:db (assoc db :popover/popover {:view :frozen-card})})) + (fx/defn on-get-keys-error {:events [:keycard.callback/on-get-keys-error]} [{:keys [db] :as cofx} error] (log/debug "[keycard] get keys error: " error) (let [tag-was-lost? (tag-lost? (:error error)) key-uid (get-in db [:keycard :application-info :key-uid]) - flow (get-in db [:keycard :flow])] + flow (get-in db [:keycard :flow]) + pin-retries-count (pin-retries (:error error))] (if tag-was-lost? {:db (assoc-in db [:keycard :pin :status] nil)} - (if (re-matches pin-mismatch-error (:error error)) + (if-not (nil? pin-retries-count) (fx/merge cofx - {:keycard/get-application-info - {:pairing (get-pairing db key-uid)} - - :db - (update-in db [:keycard :pin] merge - {:status :error - :login [] - :import-multiaccount [] - :error-label :t/pin-mismatch})} + {:db (-> db + (assoc-in [:keycard :application-info :pin-retry-counter] pin-retries-count) + (update-in [:keycard :pin] assoc + :status :error + :login [] + :import-multiaccount [] + :error-label :t/pin-mismatch))} (hide-connection-sheet) + (when (zero? pin-retries-count) (frozen-keycard-popup)) (when (= flow :import) (navigation/navigate-to-cofx :keycard-recovery-pin nil))) (show-wrong-keycard-alert true))))) @@ -384,15 +427,6 @@ {:keycard/get-application-info {:pairing pairing' :on-success on-card-read}})) -(fx/defn frozen-keycard-popup - [{:keys [db] :as cofx}] - (if (:multiaccounts/login db) - (fx/merge - cofx - {:db (assoc-in db [:keycard :pin :status] :frozen-card)} - hide-connection-sheet) - {:db (assoc db :popover/popover {:view :frozen-card})})) - (fx/defn on-get-application-info-success {:events [:keycard.callback/on-get-application-info-success]} [{:keys [db] :as cofx} info on-success] @@ -426,7 +460,6 @@ hide-connection-sheet) (when on-success' (dispatch-event cofx on-success'))))))) - (fx/defn on-get-application-info-error {:events [:keycard.callback/on-get-application-info-error]} [{:keys [db] :as cofx} error] diff --git a/src/status_im/keycard/common_test.cljs b/src/status_im/keycard/common_test.cljs index 1b92c619a2..6f09863830 100644 --- a/src/status_im/keycard/common_test.cljs +++ b/src/status_im/keycard/common_test.cljs @@ -5,7 +5,7 @@ (deftest test-show-connection-sheet (testing "the card is not connected yet" (let [db {:keycard {:card-connected? false}} - res (common/show-connection-sheet + res (common/show-connection-sheet-component {:db db} {:on-card-connected :do-something :handler (fn [{:keys [db]}] @@ -16,7 +16,7 @@ (is (true? (get-in res [:db :bottom-sheet/show?]))))) (testing "the card is connected before the interaction" (let [db {:keycard {:card-connected? true}} - res (common/show-connection-sheet + res (common/show-connection-sheet-component {:db db} {:on-card-connected :do-something :handler (fn [{:keys [db]}] @@ -30,13 +30,13 @@ (is (thrown? js/Error - (common/show-connection-sheet + (common/show-connection-sheet-component {:db {}} {:handler (fn [_])})))) (testing "handler is not specified" (is (thrown? js/Error - (common/show-connection-sheet + (common/show-connection-sheet-component {:db {}} {:on-card-connected :do-something}))))) diff --git a/src/status_im/keycard/core.cljs b/src/status_im/keycard/core.cljs index d495aad311..e0b78a8980 100644 --- a/src/status_im/keycard/core.cljs +++ b/src/status_im/keycard/core.cljs @@ -135,18 +135,19 @@ (let [pairing (common/get-pairing db) reset-pin (get-in db [:keycard :pin :reset])] (fx/merge cofx - {:keycard/get-application-info - {:pairing pairing} - - :db - (update-in db [:keycard :pin] merge - {:status :after-unblocking - :enter-step :login - :login reset-pin - :confirmation [] - :puk [] - :puk-restore? true - :error-label nil})} + {:db + (-> db + (update-in [:keycard :application-info] assoc + :puk-retry-counter 5 + :pin-retry-counter 3) + (update-in [:keycard :pin] assoc + :status :after-unblocking + :enter-step :login + :login reset-pin + :confirmation [] + :puk [] + :puk-restore? true + :error-label nil))} (common/hide-connection-sheet) (common/clear-on-card-connected) (common/clear-on-card-read)))) @@ -155,19 +156,20 @@ {:events [:keycard.callback/on-unblock-pin-error]} [{:keys [db] :as cofx} error] (let [pairing (common/get-pairing db) - tag-was-lost? (common/tag-lost? (:error error))] + tag-was-lost? (common/tag-lost? (:error error)) + puk-retries (common/pin-retries (:error error))] (log/debug "[keycard] unblock pin error" error) (when-not tag-was-lost? (fx/merge cofx - {:keycard/get-application-info - {:pairing pairing} + {:db + (-> db + (assoc-in [:keycard :application-info :puk-retry-counter] puk-retries) + (update-in [:keycard :pin] merge + {:status (if (zero? puk-retries) :blocked-card :error) + :error-label :t/puk-mismatch + :enter-step :puk + :puk []}))} - :db - (update-in db [:keycard :pin] merge - {:status :error - :error-label :t/puk-mismatch - :enter-step :puk - :puk []})} (common/hide-connection-sheet))))) (fx/defn clear-on-verify-handlers @@ -188,8 +190,9 @@ (common/clear-on-card-read) ;; TODO(Ferossgp): Each pin input should handle this event on it's own, ;; now for simplicity do not hide bottom sheet when generating key - ;; but should be refactored. - (when-not (= on-verified :keycard/generate-and-load-key) + ;; and exporting key but should be refactored. + (when-not (contains? #{:keycard/generate-and-load-key + :wallet.accounts/generate-new-keycard-account} on-verified) (common/hide-connection-sheet)) (when-not (contains? #{:keycard/unpair :keycard/generate-and-load-key @@ -207,28 +210,30 @@ (let [tag-was-lost? (common/tag-lost? (:error error)) setup? (boolean (get-in db [:keycard :setup-step])) on-verified-failure (get-in db [:keycard :pin :on-verified-failure]) - exporting? (get-in db [:keycard :on-export-success])] + exporting? (get-in db [:keycard :on-export-success]) + pin-retries (common/pin-retries (:error error))] (log/debug "[keycard] verify pin error" error) (when-not tag-was-lost? - (if (re-matches common/pin-mismatch-error (:error error)) + (if-not (nil? pin-retries) (fx/merge cofx - {:db (update-in db [:keycard :pin] - merge - {:status :error - :enter-step :current - :puk [] - :current [] - :original [] - :confirmation [] - :sign [] - :error-label :t/pin-mismatch})} + {:db (-> db + (assoc-in [:keycard :application-info :pin-retry-counter] pin-retries) + (update-in [:keycard :pin] assoc + :status :error + :enter-step :current + :puk [] + :current [] + :original [] + :confirmation [] + :sign [] + :error-label :t/pin-mismatch))} (common/hide-connection-sheet) (when (and (not setup?) (not on-verified-failure)) (if exporting? (navigation/navigate-back) (navigation/navigate-to-cofx :enter-pin-settings nil))) - (common/get-application-info (common/get-pairing db) nil) + (when (zero? pin-retries) (common/frozen-keycard-popup)) (when on-verified-failure (fn [_] {:utils/dispatch-later [{:dispatch [on-verified-failure] @@ -414,7 +419,7 @@ (assoc-in [:keycard :setup-step] next-step) (assoc-in [:keycard :secrets :pairing] pairing) (assoc-in [:keycard :secrets :paired-on] paired-on))} - (common/hide-connection-sheet) + (when-not (and (= flow :recovery) (= next-step :card-ready)) (common/hide-connection-sheet)) (when multiaccount (set-multiaccount-pairing multiaccount pairing paired-on)) (when (= flow :login) @@ -525,6 +530,21 @@ (log/debug "[keycard] card disconnected") {:db (assoc-in db [:keycard :card-connected?] false)}) +(fx/defn on-nfc-user-cancelled + {:events [:keycard.callback/on-nfc-user-cancelled]} + [{:keys [db]} _] + (log/debug "[keycard] nfc user cancelled") + {:dispatch [:signing.ui/cancel-is-pressed]}) + +(fx/defn on-nfc-timeout + {:events [:keycard.callback/on-nfc-timeout]} + [{:keys [db]} _] + (log/debug "[keycard] nfc timeout") + {:db (-> db + (assoc-in [:keycard :nfc-running?] false) + (assoc-in [:keycard :card-connected?] false)) + :keycard/start-nfc nil}) + (fx/defn on-register-card-events {:events [:keycard.callback/on-register-card-events]} [{:keys [db]} listeners] @@ -552,4 +572,40 @@ {:events [:keycard.ui/pin-numpad-delete-button-pressed]} [{:keys [db]} step] (when-not (empty? (get-in db [:keycard :pin step])) - {:db (update-in db [:keycard :pin step] pop)})) \ No newline at end of file + {:db (update-in db [:keycard :pin step] pop)})) + +(fx/defn start-nfc + {:events [:keycard.ui/start-nfc]} + [cofx] + {:keycard/start-nfc nil}) + +(fx/defn stop-nfc + {:events [:keycard.ui/stop-nfc]} + [cofx] + {:keycard/stop-nfc nil + :keycard.callback/on-card-disconnected nil}) + +(fx/defn start-nfc-success + {:events [:keycard.callback/start-nfc-success]} + [{:keys [db]} _] + (log/debug "[keycard] nfc started success") + {:db (assoc-in db [:keycard :nfc-running?] true)}) + +(fx/defn start-nfc-failure + {:events [:keycard.callback/start-nfc-failure]} + [{:keys [db]} _] + (log/debug "[keycard] nfc failed starting")) ;; leave current value on :nfc-running + +(fx/defn stop-nfc-success + {:events [:keycard.callback/stop-nfc-success]} + [{:keys [db]} _] + (log/debug "[keycard] nfc stopped success") + (log/debug "[keycard] setting card-connected? and nfc-running? to false") + {:db (-> db + (assoc-in [:keycard :nfc-running?] false) + (assoc-in [:keycard :card-connected?] false))}) + +(fx/defn stop-nfc-failure + {:events [:keycard.callback/stop-nfc-failure]} + [{:keys [db]} _] + (log/debug "[keycard] nfc failed stopping")) ;; leave current value on :nfc-running diff --git a/src/status_im/keycard/export_key.cljs b/src/status_im/keycard/export_key.cljs index d0b10e9131..59faf6690e 100644 --- a/src/status_im/keycard/export_key.cljs +++ b/src/status_im/keycard/export_key.cljs @@ -8,26 +8,29 @@ {:events [:keycard.callback/on-export-key-error]} [{:keys [db] :as cofx} error] (log/debug "[keycard] export key error" error) - (let [tag-was-lost? (common/tag-lost? (:error error))] + (let [tag-was-lost? (common/tag-lost? (:error error)) + pin-retries (common/pin-retries (:error error))] (cond tag-was-lost? (fx/merge cofx {:db (assoc-in db [:keycard :pin :status] nil)} (common/set-on-card-connected :wallet.accounts/generate-new-keycard-account)) - (re-matches common/pin-mismatch-error (:error error)) + (not (nil? pin-retries)) (fx/merge cofx - {:db (update-in db [:keycard :pin] merge {:status :error - :enter-step :export-key - :puk [] - :current [] - :original [] - :confirmation [] - :sign [] - :export-key [] - :error-label :t/pin-mismatch})} + {:db (-> db + (assoc-in [:keycard :application-info :pin-retry-counter] pin-retries) + (update-in [:keycard :pin] assoc + :status :error + :enter-step :export-key + :puk [] + :current [] + :original [] + :confirmation [] + :sign [] + :export-key [] + :error-label :t/pin-mismatch))} (common/hide-connection-sheet) - (common/get-application-info (common/get-pairing db) nil)) - + (when (zero? pin-retries) (common/frozen-keycard-popup))) :else (fx/merge cofx (common/show-wrong-keycard-alert true) diff --git a/src/status_im/keycard/fx.cljs b/src/status_im/keycard/fx.cljs index 655297f15d..43fc9aae4b 100644 --- a/src/status_im/keycard/fx.cljs +++ b/src/status_im/keycard/fx.cljs @@ -3,10 +3,58 @@ [status-im.utils.types :as types] [status-im.keycard.card :as card] [status-im.native-module.core :as status] - [status-im.utils.platform :as platform] ["react-native" :refer (BackHandler)] + [taoensso.timbre :as log] ["@react-native-community/async-storage" :default AsyncStorage])) +(re-frame/reg-fx + :keycard/start-nfc + (fn [] + (log/debug "fx start-nfc") + (card/start-nfc + {:on-success #(re-frame/dispatch [:keycard.callback/start-nfc-success]) + :on-failure #(re-frame/dispatch [:keycard.callback/start-nfc-failure])}))) + +(re-frame/reg-fx + :keycard/stop-nfc + (fn [] + (log/debug "fx stop-nfc") + (card/stop-nfc + {:on-success #(re-frame/dispatch [:keycard.callback/stop-nfc-success]) + :on-failure #(re-frame/dispatch [:keycard.callback/stop-nfc-failure])}))) + +(re-frame/reg-fx + :keycard/set-nfc-message + card/set-nfc-message) + +(re-frame/reg-fx + :keycard/start-nfc-and-show-connection-sheet + (fn [args] + (log/debug "fx start-nfc-and-show-connection-sheet") + (card/start-nfc + {:on-success + (fn [] + (log/debug "nfc started successfully. next: show-connection-sheet") + (re-frame/dispatch [:keycard.callback/start-nfc-success]) + (re-frame/dispatch [:keycard.callback/show-connection-sheet args])) + :on-failure + (fn [] + (log/debug "nfc failed star starting. not calling show-connection-sheet") + (re-frame/dispatch [:keycard.callback/start-nfc-failure]))}))) + +(re-frame/reg-fx + :keycard/stop-nfc-and-hide-connection-sheet + (fn [] + (log/debug "fx stop-nfc-and-hide-connection-sheet") + (card/stop-nfc + {:on-success + (fn [] + (re-frame/dispatch [:keycard.callback/stop-nfc-success]) + (re-frame/dispatch [:keycard.callback/hide-connection-sheet])) + :on-failure + (fn [] + (re-frame/dispatch [:keycard.callback/stop-nfc-failure]))}))) + (re-frame/reg-fx :keycard/get-application-info card/get-application-info) @@ -112,11 +160,10 @@ (re-frame/reg-fx :keycard/retrieve-pairings (fn [] - (when platform/android? - (.. AsyncStorage - (getItem "status-keycard-pairings") - (then #(re-frame/dispatch [:keycard.callback/on-retrieve-pairings-success - (types/deserialize %)])))))) + (.. AsyncStorage + (getItem "status-keycard-pairings") + (then #(re-frame/dispatch [:keycard.callback/on-retrieve-pairings-success + (types/deserialize %)]))))) ;; TODO: Should act differently on different views (re-frame/reg-fx diff --git a/src/status_im/keycard/keycard.cljs b/src/status_im/keycard/keycard.cljs index 0d47ccd789..da6cdde68e 100644 --- a/src/status_im/keycard/keycard.cljs +++ b/src/status_im/keycard/keycard.cljs @@ -1,6 +1,9 @@ (ns status-im.keycard.keycard) (defprotocol Keycard + (start-nfc [this args]) + (stop-nfc [this args]) + (set-nfc-message [this args]) (check-nfc-support [this args]) (check-nfc-enabled [this args]) (open-nfc-settings [this]) diff --git a/src/status_im/keycard/login.cljs b/src/status_im/keycard/login.cljs index 7bbe328d1a..260ea821d9 100644 --- a/src/status_im/keycard/login.cljs +++ b/src/status_im/keycard/login.cljs @@ -123,7 +123,7 @@ (and (zero? pin-retry-counter) (or (nil? puk-retry-counter) - (= 5 puk-retry-counter))) + (pos? puk-retry-counter))) nil #_(frozen-keycard-popup cofx) :else diff --git a/src/status_im/keycard/real_keycard.cljs b/src/status_im/keycard/real_keycard.cljs index adf1a35ef6..e70d0df9f8 100644 --- a/src/status_im/keycard/real_keycard.cljs +++ b/src/status_im/keycard/real_keycard.cljs @@ -5,11 +5,36 @@ [status-im.native-module.core :as status] [status-im.ethereum.core :as ethereum] [status-im.keycard.keycard :as keycard] - [taoensso.timbre :as log])) + [taoensso.timbre :as log] + [status-im.utils.platform :as platform])) + +(defonce event-emitter (if platform/ios? + (new (.-NativeEventEmitter rn) status-keycard) + (.-DeviceEventEmitter rn))) -(defonce event-emitter (.-DeviceEventEmitter rn)) (defonce active-listeners (atom [])) +(defn start-nfc [{:keys [on-success on-failure prompt-message]}] + (log/debug "start-nfc") + (.. status-keycard + (startNFC (str prompt-message)) + (then on-success) + (catch on-failure))) + +(defn stop-nfc [{:keys [on-success on-failure error-message]}] + (log/debug "stop-nfc") + (.. status-keycard + (stopNFC (str error-message)) + (then on-success) + (catch on-failure))) + +(defn set-nfc-message [{:keys [on-success on-failure status-message]}] + (log/debug "set-nfc-message") + (.. status-keycard + (setNFCMessage (str status-message)) + (then on-success) + (catch on-failure))) + (defn check-nfc-support [{:keys [on-success]}] (.. status-keycard nfcIsSupported @@ -24,7 +49,7 @@ (.openNfcSettings status-keycard)) (defn remove-event-listeners [] - (doseq [event ["keyCardOnConnected" "keyCardOnDisconnected"]] + (doseq [event ["keyCardOnConnected" "keyCardOnDisconnected", "keyCardOnNFCUserCancelled", "keyCardOnNFCTimeout"]] (.removeAllListeners ^js event-emitter event))) (defn remove-event-listener @@ -39,6 +64,14 @@ [callback] (.addListener ^js event-emitter "keyCardOnDisconnected" callback)) +(defn on-nfc-user-cancelled + [callback] + (.addListener ^js event-emitter "keyCardOnNFCUserCancelled" callback)) + +(defn on-nfc-timeout + [callback] + (.addListener ^js event-emitter "keyCardOnNFCTimeout" callback)) + (defn on-nfc-enabled [callback] (.addListener ^js event-emitter "keyCardOnNFCEnabled" callback)) @@ -54,6 +87,8 @@ (reset! active-listeners [(on-card-connected (:on-card-connected args)) (on-card-disconnected (:on-card-disconnected args)) + (on-nfc-user-cancelled (:on-nfc-user-cancelled args)) + (on-nfc-timeout (:on-nfc-timeout args)) (on-nfc-enabled (:on-nfc-enabled args)) (on-nfc-disabled (:on-nfc-disabled args))])) @@ -226,6 +261,12 @@ (defrecord RealKeycard [] keycard/Keycard + (keycard/start-nfc [this args] + (start-nfc args)) + (keycard/stop-nfc [this args] + (stop-nfc args)) + (keycard/set-nfc-message [this args] + (set-nfc-message args)) (keycard/check-nfc-support [this args] (check-nfc-support args)) (keycard/check-nfc-enabled [this args] diff --git a/src/status_im/keycard/recovery.cljs b/src/status_im/keycard/recovery.cljs index 4dd7823e03..acf647d2f4 100644 --- a/src/status_im/keycard/recovery.cljs +++ b/src/status_im/keycard/recovery.cljs @@ -215,6 +215,7 @@ (update :instance-uid #(get-in db [:keycard :multiaccount :instance-uid] %)))) (assoc-in [:keycard :multiaccount-wallet-address] (:wallet-address account-data)) (assoc-in [:keycard :multiaccount-whisper-public-key] (:whisper-public-key account-data)) + (assoc-in [:keycard :pin :status] nil) (assoc-in [:keycard :application-info :key-uid] (ethereum/normalized-hex (:key-uid account-data))) (update :keycard dissoc :recovery-phrase) @@ -246,6 +247,7 @@ (fx/merge cofx {:db (-> db (assoc-in [:keycard :multiaccount :instance-uid] instance-uid) + (assoc-in [:keycard :pin :status] :verifying) (assoc-in [:keycard :secrets] {:pairing pairing' :paired-on (utils.datetime/timestamp)})) :keycard/get-keys {:pairing pairing' diff --git a/src/status_im/keycard/sign.cljs b/src/status_im/keycard/sign.cljs index 77bb37db22..de150c72a8 100644 --- a/src/status_im/keycard/sign.cljs +++ b/src/status_im/keycard/sign.cljs @@ -198,20 +198,20 @@ [{:keys [db] :as cofx} error] (log/debug "[keycard] sign error: " error) (let [tag-was-lost? (common/tag-lost? (:error error)) - pin-retries (get-in db [:keycard :application-info :pin-retry-counter])] + pin-retries (common/pin-retries (:error error))] (when-not tag-was-lost? - (if (re-matches common/pin-mismatch-error (:error error)) + (if (not (nil? pin-retries)) (fx/merge cofx {:db (-> db - (assoc-in [:keycard :application-info :pin-retry-counter] (dec pin-retries)) - (update-in [:keycard :pin] merge {:status :error - :sign [] - :error-label :t/pin-mismatch}) + (assoc-in [:keycard :application-info :pin-retry-counter] pin-retries) + (update-in [:keycard :pin] assoc + :status :error + :sign [] + :error-label :t/pin-mismatch) (assoc-in [:signing/sign :keycard-step] :pin))} (common/hide-connection-sheet) - (common/get-application-info (common/get-pairing db) nil) - (when (zero? (dec pin-retries)) - (common/frozen-keycard-popup))) + (when (zero? pin-retries) (common/frozen-keycard-popup))) + (fx/merge cofx (common/hide-connection-sheet) (common/show-wrong-keycard-alert true)))))) diff --git a/src/status_im/keycard/simulated_keycard.cljs b/src/status_im/keycard/simulated_keycard.cljs index d0469af3ab..6e349cac6b 100644 --- a/src/status_im/keycard/simulated_keycard.cljs +++ b/src/status_im/keycard/simulated_keycard.cljs @@ -14,6 +14,7 @@ (def initial-state {:card-connected? false + :nfc-started? false :application-info {:initialized? false}}) (defonce state (atom initial-state)) @@ -68,6 +69,16 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(defn start-nfc [{:keys [on-success]}] + (when (get @state :card-connected?) (connect-card)) + (later #(on-success true))) + +(defn stop-nfc [{:keys [on-success]}] + (later #(on-success true))) + +(defn set-nfc-message [{:keys [on-success]}] + (later #(on-success true))) + (defn check-nfc-support [{:keys [on-success]}] (later #(on-success true))) @@ -87,18 +98,22 @@ id)) (defn register-card-events [args] + (log/debug "register-card-events") (on-card-connected (:on-card-connected args)) (on-card-disconnected (:on-card-disconnected args))) (defn remove-event-listener [id] + (log/debug "remove-event-listener") (swap! state update :on-card-connected dissoc id) (swap! state update :on-card-disconnected dissoc id)) (defn remove-event-listeners [] + (log/debug "remove-event-listeners") (swap! state dissoc :on-card-connected) (swap! state dissoc :on-card-disconnected)) (defn get-application-info [{:keys [on-success]}] + (log/debug "get-application-info") (later #(on-success (get @state :application-info)))) (defn install-applet [_]) @@ -390,6 +405,15 @@ (defrecord SimulatedKeycard [] keycard/Keycard + (keycard/start-nfc [this args] + (log/debug "simulated card start-nfc") + (start-nfc args)) + (keycard/stop-nfc [this args] + (log/debug "simulated card stop-nfc") + (stop-nfc args)) + (keycard/set-nfc-message [this args] + (log/debug "simulated card set-nfc-message") + (set-nfc-message args)) (keycard/check-nfc-support [this args] (log/debug "simulated card check-nfc-support") (check-nfc-support args)) diff --git a/src/status_im/multiaccounts/create/core.cljs b/src/status_im/multiaccounts/create/core.cljs index 6016f2b502..f70ba87788 100644 --- a/src/status_im/multiaccounts/create/core.cljs +++ b/src/status_im/multiaccounts/create/core.cljs @@ -14,7 +14,6 @@ [status-im.navigation :as navigation] [status-im.utils.config :as config] [status-im.utils.fx :as fx] - [status-im.utils.platform :as platform] [status-im.utils.security :as security] [status-im.utils.signing-phrase.core :as signing-phrase] [status-im.utils.types :as types] @@ -30,17 +29,14 @@ (defn decrement-step [step] (let [inverted (map-invert step-kw-to-num)] (if (and (= step :create-code) - (or (not platform/android?) - (not (nfc/nfc-supported?)))) + (not (nfc/nfc-supported?))) :choose-key (inverted (dec (step-kw-to-num step)))))) (defn inc-step [step] (let [inverted (map-invert step-kw-to-num)] (if (and (= step :choose-key) - (or (not (or platform/android? - config/keycard-test-menu-enabled?)) - (not (nfc/nfc-supported?)))) + (not (nfc/nfc-supported?))) :create-code (inverted (inc (step-kw-to-num step)))))) diff --git a/src/status_im/multiaccounts/recover/core.cljs b/src/status_im/multiaccounts/recover/core.cljs index dae5736eed..1071bd4ed5 100644 --- a/src/status_im/multiaccounts/recover/core.cljs +++ b/src/status_im/multiaccounts/recover/core.cljs @@ -14,11 +14,9 @@ [status-im.utils.fx :as fx] [status-im.utils.security :as security] [status-im.utils.types :as types] - [status-im.utils.platform :as platform] [status-im.utils.utils :as utils] [status-im.bottom-sheet.core :as bottom-sheet] - [taoensso.timbre :as log] - [status-im.utils.config :as config])) + [taoensso.timbre :as log])) (defn existing-account? [multiaccounts key-uid] @@ -234,9 +232,7 @@ assoc :step :select-key-storage :forward-action :multiaccounts.recover/select-storage-next-pressed :selected-storage-type :default)} - (if (and (or platform/android? - config/keycard-test-menu-enabled?) - (nfc/nfc-supported?)) + (if (nfc/nfc-supported?) (navigation/navigate-to-cofx :recover-multiaccount-select-storage nil) (select-storage-next-pressed)))) diff --git a/src/status_im/signing/core.cljs b/src/status_im/signing/core.cljs index 0c62cd2b49..10c5a55e42 100644 --- a/src/status_im/signing/core.cljs +++ b/src/status_im/signing/core.cljs @@ -9,6 +9,7 @@ [status-im.ethereum.tokens :as tokens] [status-im.keycard.common :as keycard.common] [status-im.i18n.i18n :as i18n] + [status-im.keycard.card :as keycard.card] [status-im.native-module.core :as status] [status-im.signing.keycard :as signing.keycard] [status-im.utils.fx :as fx] @@ -203,6 +204,8 @@ :formatted-data (if typed? (types/json->clj data) (ethereum/hex->text data)) :keycard-step (when pinless? :connect)})} (when pinless? + (keycard.card/start-nfc {:on-success #(re-frame/dispatch [:keycard.callback/start-nfc-success]) + :on-failure #(re-frame/dispatch [:keycard.callback/start-nfc-failure])}) (signing.keycard/hash-message {:data data :typed? true :on-completed #(re-frame/dispatch [:keycard/store-hash-and-sign-typed %])}))) diff --git a/src/status_im/ui/screens/intro/views.cljs b/src/status_im/ui/screens/intro/views.cljs index 7962f64ea1..a1b64f158f 100644 --- a/src/status_im/ui/screens/intro/views.cljs +++ b/src/status_im/ui/screens/intro/views.cljs @@ -12,11 +12,9 @@ [status-im.ui.components.react :as react] [status-im.ui.components.topbar :as topbar] [status-im.ui.screens.intro.styles :as styles] - [status-im.utils.config :as config] [status-im.ui.components.toolbar :as toolbar] [status-im.utils.gfycat.core :as gfy] [status-im.utils.identicon :as identicon] - [status-im.utils.platform :as platform] [status-im.utils.security :as security] [status-im.utils.debounce :refer [dispatch-and-chill]] [quo.core :as quo] @@ -103,10 +101,7 @@ {:accessibility-label (keyword (str "select-storage-" type)) :on-press #(re-frame/dispatch [:intro-wizard/on-key-storage-selected - (if (or platform/android? - config/keycard-test-menu-enabled?) - type - :default)])} + type])} [react/view (assoc (styles/list-item selected?) :align-items :flex-start :padding-top 16 diff --git a/src/status_im/ui/screens/keycard/recovery/views.cljs b/src/status_im/ui/screens/keycard/recovery/views.cljs index 0ad463f571..78b2f9502d 100644 --- a/src/status_im/ui/screens/keycard/recovery/views.cljs +++ b/src/status_im/ui/screens/keycard/recovery/views.cljs @@ -135,7 +135,8 @@ (i18n/label :t/keycard-free-pairing-slots {:n free-pairing-slots})]])] [react/view [react/view {:padding 16 - :justify-content :center} + :justify-content :center + :margin-bottom 100} [quo/text-input {:on-change-text #(re-frame/dispatch [:keycard.onboarding.pair.ui/input-changed %]) :auto-focus true diff --git a/src/status_im/ui/screens/keycard/views.cljs b/src/status_im/ui/screens/keycard/views.cljs index cd15812165..8f475c3479 100644 --- a/src/status_im/ui/screens/keycard/views.cljs +++ b/src/status_im/ui/screens/keycard/views.cljs @@ -13,6 +13,7 @@ [status-im.ui.screens.chat.photos :as photos] [status-im.ui.screens.keycard.pin.views :as pin.views] [status-im.ui.screens.keycard.styles :as styles] + [status-im.ui.screens.intro.styles :as intro-styles] [status-im.constants :as constants] [status-im.keycard.login :as keycard.login] [status-im.ui.screens.keycard.frozen-card.view :as frozen-card.view]) @@ -200,10 +201,9 @@ [react/text (i18n/label :t/keycard-can-use-with-new-passcode)]] (when-not hide-login-actions? [react/view - {:style {:width 160 + {:style {:width 260 :margin-bottom 15}} - [react/view {:flex-direction :row - :height 52} + [react/view intro-styles/buttons-container [quo/button {:on-press #(re-frame/dispatch [::keycard.login/login-after-reset])} (i18n/label :t/open)]]])]) diff --git a/src/status_im/ui/screens/multiaccounts/key_storage/views.cljs b/src/status_im/ui/screens/multiaccounts/key_storage/views.cljs index c93fb543b3..7287a00e9f 100644 --- a/src/status_im/ui/screens/multiaccounts/key_storage/views.cljs +++ b/src/status_im/ui/screens/multiaccounts/key_storage/views.cljs @@ -103,7 +103,7 @@ (defview seed-phrase [] (letsubs [{:keys [seed-word-count seed-shape-invalid?]} [:multiaccounts/key-storage]] - [react/keyboard-avoiding-view {:flex 1} + [react/keyboard-avoiding-view {:style {:display :flex :flex 1 :flex-direction :column}} [local-topbar (i18n/label :t/enter-seed-phrase)] [multiaccounts.views/seed-phrase-input {:on-change-event [::multiaccounts.key-storage/seed-phrase-input-changed] @@ -114,14 +114,15 @@ :margin-bottom 8 :text-align :center}} (i18n/label :t/multiaccounts-recover-enter-phrase-text)] - [toolbar/toolbar {:show-border? true - :right [quo/button - {:type :secondary - :disabled (or seed-shape-invalid? - (nil? seed-shape-invalid?)) - :on-press #(re-frame/dispatch [::multiaccounts.key-storage/choose-storage-pressed]) - :after :main-icons/next} - (i18n/label :t/choose-storage)]}]])) + [react/keyboard-avoiding-view {:style {:flex 1}} + [toolbar/toolbar {:show-border? true + :right [quo/button + {:type :secondary + :disabled (or seed-shape-invalid? + (nil? seed-shape-invalid?)) + :on-press #(re-frame/dispatch [::multiaccounts.key-storage/choose-storage-pressed]) + :after :main-icons/next} + (i18n/label :t/choose-storage)]}]]])) (defn keycard-subtitle [] [react/view diff --git a/src/status_im/ui/screens/multiaccounts/recover/views.cljs b/src/status_im/ui/screens/multiaccounts/recover/views.cljs index c5698b981f..435bf8e2e6 100644 --- a/src/status_im/ui/screens/multiaccounts/recover/views.cljs +++ b/src/status_im/ui/screens/multiaccounts/recover/views.cljs @@ -10,7 +10,6 @@ [status-im.utils.security] [status-im.ui.components.colors :as colors] [quo.core :as quo] - [status-im.utils.platform :as platform] [status-im.react-native.resources :as resources] [status-im.ui.components.icons.icons :as icons])) @@ -52,7 +51,6 @@ ;; Show manage storage link when on login screen, only on android devices ;; and the selected account is not paired with keycard (when (and (= view-id :login) - platform/android? (not acc-to-login-keycard-pairing)) [quo/list-item {:theme :accent @@ -67,23 +65,21 @@ :accessibility-label :enter-seed-phrase-button :icon :main-icons/text :on-press #(hide-sheet-and-dispatch [::multiaccounts.recover/enter-phrase-pressed])}] - (when (or platform/android? - config/keycard-test-menu-enabled?) - [quo/list-item - {:theme :accent - :title (i18n/label :t/recover-with-keycard) - :accessibility-label :recover-with-keycard-button - :icon [react/view {:border-width 1 - :border-radius 20 - :border-color colors/blue-light - :background-color colors/blue-light - :justify-content :center - :align-items :center - :width 40 - :height 40} - [react/image {:source (resources/get-image :keycard-logo-blue) - :style {:width 24 :height 24}}]] - :on-press #(hide-sheet-and-dispatch [::keycard/recover-with-keycard-pressed])}]) + [quo/list-item + {:theme :accent + :title (i18n/label :t/recover-with-keycard) + :accessibility-label :recover-with-keycard-button + :icon [react/view {:border-width 1 + :border-radius 20 + :border-color colors/blue-light + :background-color colors/blue-light + :justify-content :center + :align-items :center + :width 40 + :height 40} + [react/image {:source (resources/get-image :keycard-logo-blue) + :style {:width 24 :height 24}}]] + :on-press #(hide-sheet-and-dispatch [::keycard/recover-with-keycard-pressed])}] (when config/database-management-enabled? [quo/list-item {:theme :accent :on-press #(hide-sheet-and-dispatch [:multiaccounts.login.ui/import-db-submitted]) diff --git a/src/status_im/ui/screens/profile/user/views.cljs b/src/status_im/ui/screens/profile/user/views.cljs index cf717aa551..bd956d0ba1 100644 --- a/src/status_im/ui/screens/profile/user/views.cljs +++ b/src/status_im/ui/screens/profile/user/views.cljs @@ -11,7 +11,6 @@ [status-im.ui.components.qr-code-viewer.views :as qr-code-viewer] [status-im.ui.components.react :as react] [status-im.ui.screens.profile.user.styles :as styles] - [status-im.utils.platform :as platform] [status-im.utils.config :as config] [status-im.utils.gfycat.core :as gfy] [status-im.utils.universal-links.utils :as universal-links] @@ -128,9 +127,7 @@ :accessibility-label :sync-settings-button :chevron true :on-press #(re-frame/dispatch [:navigate-to :sync-settings])}] - (when (and (or platform/android? - config/keycard-test-menu-enabled?) - keycard-pairing) + (when keycard-pairing [quo/list-item {:icon :main-icons/keycard :title (i18n/label :t/keycard) diff --git a/src/status_im/ui/screens/signing/views.cljs b/src/status_im/ui/screens/signing/views.cljs index 549c5a0c3f..11d67a3a31 100644 --- a/src/status_im/ui/screens/signing/views.cljs +++ b/src/status_im/ui/screens/signing/views.cljs @@ -16,6 +16,7 @@ [status-im.ui.screens.signing.sheets :as sheets] [status-im.ethereum.tokens :as tokens] [status-im.utils.types :as types] + [status-im.utils.platform :as platform] [clojure.string :as string] [quo.core :as quo] [quo.gesture-handler :as gh] @@ -107,8 +108,9 @@ enter-step [:keycard/pin-enter-step] status [:keycard/pin-status] retry-counter [:keycard/retry-counter]] - (let [enter-step (or enter-step :sign)] - [react/view + (let [enter-step (or enter-step :sign) + margin-bottom (if platform/ios? 40 0)] + [react/view {:margin-bottom margin-bottom} [pin.views/pin-view {:pin pin :retry-counter retry-counter diff --git a/src/status_im/ui/screens/wallet/add_new/views.cljs b/src/status_im/ui/screens/wallet/add_new/views.cljs index c33ad83692..b379ce1a27 100644 --- a/src/status_im/ui/screens/wallet/add_new/views.cljs +++ b/src/status_im/ui/screens/wallet/add_new/views.cljs @@ -124,7 +124,7 @@ [topbar/topbar {:navigation :none :right-accessories - [{:label :t/cancel + [{:label (i18n/label :t/cancel) :on-press #(re-frame/dispatch [:keycard/new-account-pin-sheet-hide])}]}] [pin.views/pin-view {:pin pin diff --git a/yarn.lock b/yarn.lock index dd2d7d234d..f1a537ca3a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6751,9 +6751,9 @@ react-native-splash-screen@^3.2.0: resolved "https://registry.yarnpkg.com/react-native-splash-screen/-/react-native-splash-screen-3.2.0.tgz#d47ec8557b1ba988ee3ea98d01463081b60fff45" integrity sha512-Ls9qiNZzW/OLFoI25wfjjAcrf2DZ975hn2vr6U9gyuxi2nooVbzQeFoQS5vQcbCt9QX5NY8ASEEAtlLdIa6KVg== -"react-native-status-keycard@git+https://github.com/status-im/react-native-status-keycard.git#v2.5.28": - version "2.5.28" - resolved "git+https://github.com/status-im/react-native-status-keycard.git#6d95a0d85dd1062d2565eec89d589ecb0a56282f" +"react-native-status-keycard@git+https://github.com/status-im/react-native-status-keycard.git#v2.5.30": + version "2.5.30" + resolved "git+https://github.com/status-im/react-native-status-keycard.git#958adb1e72dea1db989b4bf4663efe04ed8b2c0c" react-native-svg@^9.8.4: version "9.13.6"