diff --git a/Gemfile b/Gemfile index 2bb45933be..f1642ccab5 100644 --- a/Gemfile +++ b/Gemfile @@ -5,6 +5,6 @@ ruby "3.1.6" gem 'rubyzip', '2.3.2' gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1' gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0' -gem "fastlane", ">= 2.224.0" +gem "fastlane", ">= 2.225.0" plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') eval_gemfile(plugins_path) if File.exist?(plugins_path) diff --git a/Gemfile.lock b/Gemfile.lock index d3df06f3df..78274a7d7e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -24,20 +24,20 @@ GEM artifactory (3.0.17) atomos (0.1.3) aws-eventstream (1.3.0) - aws-partitions (1.991.0) - aws-sdk-core (3.209.1) + aws-partitions (1.992.0) + aws-sdk-core (3.211.0) aws-eventstream (~> 1, >= 1.3.0) - aws-partitions (~> 1, >= 1.651.0) + aws-partitions (~> 1, >= 1.992.0) aws-sigv4 (~> 1.9) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.94.0) - aws-sdk-core (~> 3, >= 3.207.0) + aws-sdk-kms (1.95.0) + aws-sdk-core (~> 3, >= 3.210.0) aws-sigv4 (~> 1.5) - aws-sdk-s3 (1.168.0) - aws-sdk-core (~> 3, >= 3.207.0) + aws-sdk-s3 (1.169.0) + aws-sdk-core (~> 3, >= 3.210.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.5) - aws-sigv4 (1.10.0) + aws-sigv4 (1.10.1) aws-eventstream (~> 1, >= 1.0.2) babosa (1.0.4) base64 (0.2.0) @@ -126,7 +126,7 @@ GEM faraday_middleware (1.2.1) faraday (~> 1.0) fastimage (2.3.1) - fastlane (2.224.0) + fastlane (2.225.0) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) @@ -142,6 +142,7 @@ GEM faraday-cookie_jar (~> 0.0.6) faraday_middleware (~> 1.0) fastimage (>= 2.1.0, < 3.0.0) + fastlane-sirp (>= 1.0.0) gh_inspector (>= 1.1.2, < 2.0.0) google-apis-androidpublisher_v3 (~> 0.3) google-apis-playcustomapp_v1 (~> 0.1) @@ -169,6 +170,8 @@ GEM xcpretty-travis-formatter (>= 0.0.3, < 2.0.0) fastlane-plugin-browserstack (0.3.3) rest-client (~> 2.0, >= 2.0.2) + fastlane-sirp (1.0.0) + sysrandom (~> 1.0) ffi (1.17.0) fourflusher (2.3.1) fuzzy_match (2.0.4) @@ -266,6 +269,7 @@ GEM simctl (1.6.10) CFPropertyList naturally + sysrandom (1.0.5) terminal-notifier (2.0.0) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) @@ -299,7 +303,7 @@ PLATFORMS DEPENDENCIES activesupport (>= 6.1.7.5, != 7.1.0) cocoapods (>= 1.13, != 1.15.1, != 1.15.0) - fastlane (>= 2.224.0) + fastlane (>= 2.225.0) fastlane-plugin-browserstack rubyzip (= 2.3.2) diff --git a/components/AddressInput.tsx b/components/AddressInput.tsx index e0487c1f28..4a98fb4c2b 100644 --- a/components/AddressInput.tsx +++ b/components/AddressInput.tsx @@ -3,9 +3,6 @@ import { Image, Keyboard, Platform, StyleSheet, Text, TextInput, View } from 're import { scanQrHelper } from '../helpers/scan-qr'; import loc from '../loc'; -import { useTheme } from './themes'; -import { showFilePickerAndReadFile, showImagePickerAndReadImage } from '../blue_modules/fs'; -import Clipboard from '@react-native-clipboard/clipboard'; import presentAlert from './Alert'; import ToolTipMenu from './TooltipMenu'; diff --git a/ios/Podfile.lock b/ios/Podfile.lock index ab9b6b6444..6dd041fc28 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1321,7 +1321,7 @@ PODS: - React - react-native-randombytes (3.6.1): - React-Core - - react-native-safe-area-context (4.11.0): + - react-native-safe-area-context (4.11.1): - React-Core - react-native-screen-capture (0.2.3): - React @@ -1660,7 +1660,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - RNReanimated (3.15.5): + - RNReanimated (3.16.0): - DoubleConversion - glog - hermes-engine @@ -1680,10 +1680,10 @@ PODS: - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - RNReanimated/reanimated (= 3.15.5) - - RNReanimated/worklets (= 3.15.5) + - RNReanimated/reanimated (= 3.16.0) + - RNReanimated/worklets (= 3.16.0) - Yoga - - RNReanimated/reanimated (3.15.5): + - RNReanimated/reanimated (3.16.0): - DoubleConversion - glog - hermes-engine @@ -1703,8 +1703,30 @@ PODS: - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core + - RNReanimated/reanimated/apple (= 3.16.0) - Yoga - - RNReanimated/worklets (3.15.5): + - RNReanimated/reanimated/apple (3.16.0): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - RNReanimated/worklets (3.16.0): - DoubleConversion - glog - hermes-engine @@ -1749,7 +1771,7 @@ PODS: - Yoga - RNShare (10.2.1): - React-Core - - RNSVG (15.7.1): + - RNSVG (15.8.0): - React-Core - RNVectorIcons (10.2.0): - DoubleConversion @@ -2164,7 +2186,7 @@ SPEC CHECKSUMS: react-native-menu: c30eb7a85d7b04d51945f61ea8a8986ed366ac5c react-native-qrcode-local-image: 35ccb306e4265bc5545f813e54cc830b5d75bcfc react-native-randombytes: 421f1c7d48c0af8dbcd471b0324393ebf8fe7846 - react-native-safe-area-context: 851c62c48dce80ccaa5637b6aa5991a1bc36eca9 + react-native-safe-area-context: 5141f11858b033636f1788b14f32eaba92cee810 react-native-screen-capture: 75db9b051c41fea47fa68665506e9257d4b1dadc react-native-secure-key-store: 910e6df6bc33cb790aba6ee24bc7818df1fe5898 react-native-tcp-socket: 8c3e8bef909ab06c557eeb95363fe029391ff09d @@ -2210,10 +2232,10 @@ SPEC CHECKSUMS: RNQuickAction: 6d404a869dc872cde841ad3147416a670d13fa93 RNRate: ef3bcff84f39bb1d1e41c5593d3eea4aab2bd73a RNReactNativeHapticFeedback: 0d591ea1e150f36cb96d868d4e8d77272243d78a - RNReanimated: 625f9e7f53cba61d7b3436e8e6e209d1dd4e6e9b + RNReanimated: f6a10979b3701f8029c71dbfe35d0ff4328dce4c RNScreens: 19719a9c326e925498ac3b2d35c4e50fe87afc06 RNShare: 0fad69ae2d71de9d1f7b9a43acf876886a6cb99c - RNSVG: 4590aa95758149fa27c5c83e54a6a466349a1688 + RNSVG: 8b1a777d54096b8c2a0fd38fc9d5a454332bbb4d RNVectorIcons: 6382277afab3c54658e9d555ee0faa7a37827136 RNWatch: fd30ca40a5b5ef58dcbc195638e68219bc455236 SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d diff --git a/package.json b/package.json index 9f535f8a54..9e670c5b2c 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "coinselect": "3.1.13", "crypto-js": "4.2.0", "dayjs": "1.11.13", - "detox": "20.27.4", + "detox": "20.27.5", "ecpairgrs": "2.0.1", "ecurve": "1.0.6", "electrum-client": "github:BlueWallet/rn-electrum-client#1bfe3cc", diff --git a/screen/send/Confirm.tsx b/screen/send/Confirm.tsx index 78feab8ee8..ab2b2a20bb 100644 --- a/screen/send/Confirm.tsx +++ b/screen/send/Confirm.tsx @@ -170,15 +170,31 @@ const Confirm: React.FC = () => { return bitcoin.address.toOutputScript(recipients[0].address, bitcoin.networks.bitcoin); }; - const send = async () => { + const handleSendTransaction = async () => { dispatch({ type: ActionType.SET_BUTTON_DISABLED, payload: true }); dispatch({ type: ActionType.SET_LOADING, payload: true }); try { - const txids2watch = []; + // Perform biometric authentication first + if (await isBiometricUseCapableAndEnabled()) { + if (!(await unlockWithBiometrics())) { + // Stop execution if biometric unlock fails + dispatch({ type: ActionType.SET_LOADING, payload: false }); + dispatch({ type: ActionType.SET_BUTTON_DISABLED, payload: false }); + return; + } + } + + const txidsToWatch = []; if (!state.isPayjoinEnabled) { - await broadcast(tx); + // Only broadcast the transaction after biometrics pass + const result = await broadcastTransaction(tx); + if (!result) { + dispatch({ type: ActionType.SET_LOADING, payload: false }); + dispatch({ type: ActionType.SET_BUTTON_DISABLED, payload: false }); + return; + } } else { - const payJoinWallet = new PayjoinTransaction(psbt, (txHex: string) => broadcast(txHex), wallet as HDSegwitBech32Wallet); + const payJoinWallet = new PayjoinTransaction(psbt, (txHex: string) => broadcastTransaction(txHex), wallet as HDSegwitBech32Wallet); const paymentScript = getPaymentScript(); if (!paymentScript) { throw new Error('Invalid payment script'); @@ -191,15 +207,15 @@ const Confirm: React.FC = () => { await payjoinClient.run(); const payjoinPsbt = payJoinWallet.getPayjoinPsbt(); if (payjoinPsbt) { - const tx2watch = payjoinPsbt.extractTransaction(); - txids2watch.push(tx2watch.getId()); + const txToWatch = payjoinPsbt.extractTransaction(); + txidsToWatch.push(txToWatch.getId()); } } const txid = bitcoin.Transaction.fromHex(tx).getId(); - txids2watch.push(txid); + txidsToWatch.push(txid); // @ts-ignore: Notifications has to be TSed - // Notifications.majorTomToGroundControl([], [], txids2watch); + // Notifications.majorTomToGroundControl([], [], txidsToWatch); let amount = 0; for (const recipient of recipients) { if (recipient.value) { @@ -227,16 +243,10 @@ const Confirm: React.FC = () => { } }; - const broadcast = async (transaction: string) => { + const broadcastTransaction = async (transaction: string) => { await BlueElectrum.ping(); await BlueElectrum.waitTillConnected(); - if (await isBiometricUseCapableAndEnabled()) { - if (!(await unlockWithBiometrics())) { - return; - } - } - const result = await wallet.broadcastTx(transaction); if (!result) { throw new Error(loc.errors.broadcast); @@ -330,7 +340,7 @@ const Confirm: React.FC = () => { {state.isLoading ? ( ) : ( -