mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-02-22 06:52:41 +01:00
Merge branch 'master' into alert
This commit is contained in:
commit
9194edd4de
38 changed files with 879 additions and 532 deletions
18
.github/workflows/build-release-apk.yml
vendored
18
.github/workflows/build-release-apk.yml
vendored
|
@ -40,14 +40,28 @@ jobs:
|
|||
- name: Install node_modules
|
||||
run: npm install --production
|
||||
|
||||
- name: Extract Version Name
|
||||
id: version_name
|
||||
run: |
|
||||
VERSION_NAME=$(grep versionName android/app/build.gradle | awk '{print $2}' | tr -d '"')
|
||||
echo "VERSION_NAME=$VERSION_NAME" >> $GITHUB_ENV
|
||||
echo "::set-output name=version_name::$VERSION_NAME"
|
||||
|
||||
- name: Generate Build Number based on timestamp
|
||||
run: |
|
||||
NEW_BUILD_NUMBER=$(date +%s)
|
||||
echo "NEW_BUILD_NUMBER=$NEW_BUILD_NUMBER" >> $GITHUB_ENV
|
||||
echo "::set-output name=build_number::$NEW_BUILD_NUMBER"
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
KEYSTORE_FILE_HEX: ${{ secrets.KEYSTORE_FILE_HEX }}
|
||||
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
|
||||
BUILD_NUMBER: ${{ env.NEW_BUILD_NUMBER }}
|
||||
run: ./scripts/build-release-apk.sh
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: success()
|
||||
with:
|
||||
name: apk
|
||||
path: ./android/app/build/outputs/apk/release/app-release.apk
|
||||
name: BlueWallet-${{ env.VERSION_NAME }}(${{ env.NEW_BUILD_NUMBER }}).apk
|
||||
path: ./android/app/build/outputs/apk/release/BlueWallet-${{ env.VERSION_NAME }}(${{ env.NEW_BUILD_NUMBER }}).apk
|
||||
|
|
140
UnlockWith.js
140
UnlockWith.js
|
@ -1,140 +0,0 @@
|
|||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import { View, Image, TouchableOpacity, StyleSheet, ActivityIndicator, useColorScheme, NativeModules } from 'react-native';
|
||||
import { Icon } from 'react-native-elements';
|
||||
import Biometric from './class/biometrics';
|
||||
import { StackActions, useNavigation, useRoute } from '@react-navigation/native';
|
||||
import { BlueStorageContext } from './blue_modules/storage-context';
|
||||
import { isHandset } from './blue_modules/environment';
|
||||
import triggerHapticFeedback, { HapticFeedbackTypes } from './blue_modules/hapticFeedback';
|
||||
import SafeArea from './components/SafeArea';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flex: 1,
|
||||
},
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
|
||||
biometricRow: {
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'row',
|
||||
},
|
||||
icon: {
|
||||
width: 64,
|
||||
height: 64,
|
||||
},
|
||||
logoImage: {
|
||||
width: 100,
|
||||
height: 75,
|
||||
alignSelf: 'center',
|
||||
},
|
||||
});
|
||||
|
||||
const { SplashScreen } = NativeModules;
|
||||
|
||||
const UnlockWith = () => {
|
||||
const { setWalletsInitialized, isStorageEncrypted, startAndDecrypt } = useContext(BlueStorageContext);
|
||||
const { dispatch } = useNavigation();
|
||||
const { unlockOnComponentMount } = useRoute().params;
|
||||
const [biometricType, setBiometricType] = useState(false);
|
||||
const [isStorageEncryptedEnabled, setIsStorageEncryptedEnabled] = useState(false);
|
||||
const [isAuthenticating, setIsAuthenticating] = useState(false);
|
||||
const colorScheme = useColorScheme();
|
||||
|
||||
useEffect(() => {
|
||||
SplashScreen?.dismissSplashScreen();
|
||||
startUnlock();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const successfullyAuthenticated = () => {
|
||||
setWalletsInitialized(true);
|
||||
dispatch(StackActions.replace(isHandset ? 'Navigation' : 'DrawerRoot'));
|
||||
};
|
||||
|
||||
const unlockWithBiometrics = async () => {
|
||||
if (await isStorageEncrypted()) {
|
||||
unlockWithKey();
|
||||
} else {
|
||||
setIsAuthenticating(true);
|
||||
|
||||
if (await Biometric.unlockWithBiometrics()) {
|
||||
setIsAuthenticating(false);
|
||||
await startAndDecrypt();
|
||||
return successfullyAuthenticated();
|
||||
}
|
||||
setIsAuthenticating(false);
|
||||
}
|
||||
};
|
||||
|
||||
const unlockWithKey = async () => {
|
||||
if (isAuthenticating) return;
|
||||
setIsAuthenticating(true);
|
||||
if (await startAndDecrypt()) {
|
||||
triggerHapticFeedback(HapticFeedbackTypes.NotificationSuccess);
|
||||
successfullyAuthenticated();
|
||||
} else {
|
||||
setIsAuthenticating(false);
|
||||
}
|
||||
};
|
||||
|
||||
const renderUnlockOptions = () => {
|
||||
if (isAuthenticating) {
|
||||
return <ActivityIndicator />;
|
||||
} else {
|
||||
const color = colorScheme === 'dark' ? '#FFFFFF' : '#000000';
|
||||
if ((biometricType === Biometric.TouchID || biometricType === Biometric.Biometrics) && !isStorageEncryptedEnabled) {
|
||||
return (
|
||||
<TouchableOpacity accessibilityRole="button" disabled={isAuthenticating} onPress={unlockWithBiometrics}>
|
||||
<Icon name="fingerprint" size={64} type="font-awesome5" color={color} />
|
||||
</TouchableOpacity>
|
||||
);
|
||||
} else if (biometricType === Biometric.FaceID && !isStorageEncryptedEnabled) {
|
||||
return (
|
||||
<TouchableOpacity accessibilityRole="button" disabled={isAuthenticating} onPress={unlockWithBiometrics}>
|
||||
<Image
|
||||
source={colorScheme === 'dark' ? require('./img/faceid-default.png') : require('./img/faceid-dark.png')}
|
||||
style={styles.icon}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
} else if (isStorageEncryptedEnabled) {
|
||||
return (
|
||||
<TouchableOpacity accessibilityRole="button" disabled={isAuthenticating} onPress={unlockWithKey}>
|
||||
<Icon name="lock" size={64} type="font-awesome5" color={color} />
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const startUnlock = async () => {
|
||||
if (unlockOnComponentMount) {
|
||||
const storageIsEncrypted = await isStorageEncrypted();
|
||||
setIsStorageEncryptedEnabled(storageIsEncrypted);
|
||||
let bt = false;
|
||||
if (await Biometric.isBiometricUseCapableAndEnabled()) {
|
||||
bt = await Biometric.biometricType();
|
||||
}
|
||||
|
||||
setBiometricType(bt);
|
||||
if (!bt || storageIsEncrypted) {
|
||||
unlockWithKey();
|
||||
} else if (typeof bt === 'string') unlockWithBiometrics();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeArea style={styles.root}>
|
||||
<View style={styles.container}>
|
||||
<Image source={require('./img/icon.png')} style={styles.logoImage} resizeMode="contain" />
|
||||
</View>
|
||||
<View style={styles.biometricRow}>{renderUnlockOptions()}</View>
|
||||
</SafeArea>
|
||||
);
|
||||
};
|
||||
|
||||
export default UnlockWith;
|
196
UnlockWith.tsx
Normal file
196
UnlockWith.tsx
Normal file
|
@ -0,0 +1,196 @@
|
|||
import React, { useContext, useEffect, useReducer, useRef } from 'react';
|
||||
import { View, Image, TouchableOpacity, ActivityIndicator, useColorScheme, NativeModules, StyleSheet } from 'react-native';
|
||||
import { Icon } from 'react-native-elements';
|
||||
import Biometric, { BiometricType } from './class/biometrics';
|
||||
import { NavigationProp, RouteProp, StackActions, useNavigation, useRoute } from '@react-navigation/native';
|
||||
import { BlueStorageContext } from './blue_modules/storage-context';
|
||||
import { isHandset } from './blue_modules/environment';
|
||||
import triggerHapticFeedback, { HapticFeedbackTypes } from './blue_modules/hapticFeedback';
|
||||
import SafeArea from './components/SafeArea';
|
||||
type RootStackParamList = {
|
||||
UnlockWith: { unlockOnComponentMount?: boolean };
|
||||
};
|
||||
|
||||
type State = {
|
||||
biometricType: BiometricType | undefined;
|
||||
isStorageEncryptedEnabled: boolean;
|
||||
isAuthenticating: boolean;
|
||||
};
|
||||
|
||||
const SET_BIOMETRIC_TYPE = 'SET_BIOMETRIC_TYPE';
|
||||
const SET_IS_STORAGE_ENCRYPTED_ENABLED = 'SET_IS_STORAGE_ENCRYPTED_ENABLED';
|
||||
const SET_IS_AUTHENTICATING = 'SET_IS_AUTHENTICATING';
|
||||
|
||||
type Action =
|
||||
| { type: typeof SET_BIOMETRIC_TYPE; payload: BiometricType | undefined }
|
||||
| { type: typeof SET_IS_STORAGE_ENCRYPTED_ENABLED; payload: boolean }
|
||||
| { type: typeof SET_IS_AUTHENTICATING; payload: boolean };
|
||||
|
||||
const initialState: State = {
|
||||
biometricType: undefined,
|
||||
isStorageEncryptedEnabled: false,
|
||||
isAuthenticating: false,
|
||||
};
|
||||
|
||||
function reducer(state: State, action: Action): State {
|
||||
switch (action.type) {
|
||||
case SET_BIOMETRIC_TYPE:
|
||||
return { ...state, biometricType: action.payload };
|
||||
case SET_IS_STORAGE_ENCRYPTED_ENABLED:
|
||||
return { ...state, isStorageEncryptedEnabled: action.payload };
|
||||
case SET_IS_AUTHENTICATING:
|
||||
return { ...state, isAuthenticating: action.payload };
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
const { SplashScreen } = NativeModules;
|
||||
|
||||
const UnlockWith: React.FC = () => {
|
||||
const [state, dispatch] = useReducer(reducer, initialState);
|
||||
const isUnlockingWallets = useRef(false);
|
||||
const { setWalletsInitialized, isStorageEncrypted, startAndDecrypt } = useContext(BlueStorageContext);
|
||||
const navigation = useNavigation<NavigationProp<RootStackParamList, 'UnlockWith'>>();
|
||||
const route = useRoute<RouteProp<RootStackParamList, 'UnlockWith'>>();
|
||||
const { unlockOnComponentMount } = route.params;
|
||||
const colorScheme = useColorScheme();
|
||||
|
||||
useEffect(() => {
|
||||
SplashScreen?.dismissSplashScreen();
|
||||
startUnlock();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const successfullyAuthenticated = () => {
|
||||
setWalletsInitialized(true);
|
||||
navigation.dispatch(StackActions.replace(isHandset ? 'Navigation' : 'DrawerRoot'));
|
||||
isUnlockingWallets.current = false;
|
||||
};
|
||||
|
||||
const unlockWithBiometrics = async () => {
|
||||
if (isUnlockingWallets.current || state.isAuthenticating) return;
|
||||
isUnlockingWallets.current = true;
|
||||
dispatch({ type: SET_IS_AUTHENTICATING, payload: true });
|
||||
|
||||
if (await Biometric.unlockWithBiometrics()) {
|
||||
await startAndDecrypt();
|
||||
successfullyAuthenticated();
|
||||
}
|
||||
|
||||
dispatch({ type: SET_IS_AUTHENTICATING, payload: false });
|
||||
isUnlockingWallets.current = false;
|
||||
};
|
||||
|
||||
const unlockWithKey = async () => {
|
||||
if (isUnlockingWallets.current || state.isAuthenticating) return;
|
||||
isUnlockingWallets.current = true;
|
||||
dispatch({ type: SET_IS_AUTHENTICATING, payload: true });
|
||||
|
||||
if (await startAndDecrypt()) {
|
||||
triggerHapticFeedback(HapticFeedbackTypes.NotificationSuccess);
|
||||
successfullyAuthenticated();
|
||||
} else {
|
||||
dispatch({ type: SET_IS_AUTHENTICATING, payload: false });
|
||||
isUnlockingWallets.current = false;
|
||||
}
|
||||
};
|
||||
|
||||
const renderUnlockOptions = () => {
|
||||
if (state.isAuthenticating) {
|
||||
return <ActivityIndicator />;
|
||||
} else {
|
||||
const color = colorScheme === 'dark' ? '#FFFFFF' : '#000000';
|
||||
if (
|
||||
(state.biometricType === BiometricType.TouchID || state.biometricType === BiometricType.Biometrics) &&
|
||||
!state.isStorageEncryptedEnabled
|
||||
) {
|
||||
return (
|
||||
<TouchableOpacity accessibilityRole="button" disabled={state.isAuthenticating} onPress={unlockWithBiometrics}>
|
||||
<Icon name="fingerprint" size={64} type="font-awesome5" color={color} />
|
||||
</TouchableOpacity>
|
||||
);
|
||||
} else if (state.biometricType === BiometricType.FaceID && !state.isStorageEncryptedEnabled) {
|
||||
return (
|
||||
<TouchableOpacity accessibilityRole="button" disabled={state.isAuthenticating} onPress={unlockWithBiometrics}>
|
||||
<Image
|
||||
source={colorScheme === 'dark' ? require('./img/faceid-default.png') : require('./img/faceid-dark.png')}
|
||||
style={styles.icon}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
} else if (state.isStorageEncryptedEnabled) {
|
||||
return (
|
||||
<TouchableOpacity accessibilityRole="button" disabled={state.isAuthenticating} onPress={unlockWithKey}>
|
||||
<Icon name="lock" size={64} type="font-awesome5" color={color} />
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const startUnlock = async () => {
|
||||
if (unlockOnComponentMount) {
|
||||
const storageIsEncrypted = await isStorageEncrypted();
|
||||
dispatch({ type: SET_IS_STORAGE_ENCRYPTED_ENABLED, payload: storageIsEncrypted });
|
||||
const rawType = await Biometric.biometricType();
|
||||
|
||||
let type;
|
||||
if (rawType === 'Biometrics') {
|
||||
type = BiometricType.Biometrics;
|
||||
} else if (rawType === 'Touch ID') {
|
||||
type = BiometricType.TouchID;
|
||||
} else if (rawType === 'Face ID') {
|
||||
type = BiometricType.FaceID;
|
||||
}
|
||||
|
||||
dispatch({ type: SET_BIOMETRIC_TYPE, payload: type });
|
||||
|
||||
if (!type || storageIsEncrypted) {
|
||||
unlockWithKey();
|
||||
} else {
|
||||
unlockWithBiometrics();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeArea style={styles.root}>
|
||||
<View style={styles.container}>
|
||||
<Image source={require('./img/icon.png')} style={styles.logoImage} resizeMode="contain" />
|
||||
</View>
|
||||
<View style={styles.biometricRow}>{renderUnlockOptions()}</View>
|
||||
</SafeArea>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flex: 1,
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
biometricRow: {
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'row',
|
||||
width: 64,
|
||||
height: 64,
|
||||
alignSelf: 'center',
|
||||
marginBottom: 20,
|
||||
},
|
||||
icon: {
|
||||
width: 64,
|
||||
height: 64,
|
||||
},
|
||||
logoImage: {
|
||||
width: 100,
|
||||
height: 75,
|
||||
alignSelf: 'center',
|
||||
},
|
||||
});
|
||||
|
||||
export default UnlockWith;
|
|
@ -79,7 +79,7 @@ android {
|
|||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 1
|
||||
versionName "6.5.2"
|
||||
versionName "6.5.3"
|
||||
testBuildType System.getProperty('testBuildType', 'debug')
|
||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ buildscript {
|
|||
dependencies {
|
||||
classpath("com.android.tools.build:gradle")
|
||||
classpath("com.bugsnag:bugsnag-android-gradle-plugin:5.+")
|
||||
classpath 'com.google.gms:google-services:4.4.0' // Google Services plugin
|
||||
classpath 'com.google.gms:google-services:4.4.1' // Google Services plugin
|
||||
classpath("com.facebook.react:react-native-gradle-plugin")
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import { FiatUnit, FiatUnitType, getFiatRate } from '../models/fiatUnit';
|
|||
import WidgetCommunication from './WidgetCommunication';
|
||||
|
||||
const PREFERRED_CURRENCY_STORAGE_KEY = 'preferredCurrency';
|
||||
const PREFERRED_CURRENCY_LOCALE_STORAGE_KEY = 'preferredCurrencyLocale';
|
||||
const EXCHANGE_RATES_STORAGE_KEY = 'exchangeRates';
|
||||
const LAST_UPDATED = 'LAST_UPDATED';
|
||||
const GROUP_IO_BLUEWALLET = 'group.io.bluewallet.bluewallet';
|
||||
|
@ -27,10 +28,9 @@ let lastTimeUpdateExchangeRateWasCalled: number = 0;
|
|||
let skipUpdateExchangeRate: boolean = false;
|
||||
|
||||
async function setPreferredCurrency(item: FiatUnitType): Promise<void> {
|
||||
await AsyncStorage.setItem(PREFERRED_CURRENCY_STORAGE_KEY, JSON.stringify(item));
|
||||
await DefaultPreference.setName(GROUP_IO_BLUEWALLET);
|
||||
await DefaultPreference.set(PREFERRED_CURRENCY_STORAGE_KEY, item.endPointKey);
|
||||
await DefaultPreference.set('preferredCurrencyLocale', item.locale.replace('-', '_'));
|
||||
await DefaultPreference.set(PREFERRED_CURRENCY_LOCALE_STORAGE_KEY, item.locale.replace('-', '_'));
|
||||
// @ts-ignore: Convert to TSX later
|
||||
WidgetCommunication.reloadAllTimelines();
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ async function getPreferredCurrency(): Promise<FiatUnitType> {
|
|||
const preferredCurrency = JSON.parse((await AsyncStorage.getItem(PREFERRED_CURRENCY_STORAGE_KEY)) || '{}');
|
||||
await DefaultPreference.setName(GROUP_IO_BLUEWALLET);
|
||||
await DefaultPreference.set(PREFERRED_CURRENCY_STORAGE_KEY, preferredCurrency.endPointKey);
|
||||
await DefaultPreference.set('preferredCurrencyLocale', preferredCurrency.locale.replace('-', '_'));
|
||||
await DefaultPreference.set(PREFERRED_CURRENCY_LOCALE_STORAGE_KEY, preferredCurrency.locale.replace('-', '_'));
|
||||
return preferredCurrency;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ export const BlueStorageProvider = ({ children }) => {
|
|||
const [isElectrumDisabled, setIsElectrumDisabled] = useState(true);
|
||||
const [isPrivacyBlurEnabled, setIsPrivacyBlurEnabled] = useState(true);
|
||||
const [currentSharedCosigner, setCurrentSharedCosigner] = useState('');
|
||||
const [reloadTransactionsMenuActionFunction, setReloadTransactionsMenuActionFunction] = useState(() => {});
|
||||
|
||||
useEffect(() => {
|
||||
BlueElectrum.isDisabled().then(setIsElectrumDisabled);
|
||||
|
@ -277,6 +278,8 @@ export const BlueStorageProvider = ({ children }) => {
|
|||
setIsElectrumDisabled,
|
||||
isPrivacyBlurEnabled,
|
||||
setIsPrivacyBlurEnabled,
|
||||
reloadTransactionsMenuActionFunction,
|
||||
setReloadTransactionsMenuActionFunction,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
|
|
@ -1,37 +1,41 @@
|
|||
import FingerprintScanner from 'react-native-fingerprint-scanner';
|
||||
import { Platform, Alert } from 'react-native';
|
||||
// @ts-ignore react-native-passcode-auth wants d.ts
|
||||
import { useContext } from 'react';
|
||||
import { Alert, Platform } from 'react-native';
|
||||
import { CommonActions, StackActions } from '@react-navigation/native';
|
||||
import FingerprintScanner, { Biometrics as TBiometrics } from 'react-native-fingerprint-scanner';
|
||||
import PasscodeAuth from 'react-native-passcode-auth';
|
||||
import * as NavigationService from '../NavigationService';
|
||||
import { StackActions, CommonActions } from '@react-navigation/native';
|
||||
import RNSecureKeyStore from 'react-native-secure-key-store';
|
||||
import loc from '../loc';
|
||||
import { useContext } from 'react';
|
||||
import * as NavigationService from '../NavigationService';
|
||||
import { BlueStorageContext } from '../blue_modules/storage-context';
|
||||
import presentAlert from '../components/Alert';
|
||||
|
||||
const STORAGEKEY = 'Biometrics';
|
||||
|
||||
export enum BiometricType {
|
||||
FaceID = 'FaceID',
|
||||
TouchID = 'TouchID',
|
||||
Biometrics = 'Biometrics',
|
||||
None = 'None',
|
||||
}
|
||||
|
||||
// Define a function type with properties
|
||||
type DescribableFunction = {
|
||||
(): void; // Call signature
|
||||
STORAGEKEY: string; // Property
|
||||
FaceID: string; // Property etc...
|
||||
TouchID: string;
|
||||
Biometrics: string;
|
||||
isBiometricUseCapableAndEnabled: () => Promise<undefined | boolean>;
|
||||
isDeviceBiometricCapable: () => Promise<boolean | undefined>;
|
||||
(): null; // Call signature
|
||||
FaceID: 'Face ID';
|
||||
TouchID: 'Touch ID';
|
||||
Biometrics: 'Biometrics';
|
||||
isBiometricUseCapableAndEnabled: () => Promise<boolean>;
|
||||
isDeviceBiometricCapable: () => Promise<boolean>;
|
||||
setBiometricUseEnabled: (arg: boolean) => Promise<void>;
|
||||
biometricType: () => Promise<boolean | 'Touch ID' | 'Face ID' | 'Biometrics'>;
|
||||
biometricType: () => Promise<false | TBiometrics>;
|
||||
isBiometricUseEnabled: () => Promise<boolean>;
|
||||
unlockWithBiometrics: () => Promise<unknown>;
|
||||
clearKeychain: () => Promise<void>;
|
||||
requestDevicePasscode: () => Promise<void>;
|
||||
unlockWithBiometrics: () => Promise<boolean>;
|
||||
showKeychainWipeAlert: () => void;
|
||||
};
|
||||
|
||||
// @ts-ignore Bastard component/module. All properties are added in runtime, not at definition phase
|
||||
const Biometric: DescribableFunction = function () {
|
||||
// Bastard component/module. All properties are added in runtime
|
||||
const Biometric = function () {
|
||||
const { getItem, setItem } = useContext(BlueStorageContext);
|
||||
Biometric.STORAGEKEY = 'Biometrics';
|
||||
Biometric.FaceID = 'Face ID';
|
||||
Biometric.TouchID = 'Touch ID';
|
||||
Biometric.Biometrics = 'Biometrics';
|
||||
|
@ -46,8 +50,8 @@ const Biometric: DescribableFunction = function () {
|
|||
console.log('Biometrics isDeviceBiometricCapable failed');
|
||||
console.log(e);
|
||||
Biometric.setBiometricUseEnabled(false);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
Biometric.biometricType = async () => {
|
||||
|
@ -63,7 +67,7 @@ const Biometric: DescribableFunction = function () {
|
|||
|
||||
Biometric.isBiometricUseEnabled = async () => {
|
||||
try {
|
||||
const enabledBiometrics = await getItem(Biometric.STORAGEKEY);
|
||||
const enabledBiometrics = await getItem(STORAGEKEY);
|
||||
return !!enabledBiometrics;
|
||||
} catch (_) {}
|
||||
|
||||
|
@ -77,7 +81,7 @@ const Biometric: DescribableFunction = function () {
|
|||
};
|
||||
|
||||
Biometric.setBiometricUseEnabled = async value => {
|
||||
await setItem(Biometric.STORAGEKEY, value === true ? '1' : '');
|
||||
await setItem(STORAGEKEY, value === true ? '1' : '');
|
||||
};
|
||||
|
||||
Biometric.unlockWithBiometrics = async () => {
|
||||
|
@ -97,14 +101,14 @@ const Biometric: DescribableFunction = function () {
|
|||
return false;
|
||||
};
|
||||
|
||||
Biometric.clearKeychain = async () => {
|
||||
const clearKeychain = async () => {
|
||||
await RNSecureKeyStore.remove('data');
|
||||
await RNSecureKeyStore.remove('data_encrypted');
|
||||
await RNSecureKeyStore.remove(Biometric.STORAGEKEY);
|
||||
await RNSecureKeyStore.remove(STORAGEKEY);
|
||||
NavigationService.dispatch(StackActions.replace('WalletsRoot'));
|
||||
};
|
||||
|
||||
Biometric.requestDevicePasscode = async () => {
|
||||
const requestDevicePasscode = async () => {
|
||||
let isDevicePasscodeSupported: boolean | undefined = false;
|
||||
try {
|
||||
isDevicePasscodeSupported = await PasscodeAuth.isSupported();
|
||||
|
@ -118,7 +122,7 @@ const Biometric: DescribableFunction = function () {
|
|||
{ text: loc._.cancel, style: 'cancel' },
|
||||
{
|
||||
text: loc._.ok,
|
||||
onPress: () => Biometric.clearKeychain(),
|
||||
onPress: () => clearKeychain(),
|
||||
},
|
||||
],
|
||||
{ cancelable: false },
|
||||
|
@ -153,7 +157,7 @@ const Biometric: DescribableFunction = function () {
|
|||
},
|
||||
{
|
||||
text: loc._.ok,
|
||||
onPress: () => Biometric.requestDevicePasscode(),
|
||||
onPress: () => requestDevicePasscode(),
|
||||
style: 'default',
|
||||
},
|
||||
],
|
||||
|
@ -161,7 +165,8 @@ const Biometric: DescribableFunction = function () {
|
|||
);
|
||||
}
|
||||
};
|
||||
|
||||
return null;
|
||||
};
|
||||
} as DescribableFunction;
|
||||
|
||||
export default Biometric;
|
||||
|
|
|
@ -20,43 +20,57 @@ import {
|
|||
SegwitP2SHWallet,
|
||||
WatchOnlyWallet,
|
||||
} from '.';
|
||||
import type { TWallet } from './wallets/types';
|
||||
import loc from '../loc';
|
||||
import bip39WalletFormats from './bip39_wallet_formats.json'; // https://github.com/spesmilo/electrum/blob/master/electrum/bip39_wallet_formats.json
|
||||
import bip39WalletFormatsBlueWallet from './bip39_wallet_formats_bluewallet.json';
|
||||
|
||||
// https://github.com/bitcoinjs/bip32/blob/master/ts-src/bip32.ts#L43
|
||||
export const validateBip32 = path => path.match(/^(m\/)?(\d+'?\/)*\d+'?$/) !== null;
|
||||
export const validateBip32 = (path: string) => path.match(/^(m\/)?(\d+'?\/)*\d+'?$/) !== null;
|
||||
|
||||
type TReturn = {
|
||||
cancelled: boolean;
|
||||
stopped: boolean;
|
||||
wallets: TWallet[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Function that starts wallet search and import process. It has async generator inside, so
|
||||
* that the process can be stoped at any time. It reporst all the progress through callbacks.
|
||||
*
|
||||
* @param askPassphrase {bool} If true import process will call onPassword callback for wallet with optional password.
|
||||
* @param searchAccounts {bool} If true import process will scan for all known derivation path from bip39_wallet_formats.json. If false it will use limited version.
|
||||
* @param askPassphrase {boolean} If true import process will call onPassword callback for wallet with optional password.
|
||||
* @param searchAccounts {boolean} If true import process will scan for all known derivation path from bip39_wallet_formats.json. If false it will use limited version.
|
||||
* @param onProgress {function} Callback to report scanning progress
|
||||
* @param onWallet {function} Callback to report wallet found
|
||||
* @param onPassword {function} Callback to ask for password if needed
|
||||
* @returns {{promise: Promise, stop: function}}
|
||||
*/
|
||||
const startImport = (importTextOrig, askPassphrase = false, searchAccounts = false, onProgress, onWallet, onPassword) => {
|
||||
const startImport = (
|
||||
importTextOrig: string,
|
||||
askPassphrase: boolean = false,
|
||||
searchAccounts: boolean = false,
|
||||
onProgress: (name: string) => void,
|
||||
onWallet: (wallet: TWallet) => void,
|
||||
onPassword: (title: string, text: string) => Promise<string>,
|
||||
): { promise: Promise<TReturn>; stop: () => void } => {
|
||||
// state
|
||||
let promiseResolve;
|
||||
let promiseReject;
|
||||
let promiseResolve: (arg: TReturn) => void;
|
||||
let promiseReject: (reason?: any) => void;
|
||||
let running = true; // if you put it to false, internal generator stops
|
||||
const wallets = [];
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
const wallets: TWallet[] = [];
|
||||
const promise = new Promise<TReturn>((resolve, reject) => {
|
||||
promiseResolve = resolve;
|
||||
promiseReject = reject;
|
||||
});
|
||||
|
||||
// actions
|
||||
const reportProgress = name => {
|
||||
const reportProgress = (name: string) => {
|
||||
onProgress(name);
|
||||
};
|
||||
const reportFinish = (cancelled, stopped) => {
|
||||
const reportFinish = (cancelled: boolean = false, stopped: boolean = false) => {
|
||||
promiseResolve({ cancelled, stopped, wallets });
|
||||
};
|
||||
const reportWallet = wallet => {
|
||||
const reportWallet = (wallet: TWallet) => {
|
||||
if (wallets.some(w => w.getID() === wallet.getID())) return; // do not add duplicates
|
||||
wallets.push(wallet);
|
||||
onWallet(wallet);
|
||||
|
@ -134,7 +148,7 @@ const startImport = (importTextOrig, askPassphrase = false, searchAccounts = fal
|
|||
}
|
||||
|
||||
// is it bip38 encrypted
|
||||
if (text.startsWith('6P')) {
|
||||
if (text.startsWith('6P') && password) {
|
||||
const decryptedKey = await bip38.decryptAsync(text, password);
|
||||
|
||||
if (decryptedKey) {
|
||||
|
@ -184,7 +198,9 @@ const startImport = (importTextOrig, askPassphrase = false, searchAccounts = fal
|
|||
yield { progress: 'bip39' };
|
||||
const hd2 = new HDSegwitBech32Wallet();
|
||||
hd2.setSecret(text);
|
||||
hd2.setPassphrase(password);
|
||||
if (password) {
|
||||
hd2.setPassphrase(password);
|
||||
}
|
||||
if (hd2.validateMnemonic()) {
|
||||
let walletFound = false;
|
||||
// by default we don't try all the paths and options
|
||||
|
@ -214,7 +230,9 @@ const startImport = (importTextOrig, askPassphrase = false, searchAccounts = fal
|
|||
for (const path of paths) {
|
||||
const wallet = new WalletClass();
|
||||
wallet.setSecret(text);
|
||||
wallet.setPassphrase(password);
|
||||
if (password) {
|
||||
wallet.setPassphrase(password);
|
||||
}
|
||||
wallet.setDerivationPath(path);
|
||||
yield { progress: `bip39 ${i.script_type} ${path}` };
|
||||
if (await wallet.wasEverUsed()) {
|
||||
|
@ -230,7 +248,9 @@ const startImport = (importTextOrig, askPassphrase = false, searchAccounts = fal
|
|||
// to decide which one is it let's compare number of transactions
|
||||
const m0Legacy = new HDLegacyP2PKHWallet();
|
||||
m0Legacy.setSecret(text);
|
||||
m0Legacy.setPassphrase(password);
|
||||
if (password) {
|
||||
m0Legacy.setPassphrase(password);
|
||||
}
|
||||
m0Legacy.setDerivationPath("m/0'");
|
||||
yield { progress: "bip39 p2pkh m/0'" };
|
||||
// BRD doesn't support passphrase and only works with 12 words seeds
|
||||
|
@ -332,7 +352,9 @@ const startImport = (importTextOrig, askPassphrase = false, searchAccounts = fal
|
|||
yield { progress: 'electrum p2wpkh-p2sh' };
|
||||
const el1 = new HDSegwitElectrumSeedP2WPKHWallet();
|
||||
el1.setSecret(text);
|
||||
el1.setPassphrase(password);
|
||||
if (password) {
|
||||
el1.setPassphrase(password);
|
||||
}
|
||||
if (el1.validateMnemonic()) {
|
||||
yield { wallet: el1 }; // not fetching txs or balances, fuck it, yolo, life is too short
|
||||
}
|
||||
|
@ -341,7 +363,9 @@ const startImport = (importTextOrig, askPassphrase = false, searchAccounts = fal
|
|||
yield { progress: 'electrum p2pkh' };
|
||||
const el2 = new HDLegacyElectrumSeedP2PKHWallet();
|
||||
el2.setSecret(text);
|
||||
el2.setPassphrase(password);
|
||||
if (password) {
|
||||
el2.setPassphrase(password);
|
||||
}
|
||||
if (el2.validateMnemonic()) {
|
||||
yield { wallet: el2 }; // not fetching txs or balances, fuck it, yolo, life is too short
|
||||
}
|
||||
|
@ -350,7 +374,9 @@ const startImport = (importTextOrig, askPassphrase = false, searchAccounts = fal
|
|||
yield { progress: 'aezeed' };
|
||||
const aezeed2 = new HDAezeedWallet();
|
||||
aezeed2.setSecret(text);
|
||||
aezeed2.setPassphrase(password);
|
||||
if (password) {
|
||||
aezeed2.setPassphrase(password);
|
||||
}
|
||||
if (await aezeed2.validateMnemonicAsync()) {
|
||||
yield { wallet: aezeed2 }; // not fetching txs or balances, fuck it, yolo, life is too short
|
||||
}
|
||||
|
@ -364,14 +390,18 @@ const startImport = (importTextOrig, askPassphrase = false, searchAccounts = fal
|
|||
|
||||
if (s1.validateMnemonic()) {
|
||||
yield { progress: 'SLIP39 p2wpkh-p2sh' };
|
||||
s1.setPassphrase(password);
|
||||
if (password) {
|
||||
s1.setPassphrase(password);
|
||||
}
|
||||
if (await s1.wasEverUsed()) {
|
||||
yield { wallet: s1 };
|
||||
}
|
||||
|
||||
yield { progress: 'SLIP39 p2pkh' };
|
||||
const s2 = new SLIP39LegacyP2PKHWallet();
|
||||
s2.setPassphrase(password);
|
||||
if (password) {
|
||||
s2.setPassphrase(password);
|
||||
}
|
||||
s2.setSecret(text);
|
||||
if (await s2.wasEverUsed()) {
|
||||
yield { wallet: s2 };
|
||||
|
@ -380,7 +410,9 @@ const startImport = (importTextOrig, askPassphrase = false, searchAccounts = fal
|
|||
yield { progress: 'SLIP39 p2wpkh' };
|
||||
const s3 = new SLIP39SegwitBech32Wallet();
|
||||
s3.setSecret(text);
|
||||
s3.setPassphrase(password);
|
||||
if (password) {
|
||||
s3.setPassphrase(password);
|
||||
}
|
||||
yield { wallet: s3 };
|
||||
}
|
||||
}
|
|
@ -1,5 +1,20 @@
|
|||
import bitcoin from 'bitcoinjs-lib';
|
||||
import { CoinSelectOutput, CoinSelectReturnInput } from 'coinselect';
|
||||
import { HDAezeedWallet } from './hd-aezeed-wallet';
|
||||
import { HDLegacyBreadwalletWallet } from './hd-legacy-breadwallet-wallet';
|
||||
import { HDLegacyElectrumSeedP2PKHWallet } from './hd-legacy-electrum-seed-p2pkh-wallet';
|
||||
import { HDLegacyP2PKHWallet } from './hd-legacy-p2pkh-wallet';
|
||||
import { HDSegwitBech32Wallet } from './hd-segwit-bech32-wallet';
|
||||
import { HDSegwitElectrumSeedP2WPKHWallet } from './hd-segwit-electrum-seed-p2wpkh-wallet';
|
||||
import { HDSegwitP2SHWallet } from './hd-segwit-p2sh-wallet';
|
||||
import { LegacyWallet } from './legacy-wallet';
|
||||
import { LightningCustodianWallet } from './lightning-custodian-wallet';
|
||||
import { LightningLdkWallet } from './lightning-ldk-wallet';
|
||||
import { MultisigHDWallet } from './multisig-hd-wallet';
|
||||
import { SegwitBech32Wallet } from './segwit-bech32-wallet';
|
||||
import { SegwitP2SHWallet } from './segwit-p2sh-wallet';
|
||||
import { SLIP39LegacyP2PKHWallet, SLIP39SegwitBech32Wallet, SLIP39SegwitP2SHWallet } from './slip39-wallets';
|
||||
import { WatchOnlyWallet } from './watch-only-wallet';
|
||||
|
||||
export type Utxo = {
|
||||
// Returned by BlueElectrum
|
||||
|
@ -80,3 +95,22 @@ export type Transaction = {
|
|||
received?: number;
|
||||
value?: number;
|
||||
};
|
||||
|
||||
export type TWallet =
|
||||
| HDAezeedWallet
|
||||
| HDLegacyBreadwalletWallet
|
||||
| HDLegacyElectrumSeedP2PKHWallet
|
||||
| HDLegacyP2PKHWallet
|
||||
| HDSegwitBech32Wallet
|
||||
| HDSegwitElectrumSeedP2WPKHWallet
|
||||
| HDSegwitP2SHWallet
|
||||
| LegacyWallet
|
||||
| LightningCustodianWallet
|
||||
| LightningLdkWallet
|
||||
| MultisigHDWallet
|
||||
| SLIP39LegacyP2PKHWallet
|
||||
| SLIP39SegwitBech32Wallet
|
||||
| SLIP39SegwitP2SHWallet
|
||||
| SegwitBech32Wallet
|
||||
| SegwitP2SHWallet
|
||||
| WatchOnlyWallet;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { StyleSheet, Platform, useWindowDimensions, View } from 'react-native';
|
||||
import Modal from 'react-native-modal';
|
||||
import { BlueSpacing10 } from '../BlueComponents';
|
||||
|
@ -18,19 +17,32 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
});
|
||||
|
||||
const BottomModal = ({
|
||||
onBackButtonPress = undefined,
|
||||
onBackdropPress = undefined,
|
||||
interface BottomModalProps {
|
||||
children?: React.ReactNode;
|
||||
onBackButtonPress?: () => void;
|
||||
onBackdropPress?: () => void;
|
||||
onClose: () => void;
|
||||
windowHeight?: number;
|
||||
windowWidth?: number;
|
||||
doneButton?: boolean;
|
||||
avoidKeyboard?: boolean;
|
||||
allowBackdropPress?: boolean;
|
||||
isVisible: boolean;
|
||||
}
|
||||
|
||||
const BottomModal: React.FC<BottomModalProps> = ({
|
||||
onBackButtonPress,
|
||||
onBackdropPress,
|
||||
onClose,
|
||||
windowHeight = undefined,
|
||||
windowWidth = undefined,
|
||||
doneButton = undefined,
|
||||
windowHeight,
|
||||
windowWidth,
|
||||
doneButton,
|
||||
isVisible,
|
||||
avoidKeyboard = false,
|
||||
allowBackdropPress = true,
|
||||
...props
|
||||
}) => {
|
||||
const valueWindowHeight = useWindowDimensions().height;
|
||||
const valueWindowWidth = useWindowDimensions().width;
|
||||
const { height: valueWindowHeight, width: valueWindowWidth } = useWindowDimensions();
|
||||
const handleBackButtonPress = onBackButtonPress ?? onClose;
|
||||
const handleBackdropPress = allowBackdropPress ? onBackdropPress ?? onClose : undefined;
|
||||
const { colors } = useTheme();
|
||||
|
@ -39,6 +51,7 @@ const BottomModal = ({
|
|||
backgroundColor: colors.elevated,
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<Modal
|
||||
style={styles.root}
|
||||
|
@ -46,6 +59,7 @@ const BottomModal = ({
|
|||
deviceWidth={windowWidth ?? valueWindowWidth}
|
||||
onBackButtonPress={handleBackButtonPress}
|
||||
onBackdropPress={handleBackdropPress}
|
||||
isVisible={isVisible}
|
||||
{...props}
|
||||
accessibilityViewIsModal
|
||||
avoidKeyboard={avoidKeyboard}
|
||||
|
@ -62,16 +76,4 @@ const BottomModal = ({
|
|||
);
|
||||
};
|
||||
|
||||
BottomModal.propTypes = {
|
||||
children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.element), PropTypes.element]),
|
||||
onBackButtonPress: PropTypes.func,
|
||||
onBackdropPress: PropTypes.func,
|
||||
onClose: PropTypes.func,
|
||||
doneButton: PropTypes.bool,
|
||||
windowHeight: PropTypes.number,
|
||||
windowWidth: PropTypes.number,
|
||||
avoidKeyboard: PropTypes.bool,
|
||||
allowBackdropPress: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default BottomModal;
|
|
@ -11,7 +11,7 @@ EventEmitter on the native side should receive a payload and rebuild menus.
|
|||
|
||||
const eventEmitter = Platform.OS === 'ios' || Platform.OS === 'macos' ? new NativeEventEmitter(NativeModules.EventEmitter) : undefined;
|
||||
const MenuElements = () => {
|
||||
const { walletsInitialized } = useContext(BlueStorageContext);
|
||||
const { walletsInitialized, reloadTransactionsMenuActionFunction } = useContext(BlueStorageContext);
|
||||
|
||||
// BlueWallet -> Settings
|
||||
const openSettings = useCallback(() => {
|
||||
|
@ -23,25 +23,50 @@ const MenuElements = () => {
|
|||
dispatchNavigate('AddWalletRoot');
|
||||
}, []);
|
||||
|
||||
const dispatchNavigate = (routeName: string) => {
|
||||
NavigationService.dispatch(
|
||||
CommonActions.navigate({
|
||||
name: routeName,
|
||||
}),
|
||||
);
|
||||
// File -> Add Wallet
|
||||
const importWalletMenuAction = useCallback(() => {
|
||||
dispatchNavigate('AddWalletRoot', 'ImportWallet');
|
||||
}, []);
|
||||
|
||||
const dispatchNavigate = (routeName: string, screen?: string) => {
|
||||
const action = screen
|
||||
? CommonActions.navigate({
|
||||
name: routeName,
|
||||
params: { screen },
|
||||
})
|
||||
: CommonActions.navigate({
|
||||
name: routeName,
|
||||
});
|
||||
|
||||
NavigationService.dispatch(action);
|
||||
};
|
||||
|
||||
const reloadTransactionsMenuElementsFunction = useCallback(() => {
|
||||
reloadTransactionsMenuActionFunction();
|
||||
}, [reloadTransactionsMenuActionFunction]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('MenuElements: useEffect');
|
||||
if (walletsInitialized) {
|
||||
eventEmitter?.addListener('openSettings', openSettings);
|
||||
eventEmitter?.addListener('addWalletMenuAction', addWalletMenuAction);
|
||||
eventEmitter?.addListener('importWalletMenuAction', importWalletMenuAction);
|
||||
eventEmitter?.addListener('reloadTransactionsMenuAction', reloadTransactionsMenuElementsFunction);
|
||||
}
|
||||
return () => {
|
||||
eventEmitter?.removeAllListeners('openSettings');
|
||||
eventEmitter?.removeAllListeners('addWalletMenuAction');
|
||||
eventEmitter?.removeAllListeners('importWalletMenuAction');
|
||||
eventEmitter?.removeAllListeners('reloadTransactionsMenuAction');
|
||||
};
|
||||
}, [addWalletMenuAction, openSettings, walletsInitialized]);
|
||||
}, [
|
||||
addWalletMenuAction,
|
||||
importWalletMenuAction,
|
||||
openSettings,
|
||||
reloadTransactionsMenuActionFunction,
|
||||
reloadTransactionsMenuElementsFunction,
|
||||
walletsInitialized,
|
||||
]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
|
|
|
@ -77,11 +77,9 @@ const TransactionsNavigationHeader: React.FC<TransactionsNavigationHeaderProps>
|
|||
};
|
||||
|
||||
const handleBalanceVisibility = async () => {
|
||||
// @ts-ignore: Gotta update this class
|
||||
const isBiometricsEnabled = await Biometric.isBiometricUseCapableAndEnabled();
|
||||
|
||||
if (isBiometricsEnabled && wallet.hideBalance) {
|
||||
// @ts-ignore: Ugh
|
||||
if (!(await Biometric.unlockWithBiometrics())) {
|
||||
return navigation.goBack();
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@ import { BlueStorageContext } from '../blue_modules/storage-context';
|
|||
|
||||
interface HandoffComponentProps {
|
||||
url?: string;
|
||||
title?: string;
|
||||
type: (typeof HandoffComponent.activityTypes)[keyof typeof HandoffComponent.activityTypes];
|
||||
userInfo?: object;
|
||||
}
|
||||
|
||||
interface HandoffComponentWithActivityTypes extends React.FC<HandoffComponentProps> {
|
||||
|
|
|
@ -44,19 +44,23 @@ export type NavigationOptionsGetter = (theme: Theme) => (deps: { navigation: any
|
|||
|
||||
const navigationStyle = (
|
||||
{
|
||||
closeButton = false,
|
||||
closeButtonFunc,
|
||||
headerBackVisible = true,
|
||||
...opts
|
||||
}: NavigationOptions & {
|
||||
closeButton?: boolean;
|
||||
|
||||
closeButtonFunc?: (deps: { navigation: any; route: any }) => React.ReactElement;
|
||||
},
|
||||
formatter: OptionsFormatter,
|
||||
): NavigationOptionsGetter => {
|
||||
return theme =>
|
||||
({ navigation, route }) => {
|
||||
// Determine if the current screen is the first one in the stack using the updated method
|
||||
const isFirstRouteInStack = navigation.getState().index === 0;
|
||||
|
||||
// Default closeButton to true if the current screen is the first one in the stack
|
||||
const closeButton = opts.closeButton !== undefined ? opts.closeButton : isFirstRouteInStack;
|
||||
|
||||
let headerRight;
|
||||
let headerLeft;
|
||||
if (closeButton) {
|
||||
|
@ -79,12 +83,11 @@ const navigationStyle = (
|
|||
);
|
||||
}
|
||||
|
||||
// Workaround for https://github.com/BlueWallet/BlueWallet/issues/6030
|
||||
if (!headerBackVisible) {
|
||||
headerLeft = () => <></>;
|
||||
// @ts-ignore: Fix later
|
||||
opts.headerLeft = headerLeft;
|
||||
}
|
||||
//
|
||||
|
||||
let options: NavigationOptions = {
|
||||
headerShadowVisible: false,
|
||||
|
@ -92,6 +95,7 @@ const navigationStyle = (
|
|||
fontWeight: '600',
|
||||
color: theme.colors.foregroundColor,
|
||||
},
|
||||
// @ts-ignore: Fix later
|
||||
headerRight,
|
||||
headerBackTitleVisible: false,
|
||||
headerTintColor: theme.colors.foregroundColor,
|
||||
|
@ -124,6 +128,7 @@ export const navigationStyleTx = (opts: NavigationOptions, formatter: OptionsFor
|
|||
// headerBackTitle: null,
|
||||
headerBackTitleVisible: false,
|
||||
headerTintColor: theme.colors.foregroundColor,
|
||||
// @ts-ignore: Fix later
|
||||
headerLeft: () => (
|
||||
<TouchableOpacity
|
||||
accessibilityRole="button"
|
||||
|
|
|
@ -28,7 +28,6 @@ function scanQrHelper(
|
|||
|
||||
params.onBarScanned = function (data: any) {
|
||||
setTimeout(() => resolve(data.data || data), 1);
|
||||
navigateFunc(currentScreenName);
|
||||
navigateFunc({ name: currentScreenName, params: {}, merge: true });
|
||||
};
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
import { AbstractWallet } from '../class';
|
||||
|
||||
module.exports = function (
|
||||
navigateFunc: (scr: string, params?: any) => void,
|
||||
navigateFunc: (scr: string | any, params?: any) => void,
|
||||
currentScreenName: string,
|
||||
chainType: string | null,
|
||||
availableWallets?: AbstractWallet[],
|
||||
|
@ -40,7 +40,7 @@ module.exports = function (
|
|||
|
||||
setTimeout(() => resolve(selectedWallet), 1);
|
||||
console.warn('trying to navigate back to', currentScreenName);
|
||||
navigateFunc(currentScreenName);
|
||||
navigateFunc({ name: currentScreenName, params: {}, merge: true });
|
||||
};
|
||||
|
||||
navigateFunc('SelectWallet', params);
|
||||
|
|
|
@ -89,7 +89,7 @@
|
|||
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 */; };
|
||||
C978A716948AB7DEC5B6F677 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; };
|
||||
C978A716948AB7DEC5B6F677 /* (null) in Frameworks */ = {isa = PBXBuildFile; };
|
||||
E5D4794B26781FC0007838C1 /* fiatUnits.json in Resources */ = {isa = PBXBuildFile; fileRef = 6DD410AD266CAF1F0087DE03 /* fiatUnits.json */; };
|
||||
E5D4794C26781FC1007838C1 /* fiatUnits.json in Resources */ = {isa = PBXBuildFile; fileRef = 6DD410AD266CAF1F0087DE03 /* fiatUnits.json */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
@ -393,7 +393,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;
|
||||
|
@ -1001,7 +1001,7 @@
|
|||
);
|
||||
mainGroup = 83CBB9F61A601CBA00E9B192;
|
||||
packageReferences = (
|
||||
6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode.git" */,
|
||||
6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode" */,
|
||||
B41B76832B66B2FF002C48D5 /* XCRemoteSwiftPackageReference "bugsnag-cocoa" */,
|
||||
);
|
||||
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
|
||||
|
@ -1526,7 +1526,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 1703112800;
|
||||
CURRENT_PROJECT_VERSION = 1703112810;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = A7W54YZ4WU;
|
||||
|
@ -1551,7 +1551,7 @@
|
|||
"$(SDKROOT)/System/iOSSupport/usr/lib/swift",
|
||||
"$(inherited)",
|
||||
);
|
||||
MARKETING_VERSION = 6.5.2;
|
||||
MARKETING_VERSION = 6.5.3;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
|
@ -1584,9 +1584,9 @@
|
|||
CODE_SIGN_ENTITLEMENTS = BlueWallet/BlueWalletRelease.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 1703112800;
|
||||
CURRENT_PROJECT_VERSION = 1703112810;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = A7W54YZ4WU;
|
||||
|
@ -1606,7 +1606,7 @@
|
|||
"$(SDKROOT)/System/iOSSupport/usr/lib/swift",
|
||||
"$(inherited)",
|
||||
);
|
||||
MARKETING_VERSION = 6.5.2;
|
||||
MARKETING_VERSION = 6.5.3;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
|
@ -1617,7 +1617,7 @@
|
|||
PRODUCT_NAME = BlueWallet;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore io.bluewallet.bluewallet";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "BlueWallet Mac App Store";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "match AppStore io.bluewallet.bluewallet catalyst";
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
|
@ -1643,7 +1643,7 @@
|
|||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 1703112800;
|
||||
CURRENT_PROJECT_VERSION = 1703112810;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
|
@ -1688,7 +1688,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1703112800;
|
||||
CURRENT_PROJECT_VERSION = 1703112810;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
|
@ -1733,7 +1733,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 1703112800;
|
||||
CURRENT_PROJECT_VERSION = 1703112810;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
|
@ -1787,13 +1787,15 @@
|
|||
CODE_SIGN_ENTITLEMENTS = WidgetsExtension.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1703112800;
|
||||
CURRENT_PROJECT_VERSION = 1703112810;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = A7W54YZ4WU;
|
||||
"DEVELOPMENT_TEAM[sdk=macosx*]" = A7W54YZ4WU;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = Widgets/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
||||
|
@ -1814,6 +1816,7 @@
|
|||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore io.bluewallet.bluewallet.MarketWidget";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "match AppStore io.bluewallet.bluewallet.MarketWidget catalyst";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
|
@ -1959,7 +1962,7 @@
|
|||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 1703112800;
|
||||
CURRENT_PROJECT_VERSION = 1703112810;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
|
@ -1976,7 +1979,7 @@
|
|||
"$(SDKROOT)/System/iOSSupport/usr/lib/swift",
|
||||
"$(inherited)",
|
||||
);
|
||||
MARKETING_VERSION = 6.5.2;
|
||||
MARKETING_VERSION = 6.5.3;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRESERVE_DEAD_CODE_INITS_AND_TERMS = YES;
|
||||
|
@ -2009,7 +2012,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1703112800;
|
||||
CURRENT_PROJECT_VERSION = 1703112810;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
|
@ -2026,7 +2029,7 @@
|
|||
"$(SDKROOT)/System/iOSSupport/usr/lib/swift",
|
||||
"$(inherited)",
|
||||
);
|
||||
MARKETING_VERSION = 6.5.2;
|
||||
MARKETING_VERSION = 6.5.3;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRESERVE_DEAD_CODE_INITS_AND_TERMS = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.watch.extension;
|
||||
|
@ -2058,7 +2061,7 @@
|
|||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 1703112800;
|
||||
CURRENT_PROJECT_VERSION = 1703112810;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
|
@ -2071,7 +2074,7 @@
|
|||
"$(SDKROOT)/System/iOSSupport/usr/lib/swift",
|
||||
"$(inherited)",
|
||||
);
|
||||
MARKETING_VERSION = 6.5.2;
|
||||
MARKETING_VERSION = 6.5.3;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRESERVE_DEAD_CODE_INITS_AND_TERMS = YES;
|
||||
|
@ -2106,7 +2109,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1703112800;
|
||||
CURRENT_PROJECT_VERSION = 1703112810;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
|
@ -2119,7 +2122,7 @@
|
|||
"$(SDKROOT)/System/iOSSupport/usr/lib/swift",
|
||||
"$(inherited)",
|
||||
);
|
||||
MARKETING_VERSION = 6.5.2;
|
||||
MARKETING_VERSION = 6.5.3;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRESERVE_DEAD_CODE_INITS_AND_TERMS = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.watch;
|
||||
|
@ -2149,7 +2152,7 @@
|
|||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 1703112800;
|
||||
CURRENT_PROJECT_VERSION = 1703112810;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
|
@ -2199,7 +2202,7 @@
|
|||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1703112800;
|
||||
CURRENT_PROJECT_VERSION = 1703112810;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
|
@ -2238,7 +2241,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = BlueWallet/BlueWallet.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1703112800;
|
||||
CURRENT_PROJECT_VERSION = 1703112810;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = A7W54YZ4WU;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
@ -2262,7 +2265,7 @@
|
|||
"$(SDKROOT)/System/iOSSupport/usr/lib/swift",
|
||||
"$(inherited)",
|
||||
);
|
||||
MARKETING_VERSION = 6.5.2;
|
||||
MARKETING_VERSION = 6.5.3;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
|
@ -2278,7 +2281,7 @@
|
|||
SWIFT_OBJC_BRIDGING_HEADER = "BlueWallet-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 4.2;
|
||||
TARGETED_DEVICE_FAMILY = 2;
|
||||
TARGETED_DEVICE_FAMILY = "2,6";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Debug;
|
||||
|
@ -2291,10 +2294,14 @@
|
|||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = BlueWallet/BlueWalletRelease.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1703112800;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 1703112810;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = A7W54YZ4WU;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = A7W54YZ4WU;
|
||||
"DEVELOPMENT_TEAM[sdk=macosx*]" = A7W54YZ4WU;
|
||||
ENABLE_BITCODE = NO;
|
||||
"ENABLE_HARDENED_RUNTIME[sdk=macosx*]" = YES;
|
||||
HEADER_SEARCH_PATHS = "$(inherited)";
|
||||
|
@ -2311,7 +2318,7 @@
|
|||
"$(SDKROOT)/System/iOSSupport/usr/lib/swift",
|
||||
"$(inherited)",
|
||||
);
|
||||
MARKETING_VERSION = 6.5.2;
|
||||
MARKETING_VERSION = 6.5.3;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
|
@ -2321,12 +2328,14 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet;
|
||||
PRODUCT_NAME = BlueWallet;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore io.bluewallet.bluewallet";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "match AppStore io.bluewallet.bluewallet catalyst";
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "BlueWallet-Bridging-Header.h";
|
||||
SWIFT_VERSION = 4.2;
|
||||
TARGETED_DEVICE_FAMILY = 2;
|
||||
TARGETED_DEVICE_FAMILY = "2,6";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Release;
|
||||
|
@ -2409,7 +2418,7 @@
|
|||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode.git" */ = {
|
||||
6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/EFPrefix/EFQRCode.git";
|
||||
requirement = {
|
||||
|
@ -2430,7 +2439,7 @@
|
|||
/* Begin XCSwiftPackageProductDependency section */
|
||||
6DFC806F24EA0B6C007B8700 /* EFQRCode */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode.git" */;
|
||||
package = 6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode" */;
|
||||
productName = EFQRCode;
|
||||
};
|
||||
B41B76842B66B2FF002C48D5 /* Bugsnag */ = {
|
||||
|
|
|
@ -24,6 +24,11 @@
|
|||
<key>orderHint</key>
|
||||
<integer>100</integer>
|
||||
</dict>
|
||||
<key>BlueWallet-NoLDK.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>134</integer>
|
||||
</dict>
|
||||
<key>BlueWallet.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
|
@ -32,7 +37,7 @@
|
|||
<key>BlueWalletUITests.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>99</integer>
|
||||
<integer>97</integer>
|
||||
</dict>
|
||||
<key>BlueWalletWatch (Complication).xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
|
|
|
@ -127,10 +127,6 @@
|
|||
completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
|
||||
}
|
||||
|
||||
- (void)openSettings:(UIKeyCommand *)keyCommand {
|
||||
[EventEmitter.sharedInstance openSettings];
|
||||
}
|
||||
|
||||
- (void)buildMenuWithBuilder:(id<UIMenuBuilder>)builder {
|
||||
[super buildMenuWithBuilder:builder];
|
||||
[builder removeMenuForIdentifier:UIMenuServices];
|
||||
|
@ -138,18 +134,27 @@
|
|||
[builder removeMenuForIdentifier:UIMenuToolbar];
|
||||
|
||||
// File -> Add Wallet (Command + A)
|
||||
UIKeyCommand *addWalletCommand = [UIKeyCommand keyCommandWithInput:@"A" modifierFlags:UIKeyModifierCommand action:@selector(addWalletAction:)];
|
||||
[addWalletCommand setTitle:@"Add Wallet"];
|
||||
UIMenu *addWalletMenu = [UIMenu menuWithTitle:@"" image:nil identifier:nil options:UIMenuOptionsDisplayInline children:@[addWalletCommand]];
|
||||
UIKeyCommand *addWalletCommand = [UIKeyCommand keyCommandWithInput:@"A" modifierFlags:UIKeyModifierCommand action:@selector(addWalletAction:)];
|
||||
[addWalletCommand setTitle:@"Add Wallet"];
|
||||
|
||||
|
||||
// Modify the existing File menu
|
||||
UIMenu *fileMenu = [builder menuForIdentifier:UIMenuFile];
|
||||
if (fileMenu) {
|
||||
// Replace the children of the File menu with the Add Wallet menu
|
||||
UIMenu *newFileMenu = [UIMenu menuWithTitle:fileMenu.title image:nil identifier:fileMenu.identifier options:fileMenu.options children:@[addWalletMenu]];
|
||||
[builder replaceMenuForIdentifier:UIMenuFile withMenu:newFileMenu];
|
||||
}
|
||||
// File -> Import Wallet
|
||||
UIKeyCommand *importWalletCommand = [UIKeyCommand keyCommandWithInput:@"I" modifierFlags:UIKeyModifierCommand action:@selector(importWalletAction:)];
|
||||
[importWalletCommand setTitle:@"Import Wallet"];
|
||||
|
||||
// Group Add Wallet and Import Wallet in a displayInline menu
|
||||
UIMenu *walletOperationsMenu = [UIMenu menuWithTitle:@"" image:nil identifier:nil options:UIMenuOptionsDisplayInline children:@[addWalletCommand, importWalletCommand]];
|
||||
|
||||
// Modify the existing File menu to include Wallet Operations
|
||||
UIMenu *fileMenu = [builder menuForIdentifier:UIMenuFile];
|
||||
if (fileMenu) {
|
||||
// Add "Reload Transactions"
|
||||
UIKeyCommand *reloadTransactionsCommand = [UIKeyCommand keyCommandWithInput:@"R" modifierFlags:UIKeyModifierCommand action:@selector(reloadTransactionsAction:)];
|
||||
[reloadTransactionsCommand setTitle:@"Reload Transactions"];
|
||||
|
||||
// Combine wallet operations and Reload Transactions into the new File menu
|
||||
UIMenu *newFileMenu = [UIMenu menuWithTitle:fileMenu.title image:nil identifier:fileMenu.identifier options:fileMenu.options children:@[walletOperationsMenu, reloadTransactionsCommand]];
|
||||
[builder replaceMenuForIdentifier:UIMenuFile withMenu:newFileMenu];
|
||||
}
|
||||
|
||||
// BlueWallet -> Settings (Command + ,)
|
||||
UIKeyCommand *settingsCommand = [UIKeyCommand keyCommandWithInput:@"," modifierFlags:UIKeyModifierCommand action:@selector(openSettings:)];
|
||||
|
@ -159,7 +164,11 @@
|
|||
[builder insertSiblingMenu:settings afterMenuForIdentifier:UIMenuAbout];
|
||||
}
|
||||
|
||||
// Action for Add Wallet
|
||||
|
||||
- (void)openSettings:(UIKeyCommand *)keyCommand {
|
||||
[EventEmitter.sharedInstance openSettings];
|
||||
}
|
||||
|
||||
- (void)addWalletAction:(UIKeyCommand *)keyCommand {
|
||||
// Implement the functionality for adding a wallet
|
||||
[EventEmitter.sharedInstance addWalletMenuAction];
|
||||
|
@ -167,6 +176,21 @@
|
|||
NSLog(@"Add Wallet action performed");
|
||||
}
|
||||
|
||||
- (void)importWalletAction:(UIKeyCommand *)keyCommand {
|
||||
// Implement the functionality for adding a wallet
|
||||
[EventEmitter.sharedInstance importWalletMenuAction];
|
||||
|
||||
NSLog(@"Add Wallet action performed");
|
||||
}
|
||||
|
||||
- (void)reloadTransactionsAction:(UIKeyCommand *)keyCommand {
|
||||
// Implement the functionality for adding a wallet
|
||||
[EventEmitter.sharedInstance reloadTransactionsMenuAction];
|
||||
|
||||
NSLog(@"Add Wallet action performed");
|
||||
}
|
||||
|
||||
|
||||
|
||||
-(void)showHelp:(id)sender {
|
||||
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://bluewallet.io/docs"] options:@{} completionHandler:nil];
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
- (void)sendNotification:(NSDictionary *)userInfo;
|
||||
- (void)openSettings;
|
||||
- (void)addWalletMenuAction;
|
||||
- (void)importWalletMenuAction;
|
||||
- (void)reloadTransactionsMenuAction;
|
||||
- (void)sendUserActivity:(NSDictionary *)userInfo;
|
||||
|
||||
@end
|
||||
|
|
|
@ -32,7 +32,7 @@ RCT_EXPORT_MODULE();
|
|||
}
|
||||
|
||||
- (NSArray<NSString *> *)supportedEvents {
|
||||
return @[@"onNotificationReceived",@"openSettings",@"onUserActivityOpen",@"addWalletMenuAction"];
|
||||
return @[@"onNotificationReceived",@"openSettings",@"onUserActivityOpen",@"addWalletMenuAction", @"importWalletMenuAction", @"reloadTransactionsMenuAction"];
|
||||
}
|
||||
|
||||
- (void)sendNotification:(NSDictionary *)userInfo
|
||||
|
@ -62,4 +62,12 @@ RCT_REMAP_METHOD(getMostRecentUserActivity, resolve: (RCTPromiseResolveBlock)res
|
|||
[sharedInstance sendEventWithName:@"addWalletMenuAction" body:nil];
|
||||
}
|
||||
|
||||
- (void)importWalletMenuAction {
|
||||
[sharedInstance sendEventWithName:@"importWalletMenuAction" body:nil];
|
||||
}
|
||||
|
||||
- (void)reloadTransactionsMenuAction {
|
||||
[sharedInstance sendEventWithName:@"reloadTransactionsMenuAction" body:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -352,7 +352,7 @@ PODS:
|
|||
- react-native-tcp-socket (6.0.6):
|
||||
- CocoaAsyncSocket
|
||||
- React-Core
|
||||
- react-native-webview (13.7.1):
|
||||
- react-native-webview (13.8.1):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core
|
||||
- react-native-widget-center (0.0.9):
|
||||
|
@ -504,7 +504,7 @@ PODS:
|
|||
- React-Core
|
||||
- RNReactNativeHapticFeedback (2.2.0):
|
||||
- React-Core
|
||||
- RNReanimated (3.6.2):
|
||||
- RNReanimated (3.7.0):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- React-Core
|
||||
- ReactCommon/turbomodule/core
|
||||
|
@ -823,7 +823,7 @@ SPEC CHECKSUMS:
|
|||
react-native-safe-area-context: b97eb6f9e3b7f437806c2ce5983f479f8eb5de4b
|
||||
react-native-secure-key-store: 910e6df6bc33cb790aba6ee24bc7818df1fe5898
|
||||
react-native-tcp-socket: e724380c910c2e704816ec817ed28f1342246ff7
|
||||
react-native-webview: 83525c9ed4138faf5d5e4f8eb74bf050992935be
|
||||
react-native-webview: bdc091de8cf7f8397653e30182efcd9f772e03b3
|
||||
react-native-widget-center: 12dfba20a4fa995850b52cf0afecf734397f4b9c
|
||||
React-NativeModulesApple: c3e696ff867e4bc212266cbdf7e862e48a0166fd
|
||||
React-perflogger: 43287389ea08993c300897a46f95cfac04bb6c1a
|
||||
|
@ -860,7 +860,7 @@ SPEC CHECKSUMS:
|
|||
RNQuickAction: 6d404a869dc872cde841ad3147416a670d13fa93
|
||||
RNRate: ef3bcff84f39bb1d1e41c5593d3eea4aab2bd73a
|
||||
RNReactNativeHapticFeedback: ec56a5f81c3941206fd85625fa669ffc7b4545f9
|
||||
RNReanimated: ce6bef77caeee09d7f022532cee0c8d9bad09c9a
|
||||
RNReanimated: 9dfe7a19dd7c3e123b23db42e74bf051725f2ea3
|
||||
RNScreens: 3c5b9f4a9dcde752466854b6109b79c0e205dad3
|
||||
RNShare: 859ff710211285676b0bcedd156c12437ea1d564
|
||||
RNSVG: d00c8f91c3cbf6d476451313a18f04d220d4f396
|
||||
|
|
|
@ -281,6 +281,7 @@
|
|||
"language": "Idioma",
|
||||
"last_updated": "Última actualización",
|
||||
"language_isRTL": "Es necesario reiniciar BlueWallet para que la orientación del idioma surta efecto.",
|
||||
"license": "Licencia",
|
||||
"lightning_error_lndhub_uri": "URI de LNDHub inválido",
|
||||
"lightning_saved": "Tus cambios han sido guardados correctamente.",
|
||||
"lightning_settings": "Configuración de Lightning",
|
||||
|
|
146
package-lock.json
generated
146
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "bluewallet",
|
||||
"version": "6.5.2",
|
||||
"version": "6.5.3",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "bluewallet",
|
||||
"version": "6.5.2",
|
||||
"version": "6.5.3",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
@ -19,9 +19,9 @@
|
|||
"@react-native-async-storage/async-storage": "1.21.0",
|
||||
"@react-native-clipboard/clipboard": "1.13.2",
|
||||
"@react-native-community/push-notification-ios": "1.11.0",
|
||||
"@react-navigation/drawer": "6.6.6",
|
||||
"@react-navigation/native": "6.1.9",
|
||||
"@react-navigation/native-stack": "6.9.17",
|
||||
"@react-navigation/drawer": "6.6.7",
|
||||
"@react-navigation/native": "6.1.10",
|
||||
"@react-navigation/native-stack": "6.9.18",
|
||||
"@remobile/react-native-qrcode-local-image": "https://github.com/BlueWallet/react-native-qrcode-local-image",
|
||||
"@spsina/bip47": "github:BlueWallet/bip47#0a2f02c90350802f2ec93afa4e6c8843be2d687c",
|
||||
"aezeed": "0.0.5",
|
||||
|
@ -42,7 +42,7 @@
|
|||
"coinselect": "3.1.13",
|
||||
"crypto-js": "4.2.0",
|
||||
"dayjs": "1.11.10",
|
||||
"detox": "20.17.0",
|
||||
"detox": "20.17.1",
|
||||
"ecpair": "2.0.1",
|
||||
"ecurve": "1.0.6",
|
||||
"electrum-client": "github:BlueWallet/rn-electrum-client#1bfe3cc",
|
||||
|
@ -89,7 +89,7 @@
|
|||
"react-native-quick-actions": "0.3.13",
|
||||
"react-native-randombytes": "3.6.1",
|
||||
"react-native-rate": "1.2.12",
|
||||
"react-native-reanimated": "3.6.2",
|
||||
"react-native-reanimated": "3.7.0",
|
||||
"react-native-safe-area-context": "4.9.0",
|
||||
"react-native-screens": "3.29.0",
|
||||
"react-native-secure-key-store": "https://github.com/BlueWallet/react-native-secure-key-store#2076b48",
|
||||
|
@ -98,7 +98,7 @@
|
|||
"react-native-tcp-socket": "6.0.6",
|
||||
"react-native-vector-icons": "10.0.3",
|
||||
"react-native-watch-connectivity": "1.1.0",
|
||||
"react-native-webview": "13.7.1",
|
||||
"react-native-webview": "13.8.1",
|
||||
"react-native-widget-center": "https://github.com/BlueWallet/react-native-widget-center#a128c38",
|
||||
"readable-stream": "3.6.2",
|
||||
"realm": "12.6.0",
|
||||
|
@ -117,12 +117,14 @@
|
|||
"@react-native/eslint-config": "^0.72.2",
|
||||
"@react-native/metro-config": "^0.73.0",
|
||||
"@tsconfig/react-native": "^3.0.2",
|
||||
"@types/bip38": "^3.1.2",
|
||||
"@types/bs58check": "^2.1.0",
|
||||
"@types/create-hash": "^1.2.2",
|
||||
"@types/jest": "^29.4.0",
|
||||
"@types/react": "^18.2.16",
|
||||
"@types/react-native": "^0.72.0",
|
||||
"@types/react-test-renderer": "^18.0.0",
|
||||
"@types/wif": "^2.0.5",
|
||||
"@typescript-eslint/eslint-plugin": "^6.2.0",
|
||||
"@typescript-eslint/parser": "^6.2.0",
|
||||
"eslint": "^8.45.0",
|
||||
|
@ -6379,11 +6381,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@react-navigation/drawer": {
|
||||
"version": "6.6.6",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/drawer/-/drawer-6.6.6.tgz",
|
||||
"integrity": "sha512-DW/oNRisSOGOqvZfCzfhKBxnzT97Teqtg1Gal85g+K3gnVbM1jOBE2PdnYsKU0fULfFtDwvp/QZSbcgjDpr12A==",
|
||||
"version": "6.6.7",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/drawer/-/drawer-6.6.7.tgz",
|
||||
"integrity": "sha512-9hSJySPQcG33vV199uzkI3jHewvAGjVFF2bhC28TkQYDKtp/DmtTvjCEiecOm+qep1Qp4ksh5vBo2P0A1hF6vQ==",
|
||||
"dependencies": {
|
||||
"@react-navigation/elements": "^1.3.21",
|
||||
"@react-navigation/elements": "^1.3.22",
|
||||
"color": "^4.2.3",
|
||||
"warn-once": "^0.1.0"
|
||||
},
|
||||
|
@ -6398,9 +6400,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@react-navigation/elements": {
|
||||
"version": "1.3.21",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.21.tgz",
|
||||
"integrity": "sha512-eyS2C6McNR8ihUoYfc166O1D8VYVh9KIl0UQPI8/ZJVsStlfSTgeEEh+WXge6+7SFPnZ4ewzEJdSAHH+jzcEfg==",
|
||||
"version": "1.3.22",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.22.tgz",
|
||||
"integrity": "sha512-HYKucs0TwQT8zMvgoZbJsY/3sZfzeP8Dk9IDv4agst3zlA7ReTx4+SROCG6VGC7JKqBCyQykHIwkSwxhapoc+Q==",
|
||||
"peerDependencies": {
|
||||
"@react-navigation/native": "^6.0.0",
|
||||
"react": "*",
|
||||
|
@ -6409,9 +6411,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@react-navigation/native": {
|
||||
"version": "6.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.9.tgz",
|
||||
"integrity": "sha512-AMuJDpwXE7UlfyhIXaUCCynXmv69Kb8NzKgKJO7v0k0L+u6xUTbt6xvshmJ79vsvaFyaEH9Jg5FMzek5/S5qNw==",
|
||||
"version": "6.1.10",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.10.tgz",
|
||||
"integrity": "sha512-jDG89TbZItY7W7rIcS1RqT63vWOPD4XuQLNKqZO0DY7mKnKh/CGBd0eg3nDMXUl143Qp//IxJKe2TfBQRDEU4A==",
|
||||
"dependencies": {
|
||||
"@react-navigation/core": "^6.4.10",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
|
@ -6424,11 +6426,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@react-navigation/native-stack": {
|
||||
"version": "6.9.17",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/native-stack/-/native-stack-6.9.17.tgz",
|
||||
"integrity": "sha512-X8p8aS7JptQq7uZZNFEvfEcPf6tlK4PyVwYDdryRbG98B4bh2wFQYMThxvqa+FGEN7USEuHdv2mF0GhFKfX0ew==",
|
||||
"version": "6.9.18",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/native-stack/-/native-stack-6.9.18.tgz",
|
||||
"integrity": "sha512-PSe0qjROy8zD78ehW048NSuzWRktioSCJmB8LzWSR65ndgVaC2rO+xvgyjhHjqm01YdyVM1XTct2EorSjDV2Ow==",
|
||||
"dependencies": {
|
||||
"@react-navigation/elements": "^1.3.21",
|
||||
"@react-navigation/elements": "^1.3.22",
|
||||
"warn-once": "^0.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
@ -6556,6 +6558,15 @@
|
|||
"@babel/types": "^7.20.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/bip38": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/bip38/-/bip38-3.1.2.tgz",
|
||||
"integrity": "sha512-KF5aiS7DUJs2llJJeg1O1Io129PETszfUfDQotJ4VPBXzytpIUmb7n2MHWEdFYRHs2LYoaRivP/aJbTlF56J+Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/bn.js": {
|
||||
"version": "4.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz",
|
||||
|
@ -6719,6 +6730,15 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
|
||||
"integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="
|
||||
},
|
||||
"node_modules/@types/wif": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/wif/-/wif-2.0.5.tgz",
|
||||
"integrity": "sha512-addYBlYjDxLfJxDUoyTzICnu0u4snCdGJpICIIFk65zGcdjah3twTJq1Fdy+OdeZSRiof2raFtMqSqF9KeqthQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/yargs": {
|
||||
"version": "16.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz",
|
||||
|
@ -9626,9 +9646,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/detox": {
|
||||
"version": "20.17.0",
|
||||
"resolved": "https://registry.npmjs.org/detox/-/detox-20.17.0.tgz",
|
||||
"integrity": "sha512-IasYgexfkrCoZuJTaqqKHQ2yflK+tnqifzdLwrp4hdTWlXUlG9j/YcM1Dn3ThSs3b6VNMtbSe6xoPkKD0oNiIQ==",
|
||||
"version": "20.17.1",
|
||||
"resolved": "https://registry.npmjs.org/detox/-/detox-20.17.1.tgz",
|
||||
"integrity": "sha512-10pey6CR9D5GSloRkH60ObBGZ8VS11H7iuBNY7qq6jO2swiqqckHhPLRXfH9+WGR7l3vDnfU+G/gQs7JxQkJwA==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"ajv": "^8.6.3",
|
||||
|
@ -19875,9 +19895,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/react-native-reanimated": {
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.6.2.tgz",
|
||||
"integrity": "sha512-IIMREMOrxhtK35drfpzh2UhxNqAOHnuvGgtMofj7yHcMj16tmWZR2zFvMUf6z2MfmXv+aVgFQ6TRZ6yKYf7LNA==",
|
||||
"version": "3.7.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.7.0.tgz",
|
||||
"integrity": "sha512-KM+MKa3CJWqsF4GlOLLKBxTR2NEcrg5/HP9J2b6Dfgvll1sjZPywCOEEIh967SboEU8N9LjYZuoVm2UoXGxp2Q==",
|
||||
"dependencies": {
|
||||
"@babel/plugin-transform-object-assign": "^7.16.7",
|
||||
"@babel/preset-typescript": "^7.16.7",
|
||||
|
@ -20053,9 +20073,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/react-native-webview": {
|
||||
"version": "13.7.1",
|
||||
"resolved": "https://registry.npmjs.org/react-native-webview/-/react-native-webview-13.7.1.tgz",
|
||||
"integrity": "sha512-tnfTgjIYY3KnBfbN9hRCJf2y/6JZBev3aq2ZacLml0AZn4ufTe4MyCiE1NAZ/l5WHV/1eaqN0srxn45ATL0+Ow==",
|
||||
"version": "13.8.1",
|
||||
"resolved": "https://registry.npmjs.org/react-native-webview/-/react-native-webview-13.8.1.tgz",
|
||||
"integrity": "sha512-7Jqm1WzWJrOWraBAXQfKtr/Uo5Jw/IJHzC40jYLwgV/eVGmLJ9BpGKw6QVw7wpRkjmTZ2Typ4B1aHJLJJQFslA==",
|
||||
"dependencies": {
|
||||
"escape-string-regexp": "2.0.0",
|
||||
"invariant": "2.2.4"
|
||||
|
@ -27344,24 +27364,24 @@
|
|||
}
|
||||
},
|
||||
"@react-navigation/drawer": {
|
||||
"version": "6.6.6",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/drawer/-/drawer-6.6.6.tgz",
|
||||
"integrity": "sha512-DW/oNRisSOGOqvZfCzfhKBxnzT97Teqtg1Gal85g+K3gnVbM1jOBE2PdnYsKU0fULfFtDwvp/QZSbcgjDpr12A==",
|
||||
"version": "6.6.7",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/drawer/-/drawer-6.6.7.tgz",
|
||||
"integrity": "sha512-9hSJySPQcG33vV199uzkI3jHewvAGjVFF2bhC28TkQYDKtp/DmtTvjCEiecOm+qep1Qp4ksh5vBo2P0A1hF6vQ==",
|
||||
"requires": {
|
||||
"@react-navigation/elements": "^1.3.21",
|
||||
"@react-navigation/elements": "^1.3.22",
|
||||
"color": "^4.2.3",
|
||||
"warn-once": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"@react-navigation/elements": {
|
||||
"version": "1.3.21",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.21.tgz",
|
||||
"integrity": "sha512-eyS2C6McNR8ihUoYfc166O1D8VYVh9KIl0UQPI8/ZJVsStlfSTgeEEh+WXge6+7SFPnZ4ewzEJdSAHH+jzcEfg=="
|
||||
"version": "1.3.22",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.22.tgz",
|
||||
"integrity": "sha512-HYKucs0TwQT8zMvgoZbJsY/3sZfzeP8Dk9IDv4agst3zlA7ReTx4+SROCG6VGC7JKqBCyQykHIwkSwxhapoc+Q=="
|
||||
},
|
||||
"@react-navigation/native": {
|
||||
"version": "6.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.9.tgz",
|
||||
"integrity": "sha512-AMuJDpwXE7UlfyhIXaUCCynXmv69Kb8NzKgKJO7v0k0L+u6xUTbt6xvshmJ79vsvaFyaEH9Jg5FMzek5/S5qNw==",
|
||||
"version": "6.1.10",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.10.tgz",
|
||||
"integrity": "sha512-jDG89TbZItY7W7rIcS1RqT63vWOPD4XuQLNKqZO0DY7mKnKh/CGBd0eg3nDMXUl143Qp//IxJKe2TfBQRDEU4A==",
|
||||
"requires": {
|
||||
"@react-navigation/core": "^6.4.10",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
|
@ -27370,11 +27390,11 @@
|
|||
}
|
||||
},
|
||||
"@react-navigation/native-stack": {
|
||||
"version": "6.9.17",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/native-stack/-/native-stack-6.9.17.tgz",
|
||||
"integrity": "sha512-X8p8aS7JptQq7uZZNFEvfEcPf6tlK4PyVwYDdryRbG98B4bh2wFQYMThxvqa+FGEN7USEuHdv2mF0GhFKfX0ew==",
|
||||
"version": "6.9.18",
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/native-stack/-/native-stack-6.9.18.tgz",
|
||||
"integrity": "sha512-PSe0qjROy8zD78ehW048NSuzWRktioSCJmB8LzWSR65ndgVaC2rO+xvgyjhHjqm01YdyVM1XTct2EorSjDV2Ow==",
|
||||
"requires": {
|
||||
"@react-navigation/elements": "^1.3.21",
|
||||
"@react-navigation/elements": "^1.3.22",
|
||||
"warn-once": "^0.1.0"
|
||||
}
|
||||
},
|
||||
|
@ -27490,6 +27510,15 @@
|
|||
"@babel/types": "^7.20.7"
|
||||
}
|
||||
},
|
||||
"@types/bip38": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/bip38/-/bip38-3.1.2.tgz",
|
||||
"integrity": "sha512-KF5aiS7DUJs2llJJeg1O1Io129PETszfUfDQotJ4VPBXzytpIUmb7n2MHWEdFYRHs2LYoaRivP/aJbTlF56J+Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/bn.js": {
|
||||
"version": "4.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz",
|
||||
|
@ -27655,6 +27684,15 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
|
||||
"integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="
|
||||
},
|
||||
"@types/wif": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/wif/-/wif-2.0.5.tgz",
|
||||
"integrity": "sha512-addYBlYjDxLfJxDUoyTzICnu0u4snCdGJpICIIFk65zGcdjah3twTJq1Fdy+OdeZSRiof2raFtMqSqF9KeqthQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/yargs": {
|
||||
"version": "16.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz",
|
||||
|
@ -29873,9 +29911,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"detox": {
|
||||
"version": "20.17.0",
|
||||
"resolved": "https://registry.npmjs.org/detox/-/detox-20.17.0.tgz",
|
||||
"integrity": "sha512-IasYgexfkrCoZuJTaqqKHQ2yflK+tnqifzdLwrp4hdTWlXUlG9j/YcM1Dn3ThSs3b6VNMtbSe6xoPkKD0oNiIQ==",
|
||||
"version": "20.17.1",
|
||||
"resolved": "https://registry.npmjs.org/detox/-/detox-20.17.1.tgz",
|
||||
"integrity": "sha512-10pey6CR9D5GSloRkH60ObBGZ8VS11H7iuBNY7qq6jO2swiqqckHhPLRXfH9+WGR7l3vDnfU+G/gQs7JxQkJwA==",
|
||||
"requires": {
|
||||
"ajv": "^8.6.3",
|
||||
"bunyan": "^1.8.12",
|
||||
|
@ -37593,9 +37631,9 @@
|
|||
}
|
||||
},
|
||||
"react-native-reanimated": {
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.6.2.tgz",
|
||||
"integrity": "sha512-IIMREMOrxhtK35drfpzh2UhxNqAOHnuvGgtMofj7yHcMj16tmWZR2zFvMUf6z2MfmXv+aVgFQ6TRZ6yKYf7LNA==",
|
||||
"version": "3.7.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.7.0.tgz",
|
||||
"integrity": "sha512-KM+MKa3CJWqsF4GlOLLKBxTR2NEcrg5/HP9J2b6Dfgvll1sjZPywCOEEIh967SboEU8N9LjYZuoVm2UoXGxp2Q==",
|
||||
"requires": {
|
||||
"@babel/plugin-transform-object-assign": "^7.16.7",
|
||||
"@babel/preset-typescript": "^7.16.7",
|
||||
|
@ -37709,9 +37747,9 @@
|
|||
}
|
||||
},
|
||||
"react-native-webview": {
|
||||
"version": "13.7.1",
|
||||
"resolved": "https://registry.npmjs.org/react-native-webview/-/react-native-webview-13.7.1.tgz",
|
||||
"integrity": "sha512-tnfTgjIYY3KnBfbN9hRCJf2y/6JZBev3aq2ZacLml0AZn4ufTe4MyCiE1NAZ/l5WHV/1eaqN0srxn45ATL0+Ow==",
|
||||
"version": "13.8.1",
|
||||
"resolved": "https://registry.npmjs.org/react-native-webview/-/react-native-webview-13.8.1.tgz",
|
||||
"integrity": "sha512-7Jqm1WzWJrOWraBAXQfKtr/Uo5Jw/IJHzC40jYLwgV/eVGmLJ9BpGKw6QVw7wpRkjmTZ2Typ4B1aHJLJJQFslA==",
|
||||
"requires": {
|
||||
"escape-string-regexp": "2.0.0",
|
||||
"invariant": "2.2.4"
|
||||
|
|
10
package.json
10
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "bluewallet",
|
||||
"version": "6.5.2",
|
||||
"version": "6.5.3",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -13,12 +13,14 @@
|
|||
"@react-native/eslint-config": "^0.72.2",
|
||||
"@react-native/metro-config": "^0.73.0",
|
||||
"@tsconfig/react-native": "^3.0.2",
|
||||
"@types/bip38": "^3.1.2",
|
||||
"@types/bs58check": "^2.1.0",
|
||||
"@types/create-hash": "^1.2.2",
|
||||
"@types/jest": "^29.4.0",
|
||||
"@types/react": "^18.2.16",
|
||||
"@types/react-native": "^0.72.0",
|
||||
"@types/react-test-renderer": "^18.0.0",
|
||||
"@types/wif": "^2.0.5",
|
||||
"@typescript-eslint/eslint-plugin": "^6.2.0",
|
||||
"@typescript-eslint/parser": "^6.2.0",
|
||||
"eslint": "^8.45.0",
|
||||
|
@ -95,7 +97,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@babel/preset-env": "^7.20.0",
|
||||
"@bugsnag/react-native": "7.22.4",
|
||||
"@bugsnag/react-native": "7.22.5",
|
||||
"@bugsnag/source-maps": "2.3.1",
|
||||
"@keystonehq/bc-ur-registry": "0.6.4",
|
||||
"@ngraveio/bc-ur": "1.1.6",
|
||||
|
@ -173,7 +175,7 @@
|
|||
"react-native-quick-actions": "0.3.13",
|
||||
"react-native-randombytes": "3.6.1",
|
||||
"react-native-rate": "1.2.12",
|
||||
"react-native-reanimated": "3.6.2",
|
||||
"react-native-reanimated": "3.7.0",
|
||||
"react-native-safe-area-context": "4.9.0",
|
||||
"react-native-screens": "3.29.0",
|
||||
"react-native-secure-key-store": "https://github.com/BlueWallet/react-native-secure-key-store#2076b48",
|
||||
|
@ -182,7 +184,7 @@
|
|||
"react-native-tcp-socket": "6.0.6",
|
||||
"react-native-vector-icons": "10.0.3",
|
||||
"react-native-watch-connectivity": "1.1.0",
|
||||
"react-native-webview": "13.7.1",
|
||||
"react-native-webview": "13.8.1",
|
||||
"react-native-widget-center": "https://github.com/BlueWallet/react-native-widget-center#a128c38",
|
||||
"readable-stream": "3.6.2",
|
||||
"realm": "12.6.0",
|
||||
|
|
|
@ -9,7 +9,6 @@ import { BlueStorageContext } from '../blue_modules/storage-context';
|
|||
import presentAlert from '../components/Alert';
|
||||
import Button from '../components/Button';
|
||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../blue_modules/hapticFeedback';
|
||||
import SafeArea from '../components/SafeArea';
|
||||
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
|
||||
const prompt = require('../helpers/prompt');
|
||||
|
||||
|
@ -75,14 +74,12 @@ const PlausibleDeniability: React.FC = () => {
|
|||
}
|
||||
};
|
||||
|
||||
return state.isLoading ? (
|
||||
<SafeArea>
|
||||
<BlueLoading />
|
||||
</SafeArea>
|
||||
) : (
|
||||
<SafeArea>
|
||||
<BlueCard>
|
||||
<ScrollView>
|
||||
return (
|
||||
<ScrollView centerContent={state.isLoading} automaticallyAdjustContentInsets contentInsetAdjustmentBehavior="automatic">
|
||||
{state.isLoading ? (
|
||||
<BlueLoading />
|
||||
) : (
|
||||
<BlueCard>
|
||||
<BlueText>{loc.plausibledeniability.help}</BlueText>
|
||||
<BlueText />
|
||||
<BlueText>{loc.plausibledeniability.help2}</BlueText>
|
||||
|
@ -92,9 +89,9 @@ const PlausibleDeniability: React.FC = () => {
|
|||
title={loc.plausibledeniability.create_fake_storage}
|
||||
onPress={handleOnCreateFakeStorageButtonPressed}
|
||||
/>
|
||||
</ScrollView>
|
||||
</BlueCard>
|
||||
</SafeArea>
|
||||
</BlueCard>
|
||||
)}
|
||||
</ScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -77,16 +77,12 @@ const LdkOpenChannel = (props: any) => {
|
|||
}, [psbt]);
|
||||
|
||||
useEffect(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
Biometric.isBiometricUseCapableAndEnabled().then(setIsBiometricUseCapableAndEnabled);
|
||||
}, []);
|
||||
|
||||
const finalizeOpenChannel = async () => {
|
||||
setIsLoading(true);
|
||||
if (isBiometricUseCapableAndEnabled) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
if (!(await Biometric.unlockWithBiometrics())) {
|
||||
setIsLoading(false);
|
||||
return;
|
||||
|
|
|
@ -23,8 +23,7 @@ import Button from '../../components/Button';
|
|||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||
import SafeArea from '../../components/SafeArea';
|
||||
import presentAlert from '../../components/Alert';
|
||||
|
||||
const scanqr = require('../../helpers/scan-qr');
|
||||
import { scanQrHelper } from '../../helpers/scan-qr';
|
||||
|
||||
const BROADCAST_RESULT = Object.freeze({
|
||||
none: 'Input transaction hex',
|
||||
|
@ -78,7 +77,7 @@ const Broadcast = () => {
|
|||
};
|
||||
|
||||
const handleQRScan = async () => {
|
||||
const scannedData = await scanqr(navigate, name);
|
||||
const scannedData = await scanQrHelper(navigate, name);
|
||||
if (!scannedData) return;
|
||||
|
||||
if (scannedData.indexOf('+') === -1 && scannedData.indexOf('=') === -1 && scannedData.indexOf('=') === -1) {
|
||||
|
|
|
@ -2,40 +2,37 @@ import React from 'react';
|
|||
import { ScrollView } from 'react-native';
|
||||
import navigationStyle from '../../components/navigationStyle';
|
||||
import { BlueCard, BlueText, BlueSpacing20 } from '../../BlueComponents';
|
||||
import SafeArea from '../../components/SafeArea';
|
||||
import loc from '../../loc';
|
||||
|
||||
const Licensing = () => {
|
||||
return (
|
||||
<SafeArea>
|
||||
<ScrollView>
|
||||
<BlueCard>
|
||||
<BlueText>MIT License</BlueText>
|
||||
<BlueSpacing20 />
|
||||
<BlueText>Copyright (c) 2018-2024 BlueWallet developers</BlueText>
|
||||
<BlueSpacing20 />
|
||||
<BlueText>
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
|
||||
(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
</BlueText>
|
||||
<BlueSpacing20 />
|
||||
<ScrollView contentInsetAdjustmentBehavior="automatic" automaticallyAdjustContentInsets>
|
||||
<BlueCard>
|
||||
<BlueText>MIT License</BlueText>
|
||||
<BlueSpacing20 />
|
||||
<BlueText>Copyright (c) 2018-2024 BlueWallet developers</BlueText>
|
||||
<BlueSpacing20 />
|
||||
<BlueText>
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
|
||||
(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
</BlueText>
|
||||
<BlueSpacing20 />
|
||||
|
||||
<BlueText>
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
</BlueText>
|
||||
<BlueSpacing20 />
|
||||
<BlueText>
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
</BlueText>
|
||||
<BlueSpacing20 />
|
||||
|
||||
<BlueText>
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
</BlueText>
|
||||
</BlueCard>
|
||||
</ScrollView>
|
||||
</SafeArea>
|
||||
<BlueText>
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
</BlueText>
|
||||
</BlueCard>
|
||||
</ScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -53,8 +53,8 @@ const EncryptStorage = () => {
|
|||
popToTop();
|
||||
} catch (e) {
|
||||
if (password) {
|
||||
presentAlert({ message: loc._.bad_password });
|
||||
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
|
||||
presentAlert({ message: loc._.bad_password });
|
||||
}
|
||||
|
||||
setIsLoading(false);
|
||||
|
@ -83,6 +83,7 @@ const EncryptStorage = () => {
|
|||
saveToDisk();
|
||||
} else {
|
||||
setIsLoading(false);
|
||||
triggerHapticFeedback(HapticFeedbackTypes.NotificationError);
|
||||
presentAlert({ message: loc.settings.passwords_do_not_match });
|
||||
}
|
||||
} else {
|
||||
|
@ -124,7 +125,7 @@ const EncryptStorage = () => {
|
|||
};
|
||||
|
||||
return isLoading ? (
|
||||
<ScrollView>
|
||||
<ScrollView centerContent>
|
||||
<BlueLoading />
|
||||
</ScrollView>
|
||||
) : (
|
||||
|
|
|
@ -36,8 +36,15 @@ const WalletsListSections = { CAROUSEL: 'CAROUSEL', TRANSACTIONS: 'TRANSACTIONS'
|
|||
const WalletsList = () => {
|
||||
const walletsCarousel = useRef();
|
||||
const currentWalletIndex = useRef(0);
|
||||
const { wallets, getTransactions, getBalance, refreshAllWalletTransactions, setSelectedWalletID, isElectrumDisabled } =
|
||||
useContext(BlueStorageContext);
|
||||
const {
|
||||
wallets,
|
||||
getTransactions,
|
||||
getBalance,
|
||||
refreshAllWalletTransactions,
|
||||
setSelectedWalletID,
|
||||
isElectrumDisabled,
|
||||
setReloadTransactionsMenuActionFunction,
|
||||
} = useContext(BlueStorageContext);
|
||||
const { width } = useWindowDimensions();
|
||||
const { colors, scanImage } = useTheme();
|
||||
const { navigate, setOptions } = useNavigation();
|
||||
|
@ -67,6 +74,10 @@ const WalletsList = () => {
|
|||
useCallback(() => {
|
||||
verifyBalance();
|
||||
setSelectedWalletID(undefined);
|
||||
setReloadTransactionsMenuActionFunction(onRefresh);
|
||||
return () => {
|
||||
setReloadTransactionsMenuActionFunction(() => {});
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []),
|
||||
);
|
||||
|
@ -352,6 +363,12 @@ const WalletsList = () => {
|
|||
refreshTransactions(true, false);
|
||||
};
|
||||
|
||||
const refreshProps = isDesktop
|
||||
? {}
|
||||
: {
|
||||
...(isElectrumDisabled ? {} : { refreshing: isLoading, onRefresh }),
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={styles.root} onLayout={onLayout}>
|
||||
<View style={[styles.walletsListWrapper, stylesHook.walletsListWrapper]}>
|
||||
|
@ -359,8 +376,7 @@ const WalletsList = () => {
|
|||
removeClippedSubviews
|
||||
contentInsetAdjustmentBehavior="automatic"
|
||||
automaticallyAdjustContentInsets
|
||||
refreshing={isLoading}
|
||||
{...(isElectrumDisabled ? {} : { refreshing: isLoading, onRefresh })}
|
||||
{...refreshProps}
|
||||
renderItem={renderSectionItem}
|
||||
keyExtractor={sectionListKeyExtractor}
|
||||
renderSectionHeader={renderSectionHeader}
|
||||
|
|
|
@ -45,7 +45,14 @@ const buttonFontSize =
|
|||
: PixelRatio.roundToNearestPixel(Dimensions.get('window').width / 26);
|
||||
|
||||
const WalletTransactions = ({ navigation }) => {
|
||||
const { wallets, saveToDisk, setSelectedWalletID, walletTransactionUpdateStatus, isElectrumDisabled } = useContext(BlueStorageContext);
|
||||
const {
|
||||
wallets,
|
||||
saveToDisk,
|
||||
setSelectedWalletID,
|
||||
walletTransactionUpdateStatus,
|
||||
isElectrumDisabled,
|
||||
setReloadTransactionsMenuActionFunction,
|
||||
} = useContext(BlueStorageContext);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { walletID } = useRoute().params;
|
||||
const { name } = useRoute();
|
||||
|
@ -502,6 +509,22 @@ const WalletTransactions = ({ navigation }) => {
|
|||
index,
|
||||
});
|
||||
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
setReloadTransactionsMenuActionFunction(refreshTransactions);
|
||||
return () => {
|
||||
setReloadTransactionsMenuActionFunction(undefined);
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []),
|
||||
);
|
||||
|
||||
const refreshProps = isDesktop
|
||||
? {}
|
||||
: {
|
||||
...(isElectrumDisabled ? {} : { refreshing: isLoading, refreshTransactions }),
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={styles.flex}>
|
||||
<TransactionsNavigationHeader
|
||||
|
@ -567,7 +590,7 @@ const WalletTransactions = ({ navigation }) => {
|
|||
{isLightning() && <Text style={styles.emptyTxsLightning}>{loc.wallets.list_empty_txs2_lightning}</Text>}
|
||||
</ScrollView>
|
||||
}
|
||||
{...(isElectrumDisabled ? {} : { refreshing: isLoading, onRefresh: refreshTransactions })}
|
||||
{...refreshProps}
|
||||
data={dataSource}
|
||||
extraData={[timeElapsed, dataSource, wallets]}
|
||||
keyExtractor={_keyExtractor}
|
||||
|
|
|
@ -1,122 +0,0 @@
|
|||
import React, { useCallback, useContext, useEffect, useState } from 'react';
|
||||
import { InteractionManager, ActivityIndicator, View, StyleSheet } from 'react-native';
|
||||
import { useFocusEffect, useRoute, useNavigation } from '@react-navigation/native';
|
||||
import Share from 'react-native-share';
|
||||
|
||||
import navigationStyle from '../../components/navigationStyle';
|
||||
import { BlueSpacing20, BlueText, BlueCopyTextToClipboard } from '../../BlueComponents';
|
||||
import Privacy from '../../blue_modules/Privacy';
|
||||
import Biometric from '../../class/biometrics';
|
||||
import loc from '../../loc';
|
||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||
import QRCodeComponent from '../../components/QRCodeComponent';
|
||||
import HandoffComponent from '../../components/handoff';
|
||||
import { useTheme } from '../../components/themes';
|
||||
import Button from '../../components/Button';
|
||||
import SafeArea from '../../components/SafeArea';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flex: 1,
|
||||
paddingTop: 20,
|
||||
},
|
||||
container: {
|
||||
alignItems: 'center',
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
},
|
||||
share: {
|
||||
alignSelf: 'center',
|
||||
width: '40%',
|
||||
},
|
||||
});
|
||||
|
||||
const WalletXpub = () => {
|
||||
const { wallets } = useContext(BlueStorageContext);
|
||||
const { walletID, xpub } = useRoute().params;
|
||||
const wallet = wallets.find(w => w.getID() === walletID);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [xPubText, setXPubText] = useState();
|
||||
const { goBack, setParams } = useNavigation();
|
||||
const { colors } = useTheme();
|
||||
const [qrCodeSize, setQRCodeSize] = useState(90);
|
||||
const stylesHook = StyleSheet.create({ root: { backgroundColor: colors.elevated } });
|
||||
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
Privacy.enableBlur();
|
||||
const task = InteractionManager.runAfterInteractions(async () => {
|
||||
if (wallet) {
|
||||
const isBiometricsEnabled = await Biometric.isBiometricUseCapableAndEnabled();
|
||||
|
||||
if (isBiometricsEnabled) {
|
||||
if (!(await Biometric.unlockWithBiometrics())) {
|
||||
return goBack();
|
||||
}
|
||||
}
|
||||
setParams({ xpub: wallet.getXpub() });
|
||||
setIsLoading(false);
|
||||
} else if (xpub) {
|
||||
setIsLoading(false);
|
||||
}
|
||||
});
|
||||
return () => {
|
||||
task.cancel();
|
||||
Privacy.disableBlur();
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [goBack, walletID]),
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setXPubText(xpub);
|
||||
}, [xpub]);
|
||||
|
||||
const onLayout = e => {
|
||||
const { height, width } = e.nativeEvent.layout;
|
||||
setQRCodeSize(height > width ? width - 40 : e.nativeEvent.layout.width / 1.8);
|
||||
};
|
||||
|
||||
const handleShareButtonPressed = () => {
|
||||
Share.open({ message: xpub }).catch(error => console.log(error));
|
||||
};
|
||||
|
||||
return isLoading ? (
|
||||
<View style={[styles.container, stylesHook.root]}>
|
||||
<ActivityIndicator />
|
||||
</View>
|
||||
) : (
|
||||
<SafeArea style={[styles.root, stylesHook.root]} onLayout={onLayout}>
|
||||
<>
|
||||
<View style={styles.container}>
|
||||
{wallet && (
|
||||
<>
|
||||
<View>
|
||||
<BlueText>{wallet.typeReadable}</BlueText>
|
||||
</View>
|
||||
<BlueSpacing20 />
|
||||
</>
|
||||
)}
|
||||
<QRCodeComponent value={xpub} size={qrCodeSize} />
|
||||
|
||||
<BlueSpacing20 />
|
||||
<BlueCopyTextToClipboard text={xPubText} />
|
||||
</View>
|
||||
<HandoffComponent title={loc.wallets.xpub_title} type={HandoffComponent.activityTypes.Xpub} userInfo={{ xpub: xPubText }} />
|
||||
<View style={styles.share}>
|
||||
<Button onPress={handleShareButtonPressed} title={loc.receive.details_share} />
|
||||
</View>
|
||||
</>
|
||||
</SafeArea>
|
||||
);
|
||||
};
|
||||
|
||||
WalletXpub.navigationOptions = navigationStyle(
|
||||
{
|
||||
closeButton: true,
|
||||
headerBackVisible: false,
|
||||
},
|
||||
opts => ({ ...opts, headerTitle: loc.wallets.xpub_title }),
|
||||
);
|
||||
|
||||
export default WalletXpub;
|
42
screen/wallets/xpub.styles.ts
Normal file
42
screen/wallets/xpub.styles.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
import { StyleSheet } from 'react-native';
|
||||
import { useTheme } from '../../components/themes';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
root: {
|
||||
flex: 1,
|
||||
paddingTop: 20,
|
||||
},
|
||||
container: {
|
||||
alignItems: 'center',
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
},
|
||||
share: {
|
||||
alignSelf: 'center',
|
||||
width: '40%',
|
||||
},
|
||||
});
|
||||
|
||||
export const useDynamicStyles = () => {
|
||||
const theme = useTheme();
|
||||
|
||||
const stylesHook = useMemo(
|
||||
() =>
|
||||
StyleSheet.create({
|
||||
root: {
|
||||
backgroundColor: theme.colors.elevated,
|
||||
// Add more dynamic styles as needed
|
||||
},
|
||||
container: {
|
||||
// Example of another dynamic style
|
||||
borderColor: theme.colors.inputBorderColor,
|
||||
borderWidth: 1,
|
||||
},
|
||||
// You can add more dynamically themed styles here
|
||||
}),
|
||||
[theme],
|
||||
); // Recompute styles only when theme changes
|
||||
|
||||
return stylesHook;
|
||||
};
|
124
screen/wallets/xpub.tsx
Normal file
124
screen/wallets/xpub.tsx
Normal file
|
@ -0,0 +1,124 @@
|
|||
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
|
||||
import { InteractionManager, ActivityIndicator, View } from 'react-native';
|
||||
import { useFocusEffect, useRoute, useNavigation, RouteProp, NavigationProp } from '@react-navigation/native';
|
||||
import Share from 'react-native-share';
|
||||
import { styles, useDynamicStyles } from './xpub.styles';
|
||||
import navigationStyle from '../../components/navigationStyle';
|
||||
import { BlueSpacing20, BlueText, BlueCopyTextToClipboard } from '../../BlueComponents';
|
||||
import Privacy from '../../blue_modules/Privacy';
|
||||
import Biometric from '../../class/biometrics';
|
||||
import loc from '../../loc';
|
||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||
import QRCodeComponent from '../../components/QRCodeComponent';
|
||||
import HandoffComponent from '../../components/handoff';
|
||||
import Button from '../../components/Button';
|
||||
import SafeArea from '../../components/SafeArea';
|
||||
import { AbstractWallet } from '../../class';
|
||||
|
||||
type WalletXpubRouteProp = RouteProp<{ params: { walletID: string; xpub: string } }, 'params'>;
|
||||
export type RootStackParamList = {
|
||||
WalletXpub: {
|
||||
walletID: string;
|
||||
xpub: string;
|
||||
};
|
||||
};
|
||||
|
||||
const WalletXpub: React.FC = () => {
|
||||
const { wallets } = useContext(BlueStorageContext);
|
||||
const route = useRoute<WalletXpubRouteProp>();
|
||||
const { walletID, xpub } = route.params;
|
||||
const wallet = wallets.find((w: AbstractWallet) => w.getID() === walletID);
|
||||
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||
const [xPubText, setXPubText] = useState<string | undefined>(undefined);
|
||||
const navigation = useNavigation<NavigationProp<RootStackParamList, 'WalletXpub'>>();
|
||||
const stylesHook = useDynamicStyles(); // This now includes the theme implicitly
|
||||
const [qrCodeSize, setQRCodeSize] = useState<number>(90);
|
||||
const lastWalletIdRef = useRef<string | undefined>();
|
||||
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
// Skip execution if walletID hasn't changed
|
||||
if (lastWalletIdRef.current === walletID) {
|
||||
return;
|
||||
}
|
||||
Privacy.enableBlur();
|
||||
const task = InteractionManager.runAfterInteractions(async () => {
|
||||
if (wallet) {
|
||||
const isBiometricsEnabled = await Biometric.isBiometricUseCapableAndEnabled();
|
||||
|
||||
if (isBiometricsEnabled) {
|
||||
if (!(await Biometric.unlockWithBiometrics())) {
|
||||
return navigation.goBack();
|
||||
}
|
||||
}
|
||||
const walletXpub = wallet.getXpub();
|
||||
if (xpub !== walletXpub) {
|
||||
navigation.setParams({ xpub: walletXpub });
|
||||
}
|
||||
|
||||
setIsLoading(false);
|
||||
} else if (xpub) {
|
||||
setIsLoading(false);
|
||||
}
|
||||
});
|
||||
lastWalletIdRef.current = walletID;
|
||||
return () => {
|
||||
task.cancel();
|
||||
Privacy.disableBlur();
|
||||
};
|
||||
}, [wallet, xpub, walletID, navigation]),
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setXPubText(xpub);
|
||||
}, [xpub]);
|
||||
|
||||
const onLayout = (e: { nativeEvent: { layout: { width: any; height?: any } } }) => {
|
||||
const { height, width } = e.nativeEvent.layout;
|
||||
setQRCodeSize(height > width ? width - 40 : e.nativeEvent.layout.width / 1.8);
|
||||
};
|
||||
|
||||
const handleShareButtonPressed = useCallback(() => {
|
||||
Share.open({ message: xpub }).catch(console.log);
|
||||
}, [xpub]);
|
||||
|
||||
return (
|
||||
<SafeArea style={[styles.root, stylesHook.root]} onLayout={onLayout}>
|
||||
{isLoading ? (
|
||||
<ActivityIndicator />
|
||||
) : (
|
||||
<>
|
||||
<View style={styles.container}>
|
||||
{wallet && (
|
||||
<>
|
||||
<View>
|
||||
<BlueText>{wallet.typeReadable}</BlueText>
|
||||
</View>
|
||||
<BlueSpacing20 />
|
||||
</>
|
||||
)}
|
||||
<QRCodeComponent value={xpub} size={qrCodeSize} />
|
||||
|
||||
<BlueSpacing20 />
|
||||
<BlueCopyTextToClipboard text={xPubText} />
|
||||
</View>
|
||||
<HandoffComponent title={loc.wallets.xpub_title} type={HandoffComponent.activityTypes.Xpub} userInfo={{ xpub: xPubText }} />
|
||||
<View style={styles.share}>
|
||||
<Button onPress={handleShareButtonPressed} title={loc.receive.details_share} />
|
||||
</View>
|
||||
</>
|
||||
)}
|
||||
</SafeArea>
|
||||
);
|
||||
};
|
||||
|
||||
// @ts-ignore: Deal with later
|
||||
WalletXpub.navigationOptions = navigationStyle(
|
||||
{
|
||||
closeButton: true,
|
||||
headerBackVisible: false,
|
||||
},
|
||||
opts => ({ ...opts, headerTitle: loc.wallets.xpub_title }),
|
||||
);
|
||||
|
||||
export default WalletXpub;
|
|
@ -1,23 +1,28 @@
|
|||
#!/bin/bash
|
||||
|
||||
|
||||
# assumes 2 env variables: KEYSTORE_FILE_HEX & KEYSTORE_PASSWORD
|
||||
#
|
||||
|
||||
# PS. to turn file to hex and back:
|
||||
# $ xxd -plain test.txt > test.hex
|
||||
# $ xxd -plain -revert test.hex test2.txt
|
||||
|
||||
|
||||
echo $KEYSTORE_FILE_HEX > bluewallet-release-key.keystore.hex
|
||||
xxd -plain -revert bluewallet-release-key.keystore.hex > ./android/bluewallet-release-key.keystore
|
||||
rm bluewallet-release-key.keystore.hex
|
||||
|
||||
cd android
|
||||
TIMESTAMP=$(date +%s)
|
||||
sed -i'.original' "s/versionCode 1/versionCode $TIMESTAMP/g" app/build.gradle
|
||||
# Use the BUILD_NUMBER environment variable set in the GitHub Actions workflow
|
||||
sed -i'.original' "s/versionCode 1/versionCode $BUILD_NUMBER/g" app/build.gradle
|
||||
|
||||
# Extract versionName from build.gradle
|
||||
VERSION_NAME=$(grep versionName app/build.gradle | awk '{print $2}' | tr -d '"')
|
||||
|
||||
./gradlew assembleRelease
|
||||
mv ./app/build/outputs/apk/release/app-release-unsigned.apk ./app/build/outputs/apk/release/app-release.apk
|
||||
|
||||
# Rename the APK file to include the dynamic version and build number with parentheses
|
||||
mv ./app/build/outputs/apk/release/app-release-unsigned.apk "./app/build/outputs/apk/release/BlueWallet-${VERSION_NAME}($BUILD_NUMBER).apk"
|
||||
|
||||
echo wheres waldo?
|
||||
find $ANDROID_HOME | grep apksigner | grep -v jar
|
||||
$ANDROID_HOME/build-tools/34.0.0/apksigner sign --ks ./bluewallet-release-key.keystore --ks-pass=pass:$KEYSTORE_PASSWORD ./app/build/outputs/apk/release/app-release.apk
|
||||
|
||||
$ANDROID_HOME/build-tools/34.0.0/apksigner sign --ks ./bluewallet-release-key.keystore --ks-pass=pass:$KEYSTORE_PASSWORD "./app/build/outputs/apk/release/BlueWallet-${VERSION_NAME}($BUILD_NUMBER).apk"
|
||||
|
|
4
typings/react-native-passcode-auth.d.ts
vendored
Normal file
4
typings/react-native-passcode-auth.d.ts
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
declare module 'react-native-passcode-auth' {
|
||||
declare function isSupported(): Promise<boolean>;
|
||||
declare function authenticate(): Promise<boolean>;
|
||||
}
|
Loading…
Add table
Reference in a new issue