mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-02-22 06:52:41 +01:00
ADD: Biometrics
FIX: Added FaceID Usage description ADD: Use Biometrics for Show balance. ADD: Unlock With Boot Screen FIX: Allow the use of Biometrics after decrypt FIX: Build system revert. FIX: Remove biometric from receive address. ADD: Biometric for export FIX: Use RNSecureKeyStore for biometrics FIX: Realign views Update biometrics.js
This commit is contained in:
parent
461a8e24f7
commit
29ce0271f8
23 changed files with 302 additions and 42 deletions
|
@ -33,6 +33,7 @@ import ToolTip from 'react-native-tooltip';
|
||||||
import { BlurView } from '@react-native-community/blur';
|
import { BlurView } from '@react-native-community/blur';
|
||||||
import showPopupMenu from 'react-native-popup-menu-android';
|
import showPopupMenu from 'react-native-popup-menu-android';
|
||||||
import NetworkTransactionFees, { NetworkTransactionFeeType } from './models/networkTransactionFees';
|
import NetworkTransactionFees, { NetworkTransactionFeeType } from './models/networkTransactionFees';
|
||||||
|
import Biometric from './class/biometrics';
|
||||||
let loc = require('./loc/');
|
let loc = require('./loc/');
|
||||||
/** @type {AppStorage} */
|
/** @type {AppStorage} */
|
||||||
let BlueApp = require('./BlueApp');
|
let BlueApp = require('./BlueApp');
|
||||||
|
@ -179,6 +180,15 @@ export class BlueWalletNavigationHeader extends Component {
|
||||||
|
|
||||||
handleBalanceVisibility = async _item => {
|
handleBalanceVisibility = async _item => {
|
||||||
const wallet = this.state.wallet;
|
const wallet = this.state.wallet;
|
||||||
|
|
||||||
|
const isBiometricsEnabled = await Biometric.isBiometricUseCapableAndEnabled();
|
||||||
|
|
||||||
|
if (isBiometricsEnabled && wallet.hideBalance) {
|
||||||
|
if (!(await Biometric.unlockWithBiometrics())) {
|
||||||
|
return this.props.navigation.goBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wallet.hideBalance = !wallet.hideBalance;
|
wallet.hideBalance = !wallet.hideBalance;
|
||||||
this.setState({ wallet });
|
this.setState({ wallet });
|
||||||
await BlueApp.saveToDisk();
|
await BlueApp.saveToDisk();
|
||||||
|
|
97
UnlockWith.js
Normal file
97
UnlockWith.js
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import { View, Image, TouchableOpacity } from 'react-native';
|
||||||
|
import { Icon } from 'react-native-elements';
|
||||||
|
import Biometric from './class/biometrics';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import Biometrics from 'react-native-biometrics';
|
||||||
|
import { SafeAreaView } from 'react-navigation';
|
||||||
|
/** @type {AppStorage} */
|
||||||
|
|
||||||
|
const BlueApp = require('./BlueApp');
|
||||||
|
|
||||||
|
export default class UnlockWith extends Component {
|
||||||
|
state = { biometricType: false, isStorageEncrypted: false, isAuthenticating: false };
|
||||||
|
|
||||||
|
async componentDidMount() {
|
||||||
|
let biometricType = false;
|
||||||
|
const isStorageEncrypted = await BlueApp.storageIsEncrypted();
|
||||||
|
if ((await Biometric.isBiometricUseCapableAndEnabled()) && !isStorageEncrypted) {
|
||||||
|
biometricType = await Biometric.biometricType();
|
||||||
|
}
|
||||||
|
this.setState({ biometricType, isStorageEncrypted }, async () => {
|
||||||
|
if (!biometricType) {
|
||||||
|
await BlueApp.startAndDecrypt();
|
||||||
|
this.props.onSuccessfullyAuthenticated();
|
||||||
|
} else if (biometricType !== false && !isStorageEncrypted) this.unlockWithBiometrics();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
successfullyAuthenticated = () => {
|
||||||
|
this.props.onSuccessfullyAuthenticated();
|
||||||
|
};
|
||||||
|
|
||||||
|
unlockWithBiometrics = () => {
|
||||||
|
this.setState({ isAuthenticating: true }, async () => {
|
||||||
|
if (await Biometric.unlockWithBiometrics()) {
|
||||||
|
await BlueApp.startAndDecrypt();
|
||||||
|
return this.props.onSuccessfullyAuthenticated();
|
||||||
|
}
|
||||||
|
this.setState({ isAuthenticating: false });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (!this.state.biometricType && !this.state.isStorageEncrypted) {
|
||||||
|
return <View />;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={{ flex: 1 }}>
|
||||||
|
<View style={{ flex: 2, justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
|
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
||||||
|
<Image source={require('./img/qr-code.png')} style={{ width: 120, height: 120 }} />
|
||||||
|
</View>
|
||||||
|
<View style={{ flex: 0.1, justifyContent: 'flex-end', marginBottom: 64 }}>
|
||||||
|
<View style={{ justifyContent: 'center', flexDirection: 'row' }}>
|
||||||
|
{this.state.biometricType === Biometrics.TouchID && (
|
||||||
|
<>
|
||||||
|
<TouchableOpacity disabled={this.state.isAuthenticating} onPress={this.unlockWithBiometrics}>
|
||||||
|
<Image source={require('./img/fingerprint.png')} style={{ width: 64, height: 64 }} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{this.state.biometricType === Biometrics.FaceID && (
|
||||||
|
<>
|
||||||
|
<TouchableOpacity disabled={this.state.isAuthenticating} onPress={this.unlockWithBiometrics}>
|
||||||
|
<Image source={require('./img/faceid.png')} style={{ width: 64, height: 64 }} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{this.state.biometricType !== false && this.state.isStorageEncrypted && (
|
||||||
|
<View style={{ backgroundColor: 'gray', width: 0.5, height: 20, marginHorizontal: 16 }} />
|
||||||
|
)}
|
||||||
|
{this.state.isStorageEncrypted && (
|
||||||
|
<>
|
||||||
|
<TouchableOpacity
|
||||||
|
disabled={this.state.isAuthenticating}
|
||||||
|
onPress={() => {
|
||||||
|
this.setState({ isAuthenticating: true }, async () => {
|
||||||
|
await BlueApp.startAndDecrypt();
|
||||||
|
this.props.onSuccessfullyAuthenticated();
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Icon name="key" size={64} type="font-awesome" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UnlockWith.propTypes = {
|
||||||
|
onSuccessfullyAuthenticated: PropTypes.func,
|
||||||
|
};
|
|
@ -118,7 +118,7 @@ android {
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "4.5.0"
|
versionName "4.5.1"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
missingDimensionStrategy 'react-native-camera', 'general'
|
missingDimensionStrategy 'react-native-camera', 'general'
|
||||||
}
|
}
|
||||||
|
|
51
class/biometrics.js
Normal file
51
class/biometrics.js
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import Biometrics from 'react-native-biometrics';
|
||||||
|
const BlueApp = require('../BlueApp');
|
||||||
|
|
||||||
|
export default class Biometric {
|
||||||
|
static STORAGEKEY = 'Biometrics';
|
||||||
|
|
||||||
|
static async isDeviceBiometricCapable() {
|
||||||
|
if ((await Biometrics.isSensorAvailable()) !== null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Biometric.setBiometricUseEnabled(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async biometricType() {
|
||||||
|
return Biometrics.isSensorAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
static async isBiometricUseEnabled() {
|
||||||
|
try {
|
||||||
|
const enabledBiometrics = await BlueApp.getItem(Biometric.STORAGEKEY);
|
||||||
|
return !!enabledBiometrics;
|
||||||
|
} catch (_e) {
|
||||||
|
await BlueApp.setItem(Biometric.STORAGEKEY, '');
|
||||||
|
return !!'';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async isBiometricUseCapableAndEnabled() {
|
||||||
|
const isBiometricUseEnabled = await Biometric.isBiometricUseEnabled();
|
||||||
|
const isDeviceBiometricCapable = await Biometric.isDeviceBiometricCapable();
|
||||||
|
return !!isBiometricUseEnabled && isDeviceBiometricCapable;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async setBiometricUseEnabled(value) {
|
||||||
|
await BlueApp.setItem(Biometric.STORAGEKEY, value === true ? '1' : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
static async unlockWithBiometrics() {
|
||||||
|
const isDeviceBiometricCapable = await Biometric.isDeviceBiometricCapable();
|
||||||
|
if (isDeviceBiometricCapable) {
|
||||||
|
try {
|
||||||
|
await Biometrics.simplePrompt('Please confirm your identity.');
|
||||||
|
return true;
|
||||||
|
} catch (_e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
BIN
img/faceid.png
Normal file
BIN
img/faceid.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.6 KiB |
BIN
img/fingerprint.png
Normal file
BIN
img/fingerprint.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
13
index.js
13
index.js
|
@ -2,15 +2,15 @@ import 'intl';
|
||||||
import 'intl/locale-data/jsonp/en';
|
import 'intl/locale-data/jsonp/en';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './shim.js';
|
import './shim.js';
|
||||||
import App from './App';
|
|
||||||
import { Sentry } from 'react-native-sentry';
|
import { Sentry } from 'react-native-sentry';
|
||||||
import { AppRegistry } from 'react-native';
|
import { AppRegistry } from 'react-native';
|
||||||
import WalletMigrate from './screen/wallets/walletMigrate';
|
import WalletMigrate from './screen/wallets/walletMigrate';
|
||||||
import { name as appName } from './app.json';
|
import { name as appName } from './app.json';
|
||||||
|
import App from './App';
|
||||||
import LottieView from 'lottie-react-native';
|
import LottieView from 'lottie-react-native';
|
||||||
|
import UnlockWith from './UnlockWith.js';
|
||||||
|
|
||||||
/** @type {AppStorage} */
|
/** @type {AppStorage} */
|
||||||
const BlueApp = require('./BlueApp');
|
|
||||||
let A = require('./analytics');
|
let A = require('./analytics');
|
||||||
if (process.env.NODE_ENV !== 'development') {
|
if (process.env.NODE_ENV !== 'development') {
|
||||||
Sentry.config('https://23377936131848ca8003448a893cb622@sentry.io/1295736').install();
|
Sentry.config('https://23377936131848ca8003448a893cb622@sentry.io/1295736').install();
|
||||||
|
@ -24,7 +24,7 @@ if (!Error.captureStackTrace) {
|
||||||
class BlueAppComponent extends React.Component {
|
class BlueAppComponent extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = { isMigratingData: true, onAnimationFinished: false };
|
this.state = { isMigratingData: true, onAnimationFinished: false, successfullyAuthenticated: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -33,7 +33,6 @@ class BlueAppComponent extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsMigratingData = async () => {
|
setIsMigratingData = async () => {
|
||||||
await BlueApp.startAndDecrypt();
|
|
||||||
A(A.ENUM.INIT);
|
A(A.ENUM.INIT);
|
||||||
this.setState({ isMigratingData: false });
|
this.setState({ isMigratingData: false });
|
||||||
};
|
};
|
||||||
|
@ -46,6 +45,10 @@ class BlueAppComponent extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onSuccessfullyAuthenticated = () => {
|
||||||
|
this.setState({ successfullyAuthenticated: true })
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.state.isMigratingData) {
|
if (this.state.isMigratingData) {
|
||||||
return (
|
return (
|
||||||
|
@ -59,7 +62,7 @@ class BlueAppComponent extends React.Component {
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (this.state.onAnimationFinished) {
|
if (this.state.onAnimationFinished) {
|
||||||
return <App />;
|
return this.state.successfullyAuthenticated ? <App /> : <UnlockWith onSuccessfullyAuthenticated={this.onSuccessfullyAuthenticated} />;
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<LottieView
|
<LottieView
|
||||||
|
|
|
@ -630,7 +630,7 @@
|
||||||
13B07F861A680F5B00A75B9A = {
|
13B07F861A680F5B00A75B9A = {
|
||||||
DevelopmentTeam = A7W54YZ4WU;
|
DevelopmentTeam = A7W54YZ4WU;
|
||||||
LastSwiftMigration = 1030;
|
LastSwiftMigration = 1030;
|
||||||
ProvisioningStyle = Manual;
|
ProvisioningStyle = Automatic;
|
||||||
SystemCapabilities = {
|
SystemCapabilities = {
|
||||||
com.apple.Keychain = {
|
com.apple.Keychain = {
|
||||||
enabled = 0;
|
enabled = 0;
|
||||||
|
@ -1132,11 +1132,11 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_IDENTITY = "iPhone Distribution";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
CODE_SIGN_STYLE = Manual;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEAD_CODE_STRIPPING = NO;
|
DEAD_CODE_STRIPPING = NO;
|
||||||
DEVELOPMENT_TEAM = A7W54YZ4WU;
|
DEVELOPMENT_TEAM = "";
|
||||||
HEADER_SEARCH_PATHS = "$(inherited)";
|
HEADER_SEARCH_PATHS = "$(inherited)";
|
||||||
INFOPLIST_FILE = BlueWallet/Info.plist;
|
INFOPLIST_FILE = BlueWallet/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||||
|
@ -1152,7 +1152,7 @@
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet;
|
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet;
|
||||||
PRODUCT_NAME = BlueWallet;
|
PRODUCT_NAME = BlueWallet;
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "io.bluewallet.bluewallet AppStore";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "BlueWallet-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "BlueWallet-Bridging-Header.h";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
SWIFT_VERSION = 4.2;
|
SWIFT_VERSION = 4.2;
|
||||||
|
@ -1167,10 +1167,10 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_IDENTITY = "iPhone Distribution";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
CODE_SIGN_STYLE = Manual;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = A7W54YZ4WU;
|
DEVELOPMENT_TEAM = "";
|
||||||
HEADER_SEARCH_PATHS = "$(inherited)";
|
HEADER_SEARCH_PATHS = "$(inherited)";
|
||||||
INFOPLIST_FILE = BlueWallet/Info.plist;
|
INFOPLIST_FILE = BlueWallet/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||||
|
@ -1186,7 +1186,7 @@
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet;
|
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet;
|
||||||
PRODUCT_NAME = BlueWallet;
|
PRODUCT_NAME = BlueWallet;
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "io.bluewallet.bluewallet AppStore";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "BlueWallet-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "BlueWallet-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 4.2;
|
SWIFT_VERSION = 4.2;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
|
|
@ -27,6 +27,15 @@
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||||
|
BuildableName = "BlueWallet.app"
|
||||||
|
BlueprintName = "BlueWallet"
|
||||||
|
ReferencedContainer = "container:BlueWallet.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
<Testables>
|
<Testables>
|
||||||
<TestableReference
|
<TestableReference
|
||||||
skipped = "NO">
|
skipped = "NO">
|
||||||
|
@ -39,17 +48,6 @@
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</TestableReference>
|
</TestableReference>
|
||||||
</Testables>
|
</Testables>
|
||||||
<MacroExpansion>
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
|
||||||
BuildableName = "BlueWallet.app"
|
|
||||||
BlueprintName = "BlueWallet"
|
|
||||||
ReferencedContainer = "container:BlueWallet.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</MacroExpansion>
|
|
||||||
<AdditionalOptions>
|
|
||||||
</AdditionalOptions>
|
|
||||||
</TestAction>
|
</TestAction>
|
||||||
<LaunchAction
|
<LaunchAction
|
||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
|
@ -71,8 +69,6 @@
|
||||||
ReferencedContainer = "container:BlueWallet.xcodeproj">
|
ReferencedContainer = "container:BlueWallet.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildableProductRunnable>
|
</BuildableProductRunnable>
|
||||||
<AdditionalOptions>
|
|
||||||
</AdditionalOptions>
|
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
<ProfileAction
|
<ProfileAction
|
||||||
buildConfiguration = "Release"
|
buildConfiguration = "Release"
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>PreviewsEnabled</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -17,7 +17,7 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>4.5.0</string>
|
<string>4.5.1</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleURLTypes</key>
|
<key>CFBundleURLTypes</key>
|
||||||
|
@ -56,6 +56,8 @@
|
||||||
</dict>
|
</dict>
|
||||||
<key>NSAppleMusicUsageDescription</key>
|
<key>NSAppleMusicUsageDescription</key>
|
||||||
<string>This alert should not show up as we do not require this data</string>
|
<string>This alert should not show up as we do not require this data</string>
|
||||||
|
<key>NSFaceIDUsageDescription</key>
|
||||||
|
<string>In order to confirm your identity, we need your permission to use FaceID.</string>
|
||||||
<key>NSBluetoothPeripheralUsageDescription</key>
|
<key>NSBluetoothPeripheralUsageDescription</key>
|
||||||
<string>This alert should not show up as we do not require this data</string>
|
<string>This alert should not show up as we do not require this data</string>
|
||||||
<key>NSCalendarsUsageDescription</key>
|
<key>NSCalendarsUsageDescription</key>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>XPC!</string>
|
<string>XPC!</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>4.5.0</string>
|
<string>4.5.1</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>239</string>
|
<string>239</string>
|
||||||
<key>CLKComplicationPrincipalClass</key>
|
<key>CLKComplicationPrincipalClass</key>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>4.5.0</string>
|
<string>4.5.1</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>239</string>
|
<string>239</string>
|
||||||
<key>UISupportedInterfaceOrientations</key>
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
|
|
|
@ -84,6 +84,8 @@ PODS:
|
||||||
- React-cxxreact (= 0.60.5)
|
- React-cxxreact (= 0.60.5)
|
||||||
- React-jsi (= 0.60.5)
|
- React-jsi (= 0.60.5)
|
||||||
- React-jsinspector (0.60.5)
|
- React-jsinspector (0.60.5)
|
||||||
|
- react-native-biometrics (1.6.1):
|
||||||
|
- React
|
||||||
- react-native-blur (0.8.0):
|
- react-native-blur (0.8.0):
|
||||||
- React
|
- React
|
||||||
- react-native-camera (3.4.0):
|
- react-native-camera (3.4.0):
|
||||||
|
@ -178,6 +180,7 @@ DEPENDENCIES:
|
||||||
- React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
|
- React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
|
||||||
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
|
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
|
||||||
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
|
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
|
||||||
|
- react-native-biometrics (from `../node_modules/react-native-biometrics`)
|
||||||
- "react-native-blur (from `../node_modules/@react-native-community/blur`)"
|
- "react-native-blur (from `../node_modules/@react-native-community/blur`)"
|
||||||
- react-native-camera (from `../node_modules/react-native-camera`)
|
- react-native-camera (from `../node_modules/react-native-camera`)
|
||||||
- react-native-haptic-feedback (from `../node_modules/react-native-haptic-feedback`)
|
- react-native-haptic-feedback (from `../node_modules/react-native-haptic-feedback`)
|
||||||
|
@ -253,6 +256,8 @@ EXTERNAL SOURCES:
|
||||||
:path: "../node_modules/react-native/ReactCommon/jsiexecutor"
|
:path: "../node_modules/react-native/ReactCommon/jsiexecutor"
|
||||||
React-jsinspector:
|
React-jsinspector:
|
||||||
:path: "../node_modules/react-native/ReactCommon/jsinspector"
|
:path: "../node_modules/react-native/ReactCommon/jsinspector"
|
||||||
|
react-native-biometrics:
|
||||||
|
:path: "../node_modules/react-native-biometrics"
|
||||||
react-native-blur:
|
react-native-blur:
|
||||||
:path: "../node_modules/@react-native-community/blur"
|
:path: "../node_modules/@react-native-community/blur"
|
||||||
react-native-camera:
|
react-native-camera:
|
||||||
|
@ -338,6 +343,7 @@ SPEC CHECKSUMS:
|
||||||
React-jsi: 4d8c9efb6312a9725b18d6fc818ffc103f60fec2
|
React-jsi: 4d8c9efb6312a9725b18d6fc818ffc103f60fec2
|
||||||
React-jsiexecutor: 90ad2f9db09513fc763bc757fdc3c4ff8bde2a30
|
React-jsiexecutor: 90ad2f9db09513fc763bc757fdc3c4ff8bde2a30
|
||||||
React-jsinspector: e08662d1bf5b129a3d556eb9ea343a3f40353ae4
|
React-jsinspector: e08662d1bf5b129a3d556eb9ea343a3f40353ae4
|
||||||
|
react-native-biometrics: 4aaf49f9f8bd28c6aa3ec53534ca1b6b00486f6a
|
||||||
react-native-blur: cad4d93b364f91e7b7931b3fa935455487e5c33c
|
react-native-blur: cad4d93b364f91e7b7931b3fa935455487e5c33c
|
||||||
react-native-camera: 203091b4bf99d48b788a0682ad573e8718724893
|
react-native-camera: 203091b4bf99d48b788a0682ad573e8718724893
|
||||||
react-native-haptic-feedback: 22c9dc85fd8059f83bf9edd9212ac4bd4ae6074d
|
react-native-haptic-feedback: 22c9dc85fd8059f83bf9edd9212ac4bd4ae6074d
|
||||||
|
|
7
package-lock.json
generated
7
package-lock.json
generated
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "BlueWallet",
|
"name": "BlueWallet",
|
||||||
"version": "4.5.0",
|
"version": "4.5.1",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -10686,6 +10686,11 @@
|
||||||
"prop-types": "^15.5.10"
|
"prop-types": "^15.5.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-native-biometrics": {
|
||||||
|
"version": "1.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-biometrics/-/react-native-biometrics-1.6.1.tgz",
|
||||||
|
"integrity": "sha512-WYdZ6k3Miyl/+lEdhq6y4B6wz16d+PomO/xjR1hScYKeQWj1jaugPy0Ep+EjoWpJkPYLvnxasmIYR9v8OvWNHg=="
|
||||||
|
},
|
||||||
"react-native-camera": {
|
"react-native-camera": {
|
||||||
"version": "3.4.0",
|
"version": "3.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-camera/-/react-native-camera-3.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-camera/-/react-native-camera-3.4.0.tgz",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "BlueWallet",
|
"name": "BlueWallet",
|
||||||
"version": "4.5.0",
|
"version": "4.5.1",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.5.0",
|
"@babel/core": "^7.5.0",
|
||||||
"@babel/runtime": "^7.5.1",
|
"@babel/runtime": "^7.5.1",
|
||||||
|
@ -84,6 +84,7 @@
|
||||||
"react": "16.8.6",
|
"react": "16.8.6",
|
||||||
"react-localization": "1.0.13",
|
"react-localization": "1.0.13",
|
||||||
"react-native": "0.60.5",
|
"react-native": "0.60.5",
|
||||||
|
"react-native-biometrics": "^1.6.1",
|
||||||
"react-native-camera": "3.4.0",
|
"react-native-camera": "3.4.0",
|
||||||
"react-native-device-info": "2.2.2",
|
"react-native-device-info": "2.2.2",
|
||||||
"react-native-elements": "0.19.0",
|
"react-native-elements": "0.19.0",
|
||||||
|
|
|
@ -15,6 +15,7 @@ import { LightningCustodianWallet } from '../../class/lightning-custodian-wallet
|
||||||
import { BitcoinUnit, Chain } from '../../models/bitcoinUnits';
|
import { BitcoinUnit, Chain } from '../../models/bitcoinUnits';
|
||||||
import { Icon } from 'react-native-elements';
|
import { Icon } from 'react-native-elements';
|
||||||
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
|
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
|
||||||
|
import Biometric from '../../class/biometrics';
|
||||||
/** @type {AppStorage} */
|
/** @type {AppStorage} */
|
||||||
let BlueApp = require('../../BlueApp');
|
let BlueApp = require('../../BlueApp');
|
||||||
let EV = require('../../events');
|
let EV = require('../../events');
|
||||||
|
@ -143,6 +144,14 @@ export default class ScanLndInvoice extends React.Component {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isBiometricsEnabled = await Biometric.isBiometricUseCapableAndEnabled();
|
||||||
|
|
||||||
|
if (isBiometricsEnabled) {
|
||||||
|
if (!(await Biometric.unlockWithBiometrics())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.setState(
|
this.setState(
|
||||||
{
|
{
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { BlueButton, BlueText, SafeBlueArea, BlueCard, BlueSpacing40, BlueNaviga
|
||||||
import { BitcoinUnit } from '../../models/bitcoinUnits';
|
import { BitcoinUnit } from '../../models/bitcoinUnits';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
|
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
|
||||||
|
import Biometric from '../../class/biometrics';
|
||||||
let loc = require('../../loc');
|
let loc = require('../../loc');
|
||||||
let EV = require('../../events');
|
let EV = require('../../events');
|
||||||
let currency = require('../../currency');
|
let currency = require('../../currency');
|
||||||
|
@ -46,6 +47,15 @@ export default class Confirm extends Component {
|
||||||
try {
|
try {
|
||||||
await BlueElectrum.ping();
|
await BlueElectrum.ping();
|
||||||
await BlueElectrum.waitTillConnected();
|
await BlueElectrum.waitTillConnected();
|
||||||
|
|
||||||
|
const isBiometricsEnabled = await Biometric.isBiometricUseCapableAndEnabled();
|
||||||
|
|
||||||
|
if (isBiometricsEnabled) {
|
||||||
|
if (!(await Biometric.unlockWithBiometrics())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let result = await this.state.fromWallet.broadcastTx(this.state.tx);
|
let result = await this.state.fromWallet.broadcastTx(this.state.tx);
|
||||||
if (result && result.code) {
|
if (result && result.code) {
|
||||||
if (result.code === 1) {
|
if (result.code === 1) {
|
||||||
|
@ -163,7 +173,15 @@ export default class Confirm extends Component {
|
||||||
|
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={{ marginVertical: 24 }}
|
style={{ marginVertical: 24 }}
|
||||||
onPress={() =>
|
onPress={async () => {
|
||||||
|
const isBiometricsEnabled = await Biometric.isBiometricUseCapableAndEnabled();
|
||||||
|
|
||||||
|
if (isBiometricsEnabled) {
|
||||||
|
if (!(await Biometric.unlockWithBiometrics())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.props.navigation.navigate('CreateTransaction', {
|
this.props.navigation.navigate('CreateTransaction', {
|
||||||
fee: this.state.fee,
|
fee: this.state.fee,
|
||||||
recipients: this.state.recipients,
|
recipients: this.state.recipients,
|
||||||
|
@ -172,8 +190,8 @@ export default class Confirm extends Component {
|
||||||
satoshiPerByte: this.state.satoshiPerByte,
|
satoshiPerByte: this.state.satoshiPerByte,
|
||||||
wallet: this.state.fromWallet,
|
wallet: this.state.fromWallet,
|
||||||
feeSatoshi: this.state.feeSatoshi,
|
feeSatoshi: this.state.feeSatoshi,
|
||||||
})
|
});
|
||||||
}
|
}}
|
||||||
>
|
>
|
||||||
<Text style={{ color: '#0c2550', fontSize: 15, fontWeight: '500', alignSelf: 'center' }}>
|
<Text style={{ color: '#0c2550', fontSize: 15, fontWeight: '500', alignSelf: 'center' }}>
|
||||||
{loc.transactions.details.transaction_details}
|
{loc.transactions.details.transaction_details}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
import AsyncStorage from '@react-native-community/async-storage';
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { AppStorage } from '../../class';
|
import { AppStorage } from '../../class';
|
||||||
|
import Biometric from '../../class/biometrics';
|
||||||
let loc = require('../../loc');
|
let loc = require('../../loc');
|
||||||
|
|
||||||
export default class Settings extends Component {
|
export default class Settings extends Component {
|
||||||
|
@ -24,14 +25,19 @@ export default class Settings extends Component {
|
||||||
this.state = {
|
this.state = {
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
language: loc.getLanguage(),
|
language: loc.getLanguage(),
|
||||||
|
biometrics: { isDeviceBiometricCapable: false, isBiometricsEnabled: false },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
let advancedModeEnabled = !!(await AsyncStorage.getItem(AppStorage.ADVANCED_MODE_ENABLED));
|
const advancedModeEnabled = !!(await AsyncStorage.getItem(AppStorage.ADVANCED_MODE_ENABLED));
|
||||||
|
const isBiometricsEnabled = await Biometric.isBiometricUseEnabled();
|
||||||
|
const isDeviceBiometricCapable = await Biometric.isDeviceBiometricCapable();
|
||||||
|
const biometricsType = (await Biometric.biometricType()) || 'biometrics';
|
||||||
this.setState({
|
this.setState({
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
advancedModeEnabled,
|
advancedModeEnabled,
|
||||||
|
biometrics: { isBiometricsEnabled, isDeviceBiometricCapable, biometricsType },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +50,15 @@ export default class Settings extends Component {
|
||||||
this.setState({ advancedModeEnabled: value });
|
this.setState({ advancedModeEnabled: value });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onUseBiometricSwitch = async value => {
|
||||||
|
let isBiometricsEnabled = this.state.biometrics;
|
||||||
|
if (await Biometric.unlockWithBiometrics()) {
|
||||||
|
isBiometricsEnabled.isBiometricsEnabled = value;
|
||||||
|
await Biometric.setBiometricUseEnabled(value);
|
||||||
|
this.setState({ biometrics: isBiometricsEnabled });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.state.isLoading) {
|
if (this.state.isLoading) {
|
||||||
return <BlueLoading />;
|
return <BlueLoading />;
|
||||||
|
@ -56,6 +71,15 @@ export default class Settings extends Component {
|
||||||
<TouchableOpacity onPress={() => this.props.navigation.navigate('EncryptStorage')}>
|
<TouchableOpacity onPress={() => this.props.navigation.navigate('EncryptStorage')}>
|
||||||
<BlueListItem title={loc.settings.encrypt_storage} />
|
<BlueListItem title={loc.settings.encrypt_storage} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
{this.state.biometrics.isDeviceBiometricCapable && (
|
||||||
|
<BlueListItem
|
||||||
|
hideChevron
|
||||||
|
title={`Use ${this.state.biometrics.biometricsType}`}
|
||||||
|
switchButton
|
||||||
|
onSwitch={this.onUseBiometricSwitch}
|
||||||
|
switched={this.state.biometrics.isBiometricsEnabled}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<TouchableOpacity onPress={() => this.props.navigation.navigate('LightningSettings')}>
|
<TouchableOpacity onPress={() => this.props.navigation.navigate('LightningSettings')}>
|
||||||
<BlueListItem title={loc.settings.lightning_settings} />
|
<BlueListItem title={loc.settings.lightning_settings} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { HDLegacyP2PKHWallet } from '../../class/hd-legacy-p2pkh-wallet';
|
||||||
import { HDSegwitP2SHWallet } from '../../class/hd-segwit-p2sh-wallet';
|
import { HDSegwitP2SHWallet } from '../../class/hd-segwit-p2sh-wallet';
|
||||||
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
|
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
|
||||||
import { HDSegwitBech32Wallet } from '../../class';
|
import { HDSegwitBech32Wallet } from '../../class';
|
||||||
|
import Biometric from '../../class/biometrics';
|
||||||
let EV = require('../../events');
|
let EV = require('../../events');
|
||||||
let prompt = require('../../prompt');
|
let prompt = require('../../prompt');
|
||||||
/** @type {AppStorage} */
|
/** @type {AppStorage} */
|
||||||
|
@ -75,6 +76,14 @@ export default class WalletDetails extends Component {
|
||||||
'plain-text',
|
'plain-text',
|
||||||
);
|
);
|
||||||
if (Number(walletBalanceConfirmation) === this.state.wallet.getBalance()) {
|
if (Number(walletBalanceConfirmation) === this.state.wallet.getBalance()) {
|
||||||
|
const isBiometricsEnabled = await Biometric.isBiometricUseCapableAndEnabled();
|
||||||
|
|
||||||
|
if (isBiometricsEnabled) {
|
||||||
|
if (!(await Biometric.unlockWithBiometrics())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.props.navigation.setParams({ isLoading: true });
|
this.props.navigation.setParams({ isLoading: true });
|
||||||
this.setState({ isLoading: true }, async () => {
|
this.setState({ isLoading: true }, async () => {
|
||||||
BlueApp.deleteWallet(this.state.wallet);
|
BlueApp.deleteWallet(this.state.wallet);
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { BlueSpacing20, SafeBlueArea, BlueNavigationStyle, BlueText } from '../.
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import Privacy from '../../Privacy';
|
import Privacy from '../../Privacy';
|
||||||
import SystemSetting from 'react-native-system-setting';
|
import SystemSetting from 'react-native-system-setting';
|
||||||
|
import Biometric from '../../class/biometrics';
|
||||||
/** @type {AppStorage} */
|
/** @type {AppStorage} */
|
||||||
let BlueApp = require('../../BlueApp');
|
let BlueApp = require('../../BlueApp');
|
||||||
let loc = require('../../loc');
|
let loc = require('../../loc');
|
||||||
|
@ -39,11 +40,20 @@ export default class WalletExport extends Component {
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
Privacy.enableBlur();
|
Privacy.enableBlur();
|
||||||
|
|
||||||
|
await SystemSetting.saveBrightness();
|
||||||
|
await SystemSetting.setAppBrightness(1.0);
|
||||||
|
const isBiometricsEnabled = await Biometric.isBiometricUseCapableAndEnabled();
|
||||||
|
|
||||||
|
if (isBiometricsEnabled) {
|
||||||
|
if (!(await Biometric.unlockWithBiometrics())) {
|
||||||
|
return this.props.navigation.goBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
});
|
});
|
||||||
await SystemSetting.saveBrightness();
|
|
||||||
await SystemSetting.setAppBrightness(1.0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentWillUnmount() {
|
async componentWillUnmount() {
|
||||||
|
|
|
@ -85,6 +85,7 @@ export default class WalletMigrate {
|
||||||
const data = await AsyncStorage.getItem('data');
|
const data = await AsyncStorage.getItem('data');
|
||||||
if (data) {
|
if (data) {
|
||||||
const isEncrypted = (await AsyncStorage.getItem('data_encrypted')) || '';
|
const isEncrypted = (await AsyncStorage.getItem('data_encrypted')) || '';
|
||||||
|
await RNSecureKeyStore.set('Biometrics', '', { accessible: ACCESSIBLE.WHEN_UNLOCKED });
|
||||||
await RNSecureKeyStore.set('data', data, { accessible: ACCESSIBLE.WHEN_UNLOCKED });
|
await RNSecureKeyStore.set('data', data, { accessible: ACCESSIBLE.WHEN_UNLOCKED });
|
||||||
await RNSecureKeyStore.set('data_encrypted', isEncrypted, {
|
await RNSecureKeyStore.set('data_encrypted', isEncrypted, {
|
||||||
accessible: ACCESSIBLE.WHEN_UNLOCKED,
|
accessible: ACCESSIBLE.WHEN_UNLOCKED,
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { BlueSpacing20, SafeBlueArea, BlueText, BlueNavigationStyle, BlueCopyTex
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import Privacy from '../../Privacy';
|
import Privacy from '../../Privacy';
|
||||||
import SystemSetting from 'react-native-system-setting';
|
import SystemSetting from 'react-native-system-setting';
|
||||||
|
import Biometric from '../../class/biometrics';
|
||||||
/** @type {AppStorage} */
|
/** @type {AppStorage} */
|
||||||
let BlueApp = require('../../BlueApp');
|
let BlueApp = require('../../BlueApp');
|
||||||
let loc = require('../../loc');
|
let loc = require('../../loc');
|
||||||
|
@ -41,11 +42,20 @@ export default class WalletXpub extends Component {
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
Privacy.enableBlur();
|
Privacy.enableBlur();
|
||||||
|
await SystemSetting.saveBrightness();
|
||||||
|
await SystemSetting.setAppBrightness(1.0);
|
||||||
|
|
||||||
|
const isBiometricsEnabled = await Biometric.isBiometricUseCapableAndEnabled();
|
||||||
|
|
||||||
|
if (isBiometricsEnabled) {
|
||||||
|
if (!(await Biometric.unlockWithBiometrics())) {
|
||||||
|
return this.props.navigation.goBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
});
|
});
|
||||||
await SystemSetting.saveBrightness();
|
|
||||||
await SystemSetting.setAppBrightness(1.0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentWillUnmount() {
|
async componentWillUnmount() {
|
||||||
|
|
Loading…
Add table
Reference in a new issue