diff --git a/android/app/build.gradle b/android/app/build.gradle index ac6b5041c..50e73d0a9 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -83,8 +83,8 @@ android { applicationId "to.bitkit" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 144 - versionName "1.0.8" + versionCode 152 + versionName "1.1.0" testBuildType System.getProperty('testBuildType', 'debug') testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' } diff --git a/ios/Podfile.lock b/ios/Podfile.lock index ceb4c843e..b029ec752 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1843,7 +1843,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - RNReanimated (3.17.1): + - RNReanimated (3.16.7): - DoubleConversion - glog - hermes-engine @@ -1855,34 +1855,7 @@ PODS: - React-Fabric - React-featureflags - React-graphics - - React-hermes - - React-ImageManager - - React-jsi - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - RNReanimated/reanimated (= 3.17.1) - - RNReanimated/worklets (= 3.17.1) - - Yoga - - RNReanimated/reanimated (3.17.1): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.11.18.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-hermes - React-ImageManager - - React-jsi - React-NativeModulesApple - React-RCTFabric - React-rendererdebug @@ -1890,9 +1863,10 @@ PODS: - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - RNReanimated/reanimated/apple (= 3.17.1) + - RNReanimated/reanimated (= 3.16.7) + - RNReanimated/worklets (= 3.16.7) - Yoga - - RNReanimated/reanimated/apple (3.17.1): + - RNReanimated/reanimated (3.16.7): - DoubleConversion - glog - hermes-engine @@ -1904,9 +1878,7 @@ PODS: - React-Fabric - React-featureflags - React-graphics - - React-hermes - React-ImageManager - - React-jsi - React-NativeModulesApple - React-RCTFabric - React-rendererdebug @@ -1914,8 +1886,9 @@ PODS: - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core + - RNReanimated/reanimated/apple (= 3.16.7) - Yoga - - RNReanimated/worklets (3.17.1): + - RNReanimated/reanimated/apple (3.16.7): - DoubleConversion - glog - hermes-engine @@ -1927,9 +1900,7 @@ PODS: - React-Fabric - React-featureflags - React-graphics - - React-hermes - React-ImageManager - - React-jsi - React-NativeModulesApple - React-RCTFabric - React-rendererdebug @@ -1937,9 +1908,8 @@ PODS: - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - RNReanimated/worklets/apple (= 3.17.1) - Yoga - - RNReanimated/worklets/apple (3.17.1): + - RNReanimated/worklets (3.16.7): - DoubleConversion - glog - hermes-engine @@ -1951,9 +1921,7 @@ PODS: - React-Fabric - React-featureflags - React-graphics - - React-hermes - React-ImageManager - - React-jsi - React-NativeModulesApple - React-RCTFabric - React-rendererdebug @@ -2367,77 +2335,77 @@ SPEC CHECKSUMS: glog: eb93e2f488219332457c3c4eafd2738ddc7e80b8 hermes-engine: b417d2b2aee3b89b58e63e23a51e02be91dc876d lottie-ios: a881093fab623c467d3bce374367755c272bdd59 - lottie-react-native: 35b7c1125a01f847fa5905d380e54951132d2450 + lottie-react-native: 3fd634de5c0cc095d36687d1b92b7c242d6103e8 MMKV: ce484c1ac40bf76d5f09a0195d2ec5b3d3840d55 MMKVCore: 1eb661c6c498ab88e3df9ce5d8ff94d05fcc0567 OpenSSL-Universal: b60a3702c9fea8b3145549d421fdb018e53ab7b4 - RCT-Folly: e78785aa9ba2ed998ea4151e314036f6c49e6d82 + RCT-Folly: 36fe2295e44b10d831836cc0d1daec5f8abcf809 RCTDeprecation: b2eecf2d60216df56bc5e6be5f063826d3c1ee35 RCTRequired: 78522de7dc73b81f3ed7890d145fa341f5bb32ea RCTTypeSafety: c135dd2bf50402d87fd12884cbad5d5e64850edd React: b229c49ed5898dab46d60f61ed5a0bfa2ee2fadb React-callinvoker: 2ac508e92c8bd9cf834cc7d7787d94352e4af58f - React-Core: 325b4f6d9162ae8b9a6ff42fe78e260eb124180d - React-CoreModules: 558041e5258f70cd1092f82778d07b8b2ff01897 - React-cxxreact: 8fff17cbe76e6a8f9991b59552e1235429f9c74b + React-Core: 13cdd1558d0b3f6d9d5a22e14d89150280e79f02 + React-CoreModules: b07a6744f48305405e67c845ebf481b6551b712a + React-cxxreact: 1055a86c66ac35b4e80bd5fb766aed5f494dfff4 React-debug: 0a5fcdbacc6becba0521e910c1bcfdb20f32a3f6 - React-defaultsnativemodule: 618dc50a0fad41b489997c3eb7aba3a74479fd14 - React-domnativemodule: 7ba599afb6c2a7ec3eb6450153e2efe0b8747e9a - React-Fabric: 252112089d2c63308f4cbfade4010b6606db67d1 - React-FabricComponents: 3c0f75321680d14d124438ab279c64ec2a3d13c4 - React-FabricImage: 728b8061cdec2857ca885fd605ee03ad43ffca98 + React-defaultsnativemodule: 4bb28fc97fee5be63a9ebf8f7a435cfe8ba69459 + React-domnativemodule: b36a11c2597243d7563985028c51ece988d8ae33 + React-Fabric: afc561718f25b2cd800b709d934101afe376a12c + React-FabricComponents: f4e0a4e18a27bf6d39cbf2a0b42f37a92fa4e37f + React-FabricImage: 37d8e8b672eda68a19d71143eb65148084efb325 React-featureflags: 19682e02ef5861d96b992af16a19109c3dfc1200 - React-featureflagsnativemodule: 23528c7e7d50782b7ef0804168ba40bbaf1e86ab - React-graphics: fefe48f71bfe6f48fd037f59e8277b12e91b6be1 - React-hermes: a9a0c8377627b5506ef9a7b6f60a805c306e3f51 - React-idlecallbacksnativemodule: 7e2b6a3b70e042f89cd91dbd73c479bb39a72a7e - React-ImageManager: e3300996ac2e2914bf821f71e2f2c92ae6e62ae2 - React-jserrorhandler: fa75876c662e5d7e79d6efc763fc9f4c88e26986 - React-jsi: f3f51595cc4c089037b536368f016d4742bf9cf7 - React-jsiexecutor: cca6c232db461e2fd213a11e9364cfa6fdaa20eb - React-jsinspector: 2bd4c9fddf189d6ec2abf4948461060502582bef - React-jsinspectortracing: a417d8a0ad481edaa415734b4dac81e3e5ee7dc6 - React-jsitracing: 1ff7172c5b0522cbf6c98d82bdbb160e49b5804e - React-logger: 018826bfd51b9f18e87f67db1590bc510ad20664 - React-Mapbuffer: 3c11cee7737609275c7b66bd0b1de475f094cedf - React-microtasksnativemodule: 843f352b32aacbe13a9c750190d34df44c3e6c2c - react-native-address-generator: e2148d02756126b3c6123894aa0af2a36528173f - react-native-biometrics: 43ed5b828646a7862dbc7945556446be00798e7d - react-native-blur: b06c3fe88680beac622d8d13b8c36ec15c50383b - react-native-image-picker: 037a6ccde76aa165446e1eaeb8866cb00f461916 - react-native-ldk: 2b77f83c7ca5809d1221288dfc4ee9ffef13f1a3 - react-native-mmkv: a6e08ad1b51b84af075f91798f8a92c878472265 - react-native-netinfo: cec9c4e86083cb5b6aba0e0711f563e2fbbff187 - react-native-pubky: 54d37810f35d9da11f8c199a6036e5729081951b - react-native-quick-base64: 99ddcde16a1bdab6aed68f375ab1ed5431946f13 - react-native-quick-crypto: 43bac82b1ce916efb64a6dccb8e020678d8d9c14 - react-native-restart: 0bc732f4461709022a742bb29bcccf6bbc5b4863 - react-native-safe-area-context: 3e33e7c43c8b74dba436a5a32651cb8d7064c740 - react-native-skia: 78dfcd1f530419f762a56988969f6430b4eabdc2 - react-native-tcp-socket: ae8abcfebc071216302a09d9ed1e375d4e877484 - React-NativeModulesApple: 88433b6946778bea9c153e27b671de15411bf225 - React-perflogger: 9e8d3c0dc0194eb932162812a168aa5dc662f418 - React-performancetimeline: 5a2d6efef52bdcefac079c7baa30934978acd023 + React-featureflagsnativemodule: d7cddf6d907b4e5ab84f9e744b7e88461656e48c + React-graphics: b0f78580cdaf5800d25437e3d41cc6c3d83b7aea + React-hermes: 71186f872c932e4574d5feb3ed754dda63a0b3bd + React-idlecallbacksnativemodule: dd2af19cdd3bc55149d17a2409ed72b694dfbe9c + React-ImageManager: a77dde8d5aa6a2b6962c702bf3a47695ef0aa32b + React-jserrorhandler: 9c14e89f12d5904257a79aaf84a70cd2e5ac07ba + React-jsi: 0775a66820496769ad83e629f0f5cce621a57fc7 + React-jsiexecutor: 2cf5ba481386803f3c88b85c63fa102cba5d769e + React-jsinspector: 8052d532bb7a98b6e021755674659802fb140cc5 + React-jsinspectortracing: bdd8fd0adcb4813663562e7874c5842449df6d8a + React-jsitracing: 2bab3bf55de3d04baf205def375fa6643c47c794 + React-logger: 795cd5055782db394f187f9db0477d4b25b44291 + React-Mapbuffer: 0502faf46cab8fb89cfc7bf3e6c6109b6ef9b5de + React-microtasksnativemodule: 663bc64e3a96c5fc91081923ae7481adc1359a78 + react-native-address-generator: d246f305d2b93bd82cdf9d2901344f240a8792db + react-native-biometrics: 352e5a794bfffc46a0c86725ea7dc62deb085bdc + react-native-blur: 5b2d13981ad6ce3d15339e135377336cb9be2d68 + react-native-image-picker: b779fcdd787275d7315555888e8f69b609a5c6ed + react-native-ldk: a69e33733ae66053cba652e5a2dacd7545b71402 + react-native-mmkv: 637830702ab3cb525fface3eab763ad9cee00617 + react-native-netinfo: f0a9899081c185db1de5bb2fdc1c88c202a059ac + react-native-pubky: e8080719ae924287d3d75aa22ef0c9db253a2ccc + react-native-quick-base64: 27bade09b88268e7ed63121def711e55fb4aef82 + react-native-quick-crypto: 8ed2e6b19357620772d1886a7c21b53c1947b4e0 + react-native-restart: 7595693413fe3ca15893702f2c8306c62a708162 + react-native-safe-area-context: 849d7df29ecb2a7155c769c0b76849ba952c2aa3 + react-native-skia: d646e9b3a4991b264426c8cd8ca1dbcb5cbebd4c + react-native-tcp-socket: e724380c910c2e704816ec817ed28f1342246ff7 + React-NativeModulesApple: 16fbd5b040ff6c492dacc361d49e63cba7a6a7a1 + React-perflogger: ab51b7592532a0ea45bf6eed7e6cae14a368b678 + React-performancetimeline: bc2e48198ec814d578ac8401f65d78a574358203 React-RCTActionSheet: 592674cf61142497e0e820688f5a696e41bf16dd - React-RCTAnimation: e6d669872f9b3b4ab9527aab283b7c49283236b7 - React-RCTAppDelegate: 1768f69e774410cbd0716465db9494acc823a63a - React-RCTBlob: 3e2dce94c56218becc4b32b627fc2293149f798d - React-RCTFabric: 4dd8a0d13c5e15acc48fac2996a7ef76fc7c5e6a - React-RCTFBReactNativeSpec: b2aeef7ea8755ddfdf0c6ca1363ff6766a91080f - React-RCTImage: dc04b176c022d12a8f55ae7a7279b1e091066ae0 - React-RCTLinking: 88f5e37fe4f26fbc80791aa2a5f01baf9b9a3fd5 - React-RCTNetwork: f213693565efbd698b8e9c18d700a514b49c0c8e - React-RCTSettings: a2d32a90c45a3575568cad850abc45924999b8a5 - React-RCTText: 54cdcd1cbf6f6a91dc6317f5d2c2b7fc3f6bf7a0 - React-RCTVibration: 11dae0e7f577b5807bb7d31e2e881eb46f854fd4 + React-RCTAnimation: 8fbb8dba757b49c78f4db403133ab6399a4ce952 + React-RCTAppDelegate: 346f71ef725906ba8fac77c2fe9c6c9b89d09c96 + React-RCTBlob: f89b162d0fe6b570a18e755eb16cbe356d3c6d17 + React-RCTFabric: ae3cfd54caf162df6224c841466e4c1220f82b2b + React-RCTFBReactNativeSpec: ce1d60e8eae94c0adaa9acae24d26149c7fe181e + React-RCTImage: ccac9969940f170503857733f9a5f63578e106e1 + React-RCTLinking: d82427bbf18415a3732105383dff119131cadd90 + React-RCTNetwork: 12ad4d0fbde939e00251ca5ca890da2e6825cc3c + React-RCTSettings: e7865bf9f455abf427da349c855f8644b5c39afa + React-RCTText: 2cdfd88745059ec3202a0842ea75a956c7d6f27d + React-RCTVibration: a3a1458e6230dfd64b3768ebc0a4aac430d9d508 React-rendererconsistency: 64e897e00d2568fd8dfe31e2496f80e85c0aaad1 - React-rendererdebug: 41ce452460c44bba715d9e41d5493a96de277764 + React-rendererdebug: a3f6d3ae7d2fa0035885026756281c07ee32479e React-rncore: 58748c2aa445f56b99e5118dad0aedb51c40ce9f - React-RuntimeApple: 7785ed0d8ae54da65a88736bb63ca97608a6d933 - React-RuntimeCore: 6029ea70bc77f98cfd43ebe69217f14e93ba1f12 + React-RuntimeApple: f0fda7bacabd32daa099cfda8f07466c30acd149 + React-RuntimeCore: 683ee0b6a76d4b4bf6fbf83a541895b4887cc636 React-runtimeexecutor: a188df372373baf5066e6e229177836488799f80 - React-RuntimeHermes: a264609c28b796edfffc8ae4cb8fad1773ab948b - React-runtimescheduler: 23ec3a1e0fb1ec752d1a9c1fb15258c30bfc7222 + React-RuntimeHermes: 907c8e9bec13ea6466b94828c088c24590d4d0b6 + React-runtimescheduler: a2e2a39125dd6426b5d8b773f689d660cd7c5f60 React-timing: bb220a53a795ed57976a4855c521f3de2f298fe5 React-utils: 3b054aaebe658fc710a8d239d0e4b9fd3e0b78f9 ReactAppDependencyProvider: a1fb08dfdc7ebc387b2e54cfc9decd283ed821d8 @@ -2455,13 +2423,13 @@ SPEC CHECKSUMS: RNQrGenerator: afacf12b55dfba0e3aaca963eec23691e8426431 RNQuickAction: c2c8f379e614428be0babe4d53a575739667744d RNReactNativeHapticFeedback: f9cfb40676f21a52e9e172648d033f539156a5ec - RNReanimated: cdbe5dfe73c9143df3f750ff547a758eb16d2ab8 + RNReanimated: f999fb5f61876de2729bc4863f036dd5841200fc RNScreens: 96fe858d87d26c3f46f0696f9e8824ce33a05aa7 RNShare: b1660f26d8bc57cbf9acf11872a8eb2f3ecf4825 RNSVG: e1b90420e46f8923da4b5023963afd4964d0d12a RNZipArchive: f4a5af907d1581e995c879e34799be35c6bc3e21 SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 - sodium-react-native-direct: daae90d1cfeea4837002395183ade1cac0d49795 + sodium-react-native-direct: b1a221d1fd27faafcb70a373ba6928a354e04cf6 SSZipArchive: c69881e8ac5521f0e622291387add5f60f30f3c4 Yoga: afd04ff05ebe0121a00c468a8a3c8080221cb14c ZXingObjC: 8898711ab495761b2dbbdec76d90164a6d7e14c5 diff --git a/ios/bitkit.xcodeproj/project.pbxproj b/ios/bitkit.xcodeproj/project.pbxproj index cf5697294..a79397a55 100644 --- a/ios/bitkit.xcodeproj/project.pbxproj +++ b/ios/bitkit.xcodeproj/project.pbxproj @@ -170,10 +170,6 @@ attributes = { LastUpgradeCheck = 1400; TargetAttributes = { - 00E356ED1AD99517003FC87E = { - CreatedOnToolsVersion = 6.2; - TestTargetID = 13B07F861A680F5B00A75B9A; - }; 13B07F861A680F5B00A75B9A = { LastSwiftMigration = 1120; }; @@ -311,7 +307,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIconOrange; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 144; + CURRENT_PROJECT_VERSION = 152; DEVELOPMENT_TEAM = KYH47R284B; ENABLE_BITCODE = NO; INFOPLIST_FILE = bitkit/Info.plist; @@ -322,7 +318,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.8; + MARKETING_VERSION = 1.1.0; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -343,7 +339,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIconOrange; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 144; + CURRENT_PROJECT_VERSION = 152; DEVELOPMENT_TEAM = KYH47R284B; ENABLE_BITCODE = NO; INFOPLIST_FILE = bitkit/Info.plist; @@ -354,7 +350,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.8; + MARKETING_VERSION = 1.1.0; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", diff --git a/package.json b/package.json index 23ae5f156..ca64c3ff4 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "react-native-quick-base64": "2.1.2", "react-native-quick-bip39": "0.0.9", "react-native-quick-crypto": "0.7.12", - "react-native-reanimated": "3.17.1", + "react-native-reanimated": "3.16.7", "react-native-reanimated-carousel": "4.0.2", "react-native-restart": "0.0.27", "react-native-safe-area-context": "5.2.0", diff --git a/src/hooks/useWeatherWidget.ts b/src/hooks/useWeatherWidget.ts index 828459b3b..012778779 100644 --- a/src/hooks/useWeatherWidget.ts +++ b/src/hooks/useWeatherWidget.ts @@ -3,6 +3,7 @@ import { __E2E__ } from '../constants/env'; import { widgetsCache } from '../storage/widgets-cache'; import { refreshOnchainFeeEstimates } from '../store/utils/fees'; import { getDisplayValues, getFiatDisplayValues } from '../utils/displayValues'; +import { useCurrency } from './displayValues'; type TBlockFeeRates = { avgHeight: number; @@ -107,6 +108,7 @@ const calculateCondition = ( }; const useWeatherWidget = (): TWidgetState => { + const { fiatTicker } = useCurrency(); const [state, setState] = useState(() => { const cached = getCachedData(); return cached @@ -145,7 +147,7 @@ const useWeatherWidget = (): TWidgetState => { // Total fee based on average native segwit transaction of 140 vBytes const avgFee = fees.normal * VBYTES_SIZE; - const dv = getDisplayValues({ satoshis: avgFee }); + const dv = getDisplayValues({ satoshis: avgFee, currency: fiatTicker }); const currentFee = `${dv.fiatSymbol} ${dv.fiatFormatted}`; const data = { condition, currentFee, nextBlockFee: fees.fast }; @@ -170,7 +172,7 @@ const useWeatherWidget = (): TWidgetState => { clearInterval(interval); abortController.abort(); }; - }, []); + }, [fiatTicker]); return state; }; diff --git a/src/screens/Settings/AddressViewer/index.tsx b/src/screens/Settings/AddressViewer/index.tsx index 7c39f9cdf..094fadd8b 100644 --- a/src/screens/Settings/AddressViewer/index.tsx +++ b/src/screens/Settings/AddressViewer/index.tsx @@ -257,11 +257,11 @@ const AddressViewer = (): ReactElement => { ); // The private key of the currently selected address to display qrcode data for. const [privateKey, setPrivateKey] = useState(undefined); - // Available array of UTXO's after checking for a balance. + // Available array of UTXOs after checking for a balance. const [utxos, setUtxos] = useState(); - // Total balance of available UTXO's after checking for a balance. + // Total balance of available UTXOs after checking for a balance. const [totalBalance, setTotalBalance] = useState(0); - // An array of UTXO's that are currently selected for spending. + // An array of UTXOs that are currently selected for spending. const [selectedUtxos, setSelectedUtxos] = useState([]); const [searchTxt, setSearchTxt] = useState(''); // Addresses filtered from a search query in onSearch. @@ -615,7 +615,7 @@ const AddressViewer = (): ReactElement => { ); /** - * This method will gather all selected UTXO's and setup an on-chain transaction. + * This method will gather all selected UTXOs and setup an on-chain transaction. * The on-chain transaction will retrieve and include the app's receiving address by default. * Finally, this method will prompt the sendNavigation modal to appear for the user to finalize and confirm the transaction. */ @@ -735,7 +735,7 @@ const AddressViewer = (): ReactElement => { }, [getMoreAddresses]); /** - * Retrieves the balance and UTXO's associated with all addresses of each type. + * Retrieves the balance and UTXOs associated with all addresses of each type. */ const onCheckBalance = useCallback(async (): Promise => { setIsCheckingBalances(true); diff --git a/src/screens/Settings/DevSettings/index.tsx b/src/screens/Settings/DevSettings/index.tsx index 22675c443..cac8aaff8 100644 --- a/src/screens/Settings/DevSettings/index.tsx +++ b/src/screens/Settings/DevSettings/index.tsx @@ -178,7 +178,7 @@ const DevSettings = ({ onPress: widgetsCache.clear, }, { - title: "Clear UTXO's", + title: 'Clear UTXOs', type: EItemType.button, onPress: clearUtxos, }, diff --git a/src/screens/Wallets/Receive/ReceiveDetails.tsx b/src/screens/Wallets/Receive/ReceiveDetails.tsx index 468ec566c..2001ad7db 100644 --- a/src/screens/Wallets/Receive/ReceiveDetails.tsx +++ b/src/screens/Wallets/Receive/ReceiveDetails.tsx @@ -1,6 +1,6 @@ import React, { ReactElement, memo, useState, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; -import { Image, Platform, StyleSheet, View } from 'react-native'; +import { Image, StyleSheet, View } from 'react-native'; import Animated, { FadeIn, FadeOut } from 'react-native-reanimated'; import BottomSheetNavigationHeader from '../../../components/BottomSheetNavigationHeader'; @@ -177,9 +177,7 @@ const ReceiveDetails = ({ + exiting={FadeOut}> {t('tags')} diff --git a/src/screens/Wallets/Send/CoinSelection.tsx b/src/screens/Wallets/Send/CoinSelection.tsx index e57773f1f..060dd2a53 100644 --- a/src/screens/Wallets/Send/CoinSelection.tsx +++ b/src/screens/Wallets/Send/CoinSelection.tsx @@ -1,7 +1,7 @@ import { BottomSheetScrollView } from '@gorhom/bottom-sheet'; import React, { ReactElement, memo, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { StyleSheet, View } from 'react-native'; +import { ScrollView, StyleSheet, View } from 'react-native'; import BottomSheetNavigationHeader from '../../../components/BottomSheetNavigationHeader'; import GradientView from '../../../components/GradientView'; @@ -9,7 +9,6 @@ import SafeAreaInset from '../../../components/SafeAreaInset'; import Switch from '../../../components/Switch'; import Tag from '../../../components/Tag'; import Button from '../../../components/buttons/Button'; -import { ScrollView } from '../../../styles/components'; import { BodyMSB, BodySSB, Caption13Up, Subtitle } from '../../../styles/text'; import { IUtxo } from 'beignet'; @@ -34,7 +33,7 @@ import { } from '../../../utils/wallet/transactions'; /** - * Some UTXO's may contain the same tx_hash. + * Some UTXOs may contain the same tx_hash. * So we include the tx_pos to ensure we can quickly distinguish. * @param {IUtxo} utxo * @return string @@ -65,9 +64,9 @@ const UtxoRow = ({ {tags && ( + centerContent={true}> {tags.map((t) => ( ))} @@ -94,7 +93,7 @@ const CoinSelection = ({ return transaction.inputs; }, [transaction.inputs]); - //Combine known utxo's with current transaction inputs in the event we're using utxo's from the address viewer. + //Combine known UTXOs with current transaction inputs in the event we're using UTXOs from the address viewer. const combinedUtxos = useMemo(() => { const combined: IUtxo[] = [...utxos, ...inputs]; diff --git a/src/store/index.ts b/src/store/index.ts index 1d3b54c70..f129ee7b6 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -32,7 +32,7 @@ const persistConfig = { key: 'root', storage: reduxStorage, // increase version after store shape changes - version: 53, + version: 54, stateReconciler: autoMergeLevel2, blacklist: ['receive', 'ui'], migrate: createMigrate(migrations, { debug: __ENABLE_MIGRATION_DEBUG__ }), diff --git a/src/store/migrations/index.ts b/src/store/migrations/index.ts index 00c837990..9d9897255 100644 --- a/src/store/migrations/index.ts +++ b/src/store/migrations/index.ts @@ -153,6 +153,33 @@ const migrations = { }, }; }, + 54: (state): PersistedState => { + // migrate widgets sort order + const newSortOrder = state.widgets.sortOrder + .map((item) => { + // Handle slashfeed items + if (item.includes('slashfeed:')) { + if (item.includes('Bitcoin Headlines')) return 'news'; + if (item.includes('Bitcoin Price')) return 'price'; + if (item.includes('Bitcoin Blocks')) return 'blocks'; + if (item.includes('Bitcoin Facts')) return 'facts'; + } + // Non-slashfeed items pass through unchanged + return item; + }) + .filter((item, index, arr) => { + // Remove duplicates + return arr.indexOf(item) === index; + }); + + return { + ...state, + widgets: { + ...state.widgets, + sortOrder: newSortOrder, + }, + }; + }, }; export default migrations; diff --git a/src/store/reselect/lightning.ts b/src/store/reselect/lightning.ts index 62b1adaaf..7a41f6a2a 100644 --- a/src/store/reselect/lightning.ts +++ b/src/store/reselect/lightning.ts @@ -166,8 +166,9 @@ export const claimableBalanceSelector = createSelector( return ( channel.closureReason && [ - EChannelClosureReason.HolderForceClosed, EChannelClosureReason.CounterpartyForceClosed, + EChannelClosureReason.ProcessingError, + EChannelClosureReason.HolderForceClosed, ].includes(channel.closureReason) ); }); diff --git a/src/store/utils/backup.ts b/src/store/utils/backup.ts index 1413e6c01..48bb3d24f 100644 --- a/src/store/utils/backup.ts +++ b/src/store/utils/backup.ts @@ -359,12 +359,12 @@ const performWidgetsRestore = async (): Promise< const backup = backupRes.value.data; const expectedBackupShape = initialWidgetsState; + // Skip restore if backup contains legacy slashfeed widgets // NOTE: can be removed after all users have updated from 1.0.9 - const hasSlashfeedWidgets = Object.keys(backup.widgets).some((key) => { - return key.includes('slashfeed'); - }); + const hasSlashfeedWidgets = + Object.keys(backup.widgets).some((key) => key.includes('slashfeed')) || + backup.sortOrder.some((key) => key.includes('slashfeed')); - // If the backup has slashfeed widgets, skip the restore. if (hasSlashfeedWidgets) { return ok({ backupExists: false }); } diff --git a/src/store/utils/ui.ts b/src/store/utils/ui.ts index 9ced50477..b79c4488a 100644 --- a/src/store/utils/ui.ts +++ b/src/store/utils/ui.ts @@ -19,7 +19,14 @@ export const showSheet = ( ): void => { const [id, params] = args; const sheetRef = getSheetRefOutsideComponent(id); - sheetRef.current?.present(params); + + if (!sheetRef.current) { + // sheetRef not ready, try again after a short wait + // NOTE: needed for deeplinks when app is closed + setTimeout(() => showSheet(...args), 100); + } else { + sheetRef.current?.present(params); + } }; export const closeSheet = async (id: SheetId): Promise => { diff --git a/src/utils/appState.ts b/src/utils/appState.ts new file mode 100644 index 000000000..70bde8a27 --- /dev/null +++ b/src/utils/appState.ts @@ -0,0 +1,26 @@ +import { AppState } from 'react-native'; + +export const appStateTracker = { + lastAppState: AppState.currentState, + lastBackgroundTime: 0, + + init() { + AppState.addEventListener('change', (nextAppState) => { + if (['background', 'inactive'].includes(nextAppState)) { + this.lastBackgroundTime = Date.now(); + } else if (['background', 'inactive'].includes(this.lastAppState)) { + // If we're leaving background state, update the time + this.lastBackgroundTime = Date.now(); + } + this.lastAppState = nextAppState; + }); + }, + + wasRecentlyInBackground(): boolean { + const currentState = AppState.currentState; + const inBackground = ['background', 'inactive'].includes(currentState); + const timeSinceLastBackground = Date.now() - this.lastBackgroundTime; + + return inBackground || timeSinceLastBackground < 3000; + }, +}; diff --git a/src/utils/i18n/locales/en/settings.json b/src/utils/i18n/locales/en/settings.json index 18a89ced4..58f28cbb5 100644 --- a/src/utils/i18n/locales/en/settings.json +++ b/src/utils/i18n/locales/en/settings.json @@ -430,31 +430,31 @@ "string": "Smallest First" }, "cs_max_description": { - "string": "Sort by and use smallest UTXO first. Potentially higher fee, but hides your largest UTXO's." + "string": "Sort by and use smallest UTXO first. Potentially higher fee, but hides your largest UTXOs." }, "cs_min": { "string": "Largest First" }, "cs_min_description": { - "string": "Sort by and use largest UTXO first. Potentially lower fee, but reveals your largest UTXO's." + "string": "Sort by and use largest UTXO first. Potentially lower fee, but reveals your largest UTXOs." }, "cs_consolidate": { "string": "Consolidate" }, "cs_consolidate_description": { - "string": "Use all available UTXO's regardless of the amount being sent. Use this method when fees are low in order to reduce fees in future transactions." + "string": "Use all available UTXOs regardless of the amount being sent. Use this method when fees are low in order to reduce fees in future transactions." }, "cs_first_in_first_out": { "string": "First-In First-Out" }, "cs_first_in_first_out_description": { - "string": "Use older UTXO's first (by block height)." + "string": "Use older UTXOs first (by block height)." }, "cs_last_in_last_out": { "string": "Last-In Last-Out" }, "cs_last_in_last_out_description": { - "string": "Use newer UTXO's first (by block height)." + "string": "Use newer UTXOs first (by block height)." }, "payment_preference": { "string": "Payment Preference" diff --git a/src/utils/i18n/locales/en/wallet.json b/src/utils/i18n/locales/en/wallet.json index d177623c0..e4f2b4703 100644 --- a/src/utils/i18n/locales/en/wallet.json +++ b/src/utils/i18n/locales/en/wallet.json @@ -228,7 +228,7 @@ "string": "Please increase your send amount to proceed." }, "send_coin_selection_output_to_small_description": { - "string": "Please remove UTXO's or increase your send amount to proceed." + "string": "Please remove UTXOs or increase your send amount to proceed." }, "send_fee_error_min": { "string": "Unable to decrease the fee any further." diff --git a/src/utils/lightning/index.ts b/src/utils/lightning/index.ts index dcdace8a0..aa6d49a83 100644 --- a/src/utils/lightning/index.ts +++ b/src/utils/lightning/index.ts @@ -1151,6 +1151,23 @@ export const waitForLdk = async (): Promise => { }); }; +export const waitForLdkChannels = async (): Promise => { + await tryNTimes({ + toTry: async () => { + const channelsResult = await ldk.listUsableChannels(); + if (channelsResult.isOk()) { + if (channelsResult.value.length > 0) { + return ok(channelsResult.value); + } + return err('no channels ready'); + } + return err('error getting channels'); + }, + times: 5, + interval: 1000, + }); +}; + /** * Returns the current LDK node id. * @returns {Promise>} @@ -1579,6 +1596,8 @@ export const payLightningInvoice = async ({ amount?: number; }): Promise> => { try { + await waitForLdkChannels(); + const addPeersResponse = await addPeers(); if (addPeersResponse.isErr()) { return err(addPeersResponse.error.message); diff --git a/src/utils/wallet/electrum.ts b/src/utils/wallet/electrum.ts index 488d10e38..45aa47b21 100644 --- a/src/utils/wallet/electrum.ts +++ b/src/utils/wallet/electrum.ts @@ -41,7 +41,7 @@ export const isConnectedElectrum = async (): Promise => { }; /** - * Formats a provided array of addresses a returns their UTXO's & balances. + * Formats a provided array of addresses a returns their UTXOs & balances. * @param {IAddress[]} allAddresses * @returns {Promise>} */ @@ -58,7 +58,7 @@ export const getAddressUtxos = async ({ }; /** - * Queries Electrum to return the available UTXO's and balance of the provided addresses. + * Queries Electrum to return the available UTXOs and balance of the provided addresses. * @param {TUnspentAddressScriptHashData} addresses */ export const listUnspentAddressScriptHashes = async ({ diff --git a/src/utils/wallet/index.ts b/src/utils/wallet/index.ts index bab7ff832..c0c6fa894 100644 --- a/src/utils/wallet/index.ts +++ b/src/utils/wallet/index.ts @@ -73,6 +73,7 @@ import { updateActivityList } from '../../store/utils/activity'; import { refreshOrdersList } from '../../store/utils/blocktank'; import { moveMetaIncTxTags } from '../../store/utils/metadata'; import { showNewOnchainTxPrompt } from '../../store/utils/ui'; +import { appStateTracker } from '../appState'; import BitcoinActions from '../bitcoin-actions'; import { btcToSats } from '../conversion'; import { promiseTimeout } from '../helpers'; @@ -90,6 +91,9 @@ import { BITKIT_WALLET_SEED_HASH_PREFIX } from './constants'; import { getBlockHeader } from './electrum'; import { getTransferForTx } from './transfer'; +// Initialize app state tracking +appStateTracker.init(); + bitcoin.initEccLib(ecc); const bip32 = BIP32Factory(ecc); @@ -197,7 +201,9 @@ const refreshBeignet = async (scanAllAddresses = false): Promise => { additionalAddresses, }); if (refreshWalletRes.isErr()) { - handleRefreshError(refreshWalletRes.error.message); + if (!appStateTracker.wasRecentlyInBackground()) { + handleRefreshError(refreshWalletRes.error.message); + } } else { // If refresh was successful, reset the throttled state. if (getStore().ui.isElectrumThrottled) { diff --git a/src/utils/wallet/transactions.ts b/src/utils/wallet/transactions.ts index d3f754379..267189bbb 100644 --- a/src/utils/wallet/transactions.ts +++ b/src/utils/wallet/transactions.ts @@ -40,7 +40,7 @@ import { } from './index'; /* - * Attempt to estimate the current fee for a given wallet and its UTXO's + * Attempt to estimate the current fee for a given wallet and its UTXOs */ export const getTotalFee = ({ satsPerByte, diff --git a/yarn.lock b/yarn.lock index 25dd211d5..ca3059a94 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5894,7 +5894,7 @@ __metadata: react-native-quick-base64: 2.1.2 react-native-quick-bip39: 0.0.9 react-native-quick-crypto: 0.7.12 - react-native-reanimated: 3.17.1 + react-native-reanimated: 3.16.7 react-native-reanimated-carousel: 4.0.2 react-native-restart: 0.0.27 react-native-safe-area-context: 5.2.0 @@ -12629,16 +12629,6 @@ __metadata: languageName: node linkType: hard -"react-native-is-edge-to-edge@npm:1.1.6": - version: 1.1.6 - resolution: "react-native-is-edge-to-edge@npm:1.1.6" - peerDependencies: - react: ">=18.2.0" - react-native: ">=0.73.0" - checksum: 4e07c1e34c01c8d50fd7c1d0460db06f6f0515197405230386a8ffb950cb724b10743af032310d1384df0a90059bfb8992ba2d93344ce86315315f0493feccc2 - languageName: node - linkType: hard - "react-native-keyboard-accessory@npm:0.1.16": version: 0.1.16 resolution: "react-native-keyboard-accessory@npm:0.1.16" @@ -12818,9 +12808,9 @@ __metadata: languageName: node linkType: hard -"react-native-reanimated@npm:3.17.1": - version: 3.17.1 - resolution: "react-native-reanimated@npm:3.17.1" +"react-native-reanimated@npm:3.16.7": + version: 3.16.7 + resolution: "react-native-reanimated@npm:3.16.7" dependencies: "@babel/plugin-transform-arrow-functions": ^7.0.0-0 "@babel/plugin-transform-class-properties": ^7.0.0-0 @@ -12833,12 +12823,11 @@ __metadata: "@babel/preset-typescript": ^7.16.7 convert-source-map: ^2.0.0 invariant: ^2.2.4 - react-native-is-edge-to-edge: 1.1.6 peerDependencies: "@babel/core": ^7.0.0-0 react: "*" react-native: "*" - checksum: fd05040a3fc6a8f4efb387657c0cd6c314e5e6b50f859e127d6891d8f81c65b020ddcf78615aa0074b4e134e450d38c40db916c544e1e2efa26c50c82815607d + checksum: 108095709cd7a3effc5b5d276d94e161b399bd2d06e32140834168a0051545401bb09228071447e5925571da3f86f335d2a82c76751cdae07f66faf50b25c97f languageName: node linkType: hard