From 7b09b3552297b299433cee8f74b5619eaeac70a4 Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Velez Date: Mon, 13 May 2024 13:08:47 -0400 Subject: [PATCH 01/19] REF: Single source of truth for useIsLargeScreen --- components/Context/LargeScreenProvider.tsx | 43 ++++++++++++++++++++ hooks/useIsLargeScreen.ts | 47 ++++------------------ index.js => index.tsx | 13 +++--- 3 files changed, 59 insertions(+), 44 deletions(-) create mode 100644 components/Context/LargeScreenProvider.tsx rename index.js => index.tsx (74%) diff --git a/components/Context/LargeScreenProvider.tsx b/components/Context/LargeScreenProvider.tsx new file mode 100644 index 000000000..5bab2d89d --- /dev/null +++ b/components/Context/LargeScreenProvider.tsx @@ -0,0 +1,43 @@ +import React, { createContext, useState, useEffect, useMemo, ReactNode } from 'react'; +import { Dimensions } from 'react-native'; +import { isTablet } from 'react-native-device-info'; +import { isDesktop } from '../../blue_modules/environment'; + +interface ILargeScreenContext { + isLargeScreen: boolean; +} + +export const LargeScreenContext = createContext(undefined); + +interface LargeScreenProviderProps { + children: ReactNode; +} + +export const LargeScreenProvider: React.FC = ({ children }) => { + const [windowWidth, setWindowWidth] = useState(Dimensions.get('window').width); + const screenWidth: number = useMemo(() => Dimensions.get('screen').width, []); + + useEffect(() => { + const updateScreenUsage = (): void => { + const newWindowWidth = Dimensions.get('window').width; + if (newWindowWidth !== windowWidth) { + setWindowWidth(newWindowWidth); + } + }; + + const subscription = Dimensions.addEventListener('change', updateScreenUsage); + return () => subscription.remove(); + }, [windowWidth]); + + const isLargeScreen: boolean = useMemo(() => { + const isRunningOnTablet = isTablet(); + const halfScreenWidth = windowWidth >= screenWidth / 2; + const condition = (isRunningOnTablet && halfScreenWidth) || isDesktop; + console.debug( + `LargeScreenProvider.isLargeScreen: width: ${windowWidth}, Screen width: ${screenWidth}, Is tablet: ${isTablet()}, Is large screen: ${condition}, isDesktkop: ${isDesktop}`, + ); + return condition; + }, [windowWidth, screenWidth]); + + return {children}; +}; diff --git a/hooks/useIsLargeScreen.ts b/hooks/useIsLargeScreen.ts index 8c706cade..14ec0cd2d 100644 --- a/hooks/useIsLargeScreen.ts +++ b/hooks/useIsLargeScreen.ts @@ -1,41 +1,10 @@ -import { useState, useEffect, useMemo } from 'react'; -import { Dimensions } from 'react-native'; -import { isTablet } from 'react-native-device-info'; -import { isDesktop } from '../blue_modules/environment'; +import { useContext } from 'react'; +import { LargeScreenContext } from '../components/Context/LargeScreenProvider'; -// Custom hook to determine if the screen is large -export const useIsLargeScreen = () => { - const [windowWidth, setWindowWidth] = useState(Dimensions.get('window').width); - const screenWidth = useMemo(() => Dimensions.get('screen').width, []); - - useEffect(() => { - const updateScreenUsage = () => { - const newWindowWidth = Dimensions.get('window').width; - if (newWindowWidth !== windowWidth) { - console.debug(`Window width changed: ${newWindowWidth}`); - setWindowWidth(newWindowWidth); - } - }; - - // Add event listener for dimension changes - const subscription = Dimensions.addEventListener('change', updateScreenUsage); - - // Cleanup function to remove the event listener - return () => { - subscription.remove(); - }; - }, [windowWidth]); - - // Determine if the window width is at least half of the screen width - const isLargeScreen = useMemo(() => { - const isRunningOnTablet = isTablet(); - const halfScreenWidth = windowWidth >= screenWidth / 2; - const condition = (isRunningOnTablet && halfScreenWidth) || isDesktop; - console.debug( - `Window width: ${windowWidth}, Screen width: ${screenWidth}, Is tablet: ${isTablet()}, Is large screen: ${condition}, isDesktkop: ${isDesktop}`, - ); - return condition; - }, [windowWidth, screenWidth]); - - return isLargeScreen; +export const useIsLargeScreen = (): boolean => { + const context = useContext(LargeScreenContext); + if (context === undefined) { + throw new Error('useIsLargeScreen must be used within a LargeScreenProvider'); + } + return context.isLargeScreen; }; diff --git a/index.js b/index.tsx similarity index 74% rename from index.js rename to index.tsx index 0783e0c0c..8055bca79 100644 --- a/index.js +++ b/index.tsx @@ -8,6 +8,7 @@ import { BlueStorageProvider } from './blue_modules/storage-context'; import A from './blue_modules/analytics'; import { SettingsProvider } from './components/Context/SettingsContext'; import { restoreSavedPreferredFiatCurrencyAndExchangeFromStorage } from './blue_modules/currency'; +import { LargeScreenProvider } from './components/Context/LargeScreenProvider'; if (!Error.captureStackTrace) { // captureStackTrace is only available when debugging @@ -21,11 +22,13 @@ const BlueAppComponent = () => { }, []); return ( - - - - - + + + + + + + ); }; From 51738e462850b67da9c0e229784e3eda80305f77 Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Velez Date: Mon, 13 May 2024 19:01:57 -0400 Subject: [PATCH 02/19] OPS: Revert --- index.tsx => index.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename index.tsx => index.js (100%) diff --git a/index.tsx b/index.js similarity index 100% rename from index.tsx rename to index.js From f7b3056360f0912e4d590b4949cc399f781f6143 Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Velez Date: Tue, 14 May 2024 19:02:08 -0400 Subject: [PATCH 03/19] FIX: Use existing file --- blue_modules/environment.ts | 5 +++-- components/Context/LargeScreenProvider.tsx | 8 +++----- screen/send/Broadcast.tsx | 5 +++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/blue_modules/environment.ts b/blue_modules/environment.ts index c6e5db789..1b6f6fd32 100644 --- a/blue_modules/environment.ts +++ b/blue_modules/environment.ts @@ -1,6 +1,7 @@ import { isTablet, getDeviceType } from 'react-native-device-info'; const isDesktop: boolean = getDeviceType() === 'Desktop'; +const isHandset: boolean = getDeviceType() === 'Handset'; +const isTabletDevice: boolean = isTablet(); -export const isHandset: boolean = getDeviceType() === 'Handset'; -export { isDesktop, isTablet }; +export { isDesktop, isTabletDevice, isHandset }; diff --git a/components/Context/LargeScreenProvider.tsx b/components/Context/LargeScreenProvider.tsx index 5bab2d89d..a831f4e09 100644 --- a/components/Context/LargeScreenProvider.tsx +++ b/components/Context/LargeScreenProvider.tsx @@ -1,7 +1,6 @@ import React, { createContext, useState, useEffect, useMemo, ReactNode } from 'react'; import { Dimensions } from 'react-native'; -import { isTablet } from 'react-native-device-info'; -import { isDesktop } from '../../blue_modules/environment'; +import { isDesktop, isTabletDevice } from '../../blue_modules/environment'; interface ILargeScreenContext { isLargeScreen: boolean; @@ -30,11 +29,10 @@ export const LargeScreenProvider: React.FC = ({ childr }, [windowWidth]); const isLargeScreen: boolean = useMemo(() => { - const isRunningOnTablet = isTablet(); const halfScreenWidth = windowWidth >= screenWidth / 2; - const condition = (isRunningOnTablet && halfScreenWidth) || isDesktop; + const condition = (isTabletDevice && halfScreenWidth) || isDesktop; console.debug( - `LargeScreenProvider.isLargeScreen: width: ${windowWidth}, Screen width: ${screenWidth}, Is tablet: ${isTablet()}, Is large screen: ${condition}, isDesktkop: ${isDesktop}`, + `LargeScreenProvider.isLargeScreen: width: ${windowWidth}, Screen width: ${screenWidth}, Is tablet: ${isTabletDevice}, Is large screen: ${condition}, isDesktkop: ${isDesktop}`, ); return condition; }, [windowWidth, screenWidth]); diff --git a/screen/send/Broadcast.tsx b/screen/send/Broadcast.tsx index 33d5358f0..774b6cc1c 100644 --- a/screen/send/Broadcast.tsx +++ b/screen/send/Broadcast.tsx @@ -21,7 +21,7 @@ import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/h import SafeArea from '../../components/SafeArea'; import presentAlert from '../../components/Alert'; import { scanQrHelper } from '../../helpers/scan-qr'; -import { isTablet } from 'react-native-device-info'; +import { isTabletDevice } from '../../blue_modules/environment'; const BROADCAST_RESULT = Object.freeze({ none: 'Input transaction hex', @@ -34,6 +34,7 @@ interface SuccessScreenProps { tx: string; } + const Broadcast: React.FC = () => { const { name } = useRoute(); const { navigate } = useNavigation(); @@ -117,7 +118,7 @@ const Broadcast: React.FC = () => { return ( - + {BROADCAST_RESULT.success !== broadcastResult && ( From 7df5c3721e5992dae75ee4d9524eb2dd679c17fb Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Velez Date: Tue, 14 May 2024 19:50:13 -0400 Subject: [PATCH 04/19] FIX: CI --- blue_modules/environment.ts | 3 +-- components/Context/LargeScreenProvider.tsx | 5 ++++- screen/send/Broadcast.tsx | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/blue_modules/environment.ts b/blue_modules/environment.ts index 1b6f6fd32..febd4c83f 100644 --- a/blue_modules/environment.ts +++ b/blue_modules/environment.ts @@ -2,6 +2,5 @@ import { isTablet, getDeviceType } from 'react-native-device-info'; const isDesktop: boolean = getDeviceType() === 'Desktop'; const isHandset: boolean = getDeviceType() === 'Handset'; -const isTabletDevice: boolean = isTablet(); -export { isDesktop, isTabletDevice, isHandset }; +export { isDesktop, isTablet, isHandset }; diff --git a/components/Context/LargeScreenProvider.tsx b/components/Context/LargeScreenProvider.tsx index a831f4e09..838b3af88 100644 --- a/components/Context/LargeScreenProvider.tsx +++ b/components/Context/LargeScreenProvider.tsx @@ -1,11 +1,14 @@ import React, { createContext, useState, useEffect, useMemo, ReactNode } from 'react'; import { Dimensions } from 'react-native'; -import { isDesktop, isTabletDevice } from '../../blue_modules/environment'; +import { isDesktop, isTablet } from '../../blue_modules/environment'; interface ILargeScreenContext { isLargeScreen: boolean; } + +const isTabletDevice: boolean = isTablet() + export const LargeScreenContext = createContext(undefined); interface LargeScreenProviderProps { diff --git a/screen/send/Broadcast.tsx b/screen/send/Broadcast.tsx index 774b6cc1c..d6e23f928 100644 --- a/screen/send/Broadcast.tsx +++ b/screen/send/Broadcast.tsx @@ -21,8 +21,9 @@ import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/h import SafeArea from '../../components/SafeArea'; import presentAlert from '../../components/Alert'; import { scanQrHelper } from '../../helpers/scan-qr'; -import { isTabletDevice } from '../../blue_modules/environment'; +import { isTablet } from '../../blue_modules/environment'; +const isTabletDevice = isTablet(); const BROADCAST_RESULT = Object.freeze({ none: 'Input transaction hex', pending: 'pending', @@ -34,7 +35,6 @@ interface SuccessScreenProps { tx: string; } - const Broadcast: React.FC = () => { const { name } = useRoute(); const { navigate } = useNavigation(); From fc73266b2fd14a1807a6341a3a2f8d0e8b59b11c Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Velez Date: Wed, 15 May 2024 07:43:13 -0400 Subject: [PATCH 05/19] Update App.tsx --- App.tsx | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/App.tsx b/App.tsx index 0772aed08..0fa875f95 100644 --- a/App.tsx +++ b/App.tsx @@ -9,6 +9,7 @@ import { NavigationProvider } from './components/NavigationProvider'; import { BlueStorageProvider } from './blue_modules/storage-context'; import MasterView from './MasterView'; import { SettingsProvider } from './components/Context/SettingsContext'; +import { LargeScreenProvider } from './components/Context/LargeScreenProvider'; const { SplashScreen } = NativeModules; const App = () => { @@ -22,17 +23,19 @@ const App = () => { }, []); return ( - - - - - - - - - - - + + + + + + + + + + + + + ); }; From 7b3b48e3b5b74f6232de4a8dec20d97ae6d77f69 Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Velez Date: Wed, 15 May 2024 08:05:42 -0400 Subject: [PATCH 06/19] REF: isTablet --- blue_modules/environment.ts | 3 ++- components/Context/LargeScreenProvider.tsx | 7 ++----- screen/send/Broadcast.tsx | 3 +-- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/blue_modules/environment.ts b/blue_modules/environment.ts index febd4c83f..987f92c9b 100644 --- a/blue_modules/environment.ts +++ b/blue_modules/environment.ts @@ -1,5 +1,6 @@ -import { isTablet, getDeviceType } from 'react-native-device-info'; +import { isTablet as checkIsTablet, getDeviceType } from 'react-native-device-info'; +const isTablet: boolean = checkIsTablet(); const isDesktop: boolean = getDeviceType() === 'Desktop'; const isHandset: boolean = getDeviceType() === 'Handset'; diff --git a/components/Context/LargeScreenProvider.tsx b/components/Context/LargeScreenProvider.tsx index 838b3af88..f39fef626 100644 --- a/components/Context/LargeScreenProvider.tsx +++ b/components/Context/LargeScreenProvider.tsx @@ -6,9 +6,6 @@ interface ILargeScreenContext { isLargeScreen: boolean; } - -const isTabletDevice: boolean = isTablet() - export const LargeScreenContext = createContext(undefined); interface LargeScreenProviderProps { @@ -33,9 +30,9 @@ export const LargeScreenProvider: React.FC = ({ childr const isLargeScreen: boolean = useMemo(() => { const halfScreenWidth = windowWidth >= screenWidth / 2; - const condition = (isTabletDevice && halfScreenWidth) || isDesktop; + const condition = (isTablet && halfScreenWidth) || isDesktop; console.debug( - `LargeScreenProvider.isLargeScreen: width: ${windowWidth}, Screen width: ${screenWidth}, Is tablet: ${isTabletDevice}, Is large screen: ${condition}, isDesktkop: ${isDesktop}`, + `LargeScreenProvider.isLargeScreen: width: ${windowWidth}, Screen width: ${screenWidth}, Is tablet: ${isTablet}, Is large screen: ${condition}, isDesktkop: ${isDesktop}`, ); return condition; }, [windowWidth, screenWidth]); diff --git a/screen/send/Broadcast.tsx b/screen/send/Broadcast.tsx index d6e23f928..83be8c227 100644 --- a/screen/send/Broadcast.tsx +++ b/screen/send/Broadcast.tsx @@ -23,7 +23,6 @@ import presentAlert from '../../components/Alert'; import { scanQrHelper } from '../../helpers/scan-qr'; import { isTablet } from '../../blue_modules/environment'; -const isTabletDevice = isTablet(); const BROADCAST_RESULT = Object.freeze({ none: 'Input transaction hex', pending: 'pending', @@ -118,7 +117,7 @@ const Broadcast: React.FC = () => { return ( - + {BROADCAST_RESULT.success !== broadcastResult && ( From bb575ee633d586796fde7388983ecefa6a07d538 Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Velez Date: Wed, 15 May 2024 10:08:22 -0400 Subject: [PATCH 07/19] Update setup.js --- tests/setup.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/setup.js b/tests/setup.js index b2803823f..fc9b4c650 100644 --- a/tests/setup.js +++ b/tests/setup.js @@ -59,6 +59,7 @@ jest.mock('react-native-device-info', () => { getDeviceType: jest.fn().mockReturnValue(false), hasGmsSync: jest.fn().mockReturnValue(true), hasHmsSync: jest.fn().mockReturnValue(false), + isTablet: jest.fn().mockReturnValue(false), }; }); From 1589dfa1956a527c22e9448b18840b86fd82f969 Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Velez Date: Wed, 15 May 2024 13:35:42 -0400 Subject: [PATCH 08/19] DEL: Artificial Splash delay --- android/app/src/main/AndroidManifest.xml | 13 +++------- .../bluewallet/bluewallet/SplashActivity.java | 26 ------------------- .../app/src/main/res/layout/splash_screen.xml | 13 ---------- blue_modules/storage-context.tsx | 15 ++++++----- 4 files changed, 12 insertions(+), 55 deletions(-) delete mode 100644 android/app/src/main/java/io/bluewallet/bluewallet/SplashActivity.java delete mode 100644 android/app/src/main/res/layout/splash_screen.xml diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 385824b24..04a9554ff 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -64,16 +64,7 @@ - - - - - - - - + + + diff --git a/android/app/src/main/java/io/bluewallet/bluewallet/SplashActivity.java b/android/app/src/main/java/io/bluewallet/bluewallet/SplashActivity.java deleted file mode 100644 index 161055463..000000000 --- a/android/app/src/main/java/io/bluewallet/bluewallet/SplashActivity.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.bluewallet.bluewallet; // Replace with your package name - -import android.content.Intent; -import android.os.Bundle; -import android.os.Handler; -import androidx.appcompat.app.AppCompatActivity; - -public class SplashActivity extends AppCompatActivity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.splash_screen); // Replace with your layout name - - int SPLASH_DISPLAY_LENGTH = 1000; // Splash screen duration in milliseconds - - new Handler().postDelayed(new Runnable() { - @Override - public void run() { - Intent mainIntent = new Intent(SplashActivity.this, MainActivity.class); - SplashActivity.this.startActivity(mainIntent); - SplashActivity.this.finish(); - } - }, SPLASH_DISPLAY_LENGTH); - } -} diff --git a/android/app/src/main/res/layout/splash_screen.xml b/android/app/src/main/res/layout/splash_screen.xml deleted file mode 100644 index c90f097b0..000000000 --- a/android/app/src/main/res/layout/splash_screen.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - diff --git a/blue_modules/storage-context.tsx b/blue_modules/storage-context.tsx index 6f79b3183..3bed3789b 100644 --- a/blue_modules/storage-context.tsx +++ b/blue_modules/storage-context.tsx @@ -73,12 +73,15 @@ export const BlueStorageProvider = ({ children }: { children: React.ReactNode }) const [reloadTransactionsMenuActionFunction, setReloadTransactionsMenuActionFunction] = useState<() => void>(() => {}); useEffect(() => { - setWallets(BlueApp.getWallets()); - - BlueElectrum.isDisabled().then(setIsElectrumDisabled); - if (walletsInitialized) { - BlueElectrum.connectMain(); - } + (async () => { + const isElectrumDisabledValue = await BlueElectrum.isDisabled(); + setIsElectrumDisabled(isElectrumDisabledValue); + if (walletsInitialized && wallets.length > 0 && !isElectrumDisabledValue) { + setWallets(BlueApp.getWallets()); + BlueElectrum.connectMain(); + } + })(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [walletsInitialized]); const saveToDisk = async (force: boolean = false) => { From 667dba4836466907e13888d3a158ff3fbf74872d Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Velez Date: Wed, 15 May 2024 15:53:08 -0400 Subject: [PATCH 09/19] Update AndroidManifest.xml --- android/app/src/main/AndroidManifest.xml | 151 ++++++++++++----------- 1 file changed, 77 insertions(+), 74 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 04a9554ff..7376d7788 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -7,50 +7,52 @@ android:required="false" /> - - - + + + - + + android:name=".MainApplication" + android:label="@string/app_name" + android:icon="@mipmap/ic_launcher" + android:roundIcon="@mipmap/ic_launcher_round" + android:allowBackup="false" + android:largeHeap="true" + android:extractNativeLibs="true" + android:usesCleartextTraffic="true" + android:supportsRtl="true" + android:theme="@style/AppTheme" + android:networkSecurityConfig="@xml/network_security_config"> - - - - - - - - - + + + + + - @@ -58,64 +60,65 @@ + android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationListenerService" + android:exported="false"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + From 7e6418316ac2762de1daecd76ed89ad319899df1 Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Velez Date: Wed, 15 May 2024 18:06:55 -0400 Subject: [PATCH 10/19] DEL: Splash iOS --- App.tsx | 12 +- MasterView.tsx | 11 +- class/wallets/lightning-ldk-wallet.ts | 316 ++++------------------- ios/BlueWallet.xcodeproj/project.pbxproj | 18 +- ios/BlueWallet/AppDelegate.mm | 18 -- ios/SplashScreen.m | 14 - ios/SplashScreen.swift | 39 --- screen/UnlockWith.tsx | 6 +- 8 files changed, 53 insertions(+), 381 deletions(-) delete mode 100644 ios/SplashScreen.m delete mode 100644 ios/SplashScreen.swift diff --git a/App.tsx b/App.tsx index 0772aed08..5f3b9bfb9 100644 --- a/App.tsx +++ b/App.tsx @@ -1,6 +1,6 @@ import 'react-native-gesture-handler'; // should be on top -import React, { useEffect } from 'react'; -import { NativeModules, Platform, useColorScheme } from 'react-native'; +import React from 'react'; +import { useColorScheme } from 'react-native'; import { NavigationContainer } from '@react-navigation/native'; import { SafeAreaProvider } from 'react-native-safe-area-context'; import { navigationRef } from './NavigationService'; @@ -9,18 +9,10 @@ import { NavigationProvider } from './components/NavigationProvider'; import { BlueStorageProvider } from './blue_modules/storage-context'; import MasterView from './MasterView'; import { SettingsProvider } from './components/Context/SettingsContext'; -const { SplashScreen } = NativeModules; const App = () => { const colorScheme = useColorScheme(); - useEffect(() => { - if (Platform.OS === 'ios') { - // Call hide to setup the listener on the native side - SplashScreen?.addObserver(); - } - }, []); - return ( diff --git a/MasterView.tsx b/MasterView.tsx index f12468d37..7bef9f3c9 100644 --- a/MasterView.tsx +++ b/MasterView.tsx @@ -1,22 +1,13 @@ import 'react-native-gesture-handler'; // should be on top -import React, { Suspense, lazy, useEffect } from 'react'; -import { NativeModules, Platform } from 'react-native'; +import React, { Suspense, lazy } from 'react'; import MainRoot from './navigation'; import { useStorage } from './blue_modules/storage-context'; import Biometric from './class/biometrics'; const CompanionDelegates = lazy(() => import('./components/CompanionDelegates')); -const { SplashScreen } = NativeModules; const MasterView = () => { const { walletsInitialized } = useStorage(); - useEffect(() => { - if (Platform.OS === 'ios') { - // Call hide to setup the listener on the native side - SplashScreen?.addObserver(); - } - }, []); - return ( <> diff --git a/class/wallets/lightning-ldk-wallet.ts b/class/wallets/lightning-ldk-wallet.ts index aab484a55..82d223c2f 100644 --- a/class/wallets/lightning-ldk-wallet.ts +++ b/class/wallets/lightning-ldk-wallet.ts @@ -1,24 +1,16 @@ -import * as bip39 from 'bip39'; -import * as bitcoin from 'bitcoinjs-lib'; -import bolt11 from 'bolt11'; -import RNFS from 'react-native-fs'; -import RnLdk from 'rn-ldk/src/index'; -import presentAlert from '../../components/Alert'; import { BitcoinUnit, Chain } from '../../models/bitcoinUnits'; -import { randomBytes } from '../rng'; -import SyncedAsyncStorage from '../synced-async-storage'; -import { HDSegwitBech32Wallet } from './hd-segwit-bech32-wallet'; import { LightningCustodianWallet } from './lightning-custodian-wallet'; +import { randomBytes } from '../rng'; +import * as bip39 from 'bip39'; +import { HDSegwitBech32Wallet } from './hd-segwit-bech32-wallet'; +import bolt11 from 'bolt11'; import { SegwitBech32Wallet } from './segwit-bech32-wallet'; +import presentAlert from '../../components/Alert'; +import * as bitcoin from 'bitcoinjs-lib'; export class LightningLdkWallet extends LightningCustodianWallet { - static readonly type = 'lightningLdk'; - static readonly typeReadable = 'Lightning LDK'; - // @ts-ignore: override - public readonly type = LightningLdkWallet.type; - // @ts-ignore: override - public readonly typeReadable = LightningLdkWallet.typeReadable; - + static type = 'lightningLdk'; + static typeReadable = 'Lightning LDK'; private _listChannels: any[] = []; private _listPayments: any[] = []; private _listInvoices: any[] = []; @@ -49,8 +41,8 @@ export class LightningLdkWallet extends LightningCustodianWallet { return pubkeyHex; } - constructor() { - super(); + constructor(props: any) { + super(props); this.preferredBalanceUnit = BitcoinUnit.SATS; this.chain = Chain.OFFCHAIN; this.user_invoices_raw = []; // compatibility with other lightning wallet class @@ -65,20 +57,16 @@ export class LightningLdkWallet extends LightningCustodianWallet { return false; } - async stop() { - return RnLdk.stop(); - } + async stop() {} async wipeLndDir() {} - async listPeers() { - return RnLdk.listPeers(); - } + async listPeers() {} async listChannels() { try { // exception might be in case of incompletely-started LDK. then just ignore and return cached version - this._listChannels = await RnLdk.listChannels(); + this._listChannels = []; } catch (_) {} return this._listChannels; @@ -89,7 +77,7 @@ export class LightningLdkWallet extends LightningCustodianWallet { } async getInfo() { - const identityPubkey = await RnLdk.getNodeId(); + const identityPubkey = ''; return { identityPubkey, }; @@ -104,15 +92,15 @@ export class LightningLdkWallet extends LightningCustodianWallet { } async fundingStateStepFinalize(txhex: string) { - return RnLdk.openChannelStep2(txhex); + return false; } async getMaturingBalance(): Promise { - return RnLdk.getMaturingBalance(); + return 0; } async getMaturingHeight(): Promise { - return RnLdk.getMaturingHeight(); + return 0; } /** @@ -121,16 +109,7 @@ export class LightningLdkWallet extends LightningCustodianWallet { * @return {Promise} */ async isStarted() { - let rez; - try { - rez = await Promise.race([new Promise(resolve => setTimeout(() => resolve('timeout'), 1000)), RnLdk.getNodeId()]); - } catch (_) {} - - if (rez === 'timeout' || !rez) { - return false; - } - - return true; + return false; } /** @@ -149,36 +128,10 @@ export class LightningLdkWallet extends LightningCustodianWallet { } async openChannel(pubkeyHex: string, host: string, amountSats: number, privateChannel: boolean) { - let triedToConnect = false; - let port = 9735; - - if (host.includes(':')) { - const splitted = host.split(':'); - host = splitted[0]; - port = +splitted[1]; - } - - for (let c = 0; c < 20; c++) { - const peers = await this.listPeers(); - if (peers.includes(pubkeyHex)) { - // all good, connected, lets open channel - return await RnLdk.openChannelStep1(pubkeyHex, +amountSats); - } - - if (!triedToConnect) { - triedToConnect = true; - await RnLdk.connectPeer(pubkeyHex, host, +port); - } - - await new Promise(resolve => setTimeout(resolve, 500)); // sleep - } - - throw new Error('timeout waiting for peer connection'); + return false; } - async connectPeer(pubkeyHex: string, host: string, port: number) { - return RnLdk.connectPeer(pubkeyHex, host, +port); - } + async connectPeer(pubkeyHex: string, host: string, port: number) {} async lookupNodeConnectionDetailsByPubkey(pubkey: string) { // first, trying cache: @@ -196,7 +149,7 @@ export class LightningLdkWallet extends LightningCustodianWallet { const ret = { pubkey, host: address.addr.split(':')[0], - port: parseInt(address.addr.split(':')[1], 10), + port: parseInt(address.addr.split(':')[1]), }; this._nodeConnectionDetailsCache[pubkey] = Object.assign({}, ret, { ts: +new Date() }); @@ -207,8 +160,8 @@ export class LightningLdkWallet extends LightningCustodianWallet { } } - getAddress(): string | false { - return false; + getAddress() { + return undefined; } getSecret() { @@ -234,9 +187,7 @@ export class LightningLdkWallet extends LightningCustodianWallet { return ret; } - getStorageNamespace() { - return RnLdk.getStorage().namespace; - } + getStorageNamespace() {} static async _decodeInvoice(invoice: string) { return bolt11.decode(invoice); @@ -246,41 +197,9 @@ export class LightningLdkWallet extends LightningCustodianWallet { return bitcoin.address.fromOutputScript(Buffer.from(scriptHex, 'hex')); } - async selftest() { - await RnLdk.getStorage().selftest(); - await RnLdk.selftest(); - } + async selftest() {} - async init() { - if (!this.getSecret()) return; - console.warn('starting ldk'); - - try { - // providing simple functions that RnLdk would otherwise rely on 3rd party APIs - RnLdk.provideDecodeInvoiceFunc(LightningLdkWallet._decodeInvoice); - RnLdk.provideScript2addressFunc(LightningLdkWallet._script2address); - const syncedStorage = new SyncedAsyncStorage(this.getEntropyHex()); - // await syncedStorage.selftest(); - // await RnLdk.selftest(); - // console.warn('selftest passed'); - await syncedStorage.synchronize(); - - RnLdk.setStorage(syncedStorage); - if (this._refundAddressScriptHex) { - await RnLdk.setRefundAddressScript(this._refundAddressScriptHex); - } else { - // fallback, unwrapping address from bip39 mnemonic we have - const address = this.unwrapFirstExternalAddressFromMnemonics(); - await this.setRefundAddress(address); - } - await RnLdk.start(this.getEntropyHex(), RNFS.DocumentDirectoryPath); - - this._execInBackground(this.reestablishChannels); - if (this.timeToCheckBlockchain()) this._execInBackground(this.checkBlockchain); - } catch (error: any) { - presentAlert({ message: 'LDK init error: ' + error.message }); - } - } + async init() {} unwrapFirstExternalAddressFromMnemonics() { if (this._unwrapFirstExternalAddressFromMnemonicsCache) return this._unwrapFirstExternalAddressFromMnemonicsCache; // cache hit @@ -297,52 +216,9 @@ export class LightningLdkWallet extends LightningCustodianWallet { return hd._getExternalWIFByIndex(0); } - async checkBlockchain() { - this._lastTimeBlockchainCheckedTs = +new Date(); - return RnLdk.checkBlockchain(); - } + async checkBlockchain() {} async payInvoice(invoice: string, freeAmount = 0) { - const decoded = this.decodeInvoice(invoice); - - // if its NOT zero amount invoice, we forcefully reset passed amount argument so underlying LDK code - // would extract amount from bolt11 - if (decoded.num_satoshis && parseInt(decoded.num_satoshis, 10) > 0) freeAmount = 0; - - if (await this.channelsNeedReestablish()) { - await this.reestablishChannels(); - await this.waitForAtLeastOneChannelBecomeActive(); - } - - const result = await RnLdk.payInvoice(invoice, freeAmount); - if (!result) throw new Error('Failed'); - - // ok, it was sent. now, waiting for an event that it was _actually_ paid: - for (let c = 0; c < 60; c++) { - await new Promise(resolve => setTimeout(resolve, 500)); // sleep - - for (const sentPayment of RnLdk.sentPayments || []) { - const paidHash = LightningLdkWallet.preimage2hash(sentPayment.payment_preimage); - if (paidHash === decoded.payment_hash) { - this._listPayments = this._listPayments || []; - this._listPayments.push( - Object.assign({}, sentPayment, { - memo: decoded.description || 'Lightning payment', - value: (freeAmount || decoded.num_satoshis) * -1, - received: +new Date(), - payment_preimage: sentPayment.payment_preimage, - payment_hash: decoded.payment_hash, - }), - ); - return; - } - } - - for (const failedPayment of RnLdk.failedPayments || []) { - if (failedPayment.payment_hash === decoded.payment_hash) throw new Error(JSON.stringify(failedPayment)); - } - } - // no? lets just throw timeout error throw new Error('Payment timeout'); } @@ -353,52 +229,12 @@ export class LightningLdkWallet extends LightningCustodianWallet { * but will never be acknowledged as 'established' by LDK until peer reconnects so that ldk & peer can negotiate and * agree that channel is now established */ - async reconnectPeersWithPendingChannels() { - const peers = await RnLdk.listPeers(); - const peers2reconnect: Record = {}; - if (this._listChannels) { - for (const channel of this._listChannels) { - if (!channel.is_funding_locked) { - // pending channel - if (!peers.includes(channel.remote_node_id)) peers2reconnect[channel.remote_node_id] = true; - } - } - } + async reconnectPeersWithPendingChannels() {} - for (const pubkey of Object.keys(peers2reconnect)) { - const { host, port } = await this.lookupNodeConnectionDetailsByPubkey(pubkey); - await this.connectPeer(pubkey, host, port); - } - } - - async getUserInvoices(limit: number | false = false) { + async getUserInvoices(limit = false) { const newInvoices: any[] = []; - let found = false; - // okay, so the idea is that `this._listInvoices` is a persistent storage of invoices, while - // `RnLdk.receivedPayments` is only a temp storage of emitted events - - // we iterate through all stored invoices - for (const invoice of this._listInvoices) { - const newInvoice = Object.assign({}, invoice); - - // iterate through events of received payments - for (const receivedPayment of RnLdk.receivedPayments || []) { - if (receivedPayment.payment_hash === invoice.payment_hash) { - // match! this particular payment was paid - newInvoice.ispaid = true; - newInvoice.value = Math.floor(parseInt(receivedPayment.amt, 10) / 1000); - found = true; - } - } - - newInvoices.push(newInvoice); - } - - // overwrite stored array if flag was set - if (found) this._listInvoices = newInvoices; - - return this._listInvoices; + return newInvoices; } isInvoiceGeneratedByWallet(paymentRequest: string) { @@ -409,36 +245,9 @@ export class LightningLdkWallet extends LightningCustodianWallet { return false; } - async addInvoice(amtSat: number, memo: string) { - if (await this.channelsNeedReestablish()) { - await this.reestablishChannels(); - await this.waitForAtLeastOneChannelBecomeActive(); - } + async addInvoice(amtSat: number, memo: string) {} - if (this.getReceivableBalance() < amtSat) throw new Error('You dont have enough inbound capacity'); - - const paymentRequest = await RnLdk.addInvoice(amtSat * 1000, memo); - if (!paymentRequest) return false; - - const decoded = this.decodeInvoice(paymentRequest); - - this._listInvoices = this._listInvoices || []; - const tx = { - payment_request: paymentRequest, - ispaid: false, - timestamp: +new Date(), - expire_time: 3600 * 1000, - amt: amtSat, - type: 'user_invoice', - payment_hash: decoded.payment_hash, - description: memo || '', - }; - this._listInvoices.push(tx); - - return paymentRequest; - } - - async getAddressAsync(): Promise { + async getAddressAsync() { throw new Error('getAddressAsync: Not implemented'); } @@ -485,35 +294,14 @@ export class LightningLdkWallet extends LightningCustodianWallet { return ret; } - async fetchTransactions() { - if (this.timeToCheckBlockchain()) { - try { - // exception might be in case of incompletely-started LDK - this._listChannels = await RnLdk.listChannels(); - await this.checkBlockchain(); - // ^^^ will be executed if above didnt throw exceptions, which means ldk fully started. - // we need this for a case when app returns from background if it was in bg for a really long time. - // ldk needs to update it's blockchain data, and this is practically the only place where it can - // do that (except on cold start) - } catch (_) {} - } - - try { - await this.reconnectPeersWithPendingChannels(); - } catch (error: any) { - console.log('fetchTransactions failed'); - console.log(error.message); - } - - await this.getUserInvoices(); // it internally updates paid user invoices - } + async fetchTransactions() {} getBalance() { let sum = 0; if (this._listChannels) { for (const channel of this._listChannels) { if (!channel.is_funding_locked) continue; // pending channel - sum += Math.floor(parseInt(channel.outbound_capacity_msat, 10) / 1000); + sum += Math.floor(parseInt(channel.outbound_capacity_msat) / 1000); } } @@ -525,7 +313,7 @@ export class LightningLdkWallet extends LightningCustodianWallet { if (this._listChannels) { for (const channel of this._listChannels) { if (!channel.is_funding_locked) continue; // pending channel - sum += Math.floor(parseInt(channel.inbound_capacity_msat, 10) / 1000); + sum += Math.floor(parseInt(channel.inbound_capacity_msat) / 1000); } } return sum; @@ -547,7 +335,7 @@ export class LightningLdkWallet extends LightningCustodianWallet { if (json && Array.isArray(json)) { for (const utxo of json) { if (utxo?.status?.confirmed) { - confirmedSat += parseInt(utxo.value, 10); + confirmedSat += parseInt(utxo.value); } } } @@ -569,7 +357,6 @@ export class LightningLdkWallet extends LightningCustodianWallet { await wallet.fetchUtxo(); console.log(wallet.getBalance(), wallet.getUtxo()); console.log('creating transaction...'); - // @ts-ignore wtf wallet.getUtxo() and first arg of createTransaction are not compatible const { tx } = wallet.createTransaction(wallet.getUtxo(), [{ address }], 2, address, 0, false, 0); if (!tx) throw new Error('claimCoins: could not create transaction'); console.log('broadcasting...'); @@ -585,7 +372,7 @@ export class LightningLdkWallet extends LightningCustodianWallet { } async closeChannel(fundingTxidHex: string, force = false) { - return force ? await RnLdk.closeChannelForce(fundingTxidHex) : await RnLdk.closeChannelCooperatively(fundingTxidHex); + return false; } getLatestTransactionTime(): string | 0 { @@ -599,17 +386,9 @@ export class LightningLdkWallet extends LightningCustodianWallet { return new Date(max).toString(); } - async getLogs() { - return RnLdk.getLogs() - .map(log => log.line) - .join('\n'); - } + async getLogs() {} - async getLogsWithTs() { - return RnLdk.getLogs() - .map(log => log.ts + ' ' + log.line) - .join('\n'); - } + async getLogsWithTs() {} async fetchPendingTransactions() {} @@ -658,24 +437,17 @@ export class LightningLdkWallet extends LightningCustodianWallet { async setRefundAddress(address: string) { const script = bitcoin.address.toOutputScript(address); this._refundAddressScriptHex = script.toString('hex'); - await RnLdk.setRefundAddressScript(this._refundAddressScriptHex); } - static async getVersion() { - return RnLdk.getVersion(); - } + static async getVersion() {} - static getPackageVersion() { - return RnLdk.getPackageVersion(); - } + static getPackageVersion() {} getChannelsClosedEvents() { - return RnLdk.channelsClosed; + return [{ reason: '', text: '' }]; } - async purgeLocalStorage() { - return RnLdk.getStorage().purgeLocalStorage(); - } + async purgeLocalStorage() {} /** * executes async function in background, so calling code can return immediately, while catching all thrown exceptions @@ -690,7 +462,7 @@ export class LightningLdkWallet extends LightningCustodianWallet { try { await func.call(that); } catch (error: any) { - presentAlert({ message: '_execInBackground error:' + error.message }); + presentAlert({ message: '_execInBackground error:' + error.message}); } })(); } diff --git a/ios/BlueWallet.xcodeproj/project.pbxproj b/ios/BlueWallet.xcodeproj/project.pbxproj index 402662366..2ba3f0c8e 100644 --- a/ios/BlueWallet.xcodeproj/project.pbxproj +++ b/ios/BlueWallet.xcodeproj/project.pbxproj @@ -151,13 +151,11 @@ B4A29A3A2B55C990002A67DF /* BlueWalletWatch.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = B40D4E30225841EC00428FCC /* BlueWalletWatch.app */; platformFilter = ios; }; B4A29A3C2B55C990002A67DF /* Stickers.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 6D2A6461258BA92C0092292B /* Stickers.appex */; platformFilter = ios; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; B4A29A3D2B55C990002A67DF /* WidgetsExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 6DD4109C266CADF10087DE03 /* WidgetsExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - B4AB21072B61D8CA0080440C /* SplashScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4AB21062B61D8CA0080440C /* SplashScreen.swift */; }; - B4AB21092B61DC3F0080440C /* SplashScreen.m in Sources */ = {isa = PBXBuildFile; fileRef = B4AB21082B61DC3F0080440C /* SplashScreen.m */; }; B4AB225D2B02AD12001F4328 /* XMLParserDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4AB225C2B02AD12001F4328 /* XMLParserDelegate.swift */; }; B4AB225E2B02AD12001F4328 /* XMLParserDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4AB225C2B02AD12001F4328 /* XMLParserDelegate.swift */; }; B4EE583C226703320003363C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B40D4E35225841ED00428FCC /* Assets.xcassets */; }; C59F90CE0D04D3E4BB39BC5D /* libPods-BlueWalletUITests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6F02C2F7CA3591E4E0B06EBA /* libPods-BlueWalletUITests.a */; }; - C978A716948AB7DEC5B6F677 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; }; + C978A716948AB7DEC5B6F677 /* (null) in Frameworks */ = {isa = PBXBuildFile; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -445,8 +443,6 @@ B49038D82B8FBAD300A8164A /* BlueWalletUITest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlueWalletUITest.swift; sourceTree = ""; }; B4A29A452B55C990002A67DF /* BlueWallet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BlueWallet.app; sourceTree = BUILT_PRODUCTS_DIR; }; B4A29A462B55C990002A67DF /* BlueWallet-NoLDK.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "BlueWallet-NoLDK.plist"; sourceTree = ""; }; - B4AB21062B61D8CA0080440C /* SplashScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashScreen.swift; sourceTree = ""; }; - B4AB21082B61DC3F0080440C /* SplashScreen.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SplashScreen.m; sourceTree = ""; }; B4AB225C2B02AD12001F4328 /* XMLParserDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XMLParserDelegate.swift; sourceTree = ""; }; B4D3235A177F4580BA52F2F9 /* libRNCSlider.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNCSlider.a; sourceTree = ""; }; B642AFB13483418CAB6FF25E /* libRCTQRCodeLocalImage.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRCTQRCodeLocalImage.a; sourceTree = ""; }; @@ -474,7 +470,7 @@ files = ( 782F075B5DD048449E2DECE9 /* libz.tbd in Frameworks */, 764B49B1420D4AEB8109BF62 /* libsqlite3.0.tbd in Frameworks */, - C978A716948AB7DEC5B6F677 /* BuildFile in Frameworks */, + C978A716948AB7DEC5B6F677 /* (null) in Frameworks */, 773E382FE62E836172AAB98B /* libPods-BlueWallet.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -865,8 +861,6 @@ B4AB21052B61D8890080440C /* SplashScreen */ = { isa = PBXGroup; children = ( - B4AB21062B61D8CA0080440C /* SplashScreen.swift */, - B4AB21082B61DC3F0080440C /* SplashScreen.m */, ); name = SplashScreen; sourceTree = ""; @@ -1116,7 +1110,7 @@ ); mainGroup = 83CBB9F61A601CBA00E9B192; packageReferences = ( - 6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode.git" */, + 6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode" */, B41B76832B66B2FF002C48D5 /* XCRemoteSwiftPackageReference "bugsnag-cocoa" */, ); productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; @@ -1502,9 +1496,7 @@ files = ( B44033E92BCC371A00162242 /* MarketData.swift in Sources */, B44033CA2BCC350A00162242 /* Currency.swift in Sources */, - B4AB21092B61DC3F0080440C /* SplashScreen.m in Sources */, B44033EE2BCC374500162242 /* Numeric+abbreviated.swift in Sources */, - B4AB21072B61D8CA0080440C /* SplashScreen.swift in Sources */, B44033DD2BCC36C300162242 /* LatestTransaction.swift in Sources */, 6D32C5C62596CE3A008C077C /* EventEmitter.m in Sources */, B44033FE2BCC37D700162242 /* MarketAPI.swift in Sources */, @@ -2627,7 +2619,7 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ - 6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode.git" */ = { + 6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/EFPrefix/EFQRCode.git"; requirement = { @@ -2648,7 +2640,7 @@ /* Begin XCSwiftPackageProductDependency section */ 6DFC806F24EA0B6C007B8700 /* EFQRCode */ = { isa = XCSwiftPackageProductDependency; - package = 6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode.git" */; + package = 6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode" */; productName = EFQRCode; }; B41B76842B66B2FF002C48D5 /* Bugsnag */ = { diff --git a/ios/BlueWallet/AppDelegate.mm b/ios/BlueWallet/AppDelegate.mm index 0785bc770..c7c6eb307 100644 --- a/ios/BlueWallet/AppDelegate.mm +++ b/ios/BlueWallet/AppDelegate.mm @@ -41,8 +41,6 @@ NSUserDefaults *group = [[NSUserDefaults alloc] initWithSuiteName:@"group.io.blu [NSUserDefaults.standardUserDefaults setValue:@"" forKey:@"deviceUIDCopy"]; } - [self addSplashScreenView]; - self.moduleName = @"BlueWallet"; // You can add your custom initial props in the dictionary below. // They will be passed down to the ViewController used by React Native. @@ -56,22 +54,6 @@ NSUserDefaults *group = [[NSUserDefaults alloc] initWithSuiteName:@"group.io.blu return [super application:application didFinishLaunchingWithOptions:launchOptions]; } -- (void)addSplashScreenView -{ - // Get the rootView - RCTRootView *rootView = (RCTRootView *)self.window.rootViewController.view; - - // Capture the launch screen view - UIStoryboard *launchScreenStoryboard = [UIStoryboard storyboardWithName:@"LaunchScreen" bundle:nil]; - UIViewController *launchScreenVC = [launchScreenStoryboard instantiateInitialViewController]; - UIView *launchScreenView = launchScreenVC.view; - launchScreenView.frame = self.window.bounds; - [self.window addSubview:launchScreenView]; - - // Keep a reference to the launch screen view to remove it later - rootView.loadingView = launchScreenView; -} - - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { #if DEBUG diff --git a/ios/SplashScreen.m b/ios/SplashScreen.m deleted file mode 100644 index 091048ffc..000000000 --- a/ios/SplashScreen.m +++ /dev/null @@ -1,14 +0,0 @@ -// -// SplashScreen.m -// BlueWallet -// -// Created by Marcos Rodriguez on 1/24/24. -// Copyright © 2024 BlueWallet. All rights reserved. -// - -#import - -@interface RCT_EXTERN_MODULE(SplashScreen, NSObject) -RCT_EXTERN_METHOD(addObserver) -RCT_EXTERN_METHOD(dismissSplashScreen) -@end diff --git a/ios/SplashScreen.swift b/ios/SplashScreen.swift deleted file mode 100644 index 6f70d3ca7..000000000 --- a/ios/SplashScreen.swift +++ /dev/null @@ -1,39 +0,0 @@ -// -// SplashScreen.swift -// BlueWallet -// -// Created by Marcos Rodriguez on 1/24/24. -// Copyright © 2024 BlueWallet. All rights reserved. -// - -import Foundation -import React - -@objc(SplashScreen) -class SplashScreen: NSObject, RCTBridgeModule { - static func moduleName() -> String! { - return "SplashScreen" - } - - static func requiresMainQueueSetup() -> Bool { - return true - } - - @objc - func addObserver() { - NotificationCenter.default.addObserver(self, selector: #selector(dismissSplashScreen), name: NSNotification.Name("HideSplashScreen"), object: nil) - } - - @objc - func dismissSplashScreen() { - DispatchQueue.main.async { - if let rootView = UIApplication.shared.delegate?.window??.rootViewController?.view as? RCTRootView { - rootView.loadingView?.removeFromSuperview() - rootView.loadingView = nil - } - NotificationCenter.default.removeObserver(self, name: NSNotification.Name("HideSplashScreen"), object: nil) - } - } - - -} diff --git a/screen/UnlockWith.tsx b/screen/UnlockWith.tsx index cb544dc80..b4f032562 100644 --- a/screen/UnlockWith.tsx +++ b/screen/UnlockWith.tsx @@ -1,5 +1,5 @@ import React, { useCallback, useContext, useEffect, useReducer, useRef } from 'react'; -import { View, Image, ActivityIndicator, NativeModules, StyleSheet } from 'react-native'; +import { View, Image, ActivityIndicator, StyleSheet } from 'react-native'; import Biometric, { BiometricType } from '../class/biometrics'; import { BlueStorageContext } from '../blue_modules/storage-context'; import triggerHapticFeedback, { HapticFeedbackTypes } from '../blue_modules/hapticFeedback'; @@ -49,8 +49,6 @@ function reducer(state: State, action: Action): State { } } -const { SplashScreen } = NativeModules; - const UnlockWith: React.FC = () => { const [state, dispatch] = useReducer(reducer, initialState); const isUnlockingWallets = useRef(false); @@ -91,8 +89,6 @@ const UnlockWith: React.FC = () => { }, [state.isAuthenticating, startAndDecrypt, successfullyAuthenticated]); useEffect(() => { - SplashScreen?.dismissSplashScreen(); - const startUnlock = async () => { const storageIsEncrypted = await isStorageEncrypted(); const isBiometricUseCapableAndEnabled = await Biometric.isBiometricUseCapableAndEnabled(); From 13ab45a20d0f20e685fbab27060c221338e26496 Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Velez Date: Wed, 15 May 2024 18:07:39 -0400 Subject: [PATCH 11/19] Update lightning-ldk-wallet.ts --- class/wallets/lightning-ldk-wallet.ts | 318 ++++++++++++++++++++++---- 1 file changed, 273 insertions(+), 45 deletions(-) diff --git a/class/wallets/lightning-ldk-wallet.ts b/class/wallets/lightning-ldk-wallet.ts index 82d223c2f..aab484a55 100644 --- a/class/wallets/lightning-ldk-wallet.ts +++ b/class/wallets/lightning-ldk-wallet.ts @@ -1,16 +1,24 @@ -import { BitcoinUnit, Chain } from '../../models/bitcoinUnits'; -import { LightningCustodianWallet } from './lightning-custodian-wallet'; -import { randomBytes } from '../rng'; import * as bip39 from 'bip39'; -import { HDSegwitBech32Wallet } from './hd-segwit-bech32-wallet'; -import bolt11 from 'bolt11'; -import { SegwitBech32Wallet } from './segwit-bech32-wallet'; -import presentAlert from '../../components/Alert'; import * as bitcoin from 'bitcoinjs-lib'; +import bolt11 from 'bolt11'; +import RNFS from 'react-native-fs'; +import RnLdk from 'rn-ldk/src/index'; +import presentAlert from '../../components/Alert'; +import { BitcoinUnit, Chain } from '../../models/bitcoinUnits'; +import { randomBytes } from '../rng'; +import SyncedAsyncStorage from '../synced-async-storage'; +import { HDSegwitBech32Wallet } from './hd-segwit-bech32-wallet'; +import { LightningCustodianWallet } from './lightning-custodian-wallet'; +import { SegwitBech32Wallet } from './segwit-bech32-wallet'; export class LightningLdkWallet extends LightningCustodianWallet { - static type = 'lightningLdk'; - static typeReadable = 'Lightning LDK'; + static readonly type = 'lightningLdk'; + static readonly typeReadable = 'Lightning LDK'; + // @ts-ignore: override + public readonly type = LightningLdkWallet.type; + // @ts-ignore: override + public readonly typeReadable = LightningLdkWallet.typeReadable; + private _listChannels: any[] = []; private _listPayments: any[] = []; private _listInvoices: any[] = []; @@ -41,8 +49,8 @@ export class LightningLdkWallet extends LightningCustodianWallet { return pubkeyHex; } - constructor(props: any) { - super(props); + constructor() { + super(); this.preferredBalanceUnit = BitcoinUnit.SATS; this.chain = Chain.OFFCHAIN; this.user_invoices_raw = []; // compatibility with other lightning wallet class @@ -57,16 +65,20 @@ export class LightningLdkWallet extends LightningCustodianWallet { return false; } - async stop() {} + async stop() { + return RnLdk.stop(); + } async wipeLndDir() {} - async listPeers() {} + async listPeers() { + return RnLdk.listPeers(); + } async listChannels() { try { // exception might be in case of incompletely-started LDK. then just ignore and return cached version - this._listChannels = []; + this._listChannels = await RnLdk.listChannels(); } catch (_) {} return this._listChannels; @@ -77,7 +89,7 @@ export class LightningLdkWallet extends LightningCustodianWallet { } async getInfo() { - const identityPubkey = ''; + const identityPubkey = await RnLdk.getNodeId(); return { identityPubkey, }; @@ -92,15 +104,15 @@ export class LightningLdkWallet extends LightningCustodianWallet { } async fundingStateStepFinalize(txhex: string) { - return false; + return RnLdk.openChannelStep2(txhex); } async getMaturingBalance(): Promise { - return 0; + return RnLdk.getMaturingBalance(); } async getMaturingHeight(): Promise { - return 0; + return RnLdk.getMaturingHeight(); } /** @@ -109,7 +121,16 @@ export class LightningLdkWallet extends LightningCustodianWallet { * @return {Promise} */ async isStarted() { - return false; + let rez; + try { + rez = await Promise.race([new Promise(resolve => setTimeout(() => resolve('timeout'), 1000)), RnLdk.getNodeId()]); + } catch (_) {} + + if (rez === 'timeout' || !rez) { + return false; + } + + return true; } /** @@ -128,10 +149,36 @@ export class LightningLdkWallet extends LightningCustodianWallet { } async openChannel(pubkeyHex: string, host: string, amountSats: number, privateChannel: boolean) { - return false; + let triedToConnect = false; + let port = 9735; + + if (host.includes(':')) { + const splitted = host.split(':'); + host = splitted[0]; + port = +splitted[1]; + } + + for (let c = 0; c < 20; c++) { + const peers = await this.listPeers(); + if (peers.includes(pubkeyHex)) { + // all good, connected, lets open channel + return await RnLdk.openChannelStep1(pubkeyHex, +amountSats); + } + + if (!triedToConnect) { + triedToConnect = true; + await RnLdk.connectPeer(pubkeyHex, host, +port); + } + + await new Promise(resolve => setTimeout(resolve, 500)); // sleep + } + + throw new Error('timeout waiting for peer connection'); } - async connectPeer(pubkeyHex: string, host: string, port: number) {} + async connectPeer(pubkeyHex: string, host: string, port: number) { + return RnLdk.connectPeer(pubkeyHex, host, +port); + } async lookupNodeConnectionDetailsByPubkey(pubkey: string) { // first, trying cache: @@ -149,7 +196,7 @@ export class LightningLdkWallet extends LightningCustodianWallet { const ret = { pubkey, host: address.addr.split(':')[0], - port: parseInt(address.addr.split(':')[1]), + port: parseInt(address.addr.split(':')[1], 10), }; this._nodeConnectionDetailsCache[pubkey] = Object.assign({}, ret, { ts: +new Date() }); @@ -160,8 +207,8 @@ export class LightningLdkWallet extends LightningCustodianWallet { } } - getAddress() { - return undefined; + getAddress(): string | false { + return false; } getSecret() { @@ -187,7 +234,9 @@ export class LightningLdkWallet extends LightningCustodianWallet { return ret; } - getStorageNamespace() {} + getStorageNamespace() { + return RnLdk.getStorage().namespace; + } static async _decodeInvoice(invoice: string) { return bolt11.decode(invoice); @@ -197,9 +246,41 @@ export class LightningLdkWallet extends LightningCustodianWallet { return bitcoin.address.fromOutputScript(Buffer.from(scriptHex, 'hex')); } - async selftest() {} + async selftest() { + await RnLdk.getStorage().selftest(); + await RnLdk.selftest(); + } - async init() {} + async init() { + if (!this.getSecret()) return; + console.warn('starting ldk'); + + try { + // providing simple functions that RnLdk would otherwise rely on 3rd party APIs + RnLdk.provideDecodeInvoiceFunc(LightningLdkWallet._decodeInvoice); + RnLdk.provideScript2addressFunc(LightningLdkWallet._script2address); + const syncedStorage = new SyncedAsyncStorage(this.getEntropyHex()); + // await syncedStorage.selftest(); + // await RnLdk.selftest(); + // console.warn('selftest passed'); + await syncedStorage.synchronize(); + + RnLdk.setStorage(syncedStorage); + if (this._refundAddressScriptHex) { + await RnLdk.setRefundAddressScript(this._refundAddressScriptHex); + } else { + // fallback, unwrapping address from bip39 mnemonic we have + const address = this.unwrapFirstExternalAddressFromMnemonics(); + await this.setRefundAddress(address); + } + await RnLdk.start(this.getEntropyHex(), RNFS.DocumentDirectoryPath); + + this._execInBackground(this.reestablishChannels); + if (this.timeToCheckBlockchain()) this._execInBackground(this.checkBlockchain); + } catch (error: any) { + presentAlert({ message: 'LDK init error: ' + error.message }); + } + } unwrapFirstExternalAddressFromMnemonics() { if (this._unwrapFirstExternalAddressFromMnemonicsCache) return this._unwrapFirstExternalAddressFromMnemonicsCache; // cache hit @@ -216,9 +297,52 @@ export class LightningLdkWallet extends LightningCustodianWallet { return hd._getExternalWIFByIndex(0); } - async checkBlockchain() {} + async checkBlockchain() { + this._lastTimeBlockchainCheckedTs = +new Date(); + return RnLdk.checkBlockchain(); + } async payInvoice(invoice: string, freeAmount = 0) { + const decoded = this.decodeInvoice(invoice); + + // if its NOT zero amount invoice, we forcefully reset passed amount argument so underlying LDK code + // would extract amount from bolt11 + if (decoded.num_satoshis && parseInt(decoded.num_satoshis, 10) > 0) freeAmount = 0; + + if (await this.channelsNeedReestablish()) { + await this.reestablishChannels(); + await this.waitForAtLeastOneChannelBecomeActive(); + } + + const result = await RnLdk.payInvoice(invoice, freeAmount); + if (!result) throw new Error('Failed'); + + // ok, it was sent. now, waiting for an event that it was _actually_ paid: + for (let c = 0; c < 60; c++) { + await new Promise(resolve => setTimeout(resolve, 500)); // sleep + + for (const sentPayment of RnLdk.sentPayments || []) { + const paidHash = LightningLdkWallet.preimage2hash(sentPayment.payment_preimage); + if (paidHash === decoded.payment_hash) { + this._listPayments = this._listPayments || []; + this._listPayments.push( + Object.assign({}, sentPayment, { + memo: decoded.description || 'Lightning payment', + value: (freeAmount || decoded.num_satoshis) * -1, + received: +new Date(), + payment_preimage: sentPayment.payment_preimage, + payment_hash: decoded.payment_hash, + }), + ); + return; + } + } + + for (const failedPayment of RnLdk.failedPayments || []) { + if (failedPayment.payment_hash === decoded.payment_hash) throw new Error(JSON.stringify(failedPayment)); + } + } + // no? lets just throw timeout error throw new Error('Payment timeout'); } @@ -229,12 +353,52 @@ export class LightningLdkWallet extends LightningCustodianWallet { * but will never be acknowledged as 'established' by LDK until peer reconnects so that ldk & peer can negotiate and * agree that channel is now established */ - async reconnectPeersWithPendingChannels() {} + async reconnectPeersWithPendingChannels() { + const peers = await RnLdk.listPeers(); + const peers2reconnect: Record = {}; + if (this._listChannels) { + for (const channel of this._listChannels) { + if (!channel.is_funding_locked) { + // pending channel + if (!peers.includes(channel.remote_node_id)) peers2reconnect[channel.remote_node_id] = true; + } + } + } - async getUserInvoices(limit = false) { + for (const pubkey of Object.keys(peers2reconnect)) { + const { host, port } = await this.lookupNodeConnectionDetailsByPubkey(pubkey); + await this.connectPeer(pubkey, host, port); + } + } + + async getUserInvoices(limit: number | false = false) { const newInvoices: any[] = []; + let found = false; - return newInvoices; + // okay, so the idea is that `this._listInvoices` is a persistent storage of invoices, while + // `RnLdk.receivedPayments` is only a temp storage of emitted events + + // we iterate through all stored invoices + for (const invoice of this._listInvoices) { + const newInvoice = Object.assign({}, invoice); + + // iterate through events of received payments + for (const receivedPayment of RnLdk.receivedPayments || []) { + if (receivedPayment.payment_hash === invoice.payment_hash) { + // match! this particular payment was paid + newInvoice.ispaid = true; + newInvoice.value = Math.floor(parseInt(receivedPayment.amt, 10) / 1000); + found = true; + } + } + + newInvoices.push(newInvoice); + } + + // overwrite stored array if flag was set + if (found) this._listInvoices = newInvoices; + + return this._listInvoices; } isInvoiceGeneratedByWallet(paymentRequest: string) { @@ -245,9 +409,36 @@ export class LightningLdkWallet extends LightningCustodianWallet { return false; } - async addInvoice(amtSat: number, memo: string) {} + async addInvoice(amtSat: number, memo: string) { + if (await this.channelsNeedReestablish()) { + await this.reestablishChannels(); + await this.waitForAtLeastOneChannelBecomeActive(); + } - async getAddressAsync() { + if (this.getReceivableBalance() < amtSat) throw new Error('You dont have enough inbound capacity'); + + const paymentRequest = await RnLdk.addInvoice(amtSat * 1000, memo); + if (!paymentRequest) return false; + + const decoded = this.decodeInvoice(paymentRequest); + + this._listInvoices = this._listInvoices || []; + const tx = { + payment_request: paymentRequest, + ispaid: false, + timestamp: +new Date(), + expire_time: 3600 * 1000, + amt: amtSat, + type: 'user_invoice', + payment_hash: decoded.payment_hash, + description: memo || '', + }; + this._listInvoices.push(tx); + + return paymentRequest; + } + + async getAddressAsync(): Promise { throw new Error('getAddressAsync: Not implemented'); } @@ -294,14 +485,35 @@ export class LightningLdkWallet extends LightningCustodianWallet { return ret; } - async fetchTransactions() {} + async fetchTransactions() { + if (this.timeToCheckBlockchain()) { + try { + // exception might be in case of incompletely-started LDK + this._listChannels = await RnLdk.listChannels(); + await this.checkBlockchain(); + // ^^^ will be executed if above didnt throw exceptions, which means ldk fully started. + // we need this for a case when app returns from background if it was in bg for a really long time. + // ldk needs to update it's blockchain data, and this is practically the only place where it can + // do that (except on cold start) + } catch (_) {} + } + + try { + await this.reconnectPeersWithPendingChannels(); + } catch (error: any) { + console.log('fetchTransactions failed'); + console.log(error.message); + } + + await this.getUserInvoices(); // it internally updates paid user invoices + } getBalance() { let sum = 0; if (this._listChannels) { for (const channel of this._listChannels) { if (!channel.is_funding_locked) continue; // pending channel - sum += Math.floor(parseInt(channel.outbound_capacity_msat) / 1000); + sum += Math.floor(parseInt(channel.outbound_capacity_msat, 10) / 1000); } } @@ -313,7 +525,7 @@ export class LightningLdkWallet extends LightningCustodianWallet { if (this._listChannels) { for (const channel of this._listChannels) { if (!channel.is_funding_locked) continue; // pending channel - sum += Math.floor(parseInt(channel.inbound_capacity_msat) / 1000); + sum += Math.floor(parseInt(channel.inbound_capacity_msat, 10) / 1000); } } return sum; @@ -335,7 +547,7 @@ export class LightningLdkWallet extends LightningCustodianWallet { if (json && Array.isArray(json)) { for (const utxo of json) { if (utxo?.status?.confirmed) { - confirmedSat += parseInt(utxo.value); + confirmedSat += parseInt(utxo.value, 10); } } } @@ -357,6 +569,7 @@ export class LightningLdkWallet extends LightningCustodianWallet { await wallet.fetchUtxo(); console.log(wallet.getBalance(), wallet.getUtxo()); console.log('creating transaction...'); + // @ts-ignore wtf wallet.getUtxo() and first arg of createTransaction are not compatible const { tx } = wallet.createTransaction(wallet.getUtxo(), [{ address }], 2, address, 0, false, 0); if (!tx) throw new Error('claimCoins: could not create transaction'); console.log('broadcasting...'); @@ -372,7 +585,7 @@ export class LightningLdkWallet extends LightningCustodianWallet { } async closeChannel(fundingTxidHex: string, force = false) { - return false; + return force ? await RnLdk.closeChannelForce(fundingTxidHex) : await RnLdk.closeChannelCooperatively(fundingTxidHex); } getLatestTransactionTime(): string | 0 { @@ -386,9 +599,17 @@ export class LightningLdkWallet extends LightningCustodianWallet { return new Date(max).toString(); } - async getLogs() {} + async getLogs() { + return RnLdk.getLogs() + .map(log => log.line) + .join('\n'); + } - async getLogsWithTs() {} + async getLogsWithTs() { + return RnLdk.getLogs() + .map(log => log.ts + ' ' + log.line) + .join('\n'); + } async fetchPendingTransactions() {} @@ -437,17 +658,24 @@ export class LightningLdkWallet extends LightningCustodianWallet { async setRefundAddress(address: string) { const script = bitcoin.address.toOutputScript(address); this._refundAddressScriptHex = script.toString('hex'); + await RnLdk.setRefundAddressScript(this._refundAddressScriptHex); } - static async getVersion() {} + static async getVersion() { + return RnLdk.getVersion(); + } - static getPackageVersion() {} + static getPackageVersion() { + return RnLdk.getPackageVersion(); + } getChannelsClosedEvents() { - return [{ reason: '', text: '' }]; + return RnLdk.channelsClosed; } - async purgeLocalStorage() {} + async purgeLocalStorage() { + return RnLdk.getStorage().purgeLocalStorage(); + } /** * executes async function in background, so calling code can return immediately, while catching all thrown exceptions @@ -462,7 +690,7 @@ export class LightningLdkWallet extends LightningCustodianWallet { try { await func.call(that); } catch (error: any) { - presentAlert({ message: '_execInBackground error:' + error.message}); + presentAlert({ message: '_execInBackground error:' + error.message }); } })(); } From ad7bdeed814c52eb9a25111a1fcf8b4c4957d1af Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Velez Date: Wed, 15 May 2024 18:09:40 -0400 Subject: [PATCH 12/19] Update storage-context.tsx --- blue_modules/storage-context.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/blue_modules/storage-context.tsx b/blue_modules/storage-context.tsx index 3bed3789b..835b3512a 100644 --- a/blue_modules/storage-context.tsx +++ b/blue_modules/storage-context.tsx @@ -73,15 +73,14 @@ export const BlueStorageProvider = ({ children }: { children: React.ReactNode }) const [reloadTransactionsMenuActionFunction, setReloadTransactionsMenuActionFunction] = useState<() => void>(() => {}); useEffect(() => { + setWallets(BlueApp.getWallets()); (async () => { const isElectrumDisabledValue = await BlueElectrum.isDisabled(); setIsElectrumDisabled(isElectrumDisabledValue); - if (walletsInitialized && wallets.length > 0 && !isElectrumDisabledValue) { - setWallets(BlueApp.getWallets()); + if (walletsInitialized && !isElectrumDisabledValue) { BlueElectrum.connectMain(); } })(); - // eslint-disable-next-line react-hooks/exhaustive-deps }, [walletsInitialized]); const saveToDisk = async (force: boolean = false) => { From 27111f3418f153cb3c9292b82aacbf4a0dbca4e1 Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Velez Date: Wed, 15 May 2024 18:10:55 -0400 Subject: [PATCH 13/19] Update storage-context.tsx --- blue_modules/storage-context.tsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/blue_modules/storage-context.tsx b/blue_modules/storage-context.tsx index 6f79b3183..835b3512a 100644 --- a/blue_modules/storage-context.tsx +++ b/blue_modules/storage-context.tsx @@ -74,11 +74,13 @@ export const BlueStorageProvider = ({ children }: { children: React.ReactNode }) useEffect(() => { setWallets(BlueApp.getWallets()); - - BlueElectrum.isDisabled().then(setIsElectrumDisabled); - if (walletsInitialized) { - BlueElectrum.connectMain(); - } + (async () => { + const isElectrumDisabledValue = await BlueElectrum.isDisabled(); + setIsElectrumDisabled(isElectrumDisabledValue); + if (walletsInitialized && !isElectrumDisabledValue) { + BlueElectrum.connectMain(); + } + })(); }, [walletsInitialized]); const saveToDisk = async (force: boolean = false) => { From 0abaf5699013239e3f9dccf300e67fe612ec22ba Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Velez Date: Wed, 15 May 2024 18:31:04 -0400 Subject: [PATCH 14/19] FIX: Reorder wallets search was missing --- navigation/LazyLoadReorderWalletsStack.tsx | 10 ---------- navigation/ReorderWalletsStack.tsx | 4 ++-- 2 files changed, 2 insertions(+), 12 deletions(-) delete mode 100644 navigation/LazyLoadReorderWalletsStack.tsx diff --git a/navigation/LazyLoadReorderWalletsStack.tsx b/navigation/LazyLoadReorderWalletsStack.tsx deleted file mode 100644 index 39f985456..000000000 --- a/navigation/LazyLoadReorderWalletsStack.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import React, { lazy, Suspense } from 'react'; -import { LazyLoadingIndicator } from './LazyLoadingIndicator'; - -const ReorderWallets = lazy(() => import('../screen/wallets/reorderWallets')); - -export const ReorderWalletsComponent = () => ( - }> - - -); diff --git a/navigation/ReorderWalletsStack.tsx b/navigation/ReorderWalletsStack.tsx index defbd53cb..076f4b363 100644 --- a/navigation/ReorderWalletsStack.tsx +++ b/navigation/ReorderWalletsStack.tsx @@ -1,9 +1,9 @@ import React from 'react'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; -import { ReorderWalletsComponent } from './LazyLoadReorderWalletsStack'; import { useTheme } from '../components/themes'; import navigationStyle from '../components/navigationStyle'; import loc from '../loc'; +import ReorderWallets from '../screen/wallets/reorderWallets'; const Stack = createNativeStackNavigator(); @@ -14,7 +14,7 @@ const ReorderWalletsStackRoot = () => { Date: Wed, 15 May 2024 18:45:46 -0400 Subject: [PATCH 15/19] REF: Use react memo on carousel item to avoid rerenders --- components/WalletsCarousel.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/WalletsCarousel.js b/components/WalletsCarousel.js index 8bf1f9159..4c7c716cd 100644 --- a/components/WalletsCarousel.js +++ b/components/WalletsCarousel.js @@ -154,7 +154,7 @@ const iStyles = StyleSheet.create({ }, }); -export const WalletCarouselItem = ({ item, _, onPress, handleLongPress, isSelectedWallet, customStyle }) => { +export const WalletCarouselItem = React.memo(({ item, _, onPress, handleLongPress, isSelectedWallet, customStyle }) => { const scaleValue = new Animated.Value(1.0); const { colors } = useTheme(); const { walletTransactionUpdateStatus } = useContext(BlueStorageContext); @@ -251,7 +251,7 @@ export const WalletCarouselItem = ({ item, _, onPress, handleLongPress, isSelect ); -}; +}); WalletCarouselItem.propTypes = { item: PropTypes.any, @@ -292,7 +292,7 @@ const WalletsCarousel = forwardRef((props, ref) => { ), // eslint-disable-next-line react-hooks/exhaustive-deps - [horizontal, selectedWallet, handleLongPress, onPress, preferredFiatCurrency, language], + [horizontal, selectedWallet, preferredFiatCurrency, language], ); const flatListRef = useRef(); From 774ce29892245b40b3324fdd35d77b775131b132 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 May 2024 23:10:19 +0000 Subject: [PATCH 16/19] Update dependency react-native-svg to v13.14.1 --- package-lock.json | 47 +++++++++++++++++++++++++---------------------- package.json | 2 +- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/package-lock.json b/package-lock.json index f0821c74e..4d4dbdfd9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "license": "MIT", "dependencies": { "@babel/preset-env": "^7.20.0", - "@bugsnag/react-native": "7.22.7", + "@bugsnag/react-native": "7.23.0", "@bugsnag/source-maps": "2.3.3", "@keystonehq/bc-ur-registry": "0.6.4", "@ngraveio/bc-ur": "1.1.12", @@ -93,7 +93,7 @@ "react-native-screens": "3.31.1", "react-native-secure-key-store": "https://github.com/BlueWallet/react-native-secure-key-store#2076b48", "react-native-share": "10.2.0", - "react-native-svg": "13.14.0", + "react-native-svg": "13.14.1", "react-native-tcp-socket": "6.0.6", "react-native-vector-icons": "10.1.0", "react-native-watch-connectivity": "1.1.0", @@ -2250,17 +2250,19 @@ } }, "node_modules/@bugsnag/plugin-react-native-unhandled-rejection": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@bugsnag/plugin-react-native-unhandled-rejection/-/plugin-react-native-unhandled-rejection-7.22.7.tgz", - "integrity": "sha512-xmFpUPYrQxwsr9RJ1HTu9lfNUbAHM+hIyUEshg+/Wfj/1Zvnkr0AnkqRWbQFqkOBklzYI4s7maJvm4S2go/KOQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@bugsnag/plugin-react-native-unhandled-rejection/-/plugin-react-native-unhandled-rejection-7.23.0.tgz", + "integrity": "sha512-z0Nlqir3nnBcXVffw8uau12SS7vVUu0yS65SS5uWUn9cNIwNSTqZ/40pHVGh1VQBbpXlYrw7RVbPtufWmS20EA==", + "license": "MIT", "peerDependencies": { "@bugsnag/core": "^7.0.0" } }, "node_modules/@bugsnag/react-native": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@bugsnag/react-native/-/react-native-7.22.7.tgz", - "integrity": "sha512-vHmynQj7rzPW+1v8aK41G9T5HSaXipgFkkCmczOiFG9YYNzVKeaPcbwcS6Z6+tLZ55ZQeJdupfezcmj4rnAZVw==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@bugsnag/react-native/-/react-native-7.23.0.tgz", + "integrity": "sha512-4xw0BDUBYPYxxBM0rbRr+uI+8IA/22p2JdzW+DMzLjue9e5PY+dTGZgREllGLuE27NtMBvnaA0rlWSYfxE04cQ==", + "license": "MIT", "dependencies": { "@bugsnag/core": "^7.22.7", "@bugsnag/delivery-react-native": "^7.22.7", @@ -2272,7 +2274,7 @@ "@bugsnag/plugin-react-native-global-error-handler": "^7.22.7", "@bugsnag/plugin-react-native-hermes": "^7.22.7", "@bugsnag/plugin-react-native-session": "^7.22.7", - "@bugsnag/plugin-react-native-unhandled-rejection": "^7.22.7", + "@bugsnag/plugin-react-native-unhandled-rejection": "^7.23.0", "iserror": "^0.0.2" } }, @@ -19755,9 +19757,10 @@ } }, "node_modules/react-native-svg": { - "version": "13.14.0", - "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-13.14.0.tgz", - "integrity": "sha512-27ZnxUkHgWICimhuj6MuqBkISN53lVvgWJB7pIypjXysAyM+nqgQBPh4vXg+7MbqLBoYvR4PiBgKfwwGAqVxHg==", + "version": "13.14.1", + "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-13.14.1.tgz", + "integrity": "sha512-0DSa0EOySzV0J9utmRFVE5Vr4mKRXA7GtH1Ga1B6fzR967HGFW1ytH6hmnOf36316hjYpXMMB7s4oVe1FqghlQ==", + "license": "MIT", "dependencies": { "css-select": "^5.1.0", "css-tree": "^1.1.3" @@ -24003,14 +24006,14 @@ "integrity": "sha512-p3C7m6GXh9ICnGt+m1FwWpBCiGNGdQvoTzzN0LAxT6YQdB3t2nmhqE3QIpHmXpJK1PveTCIOO2DbeSerWtUEsg==" }, "@bugsnag/plugin-react-native-unhandled-rejection": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@bugsnag/plugin-react-native-unhandled-rejection/-/plugin-react-native-unhandled-rejection-7.22.7.tgz", - "integrity": "sha512-xmFpUPYrQxwsr9RJ1HTu9lfNUbAHM+hIyUEshg+/Wfj/1Zvnkr0AnkqRWbQFqkOBklzYI4s7maJvm4S2go/KOQ==" + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@bugsnag/plugin-react-native-unhandled-rejection/-/plugin-react-native-unhandled-rejection-7.23.0.tgz", + "integrity": "sha512-z0Nlqir3nnBcXVffw8uau12SS7vVUu0yS65SS5uWUn9cNIwNSTqZ/40pHVGh1VQBbpXlYrw7RVbPtufWmS20EA==" }, "@bugsnag/react-native": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@bugsnag/react-native/-/react-native-7.22.7.tgz", - "integrity": "sha512-vHmynQj7rzPW+1v8aK41G9T5HSaXipgFkkCmczOiFG9YYNzVKeaPcbwcS6Z6+tLZ55ZQeJdupfezcmj4rnAZVw==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@bugsnag/react-native/-/react-native-7.23.0.tgz", + "integrity": "sha512-4xw0BDUBYPYxxBM0rbRr+uI+8IA/22p2JdzW+DMzLjue9e5PY+dTGZgREllGLuE27NtMBvnaA0rlWSYfxE04cQ==", "requires": { "@bugsnag/core": "^7.22.7", "@bugsnag/delivery-react-native": "^7.22.7", @@ -24022,7 +24025,7 @@ "@bugsnag/plugin-react-native-global-error-handler": "^7.22.7", "@bugsnag/plugin-react-native-hermes": "^7.22.7", "@bugsnag/plugin-react-native-session": "^7.22.7", - "@bugsnag/plugin-react-native-unhandled-rejection": "^7.22.7", + "@bugsnag/plugin-react-native-unhandled-rejection": "^7.23.0", "iserror": "^0.0.2" } }, @@ -37344,9 +37347,9 @@ "integrity": "sha512-mKOfBLIBFBcs9br1rlZDvxD5+mAl8Gfr5CounwJtxI6Z82rGrMO+Kgl9EIg3RMVf3G855a85YVqHJL2f5EDRlw==" }, "react-native-svg": { - "version": "13.14.0", - "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-13.14.0.tgz", - "integrity": "sha512-27ZnxUkHgWICimhuj6MuqBkISN53lVvgWJB7pIypjXysAyM+nqgQBPh4vXg+7MbqLBoYvR4PiBgKfwwGAqVxHg==", + "version": "13.14.1", + "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-13.14.1.tgz", + "integrity": "sha512-0DSa0EOySzV0J9utmRFVE5Vr4mKRXA7GtH1Ga1B6fzR967HGFW1ytH6hmnOf36316hjYpXMMB7s4oVe1FqghlQ==", "requires": { "css-select": "^5.1.0", "css-tree": "^1.1.3" diff --git a/package.json b/package.json index 4494315b2..3a703096e 100644 --- a/package.json +++ b/package.json @@ -178,7 +178,7 @@ "react-native-screens": "3.31.1", "react-native-secure-key-store": "https://github.com/BlueWallet/react-native-secure-key-store#2076b48", "react-native-share": "10.2.0", - "react-native-svg": "13.14.0", + "react-native-svg": "13.14.1", "react-native-tcp-socket": "6.0.6", "react-native-vector-icons": "10.1.0", "react-native-watch-connectivity": "1.1.0", From cc4c4e822312783338c6c2a942741a2b7a82670f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 May 2024 23:10:34 +0000 Subject: [PATCH 17/19] Update dependency realm to v12.8.1 --- package-lock.json | 47 +++++++++++++++++++++++++---------------------- package.json | 2 +- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/package-lock.json b/package-lock.json index f0821c74e..7fbacf0be 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "license": "MIT", "dependencies": { "@babel/preset-env": "^7.20.0", - "@bugsnag/react-native": "7.22.7", + "@bugsnag/react-native": "7.23.0", "@bugsnag/source-maps": "2.3.3", "@keystonehq/bc-ur-registry": "0.6.4", "@ngraveio/bc-ur": "1.1.12", @@ -99,7 +99,7 @@ "react-native-watch-connectivity": "1.1.0", "react-native-widget-center": "https://github.com/BlueWallet/react-native-widget-center#a128c38", "readable-stream": "3.6.2", - "realm": "12.8.0", + "realm": "12.8.1", "rn-ldk": "github:BlueWallet/rn-ldk#v0.8.4", "rn-nodeify": "10.3.0", "scryptsy": "2.1.0", @@ -2250,17 +2250,19 @@ } }, "node_modules/@bugsnag/plugin-react-native-unhandled-rejection": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@bugsnag/plugin-react-native-unhandled-rejection/-/plugin-react-native-unhandled-rejection-7.22.7.tgz", - "integrity": "sha512-xmFpUPYrQxwsr9RJ1HTu9lfNUbAHM+hIyUEshg+/Wfj/1Zvnkr0AnkqRWbQFqkOBklzYI4s7maJvm4S2go/KOQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@bugsnag/plugin-react-native-unhandled-rejection/-/plugin-react-native-unhandled-rejection-7.23.0.tgz", + "integrity": "sha512-z0Nlqir3nnBcXVffw8uau12SS7vVUu0yS65SS5uWUn9cNIwNSTqZ/40pHVGh1VQBbpXlYrw7RVbPtufWmS20EA==", + "license": "MIT", "peerDependencies": { "@bugsnag/core": "^7.0.0" } }, "node_modules/@bugsnag/react-native": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@bugsnag/react-native/-/react-native-7.22.7.tgz", - "integrity": "sha512-vHmynQj7rzPW+1v8aK41G9T5HSaXipgFkkCmczOiFG9YYNzVKeaPcbwcS6Z6+tLZ55ZQeJdupfezcmj4rnAZVw==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@bugsnag/react-native/-/react-native-7.23.0.tgz", + "integrity": "sha512-4xw0BDUBYPYxxBM0rbRr+uI+8IA/22p2JdzW+DMzLjue9e5PY+dTGZgREllGLuE27NtMBvnaA0rlWSYfxE04cQ==", + "license": "MIT", "dependencies": { "@bugsnag/core": "^7.22.7", "@bugsnag/delivery-react-native": "^7.22.7", @@ -2272,7 +2274,7 @@ "@bugsnag/plugin-react-native-global-error-handler": "^7.22.7", "@bugsnag/plugin-react-native-hermes": "^7.22.7", "@bugsnag/plugin-react-native-session": "^7.22.7", - "@bugsnag/plugin-react-native-unhandled-rejection": "^7.22.7", + "@bugsnag/plugin-react-native-unhandled-rejection": "^7.23.0", "iserror": "^0.0.2" } }, @@ -20110,10 +20112,11 @@ "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==" }, "node_modules/realm": { - "version": "12.8.0", - "resolved": "https://registry.npmjs.org/realm/-/realm-12.8.0.tgz", - "integrity": "sha512-U1w5+ncyURQFQTrshoGn3KV+pzR1rQlPT7s3Sw6HPIPVBH80EWU3mirwvqp6RQ+Qi32ctRrBMTNeGd5mzAyiSw==", + "version": "12.8.1", + "resolved": "https://registry.npmjs.org/realm/-/realm-12.8.1.tgz", + "integrity": "sha512-+zj2bvU0EACXvPBdvRsp2TybHPqPtftciTXsAlhrTWMiaoqC8FO6lriPbUs/JwsXz1w9otJXl5kXRBghPQHgLQ==", "hasInstallScript": true, + "license": "apache-2.0", "dependencies": { "@realm/fetch": "^0.1.1", "bson": "^4.7.2", @@ -24003,14 +24006,14 @@ "integrity": "sha512-p3C7m6GXh9ICnGt+m1FwWpBCiGNGdQvoTzzN0LAxT6YQdB3t2nmhqE3QIpHmXpJK1PveTCIOO2DbeSerWtUEsg==" }, "@bugsnag/plugin-react-native-unhandled-rejection": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@bugsnag/plugin-react-native-unhandled-rejection/-/plugin-react-native-unhandled-rejection-7.22.7.tgz", - "integrity": "sha512-xmFpUPYrQxwsr9RJ1HTu9lfNUbAHM+hIyUEshg+/Wfj/1Zvnkr0AnkqRWbQFqkOBklzYI4s7maJvm4S2go/KOQ==" + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@bugsnag/plugin-react-native-unhandled-rejection/-/plugin-react-native-unhandled-rejection-7.23.0.tgz", + "integrity": "sha512-z0Nlqir3nnBcXVffw8uau12SS7vVUu0yS65SS5uWUn9cNIwNSTqZ/40pHVGh1VQBbpXlYrw7RVbPtufWmS20EA==" }, "@bugsnag/react-native": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@bugsnag/react-native/-/react-native-7.22.7.tgz", - "integrity": "sha512-vHmynQj7rzPW+1v8aK41G9T5HSaXipgFkkCmczOiFG9YYNzVKeaPcbwcS6Z6+tLZ55ZQeJdupfezcmj4rnAZVw==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@bugsnag/react-native/-/react-native-7.23.0.tgz", + "integrity": "sha512-4xw0BDUBYPYxxBM0rbRr+uI+8IA/22p2JdzW+DMzLjue9e5PY+dTGZgREllGLuE27NtMBvnaA0rlWSYfxE04cQ==", "requires": { "@bugsnag/core": "^7.22.7", "@bugsnag/delivery-react-native": "^7.22.7", @@ -24022,7 +24025,7 @@ "@bugsnag/plugin-react-native-global-error-handler": "^7.22.7", "@bugsnag/plugin-react-native-hermes": "^7.22.7", "@bugsnag/plugin-react-native-session": "^7.22.7", - "@bugsnag/plugin-react-native-unhandled-rejection": "^7.22.7", + "@bugsnag/plugin-react-native-unhandled-rejection": "^7.23.0", "iserror": "^0.0.2" } }, @@ -37517,9 +37520,9 @@ "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==" }, "realm": { - "version": "12.8.0", - "resolved": "https://registry.npmjs.org/realm/-/realm-12.8.0.tgz", - "integrity": "sha512-U1w5+ncyURQFQTrshoGn3KV+pzR1rQlPT7s3Sw6HPIPVBH80EWU3mirwvqp6RQ+Qi32ctRrBMTNeGd5mzAyiSw==", + "version": "12.8.1", + "resolved": "https://registry.npmjs.org/realm/-/realm-12.8.1.tgz", + "integrity": "sha512-+zj2bvU0EACXvPBdvRsp2TybHPqPtftciTXsAlhrTWMiaoqC8FO6lriPbUs/JwsXz1w9otJXl5kXRBghPQHgLQ==", "requires": { "@realm/fetch": "^0.1.1", "bson": "^4.7.2", diff --git a/package.json b/package.json index 4494315b2..a20688a00 100644 --- a/package.json +++ b/package.json @@ -184,7 +184,7 @@ "react-native-watch-connectivity": "1.1.0", "react-native-widget-center": "https://github.com/BlueWallet/react-native-widget-center#a128c38", "readable-stream": "3.6.2", - "realm": "12.8.0", + "realm": "12.8.1", "rn-ldk": "github:BlueWallet/rn-ldk#v0.8.4", "rn-nodeify": "10.3.0", "scryptsy": "2.1.0", From 292db985d76e9d8c7e28ca028e8ed87709223607 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 16 May 2024 02:09:29 +0000 Subject: [PATCH 18/19] Update dependency react-native-device-info to v10.14.0 --- package-lock.json | 15 ++++++++------- package.json | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7fbacf0be..771dadd41 100644 --- a/package-lock.json +++ b/package-lock.json @@ -63,7 +63,7 @@ "react-native-camera-kit": "13.0.0", "react-native-crypto": "2.2.0", "react-native-default-preference": "1.4.4", - "react-native-device-info": "10.13.2", + "react-native-device-info": "10.14.0", "react-native-document-picker": "https://github.com/BlueWallet/react-native-document-picker#6033c4e1b0dd0a6760b5f5a5a2c3b2e5d07f2ae4", "react-native-draggable-flatlist": "github:BlueWallet/react-native-draggable-flatlist#ebfddc4", "react-native-elements": "3.4.3", @@ -19388,9 +19388,10 @@ } }, "node_modules/react-native-device-info": { - "version": "10.13.2", - "resolved": "https://registry.npmjs.org/react-native-device-info/-/react-native-device-info-10.13.2.tgz", - "integrity": "sha512-5EAls7uvGdZkVfp1KWHsR5BfJJHp/ux64+ZPj1865IcaUyrNQIWYFmrTHwTH8L/NGJUTBrzv+y6WODnN17LSbw==", + "version": "10.14.0", + "resolved": "https://registry.npmjs.org/react-native-device-info/-/react-native-device-info-10.14.0.tgz", + "integrity": "sha512-9NnTGfhEU4UgQtz4p6COk2Gbqly0dpSWrJtp+dw5rNAi96KtYbaNnO5yoOHDlJ1SVIzh8+hFu3WxVbnWkFU9gA==", + "license": "MIT", "peerDependencies": { "react-native": "*" } @@ -37103,9 +37104,9 @@ "integrity": "sha512-h0vtgiSKws3UmMRJykXAVM4ne1SgfoocUcoBD19ewRpQd6wqurE0HJRQGrSxcHK5LdKE7QPSIB1VX3YGIVS8Jg==" }, "react-native-device-info": { - "version": "10.13.2", - "resolved": "https://registry.npmjs.org/react-native-device-info/-/react-native-device-info-10.13.2.tgz", - "integrity": "sha512-5EAls7uvGdZkVfp1KWHsR5BfJJHp/ux64+ZPj1865IcaUyrNQIWYFmrTHwTH8L/NGJUTBrzv+y6WODnN17LSbw==" + "version": "10.14.0", + "resolved": "https://registry.npmjs.org/react-native-device-info/-/react-native-device-info-10.14.0.tgz", + "integrity": "sha512-9NnTGfhEU4UgQtz4p6COk2Gbqly0dpSWrJtp+dw5rNAi96KtYbaNnO5yoOHDlJ1SVIzh8+hFu3WxVbnWkFU9gA==" }, "react-native-document-picker": { "version": "git+ssh://git@github.com/BlueWallet/react-native-document-picker.git#6033c4e1b0dd0a6760b5f5a5a2c3b2e5d07f2ae4", diff --git a/package.json b/package.json index a20688a00..665c1e176 100644 --- a/package.json +++ b/package.json @@ -148,7 +148,7 @@ "react-native-camera-kit": "13.0.0", "react-native-crypto": "2.2.0", "react-native-default-preference": "1.4.4", - "react-native-device-info": "10.13.2", + "react-native-device-info": "10.14.0", "react-native-document-picker": "https://github.com/BlueWallet/react-native-document-picker#6033c4e1b0dd0a6760b5f5a5a2c3b2e5d07f2ae4", "react-native-draggable-flatlist": "github:BlueWallet/react-native-draggable-flatlist#ebfddc4", "react-native-elements": "3.4.3", From 69a32a0f418726e97d4fea2f75da99b8c19e4a1c Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Velez Date: Thu, 16 May 2024 13:43:09 -0400 Subject: [PATCH 19/19] OPS: Pod --- ios/BlueWallet.xcodeproj/project.pbxproj | 10 +++++----- ios/Podfile.lock | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/ios/BlueWallet.xcodeproj/project.pbxproj b/ios/BlueWallet.xcodeproj/project.pbxproj index 2ba3f0c8e..4b3804093 100644 --- a/ios/BlueWallet.xcodeproj/project.pbxproj +++ b/ios/BlueWallet.xcodeproj/project.pbxproj @@ -155,7 +155,7 @@ B4AB225E2B02AD12001F4328 /* XMLParserDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4AB225C2B02AD12001F4328 /* XMLParserDelegate.swift */; }; B4EE583C226703320003363C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B40D4E35225841ED00428FCC /* Assets.xcassets */; }; C59F90CE0D04D3E4BB39BC5D /* libPods-BlueWalletUITests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6F02C2F7CA3591E4E0B06EBA /* libPods-BlueWalletUITests.a */; }; - C978A716948AB7DEC5B6F677 /* (null) in Frameworks */ = {isa = PBXBuildFile; }; + C978A716948AB7DEC5B6F677 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -470,7 +470,7 @@ files = ( 782F075B5DD048449E2DECE9 /* libz.tbd in Frameworks */, 764B49B1420D4AEB8109BF62 /* libsqlite3.0.tbd in Frameworks */, - C978A716948AB7DEC5B6F677 /* (null) in Frameworks */, + C978A716948AB7DEC5B6F677 /* BuildFile in Frameworks */, 773E382FE62E836172AAB98B /* libPods-BlueWallet.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1110,7 +1110,7 @@ ); mainGroup = 83CBB9F61A601CBA00E9B192; packageReferences = ( - 6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode" */, + 6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode.git" */, B41B76832B66B2FF002C48D5 /* XCRemoteSwiftPackageReference "bugsnag-cocoa" */, ); productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; @@ -2619,7 +2619,7 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ - 6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode" */ = { + 6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode.git" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/EFPrefix/EFQRCode.git"; requirement = { @@ -2640,7 +2640,7 @@ /* Begin XCSwiftPackageProductDependency section */ 6DFC806F24EA0B6C007B8700 /* EFQRCode */ = { isa = XCSwiftPackageProductDependency; - package = 6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode" */; + package = 6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode.git" */; productName = EFQRCode; }; B41B76842B66B2FF002C48D5 /* Bugsnag */ = { diff --git a/ios/Podfile.lock b/ios/Podfile.lock index f5e9994ad..5aea7401e 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,6 +1,6 @@ PODS: - boost (1.76.0) - - BugsnagReactNative (7.22.7): + - BugsnagReactNative (7.23.0): - React-Core - BVLinearGradient (2.8.3): - React-Core @@ -466,7 +466,7 @@ PODS: - React-perflogger (= 0.72.14) - ReactNativeCameraKit (13.0.0): - React-Core - - RealmJS (12.8.0): + - RealmJS (12.8.1): - React - rn-ldk (0.8.4): - React-Core @@ -478,7 +478,7 @@ PODS: - React-Core - RNDefaultPreference (1.4.4): - React-Core - - RNDeviceInfo (10.13.2): + - RNDeviceInfo (10.14.0): - React-Core - RNFS (2.20.0): - React-Core @@ -511,7 +511,7 @@ PODS: - React-RCTImage - RNShare (10.2.0): - React-Core - - RNSVG (13.14.0): + - RNSVG (13.14.1): - React-Core - RNVectorIcons (10.1.0): - RCT-Folly (= 2021.07.22.00) @@ -777,7 +777,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 7dcd2de282d72e344012f7d6564d024930a6a440 - BugsnagReactNative: 7cc5c927f6a0b00a8e3cc7157dab4cc94a4bc575 + BugsnagReactNative: 079e8ede687b76bd8b661acd55bc5c888af56dc7 BVLinearGradient: 880f91a7854faff2df62518f0281afb1c60d49a3 CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 @@ -836,13 +836,13 @@ SPEC CHECKSUMS: React-utils: 22a77b05da25ce49c744faa82e73856dcae1734e ReactCommon: ff94462e007c568d8cdebc32e3c97af86ec93bb5 ReactNativeCameraKit: 9d46a5d7dd544ca64aa9c03c150d2348faf437eb - RealmJS: 3e6010ae878227830e947f40f996e13ccab4c8ba + RealmJS: 2c7fdb3991d7655fba5f88eb288f75eaf5cb9980 rn-ldk: 0d8749d98cc5ce67302a32831818c116b67f7643 RNCAsyncStorage: 826b603ae9c0f88b5ac4e956801f755109fa4d5c RNCClipboard: 0a720adef5ec193aa0e3de24c3977222c7e52a37 RNCPushNotificationIOS: 64218f3c776c03d7408284a819b2abfda1834bc8 RNDefaultPreference: 08bdb06cfa9188d5da97d4642dac745218d7fb31 - RNDeviceInfo: 42aadf1282ffa0a88dc38a504a7be145eb010dfa + RNDeviceInfo: 59344c19152c4b2b32283005f9737c5c64b42fba RNFS: 4ac0f0ea233904cb798630b3c077808c06931688 RNGestureHandler: 982741f345785f2927e7b28f67dc83679cf3bfc8 RNHandoff: d3b0754cca3a6bcd9b25f544f733f7f033ccf5fa @@ -856,7 +856,7 @@ SPEC CHECKSUMS: RNReanimated: d4f25b2a931c4f0b2bb12173a3096f02ea4cfb05 RNScreens: b8d370282cdeae9df85dd5eab20c88eb5181243b RNShare: 554a91f5cfbe4adac4cfe3654826ee8b299fe365 - RNSVG: d00c8f91c3cbf6d476451313a18f04d220d4f396 + RNSVG: af3907ac5d4fa26a862b75a16d8f15bc74f2ceda RNVectorIcons: 32462e7c7e58fe457474fc79c4d7de3f0ef08d70 RNWatch: fd30ca40a5b5ef58dcbc195638e68219bc455236 SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17